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

BIP-351 隐私支付

让付款双方仅凭一个可公开分享的支付码,用纯链上方式算出只有彼此能算出的收款地址,每笔付款地址都不同。本 BIP 目前处于已关闭状态。

一、档案卡

档案卡
编号BIP-351
标题Private Payments
作者Alfred Hodler <[email protected]>, Clark Moody <[email protected]>
指定日期2022-07-10
层级Applications(应用)
类型Specification(规范类)
状态Closed(已关闭)
阅读版https://bips.dev/351
官方原文https://github.com/bitcoin/bips/blob/master/bip-0351.mediawiki

二、放在哪一族

可复用收款标识与隐私支付族。它要接的是 BIP-47(Reusable Payment Codes,可复用支付码)留下的坑:支付码可以公开、可以反复收款,但通知方式会暴露谁在给谁付款。

同族的先后关系大致是:

BIP-32:分层确定性钱包,支付码与双方密钥都从种子派生

BIP-44:多账户层级结构,BIP-351 的派生路径沿用它的层级

BIP-47:可复用支付码,先行者,也是本 BIP 主要想改进的对象

BIP-352:静默支付(Silent Payments),后来同方向的另一条路线——不需要链上通知交易

与 BIP-352 相比,BIP-351 仍然需要一笔通知交易,只是把通知做得让外人认不出来;BIP-352 则连通知都省了。两条路线解决的是同一个问题:收款标识公开分享时,如何不牺牲隐私。

三、它要解决什么

收款方想长期用一个标识收款,又不想丢隐私,原有办法各有硬伤,原文逐一列过:

BIP-351 的目标是:支付码可以公开贴出来,每个付款方都为它算出一组独一无二的地址;通知只走链上,但不指向公开已知的地址,把链上足迹压到最小。

四、规则本身

4.1 支付码的结构

收款方按 BIP44 层级派生密钥,路径为 m / purpose' / coin_type' / account',其中 purpose 定为 351。路径处的公钥 P(私钥 p)就是支付码的核心。

支付码共 35 字节:前 2 字节是地址类型标志,后 33 字节是压缩公钥 P。用 bech32m 编码,主网人类可读前缀是 pay,测试网是 payt。

地址类型用 16 位大端位标志表示,当前已定义的只有三位:P2PKH(0x0001)、P2WPKH(0x0002)、P2TR(0x0004)。其余位保留给未来的地址类型。所有密钥都必须是压缩格式,用非压缩密钥在任何环节都不合法。

4.2 通知:40 字节的 OP_RETURN

付款方 Alice 想开始给收款方 Bob 付款时,先发一笔通知交易,其中带一个 40 字节的 OP_RETURN 输出,内容按顺序拼接:

Bob 扫描区块里的 OP_RETURN,凡以 PP 开头的,就用自己的私钥算 H(N_x * p) 比对前 4 字节:对上,就是发给自己的通知,把 N_x 和地址类型存下来,开始监视双方共同算出的那组地址。对不上就丢弃。

这个设计的关键点有三个:一是通知不发给任何公开地址,外人看不出通知是给谁的;二是 Alice 换一个索引 x 就能以全新身份重新通知,不与旧身份关联,也可以借此改换地址类型;三是通知码只截 4 字节,误报概率约 43 亿分之一,代价只是多监视几个地址,却省下 28 字节。原文也提醒:Alice 若做好选币隔离,通知交易与后续付款都无法归因于双方;即便她用了与自己关联的币,链分析最多认出发送方,Bob 的隐私仍然完整。

链下通知(带外通知)不被禁止,但那样 Bob 就无法仅凭链上 OP_RETURN 恢复钱包,通知记录得自己另行备份。

4.3 收款地址怎么算出来

通知之后,双方共享一个秘密点:Alice 算 S = n_x * P,Bob 算 S = N_x * p,由 ECDH 性质两边结果相同。

Alice 维护一个针对 Bob 的计数器 c(64 位整数,每笔付款递增,以大端 8 字节喂入哈希),逐笔计算:

Bob 在自己一侧镜像同样的计算生成监视列表;花费时私钥为 p_c = p + s。

4.4 扫描要求与兼容性

收款方必须能拿到完整区块,才能搜其中的 OP_RETURN 通知。原文特别指出:BIP-158 紧凑区块过滤器不覆盖 OP_RETURN 数据负载,轻客户端想用本标准,得靠外部服务发布带证明的通知交易(附录 B 的设想),或靠第三方把通知负载搭进无关交易(附录 C)。

向后兼容方面:本标准与 BIP-47 等以往静态支付码标准不兼容。它不设版本号,靠地址类型标志中的保留位扩展:旧支付码能被支持新类型的软件读取,新支付码里旧软件不认识的标志位会被忽略。

五、谁必须动

普通持币人:想隐私收款的一方生成支付码公开分享即可;付款方把对方支付码导入兼容钱包,钱包自动完成通知与地址计算。不需要运行特殊节点,但收款方钱包的扫描负担明显比普通钱包重。

钱包开发者:要实现支付码编解码(bech32m、pay 前缀)、purpose = 351 的派生、通知交易的构造与扫描、ECDH 地址推导与计数器管理,还要监视完整区块中的 OP_RETURN。原文给出了参考实现(rust-private-payments)与完整测试向量。

全节点与矿工:无特殊要求。通知交易与付款交易都是普通交易,本 BIP 不改任何节点规则。

共识层:不涉及。本 BIP 是应用层的钱包间约定。

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

状态为 Closed(已关闭)。原文变更记录写明:因缺乏活动(lack of activity)而移至 Closed。也就是说,这套方案写完了、也有参考实现,但没有形成持续推进的采用势头,流程上已经收束。它与同方向的 BIP-352 静默支付是并行探索的关系,不是被正式取代——档案里没有 Superseded-By 记录。

常见误读:“支付码公开贴出来,就等于把收款地址公开了,谁都能把付款都关联起来。”不对。支付码里只有收款方的公钥与可接受的地址类型;每笔收款地址还要经过付款方私钥参与的 ECDH 与计数器哈希才算得出,只有交易双方能算出同一组地址。外人拿着支付码,既算不出地址,也无法把不同付款方的付款关联到一起——这正是它与静态地址的根本区别。

七、延伸

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