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

BIP-147 处理哑栈元素可锻性

以 NULLDUMMY 规则要求多签的哑元素必须为空,封死 OP_CHECKMULTISIG 的一个可锻性来源。本 BIP 目前处于已激活状态。

一、档案卡

档案卡
编号BIP-147
标题Dealing with dummy stack element malleability
作者Johnson Lau <[email protected]>
指定日期2016-09-02
层级Consensus (soft fork)(共识(软分叉))
类型Specification(规范类)
状态Deployed(已激活)
阅读版https://bips.dev/147
官方原文https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki

二、放在哪一族

可锻性修复族中专治“哑元素”的单项文档。它和 BIP-11 讲的是同一个操作码的同一个历史包袱:OP_CHECKMULTISIG 验证时会多弹出一个栈元素,BIP-11 当年用 OP_0 占位绕过它;本篇则把这个占位从“习惯”升为“规矩”。

同族关系:

BIP-62:处理可锻性的总提案;原文致谢写明,本篇的 NULLDUMMY 规则即由 Peter Todd 最初提出、从 BIP-62 中抽出成文

BIP-146:处理签名编码可锻性,与本篇同源并列,但最终状态为 Closed

BIP-141 / BIP-143:本篇与它们共用同一次 segwit 部署(见第四节)

三、它要解决什么

OP_CHECKMULTISIG 与 OP_CHECKMULTISIGVERIFY 有一个由来已久的设计缺陷:它们在签名验证之后,还会额外消费一个栈元素,原文称之为哑元素(dummy element)。

问题在于,这个元素不被以任何方式检查:

后果与一般的可锻性相同:对非隔离见证交易,会改变 txid 并使未确认子交易失效;对隔离见证交易,会改变 wtxid,并可能降低紧凑区块中继(BIP-152)的效率。

修复的思路不需要动操作码本身:只要在共识层规定“哑元素只许为空”,任意填充的空间就被彻底关掉。

四、规则本身

4.1 NULLDUMMY 规则

新共识规则名为 NULLDUMMY:OP_CHECKMULTISIG 与 OP_CHECKMULTISIGVERIFY 所消费的哑元素,必须是空字节数组;只要它不是空值,整个脚本立即判定为失败。

适用范围包括:

规则就这一条,没有例外表,也不需要新的操作码或新的签名格式。

4.2 部署:与隔离见证同车

本篇通过版本位 BIP-9 部署,参数与 BIP-141、BIP-143 完全相同:部署名同为 “segwit”,使用位 1(bit 1)。

原文给出的时间参数:

也就是说,它不是单独投票,而是搭着 segwit 这一次部署一起生效。

4.3 兼容性(原文所述)

原文指出:参考客户端从一开始生成的签名就符合这一要求,NULLDUMMY 自 v0.10.0 起已作为中继策略执行;至少自 2015 年 8 月起,就没有违反该要求的交易上链。对实际在用的各类 scriptPubKey,不合规的签名都可以平凡地改成合规形式,因此这条规则不损失任何功能。唯一被特别提醒的是设计奇异脚本的人:必须额外留意这条新规则。

五、谁必须动

普通持币人:无感。正常钱包构造多签时本来就在哑元素位置放空值(即 BIP-11 里那个 OP_0 占位)。

钱包开发者:构造 CHECKMULTISIG / CHECKMULTISIGVERIFY 的解锁脚本时,哑元素只能放空字节数组;不要把它当作附带数据的通道,哪怕脚本逻辑上“读不到”它。

全节点与矿工:随 segwit 部署升级后,在共识验证中执行 NULLDUMMY:哑元素非空,多签脚本直接失败,包含此类花费的区块不被接受。

共识层:这是货真价实的共识收紧(软分叉):旧规则下有效的某些脚本,在新规则下变为无效;规则只收紧、不放宽,因此未升级节点仍承认升级节点接受的区块。

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

状态为 Deployed,中文状态记为已激活。它已随 segwit 部署成为现行共识规则的一部分:今天一笔多签花费若把哑元素填了非空值,全网节点会直接判定脚本失败。需要分清的是,它的姊妹篇 BIP-146 状态为 Closed——同源、同批提出,不等于同命。

常见误读:

“BIP-147 修好了 OP_CHECKMULTISIG 多弹一个元素的 bug。”

不对。操作码多消费一个元素的行为原样保留,本篇没有、也不打算改变它——改变它反而会破坏既有脚本的兼容。NULLDUMMY 做的只是把那个元素的值钉死为空:bug 的“形状”还在,但可被任意改动的空间没有了。

七、延伸

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