作者:josh

来源:https://delvingbitcoin.org/t/expiring-htlcs-without-free-relay/2663

摘要

我们可以创造出无需担心 “免费中继(free relay)” 可能性的 HTLC(哈希时间锁合约)。这将使我们能够通过得到确认的链状态来监控原像(而不必通过本地的交易池),从而降低负责转发交易的闪电节点的活性假设、在低带宽、无交易池的环境下保护路由节点(比如:运行 Utreexo 客户端的家用路由节点)。

实现这种 HTLC 需要变更一处共识规则:

  1. nSequence 的第 21 个比特赋予一种共识含义,从而 BIP68 的区块确认高度将强制执行一个最小的 nLockTime 数值。

还有两处可以启用优化实现的变更:

  1. OP_CSV 中强制执行第 21 比特的含义
  2. OP_LOCKTIME:一个仅限 tapscript 使用的操作码,将 nLockTime 的数值推入堆栈。

详述

nSequence 强制执行最小的 nLockTime

如果强制执行了 BIP68 ,且 nSequence 的第 21 位置 1 ,且第 31 位和第 22 位置 0 ,则:

  1. R 为基于区块高度的相对时间锁

  2. H 为 BIP68 允许该输入被挖出的最小区块高度(钱币诞生的高度 + R

  3. 如果 R <100,nLockTime ≥500,000,000 ,或者 nLockTime < H ,则交易失败。

OP_CSV 强制执行(可选)

在执行 OP_CSV 操作码时,如果栈顶元素的第 31 位和第 22 位置 0,且第 21 位置 1,则失败;并且,当 nSequence 的第 21 位置 0 时,也失败。

OP_LOCKTIME 内省操作码(可选)

OP_LOCKTIME 是一个仅限 tapscript 使用的操作码,替换一个 OP_SUCCESS 的语义;它将一个最小化编码的 nLockTime 推入堆栈(最大是 5 字节)。

应用场景:无需发布原像,就让 HTLC 过期

仅用 nSequence 字段来强制执行最小的 nLockTime,我们可以创造出一种 HTLC ,它能确保,如果原像未在 HTLC 超时的至少 100 个区块以前发布,就必定能退款。为此,我们要让原像花费路径变成一种两阶段的程序:

  1. 收款方发布一个有效性取决于原像的 TRUC 交易(Tx1),将 HTLC 的资金转移到一个阶段性的输出;并且,该交易有一个使用收款方密钥的临时锚点。

  2. 这个阶段性的输出有两种花费路径:

    a)一笔预先签名的 TRUC 交易(Tx2),仅有一个输出,将 HTLC 中的资金转给收款方,而其 nSequence 通过设置第 21 位强制执行 100 个区块的相对时间锁,而 nLockTime 则设置为 HTLC 的超时时间。

    b)一个脚本路径,允许支付方在 HTLC 超时的 N 个区块以后花费这个阶段性输出,使用 CLTV 来强制执行;其中 N 就是广播 Tx2 的窗口的长度。

这种设计的出发点是闪电转发节点所面临的 “替代交易循环攻击”,并且受到了 Peter Todd 的 “OP_EXPIRE 提议” 的启发。相对于 OP_EXPIRE ,本设计的主要优点是免疫免费转发。超时时间与父交易的区块高度绑定,也就是必须要 100 个区块确认,从而保证了一笔有效的交易不能变成无效的,除非有长达 100 个区块的重组。

OP_EXPIRE 不同的是,这种方法 不是 在退款路径中防止替代交易循环攻击。相反,它是通过消除攻击者的激励来防止攻击:它保证了,如果没有及时发布原像,就一定会退款。要么,路由节点有充足的机会来领取入账的资金,要么,他们一定可以获得退款。

译者注:本方法的原理需要我们调整对 “超时(expiry)” 的理解。

在原本的哈希时间锁合约中,“超时时间” 是一个时间点,从这个时间点开始,提出 HTLC 的一方可以发起退款(撤回合约);但获得 HTLC 的一方使用原像来取款的花费路径不会作废。

而在本方法(的这一部分)中,“超时时间” 是一个起点,从该起点开始,获得 HTLC 的一方可以广播自己的取款交易(Tx2);从该时间点再过 N 个区块,提出 HTLC 的一方可以发起退款。

又因为 Tx2 本身受本方法的约束,这种约束分成两个方面,(1)相对时间锁约束,使得 Tx2 所花费的输入(来自 Tx1)必须已经得到至少 100 个区块确认;(2)Tx1 的确认时间 + 100 必须小于 nLockTime 的数值,否则 Tx2 会因为 nLockTime < H 而失败;尽管 nLockTime 本身让 Tx2 必须等到这个时间点才能广播。

这种方法有四大局限性:

  1. HTLC 的存续时间不能短于 100 个区块。
  2. 收款方可以发布原像的时间要(从超时时间)减去 100 个区块。
  3. 收款方在发布原像之后,还必须等待 HTLC 过期,才能领取资金。
  4. 收款方必须为多笔交易支付手续费(而不是只需要支付一笔手续费)。

其中 (1) 和 (2) 都是小问题,可以通过给 CLTV 总预算加上 100 、接受更短的转发路径总长度来缓解。在实践中,唯一受到影响的是那些最后一跳的 HTLC 会在大约 100 个区块乃至更短时间内超时的支付,而这是非常罕见的。

(3) 产生了一种微小但真实的流动性限制,但只在反常的事件中产生:一个 HTLC 要在链上结算并偏向于收款方;并且下文的优化可以提供一些缓解。 (4) 仅对小额的 HTLC 来说是问题,在高手续费的环境下,也许不值得花手续费来赎回。消除在本地交易池监控原像的需要、提升转发节点的理论安全性,也许值得作出这些牺牲。

优化方法

我们可以用 OP_CSV 强制执行和 OP_LOCKTIME 内省来优化原像花费路径:

  1. 广播依赖于原像的阶段性交易(即 Tx1)。

  2. 阶段性输出有两种花费路径:

    a)收款方可以花费此阶段性输出,当 BIP68 确认高度 <= nLocktime < HTLC 超时时间,使用 CSV(设置第 21 位)、LOCKTIMELESSTHAN 来强制保证。

    b)支付方可以在 HTLC 超时之后花费此阶段性输出,由 CLTV 强制保证。

这种优化有两种显著的好处:

  1. 收款方可以在 HTLC 超时之前领取资金。
  2. 支付方可以在 HTLC 超时之后领取退款,无需等待。

(1) 缓解了未优化方法的第 3 个局限性;而 (2) 保证了提出 HTLC 的一方不会因为较晚广播阶段性交易而受到惩罚。

设计理念

使用 nSequence 强制最小 nLockTime 数值

使用 100 个区块的最小相对时间锁,是为了防止一笔挖出的交易因为深度的区块链重组而变成无效的。使用 100 这个数值,是为了提供跟成熟的 coinbase 输出同样的安全性保证,类似的实验也出现在 Peter Todd 的 OP_EXPIRE 提议中。

选择第 21 位,是因为它邻近第 22 位(相对时间锁的类型位),并且在当前的公式规则中没有含义。(据我所知)还没有应用使用这一位来表示 BIP68 限定输入的数据可用性,所以这样的共识变更不太可能造成没收。

本提议有意不支持基于钟表时间的强制直线,理由跟 Peter Todd 在 OP_EXPIRE 提议中说的一样。

最后,BIP68 强制执行的 最小 nLockTime 提供了最大的灵活性,可以满足多个输入表示不同的确认高度,同时在一个更大的区块高度上执行一个绝对时间锁。

OP_CSV 强制执行

OP_CSV 当前忽视第 21 位,所以需要一次软分叉来添加强制执行。最简单的方法是限制堆栈元素将第 31 位和第 22 位留空,因为第 21 位仅在此语境下才有共识含义。

OP_LOCKTIME 内省

CLTV 强制执行一个最小的 nLockTime,但这里描述的应用场景需要限制一个 最大 值,所以我们需要一个新的操作码。

OP_LOCKTIME 并不保证时间锁强制执行,只是在结合 CSV 第 21 位以及 LESSTHAN 时启用所需的功能。这保证了操作码的极简,将确保执行的责任交给用户。

还请注意,以高度表达的时间锁也可以表示位一个 32 比特的有符号整数,从而跟 OP_ADDOP_LESSTHAN 这样的操作码兼容。对于晚于 2038 年的基于钟表时间的时间锁,这一点不成立,那需要 BIP441 64 位整数支持。

结论

这种思路似乎提供了 OP_EXPIRE 的一种窄化的替代品,并消除了免费转发的可能性,同时消除了监视本地交易池以寻找原像的需要。我希望听到关于这种方法的意见,以及对无交易池的 HTLC 转发和交易超时的观点。

感谢反馈!