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

BIP-375 用 PSBT 发送静默支付

为 PSBTv2 新增静默支付字段与角色职责,让收款输出脚本能在全部输入到齐后算出,并可用 DLEQ 证明供其他参与方核验。本 BIP 目前处于草案状态。

一、档案卡

档案卡
编号BIP-375
标题Sending Silent Payments with PSBTs
作者Andrew Toth <[email protected]>、Ava Chow <[email protected]>、josibake <[email protected]>
指定日期2025-01-08
层级Applications(应用)
类型Specification(规范类)
状态Draft(草案)
依赖BIP-352、BIP-370、BIP-374
阅读版https://bips.dev/375
官方原文https://github.com/bitcoin/bips/blob/master/bip-0375.mediawiki

二、放在哪一族

静默支付(Silent Payments)与 PSBT 的结合部,管“发送”这一侧。

协议本体在 BIP-352:收款方只公布一个静默支付地址,发送方用自己输入的私钥与收款方的扫描公钥作 ECDH,为每笔付款算出独一无二的 P2TR 收款脚本,收款方靠扫描发现并花费这些输出。

BIP-375 只解决 PSBT 里怎么发送:它依托 BIP-370(PSBTv2),并用 BIP-374 的 DLEQ 证明担保计算正确。与它成对的是 BIP-376:管收款方日后如何用 PSBT 花费收到的静默支付输出——发送归发送,花费归花费,这正是两篇分开写的原因,原文脚注也专门说明了这一分工沿用了静默支付“按使用者是发送方还是接收方分类”的惯例。

三、它要解决什么

PSBTv2 与静默支付的发送流程天生有两处不合:

第一,时机对不上。静默支付的收款输出脚本,要等全部交易输入都确定之后才能计算——ECDH 共享秘密取决于全部合格输入的私钥之和。可 PSBT 的常规流程是构造时就把每个输出的脚本写死。脚本在输入到齐前根本算不出来,PSBT 里需要一种表示法,先记下“这个输出要发往某个静默支付地址”,脚本晚点再补。

第二,可核验性缺失。输出脚本由签名者计算,其他参与方(比如另一个共同签名者、或最终提取交易的一方)凭什么相信它算对了?算错一个脚本,交易照样共识有效,钱却可能永久丢失。因此计算过程必须留下可供他人复核的证据:ECDH 份额加上证明份额正确的 DLEQ 证明。

BIP-375 用新增字段加修订后的角色职责,同时解决这两处。

四、规则本身

4.1 新增字段

全局字段(每个扫描公钥一份):

每输入字段(签名者只掌握部分输入私钥时逐输入给出):

每输出字段:

以上字段只允许纳入 PSBTv2(版本 2),不用于 PSBTv0。

4.2 输出脚本改为可缺省

在支持静默支付的 PSBT 中,PSBT_OUT_SCRIPT 对静默支付输出改为可选:某个输出若没有它,就必须有 PSBT_OUT_SP_V0_INFO,表示“收款地址已定、脚本尚未算出”。两者都在时,后者就是已按前者算出的收款脚本。非静默支付输出仍必须有 PSBT_OUT_SCRIPT。

4.3 角色职责的变化

构造者(Constructor):每个输出必须至少有 PSBT_OUT_SCRIPT 或 PSBT_OUT_SP_V0_INFO 之一。另外有互斥约束:只要有静默支付输出,就不得加入花费见证版本大于 1 的输出脚本的输入,反之亦然。

更新者(Updater):应为 P2WPKH、P2SH-P2WPKH、P2PKH 输入补上 PSBT_IN_BIP32_DERIVATION,好让不知道私钥的一方也能拿到公钥去参与 ecdh_shared_secret 的计算;不愿透露指纹与路径时可把该字段值置零。更新者还可为输出同时记录扫描与花费两条派生路径、并在标签字段里写明标签,供签名者识别静默支付找零。

签名者(Signer):有静默支付输出时必须多做几件事——为自己有私钥的合格输入算出 ECDH 份额与 DLEQ 证明(全有私钥则用全局份额);核验自己没有私钥的那些输入的 DLEQ 证明;份额到齐后按 BIP-352 的建输出流程算出并填上 PSBT_OUT_SCRIPT,同时把“输入可改、输出可改”标志置为 False;只要还有输出缺脚本,就不得先行签名。签名哈希类型也受约束:有静默支付输出时只能用 SIGHASH_ALL,给了别的类型必须失败,没给则默认按 ALL 签——原文解释说,NONE 与 SINGLE 允许事后改动同扫描密钥下收款码的数量或位置,会让已算出的输出脚本失效。输入中若有见证版本大于 1 的花费,签名者必须失败。

交易提取者(Transaction Extractor):对静默支付 PSBT,应利用 ECDH 份额与 DLEQ 证明复算全部输出脚本并核对无误,否则失败,不得提取。

4.4 多个收款码的排序

同一扫描公钥对应多个静默支付收款码时,按字典序升序排列以确定各自的序号 k;扫描与花费公钥都相同的,再按输出下标升序排列。算错顺序,收款方就扫不到这笔钱,因此原文把排序规则写死。

五、谁必须动

普通持币人:想用 PSBT 流程(例如硬件钱包)发送静默支付,需要钱包与签名设备双方都实现本规范;单机热钱包内部直接计算的场景不一定经过 PSBT。

钱包开发者:按 4.1 至 4.4 实现字段、角色流程、份额与证明的计算核验、排序与 SIGHASH_ALL 约束,缺一环都可能发出收款方扫不到的输出。

硬件钱包与签名者:要在签名前承担份额计算、证明出具与他人证明的核验,并遵守“脚本未齐不签名”。

全节点与矿工:无需动作。最终上链的仍是普通 P2TR 输出,节点看不出它来自静默支付地址,也无需理解 PSBT。

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

状态为 Draft(草案),版本 0.1.2,原文附有 JSON 格式的测试向量与校验脚本。向后兼容方面原文说得很明确:静默支付 PSBT 只有在全部输出的 PSBT_OUT_SCRIPT 都已补齐之后,才与普通 PSBTv2 向后兼容;在此之前,未实现的软件不应处理它。读这篇时应把它当作仍在定稿中的发送侧规范。

常见误读:“ BIP-375 让静默支付在链上可被识别,或是静默支付协议本身。”都不对。静默支付协议是 BIP-352;本篇只规定发送时 PSBT 里怎么记账、谁负责算脚本、谁负责核验。链上结果与普通 Taproot 收款没有区别,旁观者无法据此认定某笔输出是静默支付收款。

七、延伸

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