作者:sipa
来源:https://delvingbitcoin.org/t/segwit-commitment-to-post-quantum-witness-data/2702
以下内容是我在读到这段关于后量子见证数据的想法之后想到的:
ajtowns:P2MR 的 EC 叶子中的公钥复原
如果我们因为 PQ(后量子)签名的体积更大而提高区块体积限值,办法是为 PQ 签名数据增加一个额外的区块空间,那么我们也可以为发生在这个额外区块空间中的 P2MR 或者 P2MR+PKR(公钥复原)的 ECC 花费附加额外的开销,并任意地调低这部分开销的价格;假设能够做到每个输入的前 32 字或 64 字节是免费的,我认为,这就足以让 P2MR 的 ECC 花费路径在经济上能够跟 P2WPKH 和 P2TR 竞争。甚至无需放弃批量处理。
添加额外的见证数据区域,在技术上当然是可行的,甚至可能是无可避免的,只要我们需要大规模使用 PQC(后量子计算机)方案的时候,就看所采用的方案的 签名/公钥 的体积有多大。不过,如果其实现方式与当前的隔离见证类似,就会增加一些复杂性,可能会给采用增加阻力,而如今时间更加紧急:
- 交易的 pqwtxid 在隔离见证数据之外还涵盖了 pq 数据
- 新的 coinbase 中的区块承诺也要涵盖 pqwtxid,需要改变挖矿基础设施
- 可能要增加一个 pqwtxidrelay 转发特性,匹配 BIP339 wtxidrelay (根据隔离见证交易 id 转发交易)特性
- P2P 逻辑中的多个位置需要根据 3 种标识符来跟踪交易(增加一种,以跟使用 wtxid 的旧 协议/节点 兼容)。
我认为,也许这样设计后量子见证数据区域,可以避免一些头痛问题:将一个输入的 pq 数据的承诺放在同一输入自身的隔离见证区域中。这将使得 wtxid 也承诺跟一笔交易的有效性相关的所有数据,让它继续用作唯一的交易标识符,并避免上述部分复杂性。
这种办法有两个缺点,我认为都是可以解决的:
- 额外的 存储/带宽:这显然会比一种直接序列化的格式多出 32 字节的负担。不过,因为它只是其它数据的一个哈希值,所以在这些(直接序列化)格式中可以省去它。更有趣的是,这可以作为一项单独的优化,限制在节点的实现中,或作为一项 P2P 协议插件来协调,不会给 pq 数据特性自身的部署带来负担。
- 对 交易重量/成本 的影响:放在隔离见证 witness 中的这 32 字节(即 8 vByte),不升级的节点也会看见,这是无法避免的。不过,因为这讨论的是一种新的输出类型,所以,也可以将所有的见证数据都放到 pq 数据区域,从而可以任意为之设定价格,并且,也可以从 -8 vByte 的状态开始,以补贴这个放在 witness 区域的 pq 数据承诺(当然,如果最终交易重量还是负数,就要舍入为 0 )。
没有想得太多,对我来说,这似乎是一种明显的优化(请注意,使用这种办法,意味着每个见证至少有 33 vByte,远远超过一个 taproot 密钥路径花费得 8.5 vByte )。
- - -
此想法的更清晰版本:
- 抽象地,每一笔交易的每个输入都有一个见证类型号(0 为隔离见证;1 为 pq 数据;未来有需要则递增)。
- 每一个类型都关联着一套 P2P 协议插件,所以节点可以选择性收取特定类型的数据(或不收取)。一个全节点应该能够收取其认可的共识规则所知的所有类型。设定多个类型的理由是允许每一种类型有自己的 打折/成本计量 函数,并且这些函数可能会随着时间推移,因为签名方案的采用而变更。为了不给未来设限,必须可以选择我们还不知道其成本规则的类型。
- 序列化:
- 如果至少一种类型号 > 0 的见证出现在交易中,则在 0x00 标记之后使用标签 0x02(而不是隔离见证已经使用的标签 0x01)
- 对见证数据的编码保持不变,但每一个交易输入都有一个额外的类型字节
- 在转发到不支持特定类型的节点时,见证数据可以 “折叠” 为类型 0,办法是将它们替换成对完整数据的一个承诺。具体来说,使用一个见证堆栈,由单个长为 34 字节的元素组成,形式为
0xff + 类型号字节 + 带标签哈希值(类型号 + 序列化的折叠前见证数据), - 交易的 wtxid 和 txid 定义与普通的隔离见证交易一样,在这些所有类型 > 0 的见证数据之后。
- 交易的重量定义如同常规的隔离见证规则,加上任意专属于各数据类型的规则。
- 所有现有的隔离见证输出类型(P2TR、P2WPKH、P2WSH)获得一个 “输入数据类型 = 0” 的共识规则。
- 交易输入,如果只有一个见证元素,其类型号为 0 、长 34 字节且其第一个字节为
0xff,后面跟着已知的类型号,会被定为非法输入。这使得我们可以识别 “这是一个降级的见证数据,我应该能够得到它的完整数据”,而无需访问被花费 UTXO,或执行完整的脚本验证。这种违规行为是 “剥离见证数据” 错误,所以它们不会导致所在的 交易/区块 被标记为(永久)无效。
所以,我们不必设计一种 “幼稚的” 序列化格式(既包含两种完整的见证数据,又在普通的见证数据中放置一个承诺),而可以直接将抽象的交易当成最多只有一种类型的见证数据。后向兼容是通过添加一种 “折叠” 操作来实现的,而不是通过(相当于)剥离见证数据来实现的。