术语表 /协议与升级
Taproot 默克尔分支
- Taproot 默克尔分支是什么?
- Taproot 默克尔分支是脚本路径花费所公布的一组兄弟哈希,用于证明其脚本已被承诺在所花费的地址中。
规定于 BIP-341。
分支中的每个哈希都是 taptree 中的一个兄弟节点,按从您的叶子向上直到根的顺序排列。BIP-341将分支上限设为128个哈希,即4,096字节,并且其排序树意味着分支完全不携带左右方向位。您的分支长度是公开的,因此更深的叶子会泄露您的树的最小深度,并暗示是哪款钱包构建了该输出。
运作方式
Taproot 默克尔分支位于控制块之内,控制块是脚本路径花费的见证栈上的最后一项(若有 annex,则在其被移除之后)。
控制块的结构是固定的。第0字节携带叶子版本以及输出密钥 Y 坐标的奇偶性。第1至32字节存放内部公钥。其后的全部内容就是分支:m 个连续的32字节哈希,因此控制块长度为33 + 32m 字节,且 m 必须是从0至128的整数。任何其他长度都会使该花费在执行任何一条操作码之前就失败。
验证从底部开始。节点先用 TapLeaf 标签对所公开的脚本做哈希,然后依次用 TapBranch 标签并入分支中的每个哈希,每一步都按字典序比较两个32字节的值,并先对较小者做哈希。得出的结果是 taptree 根,它与内部密钥一起用 TapTweak 标签做哈希,再加到内部点上,并与所花费输出中的32字节核对。
这种比较就是全部的巧妙之处。由于 BIP-341在哈希之前先对两个子节点排序,分支从不说明某个兄弟节点位于哪一侧:由验证者自行推算。其设计依据对原因说得很直白:该设计并不在意特定脚本在树中的位置,只在意它们确实已被承诺。
128的上限是一项安全界限,而非任意设定的上限。在最优打包的树中,深度接近叶子概率倒数的以二为底的对数,因此深度129意味着某个脚本的使用概率低于2^128分之1,BIP-341指出这样的脚本大概可以直接删除。在另一端,只有单个叶子的 taptree 的 m 为0,即分支为空,且其 tapleaf 哈希本身就是根。
在哪里会遇到它
任何通过公开脚本(而不是用密钥签名)来花费 bc1p 输出的交易,都会出现 Taproot 默克尔分支。
BIP-341以一棵有五个叶子的树为例。A、B、C 和 E 是 TapLeaf 哈希,AB 是对前两者计算的 TapBranch 哈希。若使用脚本 D 花费,控制块依次携带 C、E、AB:三个哈希,96字节的分支,129字节的控制块。当 E 与 CD 合并时,E 先于 CD 参与哈希,因为 E 的排序更靠前。
隐私方面的代价是规划时需要考虑的重点。BIP-341的安全部分指出,脚本的深度会泄露树的最小深度,这暗示了构建该输出的钱包软件,并有助于链上分析对地址进行聚类;该部分还建议偏离由叶子概率得出的树结构。叶子复用是另一个陷阱:花费另一个输出时可能再次公布相同的分支哈希,使共享同一个32字节兄弟哈希的两笔花费看起来相互关联。
Taproot 默克尔分支 vs 默克尔区块
Taproot 默克尔分支证明某个脚本属于某个地址;默克尔区块证明某笔交易属于某个区块。taptree 分支对共识至关重要,每个验证该花费的全节点都会重新计算,并且与位置无关,因为排序使其无需说明左右。针对区块交易树的证明无法借用这一做法,因为区块默克尔根之下的交易顺序是固定且有意义的,所以它除了哈希之外还必须携带遍历路径。