协议演进 / BIP/比特币改进提案 / BIP-375
BIP-375
为 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 新增字段
全局字段(每个扫描公钥一份):
PSBT_GLOBAL_SP_ECDH_SHARE(0x07):以 33 字节扫描公钥为键;值是 33 字节 ECDH 份额,即用全部合格输入私钥之和 a 与扫描公钥算出的 a·B_scan,适用于签名者掌握全部合格输入私钥的情形。PSBT_GLOBAL_SP_DLEQ(0x08):同一扫描公钥对应的 64 字节 BIP-374 DLEQ 证明。
每输入字段(签名者只掌握部分输入私钥时逐输入给出):
PSBT_IN_SP_ECDH_SHARE(0x1d):以扫描公钥为键;值是该输入私钥与扫描公钥算出的份额。PSBT_IN_SP_DLEQ(0x1e):该份额对应的 64 字节 DLEQ 证明。
每输出字段:
PSBT_OUT_SP_V0_INFO(0x09):静默支付地址中的扫描公钥与花费公钥(各 33 字节),标明这个输出是发往静默支付地址的。PSBT_OUT_SP_V0_LABEL(0x0a):32 位小端标签(label),用于按 BIP-352 的标签机制计算花费公钥,也用于核验找零。
以上字段只允许纳入 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 收款没有区别,旁观者无法据此认定某笔输出是静默支付收款。
七、延伸
- 阅读版:https://bips.dev/375
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0375.mediawiki
- 相关:BIP-352 静默支付、BIP-370 PSBTv2、BIP-374 离散对数相等证明、BIP-376 用 PSBT 花费静默支付输出
- 仓库总目录:https://github.com/bitcoin/bips
