协议演进 / BIP/比特币改进提案 / BIP-79

BIP-79 Bustapay:实用的 CoinJoin 协议

Bustapay:付款方先交一笔可直接广播的模板交易“作押”,收款方再添自己的输入合签,让这笔付款在链上看不出是协同交易,还顺手帮商户管住 UTXO 数量。本 BIP 目前处于已关闭状态。

一、档案卡

档案卡
编号BIP-79
标题Bustapay :: a practical coinjoin protocol
作者Ryan Havar <[email protected]>
指定日期2018-10-05
层级Applications(应用)
类型Informational(信息类)
状态Closed(已关闭)
拟接替BIP-78
阅读版https://bips.dev/79
官方原文https://github.com/bitcoin/bips/blob/master/bip-0079.mediawiki

二、放在哪一族

发送方与接收方协同签交易的隐私协议族,与后来的 BIP-78(A Simple Payjoin Proposal)是直系前后任:本 BIP 档案里写着 Proposed-Replacement(拟接替)为 BIP-78,而 BIP-78 那边写着 Replaces(取代)BIP-79——两份档案正好对上。

思想源头原文写得很清楚:基于 Greg Maxwell 提出的 CoinJoin,并受 Blockstream “pay 2 endpoint” 一文简化的启发。它与传统 CoinJoin 的区别在于参与方只有交易的付款方与收款方两人,且交易外形与普通付款无异。类型上它被归为 Informational(信息类),即描述一个协议构想供实现参考,而非强制性的标准轨规范。

三、它要解决什么

3.1 “输入全属一人”这条假设太好用了

原文把矛头对准链上分析最有力的一条启发式:除非有明确反证(如传统 CoinJoin 的特殊结构、多签花费在链上可验证),否则默认一笔交易的全部输入由同一方控制。再叠加找零输出猜测等手法,追踪准确得超乎预期,把参与者暴露在个人、商业与财务风险之下,侵蚀比特币作为可用货币的可替代性。

Bustapay 的解法是让付款方与收款方合签一笔交易,直接“炸掉”(bust)这条假设。而且它特意做到交易没有可识别的结构:分析者无法判断某一笔交易到底是不是 Bustapay,于是其整套模型的置信度都被拖低——原文称这是给整个生态的正外部性。

3.2 商户的 UTXO 只进不出

收款还有一个实际好处:Bustapay 交易不会增加收款方的 UTXO 数量,反而给收款方一个在收款时顺手管理 UTXO 集的机会——这种整理平常只有在付款时才做。UTXO 集庞大既贵又麻烦,事后合并又常常毁隐私。此外,协同交易还能对付款金额起一层混淆作用。

原文明确说,本规范刻意舍弃了复杂度和一些可能有用的扩展,因为“简单”对推动采用最重要。

四、规则本身

4.1 五步流程

  1. 付款方先建一笔正常付款交易:必须全部输入都用 SegWit、完全有效且已签名、符合网络传播条件,但先不广播。这叫模板交易(template transaction)。
  2. 付款方把模板交易发给收款方:通过 HTTP POST 发到一个 bustapay url(二进制编码的请求体)。
  3. 收款方加工并回一笔部分交易:校验模板交易、确认付给自己,再加入一个或多个自己的输入(contributed inputs,贡献输入),并通常把付给自己的输出金额相应调高(加上贡献输入之和),签好自己新增的输入后回传。因付款方的输入需要重签,这笔交易此时只是“部分”完成。
  4. 付款方校验、重签、广播:必须确认部分交易被正确且无恶意地修改,只重签自己原来的输入,再把最终交易广播上网。
  5. 收款方在链上确认:看到最终交易并有足够确认后,按实收金额(而非链上表观金额)入账。若超时仍不见最终交易,收款方就广播最初的模板交易——付款照样完成,这也是强力的防拒绝服务机制。

为什么第一步就要交一笔可直接广播的交易?原文的用意是防无成本的窥探与 DoS:发起方若中途消失,收款方可以径直广播模板交易,发起的代价被绑在“花掉一个 UTXO”上,想白嫖探测就得真付钱。

4.2 如何告知端点

用 BIP21 编码的地址带一个键值:bpu(BustaPayUrl 的缩写),例如地址后跟 ?bpu=https://…/submit。原文鼓励 URL 尽量短。模板交易除只许 SegWit 输入外与普通付款无异;鼓励(但不强制)使用稍激进的费率,并开启 BIP-125 的 Opt-in Full RBF 信号。

4.3 收款方的纪律

4.4 付款方的校验清单

付款方对回传的部分交易必须查三件事:模板交易的全部输入都在(顺序可变)且 sequence 号未变;至少含一个新的、已签名的、属收款方的 SegWit 输入;模板交易的全部输出都在(顺序可变),金额只能调高、绝不能调低。

签最终交易时还有一条保命线:只能签模板交易里原有的输入。若不小心,收款方可能把付款方自己的其他输入冒充“贡献输入”塞进来,诱使付款方盲签——原文在规范与实现注记里两次提醒这一点。

4.5 广播与兜底

最终交易建成后付款方应立即广播。若合理时间(如 1 分钟)内没广播,收款方应广播模板交易,既防窥探也防 DoS。反过来,若收款方把交易做大却没把费率补够、不合理地拉低了费率,付款方也可以改广播模板交易。最终交易迟迟不确认时,双方还可以利用 RBF 把模板交易顶上去(前提是模板交易费更高)。

实现注记还给了收款方几条实务提醒:用 Bitcoin Core 0.17+ 的 testmempoolaccept 检查交易能否进内存池;只靠 txid 追踪交易并不可靠,务必全 SegWit 且认真校验;不要接受付给已用过的充值地址的 Bustapay 交易,以防被试探某地址是否属你;要保存“见过谁的 UTXO、自己暴露过哪个”的映射;若模板交易已按 BIP-69 排序,处理后应保持有序,否则可打乱输入输出顺序。参考实现是套在 Bitcoin Core 钱包 RPC 外的一层包装。

五、谁必须动

普通持币人:无感。Bustapay 是可选的付款协议,必须与普通交易处理并存;走不通时回退到普通比特币交易,本就是规范要求的必备行为。

钱包开发者(付款方):要能构造全 SegWit 的模板交易、POST 给 bpu 端点、按 4.4 清单校验回传的部分交易、只重签自己的输入,并妥善处理“收款方可能径直广播模板交易”这一前提,避免双付。

收款方与商户系统:要托管 bustapay 端点,能校验模板交易、稳定地挑选贡献输入(同一输入组回同一贡献)、调整自己的收款输出、签名并回传;还要在超时后广播模板交易兜底,并维护 UTXO 暴露映射防枚举。

全节点与矿工:不涉及。最终上链的是一笔普通 SegWit 交易,无新规则。

六、现在算不算数,以及一个常见误读

状态为 Closed(已关闭),且档案标注的拟接替者 BIP-78 已经以 Deployed 状态取代了它。今天要实现“付款方与收款方合建一笔交易”,应照 BIP-78(及其异步版 BIP-77 的方向)去做:改用 PSBT 传递、补上版本协商与标准错误码。BIP-79 的价值在于把这套打法——先交可广播的模板交易作押、收款方添输入、双方各守校验清单——第一次写成完整可落地的流程。

常见误读:

“BIP-79 既然被关闭,就是它这套做法被否定了。”

不对。关闭的原因写在两份档案的互指关系里:是被接替,不是被否定。BIP-78 明说自己的提案与 Bustapay 非常相似,只在载体(PSBT)、输出类型调整、版本协商与错误标准化上另起炉灶。把 Closed 读成“此路不通”,会错过它与现行 Payjoin 之间一脉相承的设计。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。