术语表 /协议与升级
SIGHASH_ANYPREVOUT
又称 APO。
- SIGHASH_ANYPREVOUT 是什么?
- SIGHASH_ANYPREVOUT 是一种针对 Taproot 脚本提出的签名模式,可让一个签名花费任何锁定在匹配脚本上的币,而不是仅限于它最初对应的那一枚币。
规定于 BIP-118。
BIP-118为 tapscript 定义了一种新的公钥类型,长度为33字节,以0x01 开头,而不是在普通密钥上增加一个标志。该提案于2017年2月分配编号,从未被激活,且仅适用于脚本路径花费,不适用于密钥路径花费。您的钱包中没有任何功能可以用这种方式签名,因此任何声称可在主网上使用 eltoo 通道的产品,描述的都是未来。
运作方式
状态: BIP-118为 Draft(草案),编号分配于2017-02-28,依赖 BIP-340、BIP-341和 BIP-342,其 Deployment 部分的内容为 TODO。没有任何内容被取代,因为没有任何内容上线。
Taproot 签名会承诺被花费那枚币的 outpoint,即在 BIP-118所修改的 ANYONECANPAY 摘要中,由 txid 和索引构成的36字节,使签名永远绑定于一枚币。如果从被签名的消息中去掉 outpoint,签名就不再指明某一枚币,而是指明一种形态,之后任何属于该形态的 UTXO 都可以与它绑定。该 BIP 将此称为 dynamic rebinding(动态重新绑定)。
文中定义了两个变体,二者的区别在于仍然承诺哪些内容。
- SIGHASH_ANYPREVOUT,位值为0x40,去掉 outpoint,但保留输入的金额(8字节)、其 scriptPubKey(此处始终为35字节)和 tapleaf 哈希。这样,该签名适用于任何在同一脚本下持有相同金额的币。
- SIGHASH_ANYPREVOUTANYSCRIPT,位值为0xc0,同时去掉金额、scriptPubKey 和 tapleaf 哈希。它适用于任何其脚本能被该密钥满足的币。
选择启用发生在创建地址时,而不是签名时。这类密钥只能通过 tapscript 叶子使用,因此地址的默克尔树中必须包含这样一个叶子,在被花费之前,它与其他任何 Taproot 地址无法区分。有一个常量将两者区分开:BIP-118密钥的 key_version 为0x01,普通 tapscript 密钥为0x00,因此同一个私钥无法生成在两套规则下都有效的签名。六个新的 hash_type 字节变为合法:0x41、0x42、0x43、0xc1、0xc2 和0xc3。
在哪里会遇到它
SIGHASH_ANYPREVOUT 没有出现在任何主网交易中,BIP-118预计,即使它存在,也 "only be rarely used in practice"(实际中仅会很少使用),因为脚本路径花费体积更大,也更容易被识别。
它是为 eltoo 设计的,这是一种链下更新方案。链下协议必须应对对手方发布的任何旧状态,而普通签名会承诺其所响应的那笔确切交易,因此每一个可能出现的状态都需要一个新的签名。eltoo 则利用脚本和 nLockTime 使签名具有不对称性,带有较新签名的交易可以花费带有较旧签名的交易,反之则不行,因此一个更新签名可以应用在对手方发布的任何更早的更新之上。
这个名称记录了一次更正。Joseph Poon 于2016年2月在最初的闪电网络论文提出这一想法之后,将其作为 SIGHASH_NOINPUT 提出,而更名表明输入并非真正被忽略:nSequence 始终被签名,在 SIGHASH_ANYPREVOUT 下,脚本和金额也会被签名。
该 BIP 的安全部分指出了代价:重放。ANYPREVOUT 签名可被重复用于任何具有相同脚本和相同金额的其他 UTXO,ANYPREVOUTANYSCRIPT 签名则可被用于在其任一脚本中重复使用该密钥的任何 UTXO,因此密钥重用从隐私方面的麻烦变成了损失资金的途径。这类交易也可被陌生人篡改:任何能提供匹配输入的人,无需私钥就能改变 txid。
SIGHASH_ANYPREVOUT vs SIGHASH_ANYONECANPAY
SIGHASH_ANYONECANPAY 目前已存在于网络中,它会去掉除被签名输入之外的所有输入;SIGHASH_ANYPREVOUT 则连保留下来的那个输入的一部分也去掉。BIP-118将其摘要描述为去掉 outpoint 的 ANYONECANPAY 摘要,只有一行之差,后果却很大。ANYONECANPAY 签名无法被重放,因为它所指明的 outpoint 只能被花费一次。放弃这一承诺后,重放保护必须来自构建在其上的协议,而不是来自签名本身。