协议演进 / BIP/比特币改进提案 / BIP-47
BIP-47
定义可公开张贴的“支付码”:一个码长期复用,付款方却能用 ECDH 为每笔付款算出互不关联的一次性地址,避免复用同一收款地址的隐私与安全损失。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-47 |
|---|---|
| 标题 | Reusable Payment Codes for Hierarchical Deterministic Wallets |
| 作者 | Justus Ranvier <[email protected]> |
| 指定日期 | 2015-04-24 |
| 层级 | Applications(应用) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/47 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0047.mediawiki |
二、放在哪一族
BIP-47 是 HD 钱包派生路径族的一员,是 BIP-43 的一个具体应用(purpose = 47’),并自述为对实现 BIP-44 的 HD 钱包的补充:支付码身份与 BIP-44 账户一一配对,经支付码收到的款与经 BIP-44 地址收到的款等同,花费时可以同作一笔交易的输入。
同族关系:
BIP-32:派生算法底座
BIP-43:用途字段规则
BIP-44:多账户层级,本篇的 identity 层与它的 account 层对应
它在原文状态一节另有说明:就兼容实现第 1、2 版支付码的钱包而言,本 BIP 可视为定稿;但支付码规范今后的发展(第 3 版及以上)不再经 BIP 流程发布,应查 Open Bitcoin Privacy Project 的 RFC 仓库。
三、它要解决什么
商家与个人常常需要一个能长期公开、与现实身份绑定的收款入口。直接复用同一个 P2PKH 地址收款,代价是安全与隐私尽失:所有付款在链上彼此关联,任何人都能看到这个身份收了多少、与谁往来。
一次性地址隐私好,却无法“张贴”:你不能把下个月才生成的地址印在今天的名片上。
BIP-47 要的是两者兼得。原文动机说:支付码在商家—顾客交互中给交易加上身份信息,同时保护用户隐私;它把 Darkwallet 式隐身地址的隐私收益带给 SPV 客户端,无需可信全节点协助,并大幅减少对区块链存储的依赖。
办法是把“公开的收款标识”与“实际收款地址”分开:公开的是支付码(一组扩展公钥加元数据),实际地址由付款方在付款时用 ECDH 临时算出,每笔都不同,且只有收付双方能算出彼此的关联。
四、规则本身
4.1 三层路径与三类子密钥
m / purpose' / coin_type' / identity'
purpose 为 47’(0x8000002F),coin_type 与 BIP-44 同义,identity 层等价于 BIP-44 的 account 层。前三层用硬化派生;identity 的扩展公钥加上表示一节的元数据,构成一个“支付码”。
identity 之下派生的子密钥分三种用途(除注明外均为公开派生):
- 第 0 个非硬化子密钥:通知密钥(notification key),其对应的 P2PKH 地址即通知地址;
- 第 0 至 2147483647 个非硬化密钥对:用于 ECDH,生成收款地址;
- 第 0’ 至 2147483647’ 个硬化密钥对:临时支付码(ephemeral payment codes),供匿名付款时一次性使用。
4.2 支付码的表示
二进制序列化共 80 字节:第 0 字节为版本号;第 1 字节为特征位(bit 0 表示 Bitmessage 通知,其余保留);第 2 字节为 sign(0x02 或 0x03);第 3–34 字节为公钥的 x 值;第 35–66 字节为链码;第 67–79 字节保留、全零。
展示给用户时应使用 Base58Check 编码,版本字节为 0x47,序列化结果以字母 “P” 开头。
4.3 两个版本
- 第 1 版:地址类型 P2PKH;通知方式为“地址”——向通知地址发一笔通知交易。
- 第 2 版:地址类型 P2PKH;通知方式为 bloom-multisig——把支付码标识放进多签输出,收款方用布隆过滤器发现通知交易,不再单设通知地址输出。
原文建议:具备布隆过滤能力的钱包应生成第 2 版支付码;只有缺乏该能力的钱包才推荐第 1 版。不同版本的支付码原则上互通:付款方版本与收款方版本不同,仍可互相收付,通知流程按收款方支付码的版本走。
4.4 通知交易:先把付款方的支付码私下递过去
收款方要能算出付款方为自己生成的临时地址,前提是先知道对方的支付码。第一次付款前,付款方必须发一笔通知交易:
- 向收款方的通知地址付一小笔比特币;所选输入不得容易与付款方自己的通知地址关联;
- 付款方用指定输入(designated input)对应的私钥 a 与收款方通知地址公钥 B 做 ECDH,得秘密点 S = aB,再以其 x 值与所花费的 outpoint 计算 64 字节致盲因子 s = HMAC-SHA512;
- 把自己的支付码序列化后,用 s 的前 32 字节异或 x 值、后 32 字节异或链码,使其只有收款方能读;
- 把这 80 字节放进交易的 OP_RETURN 输出。
收款方监听通知地址:收到带 80 字节 OP_RETURN 的交易后,用自己的通知私钥 b 与指定公钥 A 算出同一个 S 与 s,反异或还原出对方支付码,并校验 x 值是否属于 secp256k1 群。
通知地址收到的币要特殊处理,以免隐私泄漏:其金额不得计入用户可花费余额显示;这些输出不得用作任何涉及本用户支付码 ECDH 计算的交易的输入;可以先经混币服务,或以 dust-b-gone 一类方式捐给矿工。
4.5 正式付款:每笔一个临时地址
通知完成后,付款方每次付款都为收款方派生一个全新的 P2PKH 地址:取自己支付码的第 0 个私钥 a,与收款方支付码下“下一个未用”的公钥 B(索引按这一对收付双方的上下文计,不是全局计数)做 ECDH,得 S;标量共享秘密 s = SHA256(Sx)(若 s 不在 secp256k1 群内,则换下一个索引重试);临时公钥 B’ = B + sG,由它生成收款地址。
收款方自收到通知交易起,就用前瞻窗口(lookahead window)批量试算这些临时地址监听到账,并以 b’ = b + s 算出每个临时地址的私钥。通知只需一次,之后同一付款方可发送多达 2³² 笔付款。
退款顺理成章:收款方在通知过程中已得知付款方的支付码,可用同样流程回付;但他第一次向对方付款前,仍必须先发一笔通知交易,哪怕此前收到过对方的款。
4.6 其他要点
- 匿名付款:不想让付款与自己身份关联时,付款方用临时支付码付款——即支付码的硬化子码,一码只用一次;其通知地址仍须监听,以便接回退款。临时支付码与 BIP-44 账户是 1 对多关系。
- 冷存储:只读钱包发现通知交易后,把交易打包转给离线设备;离线设备还原支付码并预生成大量密钥对(如 10000 个)回传,在线设备用前瞻窗口监听,无需频繁过气隙。
- 从种子恢复:日常运行可用 SPV,但从种子恢复需要完整索引的区块链——钱包必须取回通知地址收到过的每一笔通知(含已花费的),逐个重建各子链的前瞻窗口。原文提醒:向公共区块浏览器查询时应经 Tor,且避免把临时地址成组查询而互相暴露关联。先前收到的资金一般不会丢,但已发出付款的记录会丢失;恢复出的钱包须把自己当作新钱包重新发送通知交易。
- 多设备共享:支付码钱包一般不应跨设备共用,除非有元数据同步机制,否则可能造成地址复用。
- 备用通知方式:收款方可在支付码特征位中指定 Bitmessage 等备用通知方式;但发送方第一次与某收款方交互时,仍必须发通知交易,以保证对方从种子恢复时不丢资金。
五、谁必须动
普通持币人(收款方):对外只公开支付码,不要再长期复用单个地址收款。要理解第一次收款前对方会发一笔小额通知交易,那笔钱不在可花费余额里显示是规范要求,不是丢币。
付款方:第一次付款前必须完成通知流程;每笔付款必须取“下一个未用”索引派生新地址,不得把同一临时地址付两次。
钱包开发者:工作量最重——支付码的生成与序列化、通知交易的构造与识别、ECDH 致盲与还原、前瞻窗口扫描、通知输出的隔离处理、种子恢复时的全链重扫,都要实现。还要在元数据里保存“已通知过的支付码清单与各自的下一索引”,并知道这部分元数据无法从种子完全恢复。
全节点与矿工:无特殊义务。通知交易与临时地址付款在链上都是普通交易形态。
共识层:无变化。
六、现在算不算数,以及一个常见误读
状态为 Deployed。按原文自己的状态说明,它的定稿范围限于第 1、2 版支付码的兼容性;第 3 版及以后的规范改到 Open Bitcoin Privacy Project 的 RFC 仓库发布,不再走 BIP 流程。因此,评价或实现 BIP-47 时,要以“v1/v2 的最终文本在此,后续演进在别处”为前提。
常见误读:
“支付码就是一个可以反复收款的地址。”
不对。支付码不是地址,它是一组扩展公钥加元数据。真正收款的地址每笔付款都由 ECDH 临时算出、互不相同;若把支付码误当地址直接反复打款,等于退回到地址复用,本篇要避免的隐私损失会原样发生。
七、延伸
- 阅读版:https://bips.dev/47
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0047.mediawiki
- 相关:BIP-32 分层确定性钱包、BIP-43 用途字段、BIP-44 多账户层级
- 仓库总目录:https://github.com/bitcoin/bips
