作者:Joost Jager

来源:https://bottlepay.com/blog/multiplexer/

img

迈着缓慢的步伐,闪电网络正在稳步走向成熟。虽然闪电网络已取得长足进步,但仍有许多研发工作尚待展开。随着节点运营日趋专业化,研发重心也发生了转移。我们最初的目标仅仅是能够完成一笔付款而已,如今在某些方面已经有了更高的期望。

可靠性就是其中一方面。如果闪电网络要向全球用户推广,需要进一步提高可靠性。

本文将聚焦于一个有助于提高闪电网络可靠性的需求:针对入账支付的故障切换。

目前,闪电网络发票往往包含一笔付款的目的地节点。这就意味着,这个目的地节点必须维持运行状态,并且与闪电网络保持连接,才能接收这笔付款。一旦目的地节点停机,发票就会变得不可用。这不仅会给付款方带来糟糕的体验,还有可能给收款方造成损失。

一个典型的解决方案是设置多个节点。如果发票的有效期很短,节点又预先设定了停机时间,我们就有可能等待该节点生成的所有发票都达到最终状态后再优雅地将节点关停。在此期间,新的发票由其余节点生成。

但是,如果停机时间未知,这种解决方案就不奏效了。即使发票已经传递给了第三方,也会变得无法结算。

闪电网络多路复用器

过去几个月来,我们一直在努力解决这个问题。我们已经开发出了闪电网络多路复用器(Lightning Multiplexer)。这个名称借鉴自电子学领域。虽然闪电网络多路复用器与传统的多路复用器略有不同,但是我们觉得以二者的相似程度来看完全可以如此命名。

多路复用器对闪电网络全节点进行了大量精简,几乎没有剩下什么。它没有通道,不与外部网络连接,也不参与点对点 gossip 传输。但是,它确实有可以用来签署发票的节点密钥,还能解码洋葱数据包。

我们的目标设置是将单个多路复用器实例和多个全节点相结合。

付款方利用节点密钥经由任意全节点将付款发送给多路复用器。当其中一个全节点检测到将要转发给多路复用器的付款时,会进入另一个处理流程。路由节点不会尝试查找转出通道(并不存在),而是直接向多路复用器请求该 HTLC(哈希时间锁合约)的原像,然后立即进行结算。这笔付款是短路的,最后一跳只是获取原像的调用。

如果其中一个全节点停机,付款方会不断寻找其它路径来与多路复用器取得联系。如果全节点 A 停机,付款方会尝试通过全节点 B 与多路复用器取得联系。全节点 B 也知道多路复用器,因此同样具备结算这笔付款的能力。这就是故障转移得以实现的原理。

由于没有通道,多路复用器无法通过闪电网络点对点 gossip 协议向全网广播其位置。付款方如何与多路复用器取得联系成了难题。因此,多路复用器发票包含路径提示。路径提示描述了从一个或多个公开已知的节点到达目的地的路径。就上文例子而言,共有两个路径提示。一个提示了从全节点 A 到多路复用器的路径,另一个提示了从全节点 B 到多路复用器的路径。

值得一提的是,付款方无法区分多路复用器和其它私有节点。

实现

多路复用器完全接管了 LND 软件的发票处理逻辑,并通过基于 Postgres 的发票数据库来追踪发票的状态。LND 实例的发票数据库不再使用。

多路复用器负责创建发票,并使用其节点密钥对发票进行签名。除了它们的节点密钥会被列为路径提示之外,LND 节点不参与发票创建流程。

multiplexer diagram

进行发票结算时,多路复用器通过 HTLC 拦截器 API 在 HTLC 层面上与 LND 进行连接。来自拦截器流的 HTLC 会接受多路复用器的检查。 如果一个 HTLC 支付了某个已知发票,会有一条包含该 HTLC 原像的结算消息发送回接受该 HTLC 的节点。届时,多路复用器会在其数据库中将该发票标记为已结算。

这一机制同样适用于拆分付款,即使每部分付款来自不同的全节点。多节点拆分付款可以让付款方充分利用所有节点的流动性来完成一笔付款,从另一个维度提高可靠性。一般来说,全额付款同样可以从中受益。付款方可以通过节点选择一条最佳路径,尽可能降低路由费用。

至关重要的是,每个 HTLC 都要传递给多路复用器处理。这适用于链上和链下解析路径。行为不一致可能会造成资金损失。

LND 中已有的 API 实现没有提供足够强大的保证。因此,我们已经提交了几个 PR,旨在改进和扩展拦截器 API,使之可以安全地与多路复用器一起使用:

  • htlcswitch:新增 HTLC 拦截器故障控制 #6177
  • htlcswitch:为 HTLC 拦截器新增始终开启模式 #6232
  • htlcswitch:拦截器有效期检查 #6212
  • contractcourt:链上 HTLC 拦截器 #6219

未来,我们有可能支持除 LND 以外的其它节点实现。搭配使用多个实现会进一步增强系统的弹性。

单点故障

在上述设置中,全节点不再对付款构成单点故障威胁。但是,使用多路复用器又引入了新的单点故障风险。既然如此,多路复用器真的给我们带来了好处吗?我们认为这个问题的答案是肯定的。

由于多路复用器数据库本身可以被复制,我们没有将其算作又一个单点故障风险。

多路复用器中包含的逻辑是有限的。多路复用器会在内存中追踪传入的 HTLC。当一组 HTLC 完成时,数据库中对应的发票会被标记为已结算。相比闪电网络全节点的所有故障模型,多路复用器出错的可能性要低得多。如果多路复用器在类似 Kubernetes 的框架中运行时出现故障,一个新的实例会自动启动,将停机时间降至最短。

可能会出现问题的一个场景是,多路复用器存在无法自行修复的漏洞。在一个去中心化程度更高的设置中,也有可能存在这种漏洞,但是不一定会在所有实例上触发。目前,我们认为这是一个可以接受的风险。但是,我们可以在必要时扩展代码以支持多个实例。

开源

我们正在开源多路复用器的代码,因为我们将全力以赴推动闪电网络的发展视为义不容辞的责任。

代码和文档都可以在我们的库中找到。请注意,该实现仍处于研发阶段,属于实验性项目。

我们欢迎任何反馈、测试和评论。有兴趣深度参与该开源项目的开发者可以查看我们的招聘页面

多路复用器是我们想要引入闪电网络社区的一系列升级之一。我们致力于让闪电网络成为新兴付款渠道。为此,我们必须共同努力,让闪电网络能够在现实世界落地。

(完)