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

BIP-116 MERKLEBRANCHVERIFY

新增 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 或赎回脚本,哪怕花费时根本用不到。后果有三层:

3.2 只承诺、按需揭示

改用默克尔哈希树承诺全部策略选项,花费时只强制揭示实际用到的那一条,未用部分继续保持隐藏。泄露最少,链上负担也最少。

同时,脚本大小与运行限制从此只约束“单条被用到的策略”,而不是所有策略之和——可行的合约复杂度因此大幅上升。

四、规则本身

4.1 操作码与栈布局

MERKLEBRANCHVERIFY 重定义 OP_NOP4。执行时若出现以下任一情形,脚本报错终止:

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 的尾调用语义,让证明通过的策略脚本被真正执行。

七、延伸

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