在 vault · jl2012/bips 中的 bips/bip-0112.mediawiki

  • jl2012
  • 发布于 2025-06-13 17:21
  • 阅读 20

该 BIP (Bitcoin Improvement Proposal) 提议引入一个新的比特币脚本操作码 CHECKSEQUENCEVERIFY,结合 BIP68,允许脚本的执行路径基于UTXO的年龄进行限制。

跳转到内容

jl2012/ bips Public

forked from bitcoin/bips

折叠文件树

文件

vault

搜索此仓库

/

bip-0112.mediawiki

复制路径

BlameMore file actions

BlameMore file actions

最新提交

luke-jrluke-jr

将 BIP 2 从 Draft->Active 提升,并实现它

打开提交详情

2016年11月30日

959fecc · 2016年11月30日

历史

历史

打开提交详情

查看此文件的提交历史。

400 行 (296 loc) · 16.4 KB

/

bip-0112.mediawiki

顶部

文件元数据和控件

  • 预览

  • 代码

  • Blame

400 行 (296 loc) · 16.4 KB

Raw

复制原始文件

下载原始文件

目录

编辑和原始操作

  BIP: 112
  Layer: Consensus (soft fork)
  Title: CHECKSEQUENCEVERIFY
  Author: BtcDrak <btcdrak@gmail.com>
          Mark Friedenbach <mark@friedenbach.org>
          Eric Lombrozo <elombrozo@gmail.com>
  Comments-Summary: No comments yet.
  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0112
  Status: Final
  Type: Standards Track
  Created: 2015-08-10
  License: PD
## 目录<br>永久链接:目录<br>- 摘要<br>- 概要<br>- 动机 <br> - 具有到期截止日期的合约 <br> - 具有超时的 Escrow<br> - 追溯失效 <br> - 哈希时间锁定合约<br> - 双向支付通道<br> - 闪电网络<br> - 双向锚定侧链<br>- 规范<br>- 参考实现<br>- 部署<br>- 致谢<br>- 参考<br>- 版权

摘要

永久链接:摘要

此 BIP 描述了比特币脚本系统的一个新操作码 (CHECKSEQUENCEVERIFY),它与 BIP 68 结合使用,允许根据所花费输出的年龄来限制脚本的执行路径。

概要

永久链接:概要

CHECKSEQUENCEVERIFY 重新定义了现有的 NOP3 操作码。 执行时,如果以下任何条件为真,脚本解释器将终止并报错:

  • 堆栈为空;或
  • 堆栈顶部的项目小于 0;或
  • 堆栈顶部的项目未设置禁用标志(1 << 31);并且
    • 交易版本小于 2;或
    • 交易输入序列号禁用标志 (1 << 31) 已设置;或
    • 相对锁定时间类型不同;或
    • 顶部堆栈项目大于交易序列(当根据 BIP68 进行屏蔽时);

否则,脚本执行将继续,就像执行了 NOP 一样。

BIP 68 阻止在相应的输入达到指定的期限(以区块高度或区块时间衡量)之前,将非最终交易选择包含在区块中。 通过将 CHECKSEQUENCEVERIFY 的参数与 nSequence 字段进行比较,我们间接验证了正在花费的输出的所需最小期限; 在达到该相对期限之前,任何包括 CHECKSEQUENCEVERIFY 的脚本执行路径都将无法验证,从而导致该交易未被选择包含在区块中。

动机

永久链接:动机

BIP 68 通过赋予序列号新的共识强制语义作为相对锁定时间,从而重新定义了交易 nSequence 字段的含义。 但是,没有办法构建比特币脚本来根据此字段做出决策。

通过使 nSequence 字段可供脚本访问,可以构造仅在发布证明后的某个最短时间后才能访问的代码路径。 这使得能够在分阶段协议中实现各种各样的应用,例如 escrow、支付通道或双向锚定。

具有到期截止日期的合约

永久链接:具有到期截止日期的合约

具有超时的 Escrow

永久链接:具有超时的 Escrow

可以在以下方式建立在资金投入后 30 天自动超时的 escrow。 Alice、Bob 和 Escrow 使用以下赎回脚本创建一个 2/3 地址。

    IF
        2 &lt;Alice's pubkey> &lt;Bob's pubkey> &lt;Escrow's pubkey> 3 CHECKMULTISIG
    ELSE
        "30d" CHECKSEQUENCEVERIFY DROP
        &lt;Alice's pubkey> CHECKSIG
    ENDIF

在任何时候,都可以使用 Alice、Bob 或 Escrow 中任意两者的签名来花费资金。

30 天后,Alice 可以单独签名。

在支付到 escrow 地址确认之前,时钟不会开始计时。

追溯失效

永久链接:追溯失效

在很多情况下,我们希望创建可以在未来事件发生时撤销的合约。 但是,鉴于区块链的不可变性,实际上不可能追溯性地使先前已确认的承诺失效。 我们真正拥有的用于追溯失效的唯一机制是区块链重组,出于基本安全原因,它的设计非常困难且成本非常高。

尽管有此限制,我们确实有一种方法可以提供在功能上类似于追溯失效的东西,同时使用 CHECKSEQUENCEVERIFY 保留过去承诺的不可逆性。 通过构建具有多个执行分支的脚本,其中一个或多个分支被延迟,我们可以提供一个时间窗口,在此期间有人可以提供使输出可花费的失效条件,从而有效地使原本会延迟的分支失效,并可能阻止另一方首先广播交易。 如果失效条件在超时之前没有发生,则延迟的分支将变为可花费,从而遵守原始合同。

此想法的一些更具体的应用:

哈希时间锁定合约

永久链接:哈希时间锁定合约

哈希时间锁定合约 (HTLC) 提供了一种用于链下合约协商的通用机制。 可以使执行路径需要知道可以在失效时间窗口内呈现的密钥(哈希原像)。 通过共享密钥,可以向交易对手保证永远不会广播交易,因为这将允许交易对手立即认领输出,而一个人将不得不等待时间窗口过去。 如果尚未共享密钥,则交易对手将无法使用即时路径,而必须改用延迟路径。

双向支付通道

永久链接:双向支付通道

在交易对手广播已撤销的交易的情况下,可脚本化的相对锁定时间提供了可预测的响应时间:绝对锁定时间需要在接近超时时关闭通道并重新打开,而使用相对锁定时间,时钟在交易在区块中确认的那一刻开始计时。 它还提供了一种准确了解在非合作交易对手的情况下,在资金可以从通道中提取之前需要等待多长时间(以区块数为单位)的方法。

闪电网络

永久链接:闪电网络

闪电网络扩展了双向支付通道的想法,允许通过多个双向支付通道跳来路由支付。

这些通道基于需要 Alice 和 Bob 的 2/2 多重签名的一个 anchor 交易,以及一系列花费该 anchor 交易的可撤销的承诺交易。 承诺交易将来自 anchor 的资金在 Alice 和 Bob 之间分配,最新的承诺交易可以由任何一方随时发布,从而最终确定该通道。

理想情况下,已撤销的承诺交易将永远无法成功花费; 并且最新的承诺交易可以非常快速地花费。

为了允许有效地撤销承诺交易,Alice 和 Bob 具有略微不同的最新承诺交易版本。 在 Alice 的版本中,承诺交易中支付给 Alice 的任何输出还包括强制延迟,以及一个允许 Bob 在知道该交易的撤销代码时花费该输出的替代分支。 在 Bob 的版本中,支付给 Bob 的款项也受到类似的限制。 当 Alice 和 Bob 协商新的余额和新的承诺交易时,他们还会公开旧的撤销代码,从而承诺不中继旧交易。

那么,支付给 Alice 的简单输出可能如下所示:

    HASH160 &lt;revokehash> EQUAL
    IF
        &lt;Bob's pubkey>
    ELSE
        "24h" CHECKSEQUENCEVERIFY DROP
        &lt;Alice's pubkey>
    ENDIF
    CHECKSIG

这允许 Alice 随时发布最新的承诺交易并在 24 小时后花费资金,但也确保如果 Alice 中继已撤销的交易,Bob 有 24 小时的时间来认领资金。

使用 CHECKLOCKTIMEVERIFY,这将如下所示:

    HASH160 &lt;revokehash> EQUAL
    IF
        &lt;Bob's pubkey>
    ELSE
        "2015/12/15" CHECKLOCKTIMEVERIFY DROP
        &lt;Alice's pubkey>
    ENDIF
    CHECKSIG

这种形式的交易意味着,如果 anchor 在 2015/12/16 未花费,Alice 可以使用此承诺,即使它已被撤销,只需立即花费它,而无需给 Bob 时间来认领它。

这意味着该通道具有一个截止日期,如果不访问区块链就无法推迟; 并且资金可能要到截止日期到达后才能使用。 CHECKSEQUENCEVERIFY 允许你避免进行这种权衡。

哈希时间锁定合约 (HTLC) 使此情况稍微复杂一些,因为原则上它们可能会支付给 Alice 或 Bob,具体取决于 Alice 是否发现了密钥 R 或是否已达到超时时间,但相同的原则适用 - 在 Alice 的承诺交易中支付给 Alice 的分支会获得延迟,并且如果知道撤销密钥,则另一方可以认领整个输出。 使用 CHECKSEQUENCEVERIFY,Alice 的承诺交易中可支付给 Alice 的 HTLC 可能如下所示:

    HASH160 DUP &lt;R-HASH> EQUAL
    IF
        "24h" CHECKSEQUENCEVERIFY
        2DROP
        &lt;Alice's pubkey>
    ELSE
        &lt;Commit-Revocation-Hash> EQUAL
        NOTIF
            "2015/10/20 10:33" CHECKLOCKTIMEVERIFY DROP
        ENDIF
        &lt;Bob's pubkey>
    ENDIF
    CHECKSIG

相应地,在 Bob 的承诺交易中:

   HASH160 DUP &lt;R-HASH> EQUAL
   SWAP &lt;Commit-Revocation-Hash> EQUAL ADD
   IF
       &lt;Alice's pubkey>
   ELSE
       "2015/10/20 10:33" CHECKLOCKTIMEVERIFY
       "24h" CHECKSEQUENCEVERIFY
       2DROP
       &lt;Bob's pubkey>
   ENDIF
   CHECKSIG

请注意,上述最终分支中使用了 CHECKSEQUENCEVERIFY 和 CHECKLOCKTIMEVERIFY,以确保 Bob 在超时完成且 Alice 有时间显示撤销密钥之后才能花费该输出。

参见可部署的闪电网络 论文。

双向锚定侧链

永久链接:双向锚定侧链

双向锚定侧链需要一个新的 REORGPROOFVERIFY 操作码,其语义不在本 BIP 的范围内。 CHECKSEQUENCEVERIFY 用于确保自发布重组证明的返回锚定以来已过去足够的时间:

    IF
        lockTxHeight &lt;lockTxHash> nlocktxOut [&lt;workAmount>] reorgBounty Hash160(&lt;...>) &lt;genesisHash> REORGPROOFVERIFY
    ELSE
        withdrawLockTime CHECKSEQUENCEVERIFY DROP HASH160 p2shWithdrawDest EQUAL
    ENDIF

规范

永久链接:规范

有关精确的语义和这些语义的详细原理,请参阅以下再现的参考实现。

/* Below flags apply in the context of BIP 68 */
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
 * relative lock-time. */
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 &lt;&lt; 31);

/* If CTxIn::nSequence encodes a relative lock-time and this flag
 * is set, the relative lock-time has units of 512 seconds,
 * otherwise it specifies blocks with a granularity of 1. */
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 &lt;&lt; 22);

/* If CTxIn::nSequence encodes a relative lock-time, this mask is
 * applied to extract that lock-time from the sequence field. */
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;

case OP_NOP3:
{
    if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
        // not enabled; treat as a NOP3
        // 未启用; 视为 NOP3
        if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
            return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
        }
        break;
    }

    if (stack.size() &lt; 1)
       return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);

    // Note that elsewhere numeric opcodes are limited to
    // operands in the range -2**31+1 to 2**31-1, however it is
    // legal for opcodes to produce results exceeding that
    // range. This limitation is implemented by CScriptNum's
    // default 4-byte limit.
    // 请注意,在其他地方,数字操作码仅限于 -2**31+1 到 2**31-1 范围内的操作数,但是操作码生成超过该范围的结果是合法的。 此限制由 CScriptNum 的默认 4 字节限制来实现。
    //
    // Thus as a special case we tell CScriptNum to accept up
    // to 5-byte bignums, which are good until 2**39-1, well
    // beyond the 2**32-1 limit of the nSequence field itself.
    // 因此,作为一种特殊情况,我们告诉 CScriptNum 接受最多 5 字节的 bignum,这很好,直到 2**39-1,远远超过 nSequence 字段本身的 2**32-1 限制。
    const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);

    // In the rare event that the argument may be &lt; 0 due to
    // some arithmetic being done first, you can always use
    // 0 MAX CHECKSEQUENCEVERIFY.
    // 在极少数情况下,由于首先进行了一些算术运算,参数可能 &lt; 0,你始终可以使用 0 MAX CHECKSEQUENCEVERIFY。
    if (nSequence &lt; 0)
        return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);

    // To provide for future soft-fork extensibility, if the
    // operand has the disabled lock-time flag set,
    // CHECKSEQUENCEVERIFY behaves as a NOP.
    // 为了提供未来的软分叉可扩展性,如果操作数设置了禁用锁定时间标志,CHECKSEQUENCEVERIFY 的行为类似于 NOP。
    if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
        break;

    // Compare the specified sequence number with the input.
    // 将指定的序列号与输入进行比较。
    if (!checker.CheckSequence(nSequence))
        return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);

    break;
}

bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
{
    // Relative lock times are supported by comparing the passed
    // in operand to the sequence number of the input.
    // 通过将传入的操作数与输入的序列号进行比较来支持相对锁定时间。
    const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;

    // Fail if the transaction's version number is not set high
    // enough to trigger BIP 68 rules.
    // 如果交易的版本号设置得不够高以触发 BIP 68 规则,则失败。
    if (static_cast&lt;uint32_t>(txTo->nVersion) &lt; 2)
        return false;

    // Sequence numbers with their most significant bit set are not
    // consensus constrained. Testing that the transaction's sequence
    // number do not have this bit set prevents using this property
    // to get around a CHECKSEQUENCEVERIFY check.
    // 设置了最高有效位的序列号不受共识约束。 测试交易的序列号没有设置此位可以防止使用此属性来绕过 CHECKSEQUENCEVERIFY 检查。
    if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
        return false;

    // Mask off any bits that do not have consensus-enforced meaning
    // before doing the integer comparisons
    // 在进行整数比较之前,屏蔽掉任何没有共识强制含义的位
    const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
    const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
    const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;

    // There are two kinds of nSequence: lock-by-blockheight
    // and lock-by-blocktime, distinguished by whether
    // nSequenceMasked &lt; CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
    // nSequence 有两种:按区块高度锁定和按区块时间锁定,区别在于 nSequenceMasked &lt; CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG。
    //
    // We want to compare apples to apples, so fail the script
    // unless the type of nSequenceMasked being tested is the same as
    // the nSequenceMasked in the transaction.
    // 我们想比较苹果和苹果,所以除非正在测试的 nSequenceMasked 类型与交易中的 nSequenceMasked 相同,否则脚本会失败。
    if (!(
        (txToSequenceMasked &lt;  CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked &lt;  CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
        (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
    ))
        return false;

    // Now that we know we're comparing apples-to-apples, the
    // comparison is a simple numeric one.
    // 既然我们知道我们正在比较苹果与苹果,那么比较就是一个简单的数字比较。
    if (nSequenceMasked > txToSequenceMasked)
        return false;

    return true;
}

参考实现

永久链接:参考实现

以下拉取请求提供了参考实现:

bitcoin/bitcoin#7524

部署

永久链接:部署

此 BIP 将使用位 0 通过 “versionbits” BIP9 进行部署。

对于比特币主网,BIP9 的 starttime 将是 2016 年 5 月 1 日午夜 UTC(Epoch 时间戳 1462060800),BIP9 的 timeout 将是 2017 年 5 月 1 日午夜 UTC(Epoch 时间戳 1493596800)。

对于比特币测试网,BIP9 的 starttime 将是 2016 年 3 月 1 日午夜 UTC(Epoch 时间戳 1456790400),BIP9 的 timeout 将是 2017 年 5 月 1 日午夜 UTC(Epoch 时间戳 1493596800)。

此 BIP 必须使用相同的部署机制与 BIP68 和 BIP113 同时部署。

致谢

永久链接:致谢

Mark Friedenbach 发明了序列号在实现相对锁定时间方面的应用,并编写了 CHECKSEQUENCEVERIFY 的参考实现。

参考实现和此 BIP 主要基于 Peter Todd 为密切相关的 BIP 65 所做的工作。

BtcDrak 撰写了此 BIP 文档。

感谢 Eric Lombrozo 和 Anthony Towns 贡献了用例示例。

参考

永久链接:参考

BIP 9 Versionbits

BIP 68 通过共识强制序列号实现相对锁定时间

BIP 65 OP_CHECKLOCKTIMEVERIFY

BIP 113 用于时间锁定约束的中间过去区块时间

使用 OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY 和撤销哈希的 HTLC

闪电网络

可部署的闪电网络

将比特币扩展到每天数十亿笔交易

软分叉部署注意事项

版本位

Jeremy Spilman 小额支付通道

版权

永久链接:版权

本文档已置于公共领域。

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

0 条评论

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