作者:Arik Sosman

来源:https://lightningdevkit.org/blog/announcing-rapid-gossip-sync/

如果你在运行闪电节点,你可能已经注意到了,有时候初始化节点会很花时间。光是开设一条通道旧需要 6 个区块的确认(大概是 1 个小时)。但是,即使你的节点已经开设了通道、只是下线了一段时间,重启节点依然需要获得最新的通道图谱数据(一般称为 “Gossip 数据”),并验证其中所有通道都完好无损。

虽然大多数的闪电节点实现都有快速跟上最新区块的机制,但它们依然有个瓶颈,就是上面提到的 Gossip 数据的交换。一般来说这个过程花不了几分钟,但当你要从移动设备发起本地路由的支付时,会大大影响用户体验。假设一个 app 一直是关着的,到你需要发送支付时你打开了它,即使只是让你等待 1 分钟,你也会觉得体验极差。

这个问题的常见解决方案是来跟意向支付的接收者使用同一个闪电网络服务提供商(Lightning Service Provider),通过牺牲隐私性的方式将路由计算的任务外包给服务商。

因此,我们非常高兴地宣布 “迅捷 gossip 同步” 协议,让节点可以通过 准-免信任 的服务器获得通道图谱数据。

当前的交换式 gossip

在我们深入介绍迅捷 gossip 同步协议的优化措施之前,我们先要理解当前的 gossip 是如何工作的。当前的 Gossip 协议包含三种主要的消息类型:通道宣布、通道更新和节点宣布(最后这种消息跟这篇文章不大相关)。

顾名思义,通道宣布消息就是在一个公开的节点启动时发出的消息,而通道更新消息就是一条通道更新状态时发出的消息。闪电通道有一种非对称性:同一条通道对不同方向的支付可能有不同的特性。举例而言,假设 Alice 和 Bob 开设了一条通道,Alice 可能会对传递到 Bob 的支付收取更高的手续费(相对于 Bob 对传递到 Alice 的支付所收取的水平)。不像通道更新消息,通道宣布消息不会携带方向信息,所以需要为不同方向的网络广播不同的通道更新消息。类似地,开启一个新状态也需要为这种非对称性发送至少两条状态更新信息。

Gossip 的一个显著特性是,消息中存在大量重复信息。举个例子,每一条通道宣布消息和更新消息,都包含着通道建立时候的区块哈希值。类似地,每一个通道宣布消息都包含节点的公钥,从而增加了连接良好的节点的数据冗余。所以,为了降低带宽需要,我们决定测验是否能剥离数据,从而创造出一种更高效的方法、携带相同的信息。

在下文中,我们会列举一部分我们提出的优化手段。

迅捷 gossip 同步

首先,迅捷 gossip 同步背后的思想是,由一个或多个 准-免信任 的服务方预先处理 Gossip 数据。这些服务方会通过常规的 gossip 协议验证节点的签名,并使用区块链来验证通道是否存在。这可以避免客户端的签名验证,并允许我们完全删除消息中的签名。

其次,服务器会发送批量的 Gossip 数据,表示最新通道图谱的快照。因为服务商已经批处理了数据,分布在所有宣布消息和更新消息中的全局属性(例如通道哈希值)可以剥离出去,只需发送一次。类似地,因为客户端主要对新信息感兴趣,一个时间戳(最新的那个) 就足以确定客户端在请求最新 Gossip 快照之前有没有看到过某个数据。

迅捷 gossip 同步最重要的优化措施是它不发送冗余的更新数据。所以,即使一个节点发送了 100 条通道更新消息,如果唯一发生变化的是其基础费用,那就不需要发送其它没有改变的属性。为此,我们重载了通道标签字节;在此之前,它只使用两个比特来表示一次更新影响到的方向以及一条通道是否被禁用。

通道更新消息会频繁发送,通常会涉及客户端之前没有见过的通道,这意味着,服务端必须包含通道的所有属性,而不能只包含改变过的。这一理解使我们意识到,许多不同的通道更新信息都把许多特性设置成了相同的值。所以我们决定统计一些哪些值是最常发送的。然后,为了减少数据开销,我们在每一条 Gossip 快照中将最常见的值设为默认值。任何其值匹配默认值的属性,都会从快照中省去。这种优化措施引起的唯一困难是,如何区分发出发出更新消息的通道是新通道还是已有的通道。碰巧的是,通道标签的最后一个位非常适合用于这个目的。这样一来,当一条更新消息是新通道发起的时,一个属性位将指明该通道与快照起点的默认值的偏离。否则,同一个位(如果设置了)将表示通道属性的突变。无论是哪一种情况,在属性位留空时,其对应的值都不需要发送。

最后,每一条宣布和更新消息都需要指定短通道 ID,每条消息需要 8 个字节。但我们可以通过渐进地排序宣布消息和更新消息,减少内存要求。相对差值会表明通道的 ID,这样一来,使用 BigSize 数据类型只需要不到 8 个字节,就可以表达出通道 ID。

迅捷 gossip 同步服务端

迅捷 gossip 同步协议只有搭配对应的服务端才能工作。它的运行原理非常简单:连接到网点网络的一组对等节点,监控 Gossip,并将带有时间戳的变更持久化到数据哭中。遇到客户端的请求时,先根据客户端提供的时间戳确定网络中发生了哪些更新(是客户端不知道的),然后以迅捷 gossip 同步协议的致密快照格式序列化变更量。但是,也有一些需要注意的地方。

通道更新消息有时候渗透得很慢,导致消息的时间戳与服务端监测到的时间不一致。为了避免歧义,服务端会给所有的宣布消息和更新消息标记一个 “看到时间戳”,以此排序所有的事件,并让差异的侦测变得简单。返回给客户端的每一个快照都包含对每一条宣布消息和更新消息的 “看到时间戳”。

此外,持续地计算图谱的变更量,需要耗费大量的资源,可能需要数十秒。为了避免这个问题,迅捷 Gossip 同步服务端会以 24 小时为间隔,规律地计算静态的快照变化量。这意味着,平均来说,客户端收到的每一条快照,都落后于最新的图谱 12 个小时。这个频率可以根据应用场景来调整。

信任模式

许多移动端闪电钱包将路由的任务委托给服务商,这就损害了闪电网络在隐私性上的一些好处。虽然交易不会发送到链上这个事实带来了一些好处,但你的支付历史离大白于天下也只有一步之遥。

依赖于迅捷 gossip 同步服务端,手机钱包不再需要牺牲用户体验来换取客户端路由的隐私性好处。迅捷 gossip 同步的信任模式将根据区块链验证通道图谱、验证节点签名的繁重工作转移给了服务端。但恶意的迅捷 gossip 同步服务端可以部分删除图谱数据来迫使支付通过自己的节点。如果这个服务端被广泛使用,他还可以通过另一个节点来集中路由,以抵御 DoS 攻击。

考虑到绝大多数的手机闪电钱包都跟钱包开发者的服务器通信,这些担忧可以容易通过部署一个迅捷 gossip 同步服务器来缓解,这样你的手机钱包就可以隐私地路由,不需要通过第三方,也不会牺牲用户体验。

结论

我们来看看上述优化措施的实际效果。

没有迅捷 gossip 同步协议,我们使用由随机的 8 万条宣布消息和 16 万条更新消息组成的集合来度量同步数据的大小,统计出平均大小在 53 MB 左右。

有了迅捷 gossip 同步协议,表示相同图谱的快照只需 4.7 MB,在 gzip 压缩之后只需 2 MB。在手机上处理数据和应用快照的时间少于 0.4 秒。想获得更准确的数字,请参考 Rapid Gossip Sync README

我们非常希望你能试试迅捷 gossip 同步协议,也请你检查一下服务端的代码。如果你不希望运行迅捷 gossip 同步的快照服务端,请看看我们的部署方案,可以在 rapidsync.lightningdevkit.org 找到。

(完)