协议演进 / BIP/比特币改进提案 / BIP-376
BIP-376
为 PSBTv2 新增静默支付花费字段,把收款时算出的微调值直接交给签名者,使其能合成正确的花费私钥并完成 Taproot 密钥路径签名。本 BIP 目前处于草案状态。
一、档案卡
| 编号 | BIP-376 |
|---|---|
| 标题 | Spending Silent Payment outputs with PSBTs |
| 作者 | nymius <[email protected]> |
| 指定日期 | 2026-02-05 |
| 讨论日期 | 2024-05-17 |
| 层级 | Applications(应用) |
| 类型 | Specification(规范类) |
| 状态 | Draft(草案) |
| 依赖 | BIP-352、BIP-370、BIP-371 |
| 阅读版 | https://bips.dev/376 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0376.mediawiki |
二、放在哪一族
静默支付与 PSBT 的结合部,管“花费”这一侧,与 BIP-375(用 PSBT 发送静默支付)正好成对。
上游是 BIP-352(静默支付协议:收款输出是经微调生成的 P2TR 输出)与 BIP-370(PSBTv2);它产出的签名最终落在 BIP-371 定义的 PSBT_IN_TAP_KEY_SIG 字段里,并按 BIP-341 的密钥路径花费规则终结。
原文专门用一则脚注解释为何不把这组字段并进 BIP-375:静默支付历来按使用者视角分类——发送方一侧与接收方一侧;BIP-375 标题就是“发送”,花费属于接收方的领域,因此另立一篇。
三、它要解决什么
静默支付的收款输出不是一把现成私钥直接对应的 P2TR 输出。收款方扫描链上交易时,会为每笔收款算出一个微调值(tweak);真正能花费该输出的私钥,是把花费私钥与这个微调值合成之后的结果。
普通输出的 PSBT 花费流程靠派生路径字段找到正确私钥就能签,静默支付输出不行:签名者手里只有花费私钥,缺了微调值这一半。现有 PSBT 字段里没有专门放这个微调值的位置——BIP-375 与配套的 BIP-374 只规定了如何创建静默支付输出,没有规定如何解锁它们。
为什么不让签名者自己重算微调值?原文在 Rationale 里算了笔账:重算需要把相关交易的原始数据一并塞进 PSBT,以“一笔含两个 P2WPKH 输入、一个 P2TR 输出的交易”为例约需 413 字节,是直接传 32 字节微调值的十倍有余,还徒增签名设备的密码学负担。而微调值本就是扫描收款时已经算出并存储的结果,存下来直接传,比每次重算更自然。
复用现有同为 32 字节的字段(例如 PSBT_IN_TAP_MERKLE_ROOT)也被原文否决:两者的微调标签哈希不同,混用还会迫使其他组件额外判断“这到底是不是静默支付输入”。结论是新开专用字段。
四、规则本身
4.1 新增的两个每输入字段
只用于 PSBTv2(版本 2):
PSBT_IN_SP_SPEND_BIP32_DERIVATION(0x1f):键是 33 字节花费公钥,即派生出锁定本输入之密钥的那把花费公钥;值是 4 字节主密钥指纹拼接该花费公钥的 BIP32 派生路径(路径元素为 32 位小端整数)。为何键用 33 字节而不是沿用 Taproot 的 x-only 32 字节:BIP-352 的花费公钥是带符号字节的 33 字节密钥,合成私钥后还要靠这个符号判断最终私钥取 d 还是 −d,现有的PSBT_IN_TAP_BIP32_DERIVATION装不下。PSBT_IN_SP_TWEAK(0x20):无键数据;值是 32 字节原始微调值。
两个字段在输入终结者构造出 PSBT_IN_FINAL_SCRIPTWITNESS 后都应移除。
4.2 更新者(Updater)
花费静默支付输出的输入,更新者必须(MUST)添加 PSBT_IN_SP_TWEAK;采用 BIP32 派生方案花费时,应当(SHOULD)添加 PSBT_IN_SP_SPEND_BIP32_DERIVATION。若不愿透露指纹与派生路径,可把该字段值写成 4 字节全零指纹且不带任何路径。
4.3 签名者(Signer)
设 P 为 PSBT_IN_WITNESS_UTXO 中 P2TR 输出脚本里的 32 字节输出密钥。签名者必须:
- 用派生字段或其他方式取得花费私钥 b_spend,算出签名私钥 d = (b_spend + tweak) mod n,其中 tweak 取自
PSBT_IN_SP_TWEAK; - 若 d·G 的 y 坐标为奇数,必须把 d 取负;
- 校验 d·G 的 x 坐标是否等于 P,不相等必须失败——微调值由更新者提供,可能出错、甚至可能作恶;不校验就签名,等于为自己并不掌控的密钥作出有效 Schnorr 签名,资金可能被盗,原文对此有专门脚注;
- 用 d 作 BIP-340 Schnorr 签名,结果写入 BIP-371 的
PSBT_IN_TAP_KEY_SIG。
4.4 输入终结者(Input Finalizer)
每个带 PSBT_IN_SP_TWEAK 的输入,必须先有 PSBT_IN_TAP_KEY_SIG 才能终结,否则视为未签完。终结时按 BIP-341 密钥路径花费规则,用该签名构造只含单个见证元素的 PSBT_IN_FINAL_SCRIPTWITNESS,并移除该输入的 PSBT_IN_SP_TWEAK、PSBT_IN_SP_SPEND_BIP32_DERIVATION 与 PSBT_IN_TAP_KEY_SIG。
五、谁必须动
普通持币人:用静默支付地址收款后,日后通过硬件钱包等 PSBT 流程花费时,需要钱包与签名设备都实现本规范;收款环节本身不受本篇影响。
钱包开发者:扫描发现静默支付收款时要保存每笔输出对应的微调值;构造花费交易时由更新者角色把微调值与花费公钥派生信息填进 PSBT,不能指望签名时临时重算。
硬件钱包与签名者:必须实现“花费私钥加微调、必要时取负、校验合成公钥与输出密钥一致、再作 Schnorr 签名”这套逻辑,校验一步不可省。
全节点与矿工:无需动作。新增的只是 PSBT 字段,PSBT 可扩展,旧软件会忽略新字段;上链的仍是普通 Taproot 密钥路径花费。
六、现在算不算数,以及一个常见误读
状态为 Draft(草案)。原文的参考实现与测试向量两处仍标注 TODO,因此它目前是设计已成文、配套实现待补的提案,不能假设现有钱包已普遍支持用 PSBT 花费静默支付输出。
常见误读:“ BIP-376 是又一种新的静默支付协议,或改变了 BIP-352 的收款与花费规则。”不对。它不改 BIP-352 的任何密码学规则,只补 PSBT 这一环:把扫描时已经算出的微调值,标准化地交到签名者手里。
七、延伸
- 阅读版:https://bips.dev/376
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0376.mediawiki
- 相关:BIP-352 静默支付、BIP-375 用 PSBT 发送静默支付、BIP-370 PSBTv2、BIP-371 PSBT 的 Taproot 字段
- 仓库总目录:https://github.com/bitcoin/bips
