Solana 共识

可行的见解

  • 历史证明(PoH)在同步中的作用:PoH不是共识算法,而是Solana共识机制用于同步的工具。同样,权益证明(PoS)并不是共识,而是实际上的女巫抵抗。
  • 投票交易对于达成共识是必要的:区块内的投票并不是人为夸大 TPS 指标的无关交易。如果投票仅通过八卦(非正式的点对点通信)传播,则可能会导致验证者对塔(投票)状态的看法出现差异。
  • Solana 有两个主要的确认规则:一个用于短期分叉选择(乐观确认),另一个用于最终性的完全 PoS 共识(最终确定/扎根)。客户和用户能够遵守这些确认规则以获得所需的安全属性和定制的用户体验选择。这体现在两个承诺级别:“已确认”和“最终确定”。
  • 了解审查风险:验证者和开发人员应该意识到审查攻击的可能性,其中验证者试图破坏区块生产的顺序。了解此类攻击的机制以及计算能力和执行这些攻击的风险的作用。
  • 未来的协议升级即将到来:验证者和开发人员应积极准备 Solana 共识机制即将发生的变化,例如异步执行和程序化削减。

介绍

随着Solana 上的活动增加,其堆栈的各个层正在以前所未有的水平进行测试。关于“热门”话题(例如本地费用市场)已有很多文章和讨论,但有关 Solana 的共识长期以来一直被忽视。然而,随着恶意攻击的动机和潜在利用的利润增加,活动和兴趣的增加需要社区对共识的透彻理解。

共识是整个社区需要理解的 Solana 最重要的方面之一,因为它决定了成千上万的验证者如何就规范的交易顺序达成一致。

分布式系统中的共识已经研究了很多年。《拜占庭将军问题》由 Lamport、Shostak 和 Pease 撰写,发表于 20 世纪 80 年代初期。RAFT等共识算法在 web2 中早已使用。在加密领域,大多数共识算法都是BFT共识的不同实现,包括Gasper (Ethereum)、Tendermint (Cosmos)、MonadBFT (Monad)、HotShot (Espresso) 和Narwhal/Tusk (Sui)。 

本文并不试图正式证明 Solana 的共识机制(TowerBFT)。相反,它旨在向开发人员和更广泛的社区解释 Solana 的共识如何发挥作用,因为到目前为止,这个主题主要是 Solana Labs 和 Firedancer 贡献者的想法。还讨论了一些关于权衡和限制的评论。

共识简介

共识协议的目标是就区块内的交易及其相对顺序达成一致。网络中的验证者有两种主要类型的共识协议来就交易的规范顺序达成一致:

  • 最长链协议:这些协议(例如比特币的中本聪共识)规范化了需要最多计算工作来构建的链。虽然这通常与具有最大数量块的链相关,但更准确的描述是体现最大量累积工作或计算能力的链。
  • BFT 型协议:大多数 PoS 协议都实现 BFT 共识算法的一个版本。这些协议(例如 pBFT)依赖于活性和安全性阈值。一致性和可用性是CAP定理的两个保证,该定理指出任何分布式数据存储只能提供以下三个保证中的两个:一致性、可用性和分区容错性。

最长链和 BFT 型共识协议都从各自的确认规则中获得安全性。安全性包括安全性和活性,源自给定的确认规则,不是链的属性按照以太坊基金会的定义,确认规则是“节点运行的算法,输出某个区块是否被确认。在这种情况下,在某些假设下,主要是关于网络同步和诚实权益的百分比,保证区块永远不会被重组。”

它是自始至终的社会共识,最终由编写客户端代码的人们定义,这些代码通过某些确认规则来表达定义安全性的内容。

股权证明为 BFT 模型引入了额外的层,要求参与者提出自己的股权。参与者因遵守一系列规则而获得奖励,但如果被证明存在不当行为(例如,双重标志),可能会被削减。这被称为负责任的安全性,并允许协议识别和惩罚恶意节点,而对诚实节点没有外部影响。这并不能取代 BFT 共识协议的基本安全机制:网络仍然需要不到三分之一的不诚实节点来避免停止,以及不到三分之二的节点来防止验证虚假交易。基于权益的系统会对可能破坏或降低网络效率的行为施加后果。

这样的 BFT 网络有两个关键阈值:

  1. 1/3:如果不诚实节点占总数的三分之一或更多,网络可能会“停止”。在这种情况下,这些节点可能只是选择不参与,而其余节点无法获得达成共识所需的三分之二绝对多数。因此,网络不会产生错误的交易。相反,它根本不再产生任何交易。一种流行的(尽管是粗略的指标)是中本聪系数,它表示产生活性故障(停止区块生产)所需的最小节点数。
  2. 2/3:如果不诚实的节点占总数的三分之二或更多,他们可以串通验证他们选择的任何交易。这代表了最坏的情况,即网络停止正常运行,而是按照不诚实的绝大多数人的指示处理交易。在敌方控制超过 67% 股份的情况下,他们可能会隔离诚实节点,例如主要交易所的节点(例如币安)。这种隔离可以通过与数据中心串通来限制节点的网络流量来实现。然后,恶意实体可以让这个孤立的节点最终确定它所制作的块,同时将冲突的块分发到网络的其余部分。这种攻击利用了孤立节点的有限视角,导致潜在的双重支出,因为网络的其余部分和孤立节点对链上状态有不同的看法。

即使赌注较低(超过 33%),类似的攻击也是可行的,但这需要创建网络分区而不仅仅是隔离。在这种情况下,拜占庭利益相关者可以利用网络分区来操纵具有冲突信息的网络不同部分,再次面临双重支出和其他安全故障的风险。

通常,大量节点会增加任何一方试图破坏大部分以达到这些阈值(假设地理隔离)的难度。然而,这种对更大网络的渴望常常与效率相冲突。由于数据传输需求增加(投票传播需要更多时间),更多的节点可能会减慢共识速度,并且某些协议对最大节点数有硬性上限。

历史证明(PoH)

虽然权益证明 (PoS) 确保网络中达成共识,但 Solana 将历史证明 (PoH) 纳入其 PoS 共识机制中,从而实现连续区块生产的同步。这是通过 Solana 跳过槽领导者速度慢或反应迟钝的槽而不等待同步一轮共识来实现的。 PoH 并不关心证明事件发生的确切时间,而是证明事件之间的顺序和时间的流逝。

与普遍看法相反,历史证明(PoH)本身并不是一种共识机制或算法。虽然当前共识的实现利用了 PoH 的各个方面,但理论上可以剔除 PoH 并进行一些小的实现更改,以便 Solana 上的共识仍然有效。

PoH 的核心是一种类似于可验证延迟函数 (VDF) 的简单哈希算法,但从技术上讲并不是 VDF。 Solana 使用连续运行的顺序抗原像哈希函数 (SHA-256) 来实现这一点,并使用一次迭代的输出作为下一次迭代的输入。该计算在每个验证器的单个核心上运行。

虽然序列生成是顺序且单线程的,但可以并行验证输出,从而可以在多核系统上进行高效验证。虽然哈希速度存在上限,但硬件的改进可能会带来额外的性能优势。

阿纳托利(索拉纳)

考虑一个涉及 Solana 网络上四个验证器的示例:验证器 A、B、C 和 D。在此示例中,领导者调度可能将块生产的顺序规定为 A - B - C - D。验证器 A 首先生成依次阻止。为此,验证者 A 使用 PoH 机制,该机制涉及迭代运行 SHA-256 哈希函数,形成“刻度”时间尺度。这个哈希过程创建了一个独特且可验证的时间记录,确保验证者 A 的区块反映了准确的时间流逝。一旦验证者 A 完成其区块,就轮到验证者 B 生成下一个区块,然后是验证者 C。

假设验证者 C 试图通过不按顺序发出一个区块来破坏序列,旨在直接跟随验证者 A,从而绕过验证者 B。为了使验证者 C 令人信服地取代验证者 B 的位置,它需要复制验证者 B 的 PoH 哈希序列会产生,这意味着它必须生成一系列哈希值,代表验证器 B 生成块所需的时间。单核哈希性能存在物理最大值,这意味着我们知道已经过去了一段时间,因为计算机在给定时间间隔内可以生成的哈希数存在最大数量。

验证者 C 可以尝试通过从前一个合法区块(验证者 A 的区块)末尾开始生成空区块链来审查领导者调度中的验证者 B,而不包含任何交易。为了成功审查 B,C 必须满足两个条件。首先,C需要算力来磨掉空的PoH链。其次,C 必须快速将其区块传播到足够数量的质押节点,以确保其区块在其指定时隙内被接受,从而有效地审查 B。由于 Turbine 优先考虑信息,因此作为具有高质押权重的验证者,这会更快。按验证者权益权重流动。

这种攻击场景是可行的,但成功审查的窗口是有限的。它要求攻击节点拥有大量的计算资源(用于 SHA-256 哈希)和大量的权益,因为它可以生成的块数量与其权益成正比。

除了需要比节点 A 更快地到达网络之外,C 还必须高速生成哈希。这种攻击主要针对这样的场景:在槽位n具有指定领导者的验证者旨在审查具有先前领导者槽位(在n之前)的验证者。该验证者可实现的审查程度取决于其权益,因为其创建领导者位置的能力与其持有的权益数量直接相关。

PoH 机制还确保以一致的速率生产区块。由于 PoH 序列可以由每个验证器独立验证,因此不需要外部时间同步。例如,以太坊在每个区块中使用网络时间协议(NTP)来达成共识。在 Solana 上,每个验证器独立验证每个块是否是在正确的时隙内生成的,无需使用外部协议。

Tower BFT(Solana 的共识机制)

Tower BFT 是 Solana 的共识机制,在碎片(部分区块)传播到其他验证器后运行:

如前所述,Solana 与历史证明一起运行 Tower BFT。 Tower BFT 是一种类似 pBFT 的共识算法,旨在利用历史证明的同步时钟计算。这在整个网络上建立了一个通用时钟,使其能够有效地绕过分配给反应缓慢或没有响应的领导者的时隙。此过程消除了网络对每个时隙进行同步共识轮的需要,并实现了连续的块生产,因为验证者不必在构建下一个块之前等待先前的块到达。

另一个误解是,Solana 的共识机制目前实行的是程序性削减。虽然削减是在路线图上,但网络目前在安全违规后停止,依赖社会共识来根据需要削减。

Solana 的共识机制对不同节点提供了不同程度的影响力。网络中的投票并不相等,而是根据每个节点的权益进行加权,在权益加权 QoSTurbine的相同原理下运行。在其他条件相同的情况下,拥有较大权益的节点比拥有较小权益的节点对确定规范共识具有更大的影响力。

例如,在一个有 4 个节点总共持有 100 个权益的网络中,分布和影响可能如下:

  • 节点 A 有 10 单位权益。
  • 节点 B 有 20 个权益单位。
  • 节点 C 有 30 单位的权益。
  • 节点 D 有 40 个权益单位。
忍系统

在此设置中,每组不诚实节点的能力各不相同。像节点 D 这样的单个节点,由于其权益较大,尽管只占节点总数的 25%,但仍可能导致网络停止运行。同样,像节点 C 和 D 这样的组合可能会批准不正确的交易,仅代表 50% 的节点,但持有足够的股份来影响结果。

通过不诚实、受损或被阻止的节点可以达到停止网络的三分之一阈值。验证错误交易的三分之二阈值;然而,这需要积极共谋,不能仅仅依靠阻止诚实节点。因此,实现后者更具挑战性。这是因为它涉及破坏或损害节点以积极参与不诚实的计划,而不是阻止诚实的计划。

槽位内的上下文

在 Solana 上,时隙领导者被分配四个连续的时隙,总共持续约 1.6 秒(4 个块 x 每个块 400 毫秒)。领导者在每个 epoch 开始时选出(432,000 个槽位或约 2-3 天)。领导者计划是根据验证者的权益权重随机选择的。

领导者被分配为每个分配的插槽构建和提议一个新块(不存在以太坊世界中存在的提议者与构建者分离)。其他验证者通过将分叉选择规则应用于 Solana 网络头部的本地视图,通过投票交易来证明给定区块的有效性。

领导者必须在给定的 PoH 刻度范围内发布区块才能使该区块有效;未在此范围内发布的块被视为已跳过。

以下面的领导者日程安排为例,有四个参与者(A、B、C、D),其中 D 试图打乱顺序。如果 D 试图在 C 的回合期间进行干预,它必须创建一系列 PoH 刻度,有效地跳过 C 的区块,从而形成一条如下所示的链:

A - B - [C 缺失] - D。

在 C 的块丢失的情况下,诚实的 D 在开始自己的时隙之前必须生成一个覆盖 C 时隙的整个持续时间的 PoH 序列。这将使 D 的块看起来有效,因为它在分配给 C 的时隙的时间之后跟随 B 的块。

当 D 为 C 的时隙生成 PoH 序列时,C 通常会流式传输其块,并通过适当的 PoH 序列连接到 B。这会导致两种可能的结果:

  • 如果 D 的 PoH 计算不比 C 快:由于 C 大约在 D 开始广播自己的区块的同时完成其区块,因此网络在看到 C 的区块后,将拒绝 D 的区块。
  • 如果 D 计算 PoH 的速度比 C 快:D 在 C 完成自己的区块之前开始广播其区块。即便如此,D 需要比 C 快得多才能显着影响序列,考虑到验证器用于 SHA-256 计算的 CPU 的高速性和(相对)相似的 CPU 能力上限,这是不太可能的。

在这两种情况下,D 成功取代 C 的机会都很小。此外,如果 D 尝试替换 C 失败,它就会失去在自己的槽中发出块的机会。在 B 之后立即发出一个区块,然后在 C 之后尝试另一个区块构成违规(为 D 的位置创建两个区块),这将导致可削减的进攻。每次失败的尝试都会导致 D 错失产生区块的机会,并表明 D 不太可能采取这种策略。 

从网络的角度来看,D 的意图是不确定的。即使不是不可能,也很难区分 D 只是没有看到 C 的区块(无意审查 C)还是 D 有审查 B 的意图。因此,这不容易被网络检测到,也不会受到网络的惩罚。

投票交易

Solana 的共识机制依靠投票交易来达成共识。投票交易存在于一个区块内,但具有优先级,以免被常规交易淹没。目前,给定区块内的大多数交易都是投票交易:

沙丘

然而,情况可能并不总是如此,因为给定区块内的投票交易百分比代表了活动与参与共识的验证者数量之间的比率。将来,投票交易可能只占给定区块的少数。

投票交易是达成共识的必要条件——它们不是人为夸大 TPS 指标的无关交易。如果投票仅通过八卦(非正式的点对点通信)传播,则可能会导致验证者对塔(投票)状态的看法出现差异。这种差异可能会导致验证者对哪个分叉更有可能是正确的观点有不同的看法,从而导致潜在的分歧,因为验证者根据不完整或不一致的信息做出贪婪的选择。连续的区块生产需要持续的投票,尤其是在之前的区块仍在确认中的情况下。这需要对塔的状态有可靠且一致的视图。

与用户发起的常规交易一样,投票交易也必须支付基础费用(0.000005 SOL)。这是由验证者身份支付的,验证者身份必须驻留在热钱包中以进行持续签名,而投票账户则用于账户查找和委托。

每张投票都由验证者签名,包括验证者的公钥和他们投票支持的区块的哈希值。

当验证器在同一槽位接收到多个块时,它会跟踪所有可能的分叉,直到确定“最佳”分叉为止。验证者在本地运行相关的状态转换函数(这在异步执行下会发生变化),然后在重播后对新块进行投票。验证者通过链上投票交易表达对给定分叉的投票。

在每笔投票交易中,验证者都会发布带有锁定期的投票。这种锁定充当了一种承诺机制,将验证者绑定到他们选择的分叉上,并为其决策施加机会成本。如今,锁定不是由运行时强制执行的,而是通过社会共识强制执行的——持续违反投票锁定的行为很可能会被手动削减。在不久的将来,可能会增加对违反锁定期的程序性削减,因为没有获得投票积分并不足以提供足够的抑制作用。

验证者还为先前投票和根/最终确定块之间的每个祖先块签署了块的哈希值。这是检测重复块所必需的。如果领导者向每个节点发送不同的块,则每个节点最终都会对同一插槽的不同前任进行投票。然而,在由 65,000 个插槽组成的 epoch 中,在最极端的情况下,每个投票的大小可能达到 2 MB。这是因为 65,000 个槽中的每个槽可能需要 32 字节的哈希值。这将在以后的文章中进行更多探讨。

验证者管理一个“投票塔”,这是一个连续的投票堆栈,其中每张投票都会强化一个分叉,并且是塔中其上方分叉的祖先。向该塔添加新投票会导致堆栈中所有先前投票的锁定加倍,从而逐渐增加早期决策的承诺和锁定期。投票过程本身受到多项检查的控制:验证者必须遵守之前投票的锁定期;他们需要确保网络的很大一部分(通常是三分之二)也致力于同一个分叉;在切换到新的分叉之前,需要对替代分叉进行绝大多数(超过 38%)的投票。

对于插槽n的区块,领导者外部的投票早在n+1时就开始出现在链上。没有投票小组委员会——所有验证者都有资格对所有区块进行投票。这些投票首先出现在 Turbine 树中距离其他验证者较近(一跳之外)的区块中。插槽n的投票最多可以出现在插槽n+512处,因为验证者可以对“插槽哈希”仍然已知的任何插槽进行投票,并且插槽哈希会保留 512 个插槽 (h/t Shinobi )。对于时隙n,在某个块上没有预定的上限;然而,建立在至少 32 个连续区块上的根槽将不再接受投票并最终确定。

投票方案中有一些怪癖,运行时并未完全执行。例如,验证者目前被激励只投票给“根”槽(忽略链的尖端),并且这不会受到共识的惩罚。这使得验证者能够持续获得分叉的投票积分,并且极有可能成为规范,同时不会为实际共识操作的链端做出贡献。这种情况现在正在发生,验证器的平均“投票延迟”超过 68 个槽。一项名为“及时投票积分”的拟议功能旨在减轻这种激励错位。

Solana 的分叉选择规则

与以太坊(LMD GhostCasper FFG)一样,Solana 有两个确认规则 - 一个用于短期分叉选择,另一个用于完全 PoS 共识以实现最终确定。这使得用户和客户能够在不同的确认规则下进行定制的用户体验选择。这体现在两个承诺级别:“已确认”和“最终确定”。

“已确认”区块(也称为乐观确认)需要至少 2/3 的验证者通过特定区块上的投票交易进行投票。为了可能违反最终性,必须削减约 4.6% 的当前权益。“最终”区块需要对至少 32 个后续插槽进行投票或获得绝对多数 (>2/3) 的投票。恶意攻击需要削减超过 1/3 的权益。这比“已确认”区块需要更多的时间,因为它必须等待之前的根区块 32 个区块才能完全确定。

分叉选择规则允许网络就链头达成共识。 Solana Labs 实现主要通过大约 4600 行的 Rust 文件(恰当地命名为 heaviest_subtree_fork_choice.rs)来处理分叉选择。这为验证者提供了必要的逻辑来确定哪个分叉最有可能成为规范。更详细的代码分解将在以后的文章中探讨,但分叉选择的高级机制的工作原理如下:

1. 使用`add_votes()`添加投票:

这将迭代新的投票,如果需要,从旧的投票槽中减去投票账户的赌注,并将赌注添加到新的投票槽中。

2. 调用generate_update_operations()创建一批fork更新操作:

这:

  • 从旧分叉中减去权益
  • 向新分叉添加权益
  • 聚合将每个叉子固定到根部

3.process_update_operations():

  • 如果需要,调用 mark_fork_valid()/invalid()
  • 在每个分叉上调用aggregate_slot()来更新分叉权重
  • 调用 add_slot_stake()/subtract_slot_stake() 更新赌注

4.aggregate_slot():

  • 总结所有子插槽的赌注
  • 按桩重量查找最重的子叉
  • 按高度查找最深的子叉
  • 向上传播这些值以找到该槽中最重/最深的叉子

5. select_forks():

  • 返回用于区块生产的最重的整体分叉
  • 返回最后一次投票中最重的分叉

根据投票添加/减少权益,聚合自下而上重新计算每个分叉的权重,并且选择具有最重权重子树的根作为构建和投票的最佳分叉。

纳入的可能性

在达到相应确认规则的必要要求后,交易包含的可能性在交易的生命周期中发生变化。

虽然时隙可以“跳过”,例如当领导者离线时,该交易要么落在未来的区块中,要么根本不落在。

这里的时段是粗略的近似值,但试图让读者了解投票何时会累积。此外,这对于每个块来说都是唯一的(块可能以不同的长度到达“已确认”或“最终确定”确认级别)。恢复风险在交易的整个生命周期中单调降低。即使在一个区块被最终确定(扎根)之后,理论上它也可以通过社会共识进行分叉,将其从“规范”链中删除。

未来的研究领域和结论

这篇文章重点介绍了 Tower BFT、Solana 共识机制以及其他相关机制的内部运作。我们在 Solana 的背景下探索了历史证明、投票交易和分叉选择的作用,以创建用于交易排序的规范分叉。

围绕这些机制还有许多其他研究和形式化方向有待探索,例如:

  • 以太坊研究人员量化了玩计时游戏的价值,即区块生产者等到时段结束才提交区块。从数量上看,这些游戏在 Solana 上的情况如何?它们现在是否正在发生?
  • 异步执行已列入 2024 年主要协议变更的路线图。对于仅对现有分叉进行投票而不是在本地计算状态转换的节点,潜在的攻击向量和相关安全注意事项是什么?
  • 如今,极少数验证者 (<20%) 对 Solana Labs 或 Jito-Solana 客户端进行修改。他们正在更改哪些不受运行时或确认规则约束的阈值?
  • 实施程序化削减。目前,除了社会共识之外,几乎没有什么经济动机可以促使人们在不进行大幅削减的情况下不执行高利润的交易策略。
  • 当运行两个完全不同的客户端时(即使它们尝试由相同的确认规则定义),Solana 共识机制的性能如何?
  • 投票小组委员会的预期绩效/状态减少好处是什么?
  • 从乐观确认的时隙(而不是已最终确定的时隙)重新启动时,潜在的攻击向量是什么?像交易所这样的第三方链下解决方案应该如何考虑使用乐观确认或完全确定性?
  • 削减的资金是否应该用作安全违规交易的保险?以 SOL 计价的保险池的机制和激励措施是什么?

在这篇文章中,我们探讨了 Solana 通过其共识机制实现的一些机制和阈值,以及它与给定时段内领导者的典型区块生产的关系。最近 Solana 上活动的增加为这些机制提供了现实世界的活跃性和安全性测试,并增加了恶意攻击的动机。

💡
原文链接:Consensus on Solana
本文由SlerfTools翻译,转载请注明出处。

SlerfTools专为Solana设计的工具箱,致力于简化区块链操作,提供无编程全可视化界面,使发币管理流动性无代码创建Dapp等复杂过程变得安全简单。