闪电 DLC

本文介绍了在闪电网络中嵌入离散日志合约(DLC)的技术实现,详细描述了如何打开、设置和关闭闪电通道中的DLC,并讨论了相关的技术组件和实现细节。

TLDR;

我们已经成功开启和关闭了第一个主网 Lightning 通道,嵌入了离散对数合约(DLC)。

在 Crypto Garage,我们一直在努力使 DLC 能够在 Lightning 通道上运行,终于达成了一个重要里程碑,成功开启了一个 Lightning 通道,在其中设置了一个 DLC,并关闭了整个通道。在本文中,我们将解释如何设置和关闭 Lightning 通道和 DLC 的技术细节。

什么是在 Lightning 上的 DLC(以及它不是什么)

在本文中,我们所指的在 Lightning 上开启 DLC 意味着与一个节点建立一个 直接 通道,并在通道内使用(部分)用于开启它的资金设置一个 DLC。DLC 可以关闭(恢复为常规 Lightning 通道),续签或更新,当然,在非合作方的情况下,通道也可以在链上关闭(我们就是这样做的,它展示了 Lightning 通道和 DLC 合约的完整交易结构)。

我们强调,目前不可能在 Lightning 上有 路由DLC(这意味着在没有直接通道的节点之间开启 DLC)。有关更多信息,请参见 此邮件列表帖子

前期准备

为了尝试使本文独立自足,我们将讨论设置 Lightning 上 DLC 的不同组成部分:Lightning 通道适配器签名DLC,以及 DLC 通道。你可以跳过你已经熟悉的概念相关部分。

Lightning 概述

由于在没有对常规 Lightning 通道的交易结构有一个粗略了解的情况下,很难理解如何在 Lightning 通道中设置 DLC,因此让我们快速回顾一下(要深入理解,这篇 Bitcoin Magazine 系列 非常不错)。我们将仅集中于上下文相关的内容,因此将跳过与路由相关的部分。

当两个 Lightning 节点相互开启通道时,他们合作构建并签署两种类型的交易,资金交易承诺交易

资金交易从一方或双方(在 双重融资 的情况下)获得多个 UTXO 作为输入,并在 2 of 2 输出中锁定用于通道的资金,需要双方的签名才能支出,这被称为 资金输出

承诺交易以资金输出作为输入,并包含两个输出,值对应于每一方的余额。请注意,这些余额在通道的生命周期内会发生变化,因此承诺交易需要可更新以反映这些变化。这是通过使承诺交易 可撤销 来完成的。在实践中,这意味着每一方持有不同版本的承诺交易,输出支付给自己被锁定在可以在一定时间后由自己解锁的脚本中,或者通过了解秘密的对方进行解锁。当双方同意更新通道余额时(例如,一方希望将一些 sats 发送给另一方),他们构建并交换新的承诺交易的签名,并通过互相揭示之前使用的秘密来撤销以前的交易。如果一方试图通过广播旧的承诺交易来欺骗,另一方有一些时间来反应,并使用秘密来获取所有通道资金。

交易结构如下图所示。

Lightning 通道的交易结构

适配器签名

适配器签名是一种已加密的签名(在感兴趣的情况下,使用公钥),我们可以证明在解密后(用相应的私钥),我们可以获得一个给定消息的有效签名。它还具有这样一个特性:了解适配器签名、加密公钥和解密后的签名,可以检索用于加密的秘密。有关涉及的公式的快速概述,请查看 这里

以下图示例了在加密、验证和解密适配器签名,以及恢复加密秘密的不同操作。

离散对数合约

DLC 使两方能够基于某个事件(体育比赛、资产价格等)设置合约,并在比特币区块链上直接结算。双方需要事先选择一个 oracle,作为将为事件结果发布签名的实体(以证明结果的价值)。

DLC 起初看起来相当类似于 Lightning 通道,但而不是将承诺交易支出于资金输出,我们有合约执行交易(CET),每个合约支付的可能性各有一笔。双方各自加密他们的签名(创建适配器签名)用于这些交易,使用 oracle 为相应事件结果生成的签名的预影(请参见 这里 获取更多详细信息),并进行交换和验证。一旦 oracle 证明事件结果,任一方都能解密对方的单一签名,并通过广播相应的 CET 来关闭合约。值得注意的是,由于使用了适配器签名,双方持有完全相同的 CET 集合。DLC 的交易结构如下图所示。

链上 DLC 的交易结构

DLC 通道

如果两方希望在到期时续签合约怎么办?当然,他们可以关闭第一个合约并重新开启另一个合约。然而,这会产生每个广播交易的费用。相反,他们可以使用 DLC 通道(ItchySats 的人们在 这里 写得更详细)。DLC 通道使得双方能够续签合约,在合约到期日之前结算,当然,在他们想要取回资金时也可以在链上关闭合约。一种简单的方法是使 CET 可撤销。不幸的是,这在续签合约时造成了问题。一旦某一方撤销了先前的 CET,他们无法阻止对方继续使用它们。这意味着对方有机会关闭以前的合约或新合约,而首先撤回 CET 的一方只能等待新合约到期后关闭(因为他们需要等待 oracle 发布证明才能广播 CET)。这为其中一方带来了不公平的优势。为了解决这个问题,我们引入了一种 缓冲交易,它支出资金输出并输出相同的值(减去费用),用于 CET 的输入。当续签合约时,如果一方没有及时撤销先前的合约,另一方可以广播新合约的缓冲交易,防止恶意(或故障)方使用以前的合约关闭通道。通过这种结构,只需将缓冲交易设置为可撤销即可撤销合约。

那么,我们如何撤销缓冲交易呢?一个方法是使用与 Lightning 中相同的方法,让每一方持有不同版本的缓冲交易。幸运的是,存在一个更好的解决方案(最初在 这篇论文 中提出)。它再次依赖于适配器签名,但与常规 DLC 的用法不同。每一方使用三组密钥对。第一组是资金密钥,双方在资金输出的 2 of 2 脚本中使用。第二组是撤销密钥,在合约被撤销时揭示。最后,第三组是发布密钥。这三组密钥用于缓冲交易输出脚本,可以有三种不同的支出方式(我们用 Alice 和 Bob 让事情简单):

  1. 利用 Alice 和 Bob 的资金密钥签名(使用其中一个 CET 交易,正如之前所说的,只能在了解 oracle 证明事件结果的情况下使用),
  2. 利用 Alice 的资金密钥签名,以及 Bob 的发布和撤销密钥的签名,
  3. 利用 Bob 的资金密钥签名,以及 Alice 的发布和撤销密钥的签名。

当通道中设置合约时,Alice 和 Bob 互相提供缓冲交易输入的适配器签名,使用对方的发布(公)密钥进行加密。如果其中一方希望广播缓冲交易,他们解密从对方那里获得的适配器签名,使用他们的发布(私)密钥。但通过广播缓冲交易(其中包含解密后的签名),他们将向对方暴露他们的发布私钥(对方已经知道适配器签名和加密密钥)。如果缓冲交易未被撤销,这并不是问题,他们将能够合法地使用其中一个 CET 支出缓冲交易输出。但如果缓冲交易被撤销,他们的对方也必须知道撤销秘密,因此能够获取所有输出资金。最后,请注意 CET 有一个相对时间锁,以给予受骗方支出被撤销的缓冲交易输出的时间。

以下图示例了交易结构及其支出条件。

DLC 通道的交易结构

Lightning 上的 DLC

现在我们已经解释了所有的构建模块,让我们看看如何在 Lightning 通道中嵌入 DLC 通道。一个明显的第一种方式是在 Lightning 通道的承诺交易中添加一个输出,以资助 DLC 通道。不幸的是,这意味着每次承诺交易更新时,DLC 的所有适配器签名都需要重新计算(并重新验证),这对于具有大量可能结果的合约来说可能是成本高昂的(此问题可以通过类似 SIGHASH_NOINPUT 的东西解决)。为了避免这种情况,我们引入了一个 分割交易,它支出资金输入并包含两个输出,一个用于 Lightning 通道,一个用于 DLC(它可能包含更多的输入,以资助多个 DLC 通道,并同时有多个开启的合约)。为了能够以后将通道恢复为“典型”的 Lightning 通道,我们使用 用于 DLC 通道的相同适配器签名机制 使分割交易可撤销。不幸的是,Lightning 通道引发了一个问题。为了让一方对已撤销分割交易的广播做出反应,支出必须在其上有某种时间锁。但是,Lightning 网络规范使用承诺交易的 nLockTime 和 nSequence 字段 来指定承诺编号。为了解决这个问题,我们在分割交易和 Lightning 通道承诺交易之间插入了一个 粘合交易 以强制执行相对时间锁(感谢 Matt Corallo 提出这个简单的解决方法)。请注意,这实际上是一个工程问题,通过采用不同的承诺交易规范可以解决(但这还需要对 Lightning 实现进行更多更改以支持它)。

总结一下,如果两个在 Lightning 网络中有直接通道的双方希望在其中设置 DLC,他们将共同创建并签署分割交易、粘合交易、更新的承诺交易(反映在 Lightning 中保留的每一方的资金)、缓冲交易和 DLC 的 CET。他们随后可以继续通过 Lightning 通道路由,并在 DLC 通道中更新或结算 DLC 合约。如果他们希望关闭 DLC 通道,他们可以撤销分割交易,并共同创建和签署更新后的承诺交易。

以下图示例了交易结构。请注意,对于分割交易和缓冲交易使用了不同的发布和撤销密钥。

嵌入 DLC 通道的 Lightning 通道交易结构

实现

上述构建在 rust-dlc 库 中得以实现,使用了 Lightning 开发工具包 (LDK) 的一个分支,该分支增加了对拆分 Lightning 通道的支持。还实现了一个 小型 CLI 工具,除了常规的 Lightning 功能外,还可以开启和管理 DLC 通道。请注意,代码非常不稳定,我们 希望强调与主网硬币一起使用它很可能导致资金损失

主网执行

我们于 11 月 21 日首次在两个支持 Lightning 的 DLC 节点之间开启了通道,相关交易见 这里。然后,从开通通道的节点到另一个节点进行了 keysend 支付(一旦双重融资在 LDK 中实现,这一步将不再必要)。我们定义了一个基于 11 月 21 日下午 4 点(JST)比特币价格的 DLC 合约,并用它在 Lightning 通道旁打开了一个 DLC 通道。在合约到期时,我们让其中一个节点强制关闭通道。该节点首先广播了分割交易,可以在 这里。在将分割交易包含到区块后的 288 个区块(缓冲和粘合交易上的 nSequence 值)后,我们使节点广播缓冲和粘合交易(见:此处此处),以及其本地承诺交易(在 这里 可见)。在将缓冲交易包含到区块后的 288 个区块时,该节点获取了事件结果的 oracle 签名,解密对应结果的对方适配器签名,并能够广播 CET 来关闭 DLC(在 这里 可见)。

结论

能够在 Lightning 中开启 DLC 为一些不错的应用打开了大门,比如将部分通道值与其他货币挂钩,利用通道中的部分资金进行衍生合约交易而不需要放弃资金的保管,或仅仅是与朋友对一场足球比赛的结果下注。通过在 rust-dlc 库中实现对这一点的支持,并通过在 Lightning 通道内执行和关闭一个 DLC 来演示其用途,我们证明了我们提出的方法的可行性。还有相当多的工作需要进行,以分析和改进该提案,并强化其实现。因此,如果你有兴趣参与这一努力、使用该技术或想了解更多信息,请随时与我们联系!

致谢

感谢 LDK 团队审查并接受了一些使得本文讨论的内容得以实现的拉取请求,以及回答了多个关于 LDK、Lightning 和 Rust 的问题!

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

0 条评论

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