协议演进 / BIP/比特币改进提案 / BIP-116
BIP-116
新增 OP_MERKLEBRANCHVERIFY,让脚本只承诺一棵默克尔树的根,花费时只揭示用到的那个数据元素及其分支证明。本 BIP 目前处于草案状态。
一、档案卡
| 编号 | BIP-116 |
|---|---|
| 标题 | MERKLEBRANCHVERIFY |
| 作者 | Mark Friedenbach <[email protected]>, Kalle Alm <[email protected]>, BtcDrak <[email protected]> |
| 指定日期 | 2017-08-25 |
| 层级 | Consensus (soft fork)(共识(软分叉)) |
| 类型 | Specification(规范类) |
| 状态 | Draft(草案) |
| 阅读版 | https://bips.dev/116 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0116.mediawiki |
二、放在哪一族
MAST(默克尔化抽象语法树)与合约脚本族的前身一族。传统写法是把合约的全部花费条件枚举进一个脚本,花费时靠 witness 里的选择值穿过一串 if/else;BIP-16(P2SH)与 BIP-141(SegWit)能把脚本推迟到花费时才揭示,但仍要揭示全部条件。
BIP-116 给出另一半拼图:用默克尔树承诺一整组数据元素,花费时只出示用到的元素与分支证明。它自己只管“证明某个元素在集合里”,不管执行代码;与它同日提出、同作者的 BIP-117(尾调用语义)负责把选出的策略脚本真正执行起来,两者合起来构成一种广义 MAST。这一思路与显式 MAST 方案 BIP-114 目标相同、路径不同;BIP-119(OP_CHECKTEMPLATEVERIFY)则是同一时期另一条契约路线——用模板哈希直接约束下一笔交易的形态。
它依赖的快速默克尔树构造来自 BIP-98,刻意不用中本聪为区块头设计的那种默克尔树(见 4.3)。
三、它要解决什么
3.1 全部条件必须全揭示
既有合约写法的通病:所有执行路径都必须写进 scriptPubKey 或赎回脚本,哪怕花费时根本用不到。后果有三层:
- 浪费链上空间,脚本还受压入(push)大小上限限制,复杂合约根本写不下;
- 隐私受损:未用到的策略条件往往带有用户特征,花费一次就全曝光;
- 可互换性(fungibility)受损:外人能从完整条件集分辨这枚币的来历与用途。
3.2 只承诺、按需揭示
改用默克尔哈希树承诺全部策略选项,花费时只强制揭示实际用到的那一条,未用部分继续保持隐藏。泄露最少,链上负担也最少。
同时,脚本大小与运行限制从此只约束“单条被用到的策略”,而不是所有策略之和——可行的合约复杂度因此大幅上升。
四、规则本身
4.1 操作码与栈布局
MERKLEBRANCHVERIFY 重定义 OP_NOP4。执行时若出现以下任一情形,脚本报错终止:
- 栈少于 3 项;
- 栈顶第一项超过 2 字节;
- 第一项按整数解释(记为 N)为负数或非最小编码;
- 第二项不是恰好 32 字节(即所承诺的默克尔根);
- 第三项不是按 BIP-98 序列化的默克尔树包含证明,且其所需 VERIFY 哈希个数不等于 floor(N/2);
- 栈中剩余元素少于 floor(N/2) 个——这些就是待验证的输入元素。
4.2 验证方式
N 的最低位决定输入元素如何变成 VERIFY 哈希:最低位为 0 时,每个输入元素用双重 SHA256 哈希;最低位为 1 时,每个元素必须恰好 32 字节,直接当作已算好的哈希。
随后用包含证明与这些 VERIFY 哈希(按栈上自顶向下的顺序)算出快速默克尔根,与栈上第二项的 32 字节根不完全一致,脚本即失败;一致则效果等同于 NOP,继续执行。
链式使用可以突破 520 字节的脚本压入上限:原文举例,30 分支的路径可分两段证明;256 分支的路径需要 18 次链式验证,仍在现行脚本限制内。
4.3 为什么用 BIP-98 的快速默克尔树
中本聪的区块头默克尔树有已知漏洞(CVE-2012-2459):重复条目会带来可锻性。在不平衡默克尔树的特权位置上,同一条目可以构造出多个证明。若证明可锻,下游协议会出事——例如用两次分支证明实现紧凑的 2-of-N 时,本可用同一条目的两个不同证明冒充两个不同密钥。快速默克尔树避开了这一构造。
4.4 为什么走 NOP 扩展而不是脚本版本
原文给了两条理由:一是基础设施兼容——NOP 扩展能直接用于现有 P2SH 或嵌套 P2SH 的 P2WSH 地址,不必等脚本版本机制与 BIP-143 签名代码普及;二是脚本版本只有 16 个,属稀缺资源,且当时脚本升级的程序问题尚未定论,不宜让本提案被它拖住。
4.5 应用示例
大集合 1-of-N:赎回脚本写成 <root> 2 MERKLEBRANCHVERIFY 2DROP DROP CHECKSIG,witness 给出签名、公钥与证明。参数 2 的最低位为 0,表示有 1 个输入元素(序列化的公钥),其哈希由操作码现算。脚本大小不随 N 线性增长。
蜜罐(honeypot):为 1000 台服务器各生成一个密钥、建一棵公钥哈希树,把同一笔赏金共享给所有服务器;哪台服务器的密钥与路径被用来领取赏金,就暴露了哪台服务器被入侵。
五、谁必须动
普通持币人:无直接动作。这类条件只会出现在主动构造复杂合约的场景里。
钱包与合约开发者:需能构建默克尔树承诺、生成分支证明,并在赎回脚本中正确安排栈布局与 N 参数。
全节点与矿工:这是共识层软分叉,需升级才能验证新语义;旧节点把该操作码当 NOP 忽略,交易仍会被接受,但证明不被验证。
共识层:OP_NOP4 被赋予验证语义,规则只收紧。部署计划用 BIP-8(按高度锁定的 version bits),部署名 “merklebranchverify”、bit 2,主网与测试网的起始高度在原文中均为待定。
六、现在算不算数,以及一个常见误读
状态为 Draft(草案),仍是草案、未激活。比特币主网没有 OP_MERKLEBRANCHVERIFY;后来真正落地的 Taproot 用默克尔树承诺脚本路径,思想相通,但机制是另一套(见 BIP-341、BIP-342),不是本提案的激活。
常见误读:“BIP-116 就是 MAST。”不对。它只提供“成员资格证明”这一个原语,本身不执行被选出的代码;要凑成广义 MAST,还必须配合 BIP-117 的尾调用语义,让证明通过的策略脚本被真正执行。
七、延伸
- 阅读版:https://bips.dev/116
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0116.mediawiki
- 相关:BIP-117 尾调用语义、BIP-98 快速默克尔树、BIP-114 MAST、BIP-16 P2SH、BIP-141 SegWit
- 仓库总目录:https://github.com/bitcoin/bips
