比特币 - OP CHECKOUTPUTSHASHVERIFY ``` - Raw Githubusercontent

该提案引入了一种新的操作码 OP_CHECKOUTPUTSHASHVERIFY,用于Tapscript版本0。它通过验证输出的哈希值来实现对交易输出的限制,从而实现交易拥塞控制、支付通道实例化等功能。该操作码通过限制单个输入和匹配输出哈希来实现最小化的合约功能,旨在提升比特币交易的效率和灵活性。

<pre> BIP: bip-coshv Title: OP_CHECKOUTPUTSHASHVERIFY Author: Jeremy Rubin <j@rubin.io> Status: Draft Type: Standards Track Created: License: BSD-3-Clause </pre>

==摘要==

此 BIP 提议一个新的操作码 OP_CHECKOUTPUTSHASHVERIFY,用于 Tapscript 版本 0 激活。

这个新的操作码有着用于交易拥塞控制和支付通道实例化等应用,这些应用将在本 BIP 的动机部分进行描述。

==概要==

CHECKOUTPUTSHASHVERIFY 在 Tapscript 执行期间使用操作码 OP_RESERVED1 (0x89)。

CHECKOUTPUTSHASHVERIFY 验证以下条件:

  • 以下脚本是 32 字节的最小数据推送
  • 此交易中只花费了一个输入
  • 序列化输出的 SHA256 双哈希与提供的值匹配

如果 CHECKOUTPUTSHASHVERIFY 之后的操作不是 32 字节的数据推送,则忽略它。否则,如果未满足条件,则执行失败。

==动机==

Covenant -- 或对一个币如何花费的限制,超出密钥所有权 -- 是一个用于构建智能合约的非常强大的结构。然而,考虑到它们的复杂性以及引入同质化风险的可能性,到目前为止,还没有认真考虑将其纳入比特币。

此 BIP 旨在引入一个最小可行的 covenant,以启用有限的一组实用功能。例如:

===拥塞控制交易===

当对区块空间的需求很大时,进行支付可能会变得非常昂贵。通过使用 CHECKOUTPUTSHASHVERIFY,一个大型支付处理商可以将所有支付聚合到一个 O(1) 交易中,以进行确认。然后,过一段时间,当对区块空间的需求减少时,这些支付可以从该 UTXO 中扩展出来。

如果没有 CHECKOUTPUTSHASHVERIFY,仍然可以使用 Schnorr 签名来实现这一点(即使使用 ECDSA,考虑到多方方案)。但是,不可能以非交互方式进行,这从根本上限制了该方法的可行性。

要构建一个拥塞控制交易,用户有多种选择 -- 它可以简单地是从 1 个输出到 N 个输出的单步操作,或者,用户可以使用 CHECKOUTPUTSHASHVERIFY 提交到一个输出树,这允许他们确认任意数量的支付。此外,Taproot 可以提交到可变大小的扩展 -- 例如,一个节点扩展 2 倍、4 倍、8 倍等等。这允许在交易开销和立即可用的区块空间之间进行权衡。在这种情况下,Merkle 树查找的额外开销为 O(log(log(N))),但可以对树进行 Huffman 编码,使其根据区块需求变为 E[O(1)]。树的每个节点也可以尝试“选择加入”到首选基于 Taproot 签名的花费,但如果参与者离线或恶意,则扩展可以继续到更小的组。

从每个用户的角度来看,这种方法的总体开销(没有优化)是 O(log(N)) 交易,期望只有 1 个额外的交易,而从网络的角度来看是 2N。但是,考虑到此类交易不需要签名,实际开销较小。

下面的图表展示了这些交易与普通交易和批量交易相比的结构。

<img src="bip-coshv/states.svg" align="middle"></img>

下面显示了一个模拟,说明了在 5% 的网络采用率和 50% 的网络采用率下,这可能对 mempool 积压产生的影响。此 BIP 的子目录中提供了模拟的代码。

<img src="bip-coshv/five.png" align="middle"></img> <img src="bip-coshv/fifty.png" align="middle"></img>

===通道工厂===

此用例与上面类似,只不过不是支付,叶子节点应设置为通道(可能在付款人和收款人之间或收款人选择的目标之间)。

对于设置而言,这些通道已经对时间不敏感,因为所有惩罚都可以相对于实际实例化进行时间锁定。

这允许使用这种延迟方法发送的币具有即时流动性。

===钱包金库===

当冷存储解决方案需要更高的安全性时,可以有默认的 Tapscript 路径,将资金从一个目标移动到另一个目标。

例如,可以设置一个冷钱包,一个客户支持部门可以在没有进一步授权的情况下,将一部分资金(使用多个预设金额)转移到一个由隔离的支持部门运营的半热钱包中。然后,支持部门可以将一些资金发放到一个热钱包中,并将剩余的资金通过类似的提款机制送回冷存储。

如果没有 CHECKOUTPUTSHASHVERIFY,这一切都是可能的,但 CHECKOUTPUTSHASHVERIFY 消除了协调和在线签名者的需要,并降低了支持部门不当转移资金的能力。

此外,所有这些设计都可以与相对时间锁结合使用,以便合规和风险部门进行干预。

===CoinJoin===

这种方法使得建立一个无需信任的 CoinJoin 变得更加容易。

所有参与者都同意一个提交到其输出哈希的单个 UTXO,然后参与者可以使用他们喜欢的任何输入来资助交易。

然后,可以确认交易。

如果需要,Tapscript 路径可以被基于签名的花费所取代,以提高同质性。

==设计==

CHECKOUTPUTSHASHVERIFY 的目标是对现有代码库产生最小的影响 -- 未来,随着我们了解到更复杂但证明是安全的用例,可能会启用新的 covenant 类型。

至关重要的是,因为这是一个 Tapscript,所以预期参与者可以合作以签名替换 Tapscript 路径。如果其他依赖项(如通道状态)可以更新,则取消了输出单独花费的要求以及输出哈希的精确匹配。

下面我们将逐一讨论规则:

====以下脚本是 32 字节的最小数据推送====

CHECKOUTPUTSHASHVERIFY 使用操作码之后的推送,而不是操作码之前的推送。如果 CHECKOUTPUTSHASHVERIFY 使用堆栈中的数据,则可以在脚本中构建提交哪些数据。通过使用数据前瞻,我们确保在花费时已知输出。

脚本程序员仍然可以有条件地检查要在哪个哈希上进行检查,例如,<code>OP_IF OP_CHECKOUTPUTSHASHVERIFY <outputs 1> OP_ELSE <outputs 2> OP_ENDIF</code>。但是,通过保持输出的字面哈希,我们限制了可能性。

在任何情况下,鉴于 Tapscript 的 API,用户更有可能将具有多个 <code>OP_CHECKOUTPUTSHASHVERIFY</code> 操作的任何代码编译成单独的分支。

====此交易中只花费了一个输入====

如果我们允许在交易中花费多个输入,那么两个输出可能会请求支付到同一组输出,导致丢弃一半的预期支付。虽然有安全的方法来允许多个输入,但该设计要复杂得多,并且用例不太清楚。

此外,对可以共同花费哪些输入的限制对于需要稳定 TXID 的支付通道结构至关重要。

====序列化输出的 SHA256 双哈希与提供的值匹配====

这是一个已经计算出的哈希,因此我们可以节省额外的验证开销。因此,<code>OP_CHECKOUTPUTSHASHVERIFY</code> 不会施加大量的额外验证开销。

将此哈希暴露在堆栈上可能会允许解析输出,这不是一个问题,因为在脚本构建时已经确切地知道它们。

===设计权衡和风险===

Covenant 在历史上一直备受争议,因为它们可能存在同质性风险 -- 可以生成对如何花费或不花费的永久限制的币。

在这里提出的方法中,对 covenant 进行了严格的限制,如下所示。所有 covenant 都用一个基于多重签名的密钥包装,该密钥可以抢占 covenant 的要求。此外,OP_CHECKOUTPUTSHASHVERIFY covenant 的结构使得在构建时必须确切地知道输出。因此,只能创建以有限数量的步骤扩展的 covenant,并且在安全意义上等同于创建所有可到达终端状态的输入的交易集。此外,covenant 仅限于作为单个输入花费,从而防止了“半花费”问题。

这些 covenant,尽管受到限制,仍然存在一些风险。提供给 OP_CHECKOUTPUTSHASHVERIFY 的前像可能是未知的,或者 Taproot 是使用具有未知私钥的公钥构建的。知道一个地址可以花费与发送者花费到任何地址(特别是 OP_RETURN)的能力不兼容。如果发送者需要知道接收者可以在花费之前删除 covenant,他们可以请求接收者对挑战字符串进行签名。最后一个风险是滥用“转发地址合约”。转发地址是一个可以以预定义方式自动执行的脚本。例如,一个热钱包可能有一些币,在相对超时后可以自动转移到冷存储地址。问题是重用这些密钥可能非常不安全。例如,假设一个人创建一个将 1 BTC 转发到冷存储的地址。创建一个输出到该地址且小于 1 BTC 的输出将被冻结,直到使用 Taproot 签名路径。如果向该地址支付了超过 1 BTC,并且 redeemscript 是公开已知的,那么任何人都可以导致超过 1 BTC 的资金作为很大的矿工费支付。以后可能会引入操作码,承诺最多应花费多少费用或其他限制,这将使可重用密钥更安全使用。目前,最好不要重用 Taproot 密钥,除非你确定所有分支都与你期望的付款兼容。此限制和风险并非 OP_CHECKOUTPUTSHASHVERIFY 所独有,Taproot 脚本可能包含许多逻辑分支,这些分支对于多次花费是不安全的(例如,哈希时间锁定分支应每次使用时都使用唯一的哈希实例化)。

如果曾经实施,像 MES16 提出的那些更强大的 covenant 将使 OP_CHECKOUTPUTSHASHVERIFY 类型的 covenant 变得多余。它们还将在提高调整费用等事宜的能力方面带来一些好处,而不是依赖于子支付父或其它机制。然而,这些功能带来了大大增加的复杂性和意外行为的空间。或者,基于 CHECKSIGFROMSTACK 或 SIGHASH_NOINPUT 的 covenant 设计可能也可以实现 covenant。SIGHASH_NOINPUT 带来了额外的风险,使其无法包含在比特币中。CHECKSIGFROMSTACK 比 OP_CHECKOUTPUTSHASHVERIFY 更复杂,并且在 OP_CHECKOUTPUTSHASHVERIFY 中不存在额外的验证开销。鉴于这种方法实现和分析的简单性,以及用户应用程序可实现的好处,因此提出了 OP_CHECKOUTPUTSHASHVERIFY 方法。

==规范== 以下代码是用于验证 <code>OP_CHECKOUTPUTSHASHVERIFY</code> 的主要逻辑。

    case OP_CHECKOUTPUTSHASHVERIFY:
    {
        // Don't verify before enabled...
        if (flags & SCRIPT_VERIFY_OUTPUTS_HASH) {
            CScript::const_iterator lookahead = pc;
            opcodetype argument;
            // Read ahead one opcode as a lookahead argument
            if (!script.GetOp(lookahead, argument, vchPushValue))
                return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
            // If lookahead argument was exactly 32 bytes, check OutputHash
            // This is so that we can later add different semantics for this opcode
            if (vchPushValue.size() == 32) {
                // Argument should be == 0x20 -- will fail later anyways
                if (!CheckMinimalPush(vchPushValue, argument)) {
                    return set_error(serror, SCRIPT_ERR_MINIMALDATA);
                }
                // If multiple inputs allowed, two inputs with the same OutputsHashVerify
                // would pay only half intended amount!
                if (!checker.CheckOnlyOneInput()) {
                    return set_error(serror, SCRIPT_ERR_OUTPUTSHASHVERIFY);
                }
                // Lastly, check that the outputs hash matches the passed value
                if (!checker.CheckOutputsHash(vchPushValue)) {
                    return set_error(serror, SCRIPT_ERR_OUTPUTSHASHVERIFY);
                }
            }
        }
    }
    break;

==部署==

该部署旨在与 Tapscript https://github.com/sipa/bips/blob/bip-schnorr/bip-tapscript.mediawiki 一起完成。

==实现==

一个实现和测试可以在这里找到:https://github.com/JeremyRubin/bitcoin/tree/congestion-control

== 参考文献 ==

[[https://cyber.stanford.edu/sites/g/files/sbiybj9936/f/jeremyrubin.pdf|在比特币中构建 Multi Transaction 合约]] [[https://github.com/jeremyrubin/lazuli]|Lazuli Notes (基于 ECDSA 的 N-of-N 签名,用于认证的过期 UTXO)]] [[https://fc16.ifca.ai/bitcoin/papers/MES16.pdf|比特币 Covenant]] [[https://bitcointalk.org/index.php?topic=278122.0|使用 SCIP 签名的 CoinCovenant,一个有趣但不好的想法。]] *[[https://fc17.ifca.ai/bitcoin/papers/bitcoin17-final28.pdf|使用 Covenant 增强比特币交易]]

==版权== 本文档的许可为 3-clause BSD 许可。

  • 原文链接: github.com/JeremyRubin/b...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
raw.githubusercontent
raw.githubusercontent
江湖只有他的大名,没有他的介绍。