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

BIP-67 经公钥排序的确定性 P2SH 多签地址

规定多签 P2SH 的公钥必须用压缩形式并按二进制字典序排列,使同一组公钥与签名门限永远生成同一个赎回脚本与地址。本 BIP 目前处于已完成状态。

一、档案卡

档案卡
编号BIP-67
标题Deterministic Pay-to-script-hash multi-signature addresses through public key sorting
作者Thomas Kerin <[email protected]>, Jean-Pierre Rupp <[email protected]>, Ruben de Vries <[email protected]>
指定日期2015-02-08
层级Applications(应用)
类型Specification(规范类)
状态Complete(已完成)
阅读版https://bips.dev/67
官方原文https://github.com/bitcoin/bips/blob/master/bip-0067.mediawiki

二、放在哪一族

BIP-67 是多签与 P2SH 族里管“同一个账户该有同一个地址”的那一份。

链条是这样的:BIP-11 把 M-of-N 多签定为标准交易;BIP-16(Pay to Script Hash)定义了多签的 P2SH 形态,花费成本由接收方以赎回脚本承担。但 BIP-16 的赎回脚本并不规定公钥的顺序与编码——脚本不同,哈希出的 P2SH 地址就不同。BIP-67 补的正是这一块:给公钥排一个唯一的序。

原文的用法一节还列了 BIP-45(确定性 P2SH 多签钱包结构)作为采用方,以及 Bitcore、Haskoin、Armory、BitcoinJ 等实现对排序函数的采用。

三、它要解决什么

对同一组公钥、同一个所需签名数,赎回脚本里公钥的每一种排列(再乘以压缩 / 非压缩两种编码的差别)都能构成一个不同的标准赎回脚本,各有自己单独的 P2SH 地址。一个多签“账户”因此没有一个规范地址。

这带来实际麻烦:

原文同时指出,当时多数网页钱包还不支持跨服务组建多签账户;能确保跨实现兼容的约定,正是为了让这类互通更容易达成。

四、规则本身

4.1 三步

第一步,统一编码。 确保拿到的每个公钥都是压缩形式:

022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da
03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9
021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18

第二步,按二进制表示做字典序排序。 上例排序后为:

021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18
022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da
03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9

第三步,组装赎回脚本并哈希。 把排好序的公钥放进标准多签赎回脚本,再按 BIP-16 哈希得到 P2SH 地址:

OP_2 <排序后公钥 1> <排序后公钥 2> <排序后公钥 3> OP_3 OP_CHECKMULTISIG
→ 3Q4sF6tv9wsdqu2NtARzNCpQgwifm2rAba

原文附有四组测试向量(含一组取自 Bitcore),向量里的所需签名数均为 2,可据此核对实现是否排对。

4.2 兼容性条款

五、谁必须动

普通持币人:不必动节点或软件规则。使用多签产品时,地址由钱包按本规范生成即可。

钱包开发者:这是主要受众——生成多签 P2SH 地址前,先确保公钥为压缩形式,再按二进制字典序排序后组装赎回脚本;收到非压缩公钥要按不兼容处理,而不是悄悄转换。

多签参与方:组建共同账户时只需共享所需签名数与各自主公钥;地址是否一致,取决于各方钱包是否都遵循本规范。

全节点与矿工、共识层:完全不必动。网络既不检查、也无法检查公钥排序。

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

状态为 Complete(已完成):它是一份写完并有实现采用的钱包约定,不是一条等待激活的网络规则。遵循它的钱包,对同一(公钥集合,门限)永远给出同一个 P2SH 地址;不遵循的也不会被网络处罚,只是与遵循者生成的地址不同。

常见误读:

“不按 BIP-67 排序做出的多签交易是无效交易。”

不对。排序发生在构造赎回脚本、生成地址的阶段,是链下约定;链上验证只看脚本与签名本身是否成立。排序不合规的后果是互通性——伙伴钱包认不出你的地址——而不是共识层面的无效。

七、延伸

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