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

BIP-341 Taproot:SegWit v1 花费规则

新增 SegWit v1 输出:32 字节 Taproot 输出公钥,平时用密钥路径一签花费,必要时才用脚本路径揭示默克尔树中的一条脚本。本 BIP 目前处于已激活状态。

一、档案卡

档案卡
编号BIP-341
标题Taproot: SegWit version 1 spending rules
作者Pieter Wuille <[email protected]>; Jonas Nick <[email protected]>; Anthony Towns <[email protected]>
指定日期2020-01-19
讨论日期2019-05-06、2019-10-09
层级Consensus (soft fork)(共识(软分叉))
类型Specification(规范类)
状态Deployed(已激活)
依赖BIP-340
阅读版https://bips.dev/341
官方原文https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki

二、放在哪一族

Taproot 三件套的核心一篇。BIP-340 定 Schnorr 签名,BIP-341 定输出结构与花费规则,BIP-342 定脚本路径里脚本的执行语义(Tapscript);三者同批部署,缺一不可。

往上接的是隔离见证族:Taproot 输出就是 BIP-141 框架下的 SegWit 版本 1 输出;其地址编码是 BIP-350 的 Bech32m。思想来源包括 MAST(默克尔化脚本树,前序提案 BIP-114、BIP-117)与 Greg Maxwell 最初的 Taproot 构想。原文 Design 一节特意划界:新的叹息哈希模式(如 BIP-118)、跨输入聚合等想法不在本批之列,留待独立升级。

激活方式另有专文:BIP-343 曾提出用 BIP8(LOT=true)强制激活本提案,最终未被采用(见第六节)。

三、它要解决什么

原文 Motivation 把目标定为三点,且明确不引入新的安全假设:提高比特币脚本能力的隐私、效率与灵活性。

旧格局下,付款给公钥与付款给脚本是两套互斥的构造,花费时必须把实际执行的条件、乃至脚本全文亮出来。观察者因此能知道:这笔钱原本可以怎么花、有哪些备选路径。而现实中的绝大多数应用,最终的花费往往是“所有参与方都同意”后的一次普通签名——为这一常态付出的,却是把全部条件上链公开的代价。

Taproot 的解法分两层:

再加上 Schnorr 的密钥聚合:多方公钥可聚合成一个公钥、合作签出一份与单签无异的签名,使“各方同意”的常态正好走最省、最隐蔽的密钥路径。原文还顺手修了签名哈希的几个老问题(见 4.3),并为未来预留了叶子版本与 annex 等升级位。

四、规则本身

4.1 输出长什么样

Taproot 输出是原生 SegWit 输出:见证版本 1,见证程序为 32 字节。程序内容不是脚本哈希,而是一个公钥 Q(按 BIP-340 的 x-only 编码),称为 Taproot 输出公钥。构造方式:

Q = P + int(hash_TapTweak(P ‖ m))·G

其中 P 是内部公钥,m 是脚本树的默克尔根(没有脚本树时,微调只对内部公钥本身计算)。原文解释了为何把公钥直接放进输出而不放哈希:为保证批量可验证,验证者最终必须拿到公钥本身,放哈希反而要在见证里多补 32 字节;且要达到 128 位碰撞安全,哈希也需 256 位,大小并不吃亏。

以下规则只适用于花费这种输出;版本 1 而长度非 32 字节的程序、P2SH 包装的 v1 输出,都不受本 BIP 约束。

4.2 两条花费路径

先处理 annex:若见证栈至少两个元素且最后一个元素首字节为 0x50,该元素即 annex(保留的未来扩展位),从栈中移除;它始终被签名承诺并计入交易重量,但当前验证中被忽略。原文警告:在另一场软分叉给它定义含义之前,用户不应在交易中包含 annex,否则可能永久损失资金。

默克尔路径中的子节点哈希前要先按字典序排序,故证明里不必携带左右方向信息。

4.3 签名哈希(sighash)改造

密钥路径签名是 64 字节 Schnorr 签名加可选的叹息字节:省略时为 64 字节、隐含新增的 SIGHASH_DEFAULT(0x00,语义等同 SIGHASH_ALL);带叹息字节时为 65 字节且该字节不得为 0x00,以防第三方把 64 字节签名锻成 65 字节、改变 wtxid 与费率。

共同签名消息 SigMsg 沿用旧体系的 SIGHASH_ALL / NONE / SINGLE / ANYONECANPAY 语义,但作了几项修正:

4.4 构造指引(钱包层,非共识)

原文专设一节给钱包软件(明确声明不属共识关键部分):内部公钥优先选最可能用到的单钥条件(聚合后);没有任何单钥条件时,可加一个“所有参与方聚合”的条件,或用无已知离散对数的 NUMS 点作内部公钥;聚合公钥场景下,即使不需要脚本路径,也应让输出公钥承诺一个不可花费的脚本路径,以防恶意一方偷偷塞入只利于自己的脚本分支;脚本树的组织,同概率用平衡树、已知概率用 Huffman 树。

4.5 部署参数

与 BIP-342 同时部署。主网与 testnet3 使用修改版 BIP-9 版本位部署:名称 taproot、比特位 2,另加 min_activation_height 参数。主网参数:开始时间 2021-04-24(UTC 零点)、超时 2021-08-11(UTC 零点)、锁定阈值 1815 块(90%,低于 BIP-9 惯常的 95%)、最小激活高度 709632;原文记载主网已在高度 709632 激活,testnet3 在高度 2011968 激活(阈值 75%)。Signet 上则恒为激活状态。

五、谁必须动

普通持币人:不动也能照常收付旧类型地址;想用 Taproot,需钱包支持生成与花费 P2TR 输出。向 v1 程序付款需要对方钱包支持 BIP-350 的 Bech32m 地址。

钱包开发者:实现输出构造(内部公钥、脚本树、微调计算与控制块生成)、新签名哈希与两条花费路径的签名流程;原文提供了钱包层测试向量(scriptPubKey 计算、密钥路径花费、控制块构造)。

全节点与矿工:升级才能强制执行新规则。原文向后兼容一节说得直白:未升级节点会把 SegWit v1 见证程序一律当作“任何人可花费”,强烈建议升级以便完整验证。

共识层:这是一次软分叉:旧软件无需修改即可继续运行(只是不验证新规则),新规则只收紧、不放松有效性判定。

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

状态为 Deployed,且已在主网激活:原文 Deployment 一节明确记载主网于区块高度 709632 激活。P2TR 自此是比特币的现行输出类型之一。激活走的是 Bitcoin Core 发布的“Speedy Trial”路径(修改版 BIP-9,见 4.5 的参数);同为激活方案的 BIP-343(BIP8 LOT=true)未被采用,其状态已是 Closed。

常见误读:

“Taproot 把一笔钱的全部花费条件都写在链上了,只是换了种编码。”

恰恰相反。输出里只有一个 32 字节公钥;脚本树只以默克尔根的形态被微调值承诺,任何一条备选脚本都不出现在输出里。用密钥路径花费时,连“有没有脚本树”都不会泄露;用脚本路径花费时,也只揭示被执行的那一条脚本加一条默克尔路径,未执行的分支永远保持哈希形态。这正是本提案隐私目标的落点。

七、延伸

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