leanConsensus 中的最终性:ethlambda 如何实现 3SF-mini

本文详细介绍了leanConsensus协议中的3SF-mini(3槽最终性,精简版)最终性机制,旨在实现比以太坊Casper FFG更快的区块最终性。它通过引入“可证明槽位”概念和自适应回退策略,确保即使在网络不稳定时也能有效聚合投票,加速共识恢复。文章还对比了3SF-mini与Casper FFG的主要差异及其在ethlambda中的实现。

在我们之前的文章中,我们介绍了 ethlambda 如何使用 LMD-GHOST 来回答“我应该遵循哪一个链尖?”的问题。我们以一个悬而未决的问题结束:协议如何决定何时尖端重组 (reorg) 不再可能?Fork choice 告诉你链的走向,但它不会告诉你一个区块何时是永久性的

这篇文章涵盖了共识的另一半:3SF-mini(3-Slot Finality,极简版本),这是 leanConsensus 使用的 Finality Gadget。如果说 LMD-GHOST 是关于在分叉中导航,那么 3SF-mini 就是关于终结分叉。

问题:区块何时是永久性的?

在今天的以太坊上,Finality 大约需要 13 分钟(Casper FFG 的两个 Epoch)。在该窗口期内,理论上链重组可以撤销任何交易。对于大多数用例来说,这没问题,但对于某些用例则不然。在协议层面,这意味着系统始终带有 13 分钟的不确定性。

leanConsensus 的目标是实现更快的 Finality,旨在 3 个 Slot 内达到 Finality,在 4 秒一个 Slot 的情况下,将 Finality 时间缩短到平均 10 秒。3SF-mini 可能不是最终的算法,但它让我们得以窥见更快速的 Finality 是什么样的。

回顾:Attestation 携带的内容

在进入 Finality 之前,让我们回顾一下验证者投票的样子。每个 Attestation 携带三个检查点 (Checkpoint):

+------------------------------------------------------------------+
|                         ATTESTATION                              |
|                                                                  |
|  head     通过运行 Fork-choice 获得的区块                           |
|           <- LMD-GHOST (在前一篇文章中已涵盖)                      |
|                                                                  |
|  target   验证者希望下一个被证明合理 (justified) 的区块             |
|           <- 源自 safe target,回溯到最近的 justifiable slot       |
|                                                                  |
|  source   最新证明合理 (justified) 的检查点                        |
|           <- 从存储状态 (store state) 读取                         |
+------------------------------------------------------------------+

head 输入到 Fork choice。sourcetarget 输入到 Finality。一张选票表示:“我认为检查点 S 是 justified 的,我希望检查点 T 接下来也成为 justified。” 当足够多的验证者在同一个 (source, target) 链路上达成一致时,target 就会变成 justified。在某些条件下,justified 检查点将变为 finalized(不可逆)。

Justification 的阈值是三分之二的 Supermajority:

$$ 3 \text{vote_count} \ge 2 \text{validator_count} $$

如果有 9 个验证者,其中 7 个为同一个 target 投票:$37=21 \ge 29=18$,则该 target 被 justified。

在 ethlambda 中: Justification 和 Finalization 发生在 crates/blockchain/state_transition/src/lib.rs 中的 process_attestations() 函数中,该函数在 process_block() 期间被调用。

达成 Finality 的三个 Slot:Happy Path

在有 4 个验证者且一切运行顺利的情况下,Finality 仅落后链尖两个 Slot:

在每个 Slot,验证者投票给最新的区块作为他们的 target,并引用最新的 justified 检查点作为 source:

  • Slot $N+1$: 投票 source=N, target=N+1。四个中的三个投票($33=9 \ge 24=8$),因此 $N+1$ 是 justified
  • Slot $N+2$: 投票 source=N+1, `target=N+2$。四个中的三个投票,因此 $N+2$ 是 justified。$N+1$ 和 $N+2$ 是连续的 justifiable Slot 且都被 justified,因此 $N+1$ 是 finalized

每个区块都携带 Attestation,用于证明父 Slot 是 justified 的,并使前一个 Slot 达到 finalized。对于 4 秒的 Slot,即从提议到 Finality 仅需 8 秒

这是稳态;但网络并不总是稳定的。

当出错时:Justifiability 时间表

当网络发生分区或验证者对 head 有分歧时,投票会分散在相互竞争的 target 上。没有单个 Slot 能达到三分之二的阈值。Justification 停滞,随之而来的是 Finalization 停滞。

这就是 3SF-mini 引入其最有趣想法的地方:不是每一个 Slot 都可以被 justified。只有距离最后一个 finalized Slot 特定距离的 Slot 才有资格。协议称这些 Slot 为 justifiable

如果 $\text{delta} = \text{slot} - \text{finalized_slot}$ 小于或等于 5、是一个完全平方数,或者是一个 pronic number,则该 Slot 是 justifiable 的:

+-------------------------------------------------------+
|             JUSTIFIABILITY 规则                       |
|                                                       |
|  规则 1:  delta <= 5          (始终是 justifiable 的)   |
|                                                       |
|  规则 2:  delta = n^2         (完全平方数)              |
|           1, 4, 9, 16, 25, 36, 49, 64, 81, 100, ...   |
|                                                       |
|  规则 3:  delta = n(n+1)      (pronic numbers)        |
|           2, 6, 12, 20, 30, 42, 56, 72, 90, 110, ...  |
|                                                       |
+-------------------------------------------------------+

在前 36 个 Slot 上的可视化:

delta: 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
       Y  Y  Y  Y  Y  Y  Y  .  .  Y  .  .  Y  .  .  .  Y  .  .  .  Y
       |- delta <= 5 -|  2*3      3^2      3*4         4^2         4*5

delta: 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
       .  .  .  .  Y  .  .  .  .  Y  .  .  .  .  .  Y
                   5^2            5*6               6^2

接近 Finalization 时,每个 Slot 都是 justifiable 的,链移动很快。随着差距扩大,justifiable Slot 变得稀疏。它们之间的间隔从 1 增加到 3、4、5,并不断扩大。

为什么限制哪些 Slot 可以被 justified?因为它创造了自然的投票集中。如果在 30 个 Slot 的窗口中只有一个 Slot 是 justifiable 的,那么该窗口中的所有验证者投票都会汇集到同一个 target。当网络难以达成共识时,协议在结构上迫使投票收敛,而不是分散在多个候选者身上。

在 ethlambda 中: crates/blockchain/state_transition/src/lib.rs 中的函数 slot_is_justifiable_after(slot, finalized_slot) 实现了这一检查。它使用 isqrt() 进行完全平方数检测,并使用恒等式 $4n(n+1) + 1 = (2n+1)^2$ 进行 pronic number 检测。

Finalization:间隔规则 (Gap Rule)

仅凭 Justification 并不能使区块成为永久性的。一个 justified 的检查点在下一个 justifiable Slot 也被 justified 且中间没有 justifiable Slot 时变为 finalized。Source 和 target 必须是 justifiability 时间表中的连续条目。

推理很优雅:如果 source 和 target 之间不存在 justifiable Slot,那么验证者就不可能将他们的投票投向其他任何地方。不存在替代的 Justification 路径。这种结构上的不可能性使得该检查点不可逆。

这与 Casper FFG 有根本不同,Casper FFG 检查的是任何中间检查点是否已 justified。3SF-mini 检查的是中间检查点根本不存在。用更简单的逻辑实现更强的保证。

在 ethlambda 中: crates/blockchain/state_transition/src/lib.rs 中的 try_finalize() 函数遍历 source 和 target 之间的 Slot,并对每个 Slot 调用 slot_is_justifiable_after。如果任何 Slot 是 justifiable 的,Finalization 就会失败。该检查使用 original_finalized_slot(区块处理开始时的 finalized Slot,而不是当前的一个),因为 Finalization 可能在处理过程中推进。

自适应退避:压力下的自我修复

除了作为过滤器外,justifiability 时间表也是一种退避机制。当 Finalization 停滞时,finalized Slot 与链尖之间的差距会增大。随着 delta 增加,justifiable Slot 变得更加稀疏。由于它们变得稀疏,投票就会集中。随着投票集中,达成共识变得更容易。系统会推动自己走向恢复。

考虑一个长期分区的网络。finalized Slot 卡在 0,链尖接近 Slot 1000:

一旦网络收敛:

阶段 1:长期停滞。 投票终于集中。Slot 992 和 1024 被 justified。它们之间没有 justifiable Slot。Slot 992 变为 finalized。新的 $F=992$。

阶段 2:部分重置。 Justifiability 时间表转移到以 $F=992$ 为锚点。在链尖(~1024)附近,delta 仅为 ~32。间隔从 31-32 缩小到约 6-7。

阶段 3:另一次 Finalization。 间隔进一步缩小。

阶段 4:恢复完成。 delta 足够小,使得每个 Slot 再次变为 justifiable。恢复快速 Finalization。

达成 Finalization 后 F Delta 附近的间隔
(停滞中) 0 ~1000 31-32
Slot 992 992 ~32 6-7
Slot 1022 1022 ~6 1

每一个 Finalization 步骤都会收紧时间表。系统逐步自我修复,无需人工干预或参数调整。

Casper FFG 没有等效机制,因为无论网络健康与否或是否分区,其 Epoch 间距都是固定的。

分叉与延迟收敛:一个实例

让我们看一个现实场景,其中分叉延迟了 Finalization,并观察系统如何恢复。这将 3SF-mini 连接回前一篇文章中的 Fork choice 机制。

设定: 9 个验证者,finalized=100,justified=101。Safe target 阈值:6 票(9 票的 2/3)。

Slot 102-103:分叉导致投票分散。

两个分支都没有超过三分之二。Safe target 卡在区块 101。Attestation 无法推进 Justification,因为从链尖的回溯总是落在 source 上,因此没有什么新的东西可以 justify。

Slot 104:分叉解决。 验证者 V7 和 V8 收到了区块 102a(因分区而延迟)并切换了阵营。

B102a 现在拥有 $7 \ge 6$ 票。Safe target 推进到 B102a。Slot 102 是 justifiable 的($\text{delta}=2 \le 5$)。带有 source=101, target=102 的 Attestation 达到 Supermajority:$37=21 \ge 29=18$。Slot 102 变为 justified。101 和 102 之间没有 justifiable Slot,因此 Slot 101 变为 finalized

Slot 105-106:完全收敛。

所有 9 个验证者都在 a 分支上。带有 target=B104a 的 Slot 105 被 justified。但 102 的 Finalization 失败了,因为 Slot 103(位于 source=102 和 target=104 之间)是 justifiable 的,但从未被 justified(在分叉中丢失了)。

在 Slot 106 中,target=B105a 被 justified。104 和 105 之间没有 justifiable Slot,因此 Slot 104 变为 finalized。Finalization 从 101 跳到了 104,跳过了 102 和 103。

分叉导致了短暂的停滞,但协议在收敛后的两个 Slot 内就恢复了。没有特殊的恢复模式,没有操作员干预。处理 Happy Path 的相同规则也处理了 Unhappy Path。

3SF-mini 对比 Casper FFG

两者都是建立在检查点之间 Supermajority 链路上的 Finality Gadget。它们共享相同的理论基础。它们的不同之处在于时间单位以及这对系统其余部分意味着什么。

Casper FFG 将 32 个 Slot(~6.4 分钟)分组为一个 Epoch,并将验证者集分配到这些 Slot 中。每个验证者每个 Epoch 见证一次。完整的统计数据仅在 Epoch 边界可用。最快的 Finalization:2 个 Epoch,大约 13 分钟。

这的存在是因为可扩展性限制,而不是协议理论偏好。以太坊上有约 1,000,000 个活跃验证者,让每个人在每个 12 秒的 Slot 都投票是无法管理的。Epoch 就是解决方案。

3SF-mini 在单个 Slot(4 秒)上运行。每个验证者在每个 Slot 都会投票。这目前之所以可行,是因为 leanConsensus 的验证者集较小。回报是:Finality 在 2 个 Slot 内达成,而不是 2 个 Epoch。

方面 3SF-mini Casper FFG
谁在何时投票 所有验证者,每个 Slot 每个验证者每个 Epoch 一次
每个 Slot 的消息数 $N$(所有验证者) $N / 32$(一个委员会)
达成 Supermajority 所需时间 1 个 Slot 1 个 Epoch
最快 Finalization 2 个 Slot ~ 8 秒 2 个 Epoch ~ 13 分钟
自适应退避 是(Justifiability 时间表) 否(固定的 Epoch 间距)
实际验证者限制 数百到数千 数百万

Finalization 逻辑也不同。Casper 使用 $k$-finality:当其后的 $k$ 个连续 Epoch 检查点也被 justified 时,一个 justified 检查点即变为 finalized(以太坊使用 $k=2$ 作为错过 Epoch 的恢复机制)。3SF-mini 使用间隔规则:当下一个 justified 检查点是其在 justifiability 时间表中的直接继任者,且没有可能的中间 target 时,一个 justified 检查点即变为 finalized。3SF-mini 不是容忍错过的窗口,而是在网络困难时使窗口变宽。

在 ethlambda 中的实现

ethlambda 中的 Finality 流水线集成在区块处理中。当一个区块被导入时,process_block() 应用 Attestation,检查 Justification,并尝试 Finalization,所有这些都在单次处理中完成。

步骤 位置 发生了什么
Attestation 收集 crates/blockchain/src/store.rs Attestation 在间隔 0 和 4 从 pending 提升为 active
Justification 检查 crates/blockchain/state_transition/src/lib.rs process_attestations() 统计投票,应用 Supermajority 规则
Justifiability 过滤器 crates/blockchain/state_transition/src/lib.rs slot_is_justifiable_after() 控制哪些 Slot 可以被 justified
Finalization 尝试 crates/blockchain/state_transition/src/lib.rs try_finalize() 检查 source 和 target 之间的间隔规则
窗口偏移 crates/blockchain/state_transition/src/justified_slots_ops.rs 当 Finalization 推进时,shift_window() 修剪 justified-slots 比特列表
指标 crates/blockchain/src/metrics.rs 每次 tick 更新 lean_head_slotlean_finalized_slot

justified_slots 比特列表使用相对索引(索引 0 映射到 finalized_slot + 1)。当 Finalization 推进时,shift_window() 会丢弃现在已经 finalized 的前缀并重新锚定比特列表。这使得数据结构无论链运行多长时间都保持有界。

如果你想查看 3SF-mini 的实际运行情况,ethlambda 是开源的,并且现在正在运行多客户端开发网:

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

0 条评论

请先 登录 后评论
lambdaclass
lambdaclass
LambdaClass是一家风险投资工作室,致力于解决与分布式系统、机器学习、编译器和密码学相关的难题。