多签脚本里必须存在的一行”废话”
如果你拆开一笔旧式多重签名交易的解锁脚本,会看到一串公钥前面顶着一个空值(通常是 OP_0 或空字节)。没有任何逻辑需要这个空值——它是一次历史事故留下的化石:早期实现在 OP_CHECKMULTISIG 的栈操作上差了一位,本该弹出 N 个公钥和 1 个签名的循环多弹了一次栈。修掉它会改变所有历史交易的有效性判定,等于撕裂账本,于是这个缺陷被永久保留:规范要求脚本在公钥与签名前额外放一个空元素,钱包生成解锁脚本时照例垫上。它是比特币”缺陷即共识”的经典标本。
它如何工作:从堆栈到布尔值
OP_CHECKMULTISIG 的语义是”栈上给定签名里,有 M 个能验证给定的 N 个公钥中对应的签名”。执行时脚本从栈顶往下依次消费:一个多余的占位元素、N 个公钥、一个数量标记,剩下的签名逐个尝试。由于签名段在早期交易格式里可被重新排列而交易依然有效,这笔账当年没人细算——直到发现顺序无关也就能容忍一个”幽灵元素”。今天的脚本编写者只需记住:这个占位符必须是”真值意义上的空”(推入空字节或 OP_0),若误放一个非空值进去,验证会失败。Miniscript 这类现代描述语言已经会自动生成正确占位,手写脚本时最容易踩的就是这里,多签策略的现代表达见 Miniscript:把多签策略写成可验证的清单。
从 1-of-N 到 P2SH 的多签谱系
裸多签(bare multisig)在标准交易策略里逐步受限——中继政策对裸多签有许可开关与签名操作数量限制(P2SH 内上限为 15 次签算),因此历史上的多签主力是 P2SH 包装的脚本哈希,隔离见证后又迁到 P2WSH 与塔普鲁特的脚本树。每种包装下那个幽灵占位符都还在,只是位置不同:P2SH 的 redeemScript、P2WSH 的 witnessScript 里照样要垫空。理解这条谱系对你选钱包格式有实际意义:同样 2-of-3 的多签,不同脚本包装的体积与费用差别明显,地址形态与选择见 比特币多签钱包怎么选?2-of-3 与 3-of-5 的差别。
为什么这个缺陷从未害死人
一次有效的多签支付必须提供足量正确签名,空占位符只提供”栈对齐”,不提供任何权限——它改变不了门限,也伪造不了签名。这正是比特币向后兼容哲学的注脚:缺陷只要不制造安全风险、且修复本身代价更高,就会被当作事实标准冻结。同类的化石还有 BIP66 与 BIP34 对版本字段合法值的永久裁剪(见 一个 BIP 的一生:从草稿文本到链上生效),以及塔普鲁特时代用新脚本路径(tapscript)另起炉灶而非修旧脚本的做法——升级比特币的方式是”绕过去”,不是”拆回去”。
小结
读解锁脚本时的那个空字节,是协议史写给的活注脚:一致性比优雅重要,账本的可验证性高于代码洁癖。对使用者的落地建议只有一条——不要手搓多签脚本,用成熟钱包或描述符工具生成,幽灵占位符交给它们处理;读旧交易做审计时,看到空值不必惊慌,那不是漏洞,是历史。本文不构成投资建议。
延伸阅读式的收尾
比特币里有三类”不该存在却永远在”的东西:OP_CHECKMULTISIG 的空占位符、被裁剪过的版本字段合法域、以及脚本里永不执行的保留操作码。它们的共同命运是被冻结而非被修复,因为链的兼容性是几千万笔历史交易共同投票的结果。读懂这一层,再看每次协议升级选择”新增路径”而非”改造旧路”(塔普鲁特的脚本树、隔离见证的见证字段都是同一思路)就不会觉得开发者保守——这是对”任何改动都会改变全体历史有效性”的清醒。脚本语言全景见 比特币脚本是什么?为什么它不需要图灵完备。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。