协议演进 / BIP/比特币改进提案 / BIP-342
BIP-342
定义叶子版本 0xc0 的 Tapscript 执行语义:签名操作码改验 Schnorr、禁用 CHECKMULTISIG 并代之以 CHECKSIGADD、改用按见证大小计算的 sigops 预算。本 BIP 目前处于已激活状态。
一、档案卡
| 编号 | BIP-342 |
|---|---|
| 标题 | Validation of Taproot Scripts |
| 作者 | Pieter Wuille <[email protected]>; Jonas Nick <[email protected]>; Anthony Towns <[email protected]> |
| 指定日期 | 2020-01-19 |
| 讨论日期 | 2019-05-06 |
| 层级 | Consensus (soft fork)(共识(软分叉)) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已激活) |
| 依赖 | BIP-340、BIP-341 |
| 阅读版 | https://bips.dev/342 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki |
二、放在哪一族
Taproot 三件套的收尾一篇:BIP-340 定 Schnorr 签名,BIP-341 定输出结构与两条花费路径,BIP-342 则回答“脚本路径被走时,叶子里的脚本按什么语义执行”——这套语义称为 Tapscript。
它的基线是 P2WSH 的脚本规则(BIP-141),连同 BIP-65 的 OP_CHECKLOCKTIMEVERIFY 与 BIP-112 的 OP_CHECKSEQUENCEVERIFY;BIP-342 在此之上作增删改。部署方式与 BIP-341 完全相同,两篇是同一次软分叉的两半:341 管“结构”,342 管“脚本内部的规则”。
三、它要解决什么
BIP-341 只改进了脚本的结构(默克尔树、密钥/脚本双路径)。但它要的一部分好处,与脚本语言内部某些操作码的旧语义直接冲突:若不与 341 同时处理,这些好处就无法保证落到脚本路径的花费上。
原文 Motivation 点名的三个目标,都必须在脚本内部兑现:
- Schnorr 签名:脚本里的验签操作码仍在验 ECDSA,脚本路径就享受不到新签名;
- 批量验证:旧的 OP_CHECKMULTISIG 一次验多个签名、与批量验证不兼容,留着它就留着一个堵点;
- 签名哈希改进:BIP-341 的新签名消息要同样适用于脚本内的签名,且希望借新体系简化 OP_CODESEPARATOR 的处理。
所以 BIP-342 不是可选的后续优化,而是与 341 捆绑的同一批共识改动:目标是在 Tapscript 诞生的第一天,就把验签体系切换干净,而不是先沿用旧语义、日后再改。
四、规则本身
4.1 适用范围
以下规则同时满足才适用:输入是 SegWit 花费、是 BIP-341 定义的 Taproot 花费(版本 1、程序 32 字节、非 P2SH 包装)、是脚本路径花费(去掉可选 annex 后见证栈至少剩两个元素)、且叶子版本为 0xc0(控制块首字节为 0xc0 或 0xc1)——这样的脚本即 Tapscript。
验证顺序被原文写死:先查 BIP-141 / BIP-341 层面的有效性;再逐一解码 Tapscript 中的操作码;检查初始栈是否触犯资源上限;执行脚本;最终栈上必须恰好留一个为真的元素,否则失败。
4.2 OP_SUCCESSx:为升级预留的操作码
解码时若遇到编号属于 80、98、126–129、131–134、137–138、141–142、149–153、187–254 的操作码,它们被改名为 OP_SUCCESSx,整个脚本无条件验证成功,后续规则一概不再适用——哪怕脚本后段根本无法解码也一样。设计意图是升级通道:将来某场软分叉可以把某个 OP_SUCCESSx 定义为真正的操作码(只能把原本有效的脚本变无效,符合软分叉方向),甚至借它引入多字节操作码或全新脚本语言。反面警示同样写在原文注脚里:在其含义被软分叉定义之前,把 OP_SUCCESSx 写进脚本是不安全的,会造成资金损失——因为现在它等于无条件放行。
4.3 被禁与被改的操作码
- 禁用 OP_CHECKMULTISIG 与 OP_CHECKMULTISIGVERIFY:执行到即如 OP_RETURN 般立即失败(在未执行的分支里出现则被忽略)。原文说明为何是“禁用”而非改成 OP_SUCCESSx:要让误用者在第一时间察觉问题,也避免脚本反汇编器被迫感知上下文;
- MINIMALIF 升为共识规则:它在 P2WSH 里只是标准性(策略)规则;在 Tapscript 中,OP_IF / OP_NOTIF 的入参必须是恰好 0(空向量)或恰好 1(单字节向量 0x01),否则共识失败,目的是让脚本天然不可锻;
- 签名操作码改验 Schnorr:OP_CHECKSIG 与 OP_CHECKSIGVERIFY 改为按 BIP-340 验证 Schnorr 签名与公钥,不再是 ECDSA。
4.4 新操作码 OP_CHECKSIGADD 与多签的写法
为补偿 CHECKMULTISIG 的移除,新增 OP_CHECKSIGADD(操作码 186,0xba):从栈上取公钥、计数 n 与一份签名,签名有效则把 n+1 压回,无效则原样把 n 压回。旧式 m <pubkey_1> … <pubkey_n> n OP_CHECKMULTISIG 可等价改写为 <pubkey_1> OP_CHECKSIG <pubkey_2> OP_CHECKSIGADD … <pubkey_n> OP_CHECKSIGADD m OP_NUMEQUAL,与批量验证兼容。原文还列了另外两种门限写法:把每个 k-of-k 组合拆成独立叶子(隐私更好),或每片叶子放一个 MuSig 聚合公钥(更省,但需要交互式签名协议)。
签名操作码的细则:公钥长度为 0 则脚本立即失败;为 32 字节则按 BIP-340 公钥真实验签,验不过立即失败;为其他非零长度则属于“未知公钥类型”——不真正验签、一律按验签成功处理,这是给未来软分叉预留的新签名规则入口。签名为空向量时,OP_CHECKSIGVERIFY 失败、OP_CHECKSIG 压入空向量、OP_CHECKSIGADD 把 n 原样压回;签名非空且需要计数的,才消耗下文的 sigops 预算。
4.5 签名消息的 Tapscript 扩展
Tapscript 的签名消息复用 BIP-341 的共同签名消息(SigMsg),以 ext_flag = 1 追加三项扩展:所执行叶子的 tapleaf_hash(32 字节,把签名绑定到具体叶子与脚本,不再受 OP_CODESEPARATOR 切割脚本的影响)、key_version(1 字节,现为 0x00)、codesep_pos(4 字节,最近一次执行的 OP_CODESEPARATOR 的操作码位置,无则为 0xffffffff)。签名本身的接受形态与密钥路径相同:64 字节视为 SIGHASH_DEFAULT,65 字节时末字节不得为 0x00,其余失败。
4.6 资源上限换算法
- 脚本大小 10000 字节上限:取消,只受区块重量隐含约束(理由是签名哈希里不再直接包含脚本原文,验签成本不再与脚本大小成正比);
- 非推送操作码 201 个上限:取消;
- sigops 改为预算制:Tapscript 的签名操作不再计入全区块 80000 的加权 sigops 上限;改为每个输入一份预算 = 50 + 该输入见证的序列化总字节数(含 CompactSize 前缀),每次执行带非空签名的签名操作码扣 50,预算扣成负数即失败;
- 保留:栈与 altstack 合计 1000 个元素上限(并扩展到初始栈)、单个栈元素 520 字节上限。
五、谁必须动
普通持币人:无直接动作。只有在用脚本路径花费 Taproot 输出时,才会实际跑到这套规则。
钱包与脚本开发者:写 Tapscript 时严守新语义——多签用 OP_CHECKSIGADD 模式或聚合公钥,不得再用 OP_CHECKMULTISIG;条件分支的入参满足共识级 MINIMALIF;绝不把未定义的 OP_SUCCESSx 写进真实脚本。
全节点与矿工:实现 Tapscript 的完整执行与资源计量(尤其是 sigops 预算制),与 BIP-341 同批升级。
共识层:软分叉的一部分,与 341 一起部署;它只改变 v1 脚本路径花费的验证,不影响任何旧输出类型。
六、现在算不算数,以及一个常见误读
状态为 Deployed,且部署方式与 BIP-341 完全相同——原文 Deployment 一节只有一句:“与 Taproot(BIP-341)以相同方式部署。”因此凡说 341 已随 Taproot 在主网激活(区块高度 709632)之处,342 同样适用:现行 Tapscript 的权威语义就是本文件。
常见误读:
“Tapscript 是旧脚本的超集,老多签脚本搬过来就能用。”
不对。Tapscript 以 P2WSH 规则为基线作了减法与替换:OP_CHECKMULTISIG 与 OP_CHECKMULTISIGVERIFY 被禁用,搬来的老多签脚本一旦执行到它们就直接失败;MINIMALIF 也从策略规则升格为共识规则。它更像一套“借旧脚本外壳、换验签内核”的新方言:结构眼熟,验签、多签与计量规则都已换新。
七、延伸
- 阅读版:https://bips.dev/342
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki
- 相关:BIP-340 Schnorr 签名、BIP-341 Taproot 花费规则、BIP-141 隔离见证(共识层)
- 仓库总目录:https://github.com/bitcoin/bips
