news 2026/10/14 17:27:26

解读 Bisq 1.10.3 安全加固发布说明:Filter 字段停用、Deposit/DPT 交易绑定与消息认证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
解读 Bisq 1.10.3 安全加固发布说明:Filter 字段停用、Deposit/DPT 交易绑定与消息认证
  • 区块链
  • DeFi
  • 金融科技

【免费下载链接】bisq

A decentralized bitcoin exchange network

项目地址:https://gitcode.com/gh_mirrors/bi/bisq
点击查看免费下载

Bisq 1.10.3 是一次典型的安全加固(security-hardening)版本:它在 10 个提交中集中处理了未签名 Filter 字段、Core API 失败交易状态迁移、Deposit/DPT 交易绑定校验以及争议消息发件人认证四大类风险点。本文基于当前仓库中的 1.10.3 完整发布说明,逐项还原其兼容性影响与实现细节,并结合FilterManager、CoreTradesService、BuyerSetupDepositTxListener、SupportManager等源码与回归测试,说明每项加固在 Bisq 代码库中具体落在哪里、如何验证。

版本概况与提交清单

1.10.3 的发布说明采用与 Bitcoin Core 发布说明一致的务实风格:用户与运维影响在前,完整可审计的提交清单在后。提交区间为358b546526d07445a857aa70da76cc1acdeca53b(含)至292f438112b3c721a1a73ff2eb8c3ed8ac7fdce6,由以下命令生成(区间含起始提交,覆盖标签v1.10.3的全部后续提交):

git log --reverse 358b546526d07445a857aa70da76cc1acdeca53b^..v1.10.3

统计信息(摘自 full-release-notes.md):

  • Total commits:10
  • Non-merge commits:7
  • Merge commits:3
  • Files changed:27
  • Generated on:2026-07-06

按git log --reverse顺序排列的完整提交清单如下(作者与日期以发布说明为准):

日期提交类型摘要作者
2026-07-04358b546526Commit停用 filter 提供的 BTC 节点与种子节点的持久化HenrikJannsen
2026-07-04ca462d1f48Commit临时停用 filter 提供的 BTC 费用接收地址HenrikJannsen
2026-07-04e6ecc74f6eCommit阻止失败交易经由 API 进入 payment-started 状态HenrikJannsen
2026-07-048aeddc7bb5Commit忽略 filter 提供的 BTC 节点与种子节点的配置值HenrikJannsen
2026-07-059d2c952555Merge合并未签名 filter 种子/BTC 节点停用Alejandro Garcia
2026-07-05802ab0e129Merge合并 BTC 费用接收地址 filter 停用Alejandro Garcia
2026-07-05c7b68d485fMerge合并失败交易 payment-start API 守卫Alejandro Garcia
2026-07-057a441aa6fcCommit版本号提升至v1.10.3Alejandro Garcia
2026-07-057e7e4ed905Commit加固 Deposit 交易与 Delayed Payout 交易绑定Alejandro Garcia
2026-07-05292f438112Commit加固支持消息与争议消息的发件人认证Alejandro Garcia

兼容性影响:升级者需要知道什么

发布说明列出的 7 条兼容性要点,是运维升级前的核心检查清单:

  1. Bisq 版本被设置为1.10.3;
  2. Filter 提供的附加 BTC 节点与种子节点被禁用,因为这些字段未包含在当前 filter 签名范围内;
  3. 之前已持久化的filterProvidedBtcNodes、filterProvidedSeedNodes配置值在本版本中被忽略;
  4. Filter 提供的 BTC 费用接收地址被临时忽略,但 mempool 费用接收列表仍包含 DAO 捐赠地址与 Burning Man 接收地址;
  5. Core API 现在拒绝为已标记为失败的交易确认付款开始(payment-start);
  6. Deposit 交易与 Delayed Payout 交易的处理在变更钱包或交易状态之前执行更严格的绑定校验;
  7. 当发件人签名公钥不匹配预期的 peer、trader 或争议代理时,交易聊天、ACK、发起争议、peer 发起争议、争议结果五类消息一律被忽略。

发布说明明确建议:这是一个安全加固版本,应尽快升级,尤其是依赖 filter、API 交易控制或争议消息处理路径的节点。

未签名 Filter 字段停用(Unsigned Filter Fields Disabled)

背景:Filter 是签名策略,未签名字段不可信

Bisq 的应急策略体系由两部分组成:P2P 分发的签名网络Filter,以及启动时加载的静态DenyList(详见 filter-and-deny-list.md)。签名 filter 由受信任的开发者密钥发布,FilterManager会拒绝验签失败的 filter、拒绝时间过远的 filter,并在多个有效 filter 中优先采用创建时间最新者。从源码结构看,受信任的开发者公钥硬编码在 FilterManager 构造函数中(非 dev 模式下为 3 个公钥),这决定了"哪些字段真正受签名保护"的边界。

问题在于:Filter对象中携带的"附加 BTC 节点"和"附加种子节点"字段位于当前 filter 签名的覆盖范围之外。这意味着攻击者若能篡改这两个字段,节点会据此连上恶意节点而不会触发验签失败。1.10.3 的处理方式是:与其信任,不如彻底停用。

源码层面的落点

  • 停用持久化(提交358b546526):FilterManager不再把 filter 提供的 BTC 节点与种子节点写回本地选项文件。这两个字段在 Config 中分别定义为filterProvidedBtcNodes与filterProvidedSeedNodes(常量FILTER_PROVIDED_BTC_NODES/FILTER_PROVIDED_SEED_NODES),并在 Config 中暴露为List<String>字段。
  • 忽略已持久化值(提交8aeddc7bb5):Config对这两个已持久化的键直接忽略,防止旧版本写入的陈旧值在升级后启动时生效。这与 filter-and-deny-list.md 中"这些持久化值是 filter 状态而非用户偏好"的描述一致——它们是 filter 派生状态,而非运维显式配置的bannedSeedNodes/bannedBtcNodes。
  • 种子节点侧的消费点:在 DefaultSeedNodeRepository 中可以看到config.filterProvidedSeedNodes原本是种子节点缓存的来源之一,并且受--ignoreNetworkFilter开关控制。1.10.3 之后,该来源在 filter 签名方案重写("replacement filter implementation")可用之前被视为不安全,按空值写入与生效。

相关测试覆盖了这条路径,包括 FilterManagerInitializationTests、FederatedBtcNodeProviderTest、BtcNodesSetupPreferencesTest 与 DefaultSeedNodeRepositoryTest。

临时停用 Filter 提供的 BTC 费用接收地址

Filter 提供的btcFeeReceiverAddresses同样被临时排除在 mempool 服务的费用接收地址列表之外。发布说明特别说明:该路径当时未被主动使用("The path was not actively used"),预期由新的 filter 实现接管;同时BtcFeeReceiverService.java本身没有被修改,行为变化发生在MempoolService。

从当前代码树看 MempoolService.getAllBtcFeeReceivers,完整的 BTC 费用接收地址列表由四部分合并而成:

  1. DAO 捐赠地址(daoFacade.getAllDonationAddresses());
  2. Burning Man 地址列表的 legacy 地址(addBurningManAddressListLegacyAddress);
  3. 经 BtcFeeReceiverService.getConfiguredReceiverAddresses 解析、来自 filter 的地址(经由 FilterPolicyService.getBtcFeeReceiverAddresses 读取当前生效 filter 的btcFeeReceiverAddresses字段);
  4. 分布式 Burning Man 地址。

需要说明的适用前提:当前仓库Version已演进到1.10.9(见 Version.java),上表反映的是当前代码树的构造方式;在 1.10.3 时点,第 3 类 filter 来源按发布说明被临时排除,仅第 1、2(、4)类地址进入 mempool 校验,用于parseJsonValidateMakerFeeTx/parseJsonValidateTakerFeeTx等费用交易 JSON 校验(MempoolService 中可见调用点)。

失败交易的 API 守卫(Failed Trade API Guard)

CoreTradesService.confirmPaymentStarted新增一条前置检查:如果交易已被标记为失败,直接抛出异常,阻止 API 客户端把失败交易沿着买方协议路径推进到 payment-started 状态。入口是 CoreApi.confirmPaymentStarted(接受tradeId及可选的txId、txKey),实现位于 CoreTradesService:

void confirmPaymentStarted(String tradeId, @Nullable String txId, @Nullable String txKey) { var trade = getTrade(tradeId); if (isFollowingBuyerProtocol(trade)) { if (trade.hasFailed()) { throw new FailedPreconditionException("Cannot confirm payment started for a failed trade."); } ... } }

同一守卫之后还有两道既有检查可对照理解:存款交易未确认(!trade.isDepositConfirmed())时同样拒绝;卖方付款账户载荷缺失时也拒绝,因为"买方没有收款细节,付款开始消息等于宣称了一笔不可能发生的付款"。这个守卫与争议流程直接相关——失败交易(FailedTradesManager 管理的交易)之后仍可能进入争议,因此 API 层不能允许它"复活"。

Deposit 交易与 Delayed Payout 交易的绑定加固

这是 1.10.3 中技术含量最高的一组变更(提交7e7e4ed905),核心思路是:所有校验必须在变更钱包或交易状态之前完成,且必须验证交易之间的密码学绑定关系,而不是只做字段级检查。

买方侧处理DepositTxAndDelayedPayoutTxMessage

在 Bisq 交易协议中,卖方通过 DepositTxAndDelayedPayoutTxMessage 把 deposit 交易与 delayed payout 交易(DPT)一起发给买方,买方协议在 BuyerProtocol 中转入BuyerProcessDepositTxAndDelayedPayoutTxMessage任务。1.10.3 之后,买方侧校验包含三层:

  1. peer deposit 交易与本地 deposit 交易一致性:买方先验证对方发来的 deposit 交易与自己本地的 deposit 交易匹配,然后才允许变更钱包或交易状态。对于 buyer-as-maker 交易,由于 maker 此时尚未设置 deposit 交易,校验对象改用已准备的(prepared)deposit 交易;
  2. DPT 必须花费 peer deposit 交易的第 0 个输出:DPT 与 peer deposit 交易做绑定校验,防止接受一笔"序列化正确、但实际绑定到另一笔 deposit 交易"的 DPT;
  3. 一切拒绝都发生在状态变更前(fail before mutation)。

回归测试 BuyerProcessDepositTxAndDelayedPayoutTxMessageTest 的测试方法名与发布说明逐条对应:

  • runAcceptsDelayedPayoutTxWithNonZeroLockTime—— 合法 DPT(含非零 lockTime)被接受;
  • runUsesPreparedDepositTxForBuyerAsMaker—— buyer-as-maker 使用 prepared deposit 交易;
  • runRejectsMismatchedDelayedPayoutTxBeforeWalletMutation—— DPT 不匹配时在钱包变更前拒绝;
  • runRejectsPeerDepositTxNotBoundToBuyersDepositTxBeforeWalletMutation—— 对方 deposit 交易未绑定到买方本地 deposit 交易时拒绝;
  • runRejectsPeerDelayedPayoutTxNotSpendingDepositTxOutputZeroBeforeWalletMutation—— DPT 输入未花费 deposit 交易 output 0 时拒绝。

存款确认回调绑定到注册时的交易 ID

Trade.setupConfidenceListener 在注册确认监听时把回调绑定到当时 deposit 交易的 txid。注释直接说明了动机:"deposit 交易可能被覆盖(例如网络观察到的交易被最终的 deposit/DPT 消息替换),来自已不是当前交易的陈旧 confidence 回调绝不能把交易标记为 deposit-confirmed"。回调触发时 setConfirmedState 先比对 txid,不一致则记录Ignoring stale deposit-tx confirmation...并忽略,只有确认通过且状态未推进过时才置为DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN。

maker-fee / taker-fee 输入必须"各自不同"

BuyerSetupDepositTxListener 的存款交易判定逻辑从"匹配输入数量 ≥ 2"升级为"必须各有一个不同的 maker-fee 输入和一个不同的 taker-fee 输入"。源码注释给出了具体攻击场景:

We must require one distinct maker-fee input AND one distinct taker-fee input, not just a count of inputs whose parent txid is one of the two fee txids. Otherwise, a malicious seller-as-maker could satisfy a count==2 check using two different outputs of his own maker fee tx (the maker fee tx can have fee, reserved-for-trade and change outputs), and get us to accept a fake deposit tx that was never co-funded by the taker.

也就是说,恶意卖方可以利用 maker fee 交易自带的多个输出(fee、reserved-for-trade、change),用同一笔 fee 交易的不同输出凑出"2 个匹配输入",骗过旧的计数检查,使买方接受一笔从未经 taker 共同出资的假 deposit 交易。新逻辑按outpoint父交易 ID 分别置位hasMakerFeeInput/hasTakerFeeInput两个布尔量;当takerFeeTxId未知(buyer-as-maker 场景)时只要求 maker-fee 输入存在。该校验还叠在既有的防地址复用逻辑之上(同文件中注释说明:历史 bug 曾导致 Multisig 地址条目被重复使用,使同一depositTxAddress出现在多笔交易中)。

支持消息与争议消息的发件人认证

提交292f438112将"解密后的发件人签名公钥"贯穿到直接消息与邮箱消息的完整处理链,并对五类消息做发件人绑定校验。

交易聊天与 ACK

SupportManager.onChatMessage 在处理聊天消息前,先用本地交易上下文解析预期的 peer 公钥环(getPeerPubKeyRing),再调用 isSenderSignaturePubKeyExpected 比对解密出的发件人签名公钥;不匹配则记录sender signature pubKey does not match the expected peer并直接丢弃,不写入聊天、不回复 ACK。

onAckMessage 的加固更为关键:ACK 消息不再从不可信的消息体数据中解析 peer 公钥,而是要求先在本地聊天记录中找到 ACK 所指的源消息(按sourceId+sourceUid检索);找不到源消息直接忽略并告警,找到后才从源消息取预期公钥环做发件人校验。

争议发起、peer 发起争议与争议结果

DisputeManager 在两条关键路径上做发件人绑定:

  • 发起争议(open dispute):校验签名发件人与内嵌合同(contract)中声明的争议发起方一致,并拒绝 trader 公钥与声明发起方不一致的争议;
  • peer 发起争议 / 争议结果(dispute-result):以本地交易记录中预期的 mediation、refund 或 arbitration 代理公钥为准校验发件人,并拒绝载荷中的代理公钥与本地交易不匹配的数据。

此外,无效争议数据现在在争议列表被变更或持久化之前被拒绝(配合 DisputeValidation 的数据校验路径),避免脏数据进入持久层。

争议认证回归测试位于 DisputeManagerAuthTest 与 MediationManagerAuthTest。前者中几个值得注意的用例直接对应发布说明的 "failed-trade lookup during dispute authentication":

  • findTradeIncludesFailedTrades—— 交易查找必须包含失败交易(否则失败交易上的争议无法通过认证);
  • agentSignatureAcceptsFailedTradeAgentKeyFromLocalTrade—— 接受来自本地交易记录的失败交易代理公钥;
  • agentSignatureRejectsFailedTradeWhenDisputeAgentKeyDoesNotMatchLocalTrade—— 代理公钥与本地交易不匹配时拒绝。

版本发布与回归验证

  • 版本提升:应用与打包版本统一提升到1.10.3(提交7a441aa6fc);v1.10.3标签包含版本号提升以及其后的 deposit/DPT、争议消息加固提交。当前仓库的版本常量见 Version.java(HEAD 已演进至后续版本,本文结论以 1.10.3 发布说明为准)。
  • 回归覆盖(摘自发布说明):DPT 输入绑定、deposit 交易不匹配拒绝、buyer-as-maker deposit 处理、陈旧存款确认处理、支持 ACK 认证、争议发起方认证、争议代理认证、争议认证期间的失败交易查找、mediation 争议结果发件人认证。
  • 发布门禁(摘自 notable-changes.md):作为安全加固版本,发布验证应包含 filter/config 路径、Core API 失败交易守卫、deposit/DPT 绑定、支持/争议消息认证四类聚焦测试。

小结

1.10.3 的改动看似分散,实际共享同一条设计原则:任何来自网络的字段、交易或消息,在触发本地状态变更(持久化、钱包、交易状态机)之前,必须先通过与"本地可信上下文"的绑定校验——未签名的 filter 字段直接停用,费用接收地址收窄到可信来源,失败交易被 API 层拦截,deposit/DPT 用密码学绑定关系(output 0 花费、fee 输入来源、txid 回调绑定)而非形状检查来防伪,聊天与争议消息一律以本地交易记录中的公钥为唯一认证基准。对于运行依赖 filter、API 交易控制或争议流程的节点,理解这五条路径既是对升级必要性的解释,也是一份可对照当前源码复核安全属性的检查清单。

  • 区块链
  • DeFi
  • 金融科技

【免费下载链接】bisq

A decentralized bitcoin exchange network

项目地址:https://gitcode.com/gh_mirrors/bi/bisq
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 17:27:22

从零实现Q-Learning:Q表更新原理与Python网格世界实践

刚接触强化学习的时候&#xff0c;我最深的感受是&#xff1a;一堆术语在脑子里打架。策略、价值函数、时序差分、免模型……每个词单独看都能查到解释&#xff0c;合在一起就不知道它在解决什么问题。直到我亲手用Q-Learning写了一个“44网格找宝藏”的小智能体&#xff0c;跑…

作者头像 李华
网站建设 2026/10/14 17:27:04

Mimics三维重建全流程:CT数据导入到STL导出避坑指南

简介&#xff1a;Mimics中文版教程&#xff08;持续更新版0812&#xff09;是一份面向医疗与生物工程领域三维建模初学者的实用PDF文档。教程依托Mimics医学图像处理软件&#xff0c;系统讲解从打开工程、窗口化、二值化、区域增长到建立3D表示并导出STL文件的完整操作流程&…

作者头像 李华
网站建设 2026/10/14 17:26:57

差动轮里程计设计与工程实现:从运动学推导到误差补偿

做移动机器人时间久了你会发现一个挺反直觉的现象&#xff1a;差动轮里程计&#xff08;odom&#xff09;几乎是所有定位方案里最容易上手、也最容易做错的东西。说它容易&#xff0c;是因为两轮差速的运动学模型几行公式就能写完&#xff1b;说它容易错&#xff0c;是因为从编…

作者头像 李华
网站建设 2026/10/14 17:26:47

SnackBar项目概览:Android Material Design风格提示条的完整前世今生

移动开发UI库/组件 【免费下载链接】SnackBar toast-like alert pattern for Android inspired by the Google Material Design Spec 项目地址&#xff1a; https://gitcode.com/gh_mirrors/sna/SnackBar 点击查看 免费下载 SnackBar 是一个经典的 Android 开源库&#xff0c;…

作者头像 李华