文章目录

  • 摘要
  • 1 介绍
  • 2 相关工作
  • 3 系统和威胁模型
    • A. 静态 BFT
    • B. 动态 BFT
    • C. 动态 BFT 的组成员资格更改
    • D. 假设
    • E. 属性规范
    • F 定义的变体
    • G. 与先前规范的比较
    • 4 动态 BFT 的挑战
  • 5 我们的协议概述
  • 6 DYNO 协议
  • 8 实施与评估
  • 9 结论

摘要

本文研究了动态 BFT,其中副本可以动态地加入和离开系统,这是当今越来越需要的一种原语。我们为动态 BFT 协议提供形式化处理,赋予它们灵活的语法和各种安全定义。

我们展示了将静态 BFT 扩展到动态 BFT 的挑战。然后我们设计并实现了部分同步模型下的高效动态 BFT 协议 Dyno。我们展示了 Dyno 可以无缝处理成员资格更改,而不会导致性能下降。

1 介绍

拜占庭容错状态机复制 (BFT) 传统上被称为构建关键任务系统的原语。如今,BFT 获得了突出地位,因为它被视为区块链的核心构建块:BFT 被称为许可区块链的模型 [54],其中成员资格是静态的,分类帐(副本)知道彼此的身份,但可能不信任彼此。BFT 也越来越多地以各种方式在无许可区块链中使用(这些协议也称为混合区块链 [26、27、56])。本文研究了具有动态成员资格的 BFT,或简称为动态 BFT,其中副本可以动态地加入和离开系统。动态 BFT 是一种传统上可能被视为从系统角度实现理想功能的原语,如今越来越需要作为无数区块链和安全应用程序的核心构建块。

正常恢复和重新配置。与任何静态分布式系统一样,静态 BFT 系统具有实际限制 [46]:例如,如果其中一个副本崩溃、需要维护或被认为有故障,则系统始终可用的概率会降低。恢复有故障的节点可能并不总是可行的,因为恢复节点可能需要时间,更重要的是,恢复可能并不总是可行的(例如,由于永久性硬件故障)。在这种情况下,更好的方法是创建一个新的副本来替换有故障的副本。

主动恢复。动态 BFT 可用于构建具有长期主动恢复功能的强大 BFT 系统。在许多先前的工作中已经研究了主动安全 BFT 系统的问题 [10, 51]。这些系统使用受信任的硬件来定期重启节点,希望它能驱逐对手。然而,对手(例如病毒)很可能会留在系统中,从而使这些努力毫无用处。然而,新鲜的副本没有这样的问题。因此,动态 BFT 为传统的主动恢复方法提供了一种替代方案,可以说是更好的解决方案。

联盟区块链。 BFT 的静态成员属性可能会极大地限制联盟区块链的适用性。区块链实体可以选择(或被迫)离开联盟,而新实体可以加入联盟。例如,现在更名为 Diem 的 Libra 已经面临这样的情况,在 BFT 达成协议后,动态成员资格由其智能合约管理。

混合区块链。使用 BFT 的混合区块链需要选择固定数量的 BFT 副本,称为委员会,很容易成为坐鸭。能够在保持系统正常运行的同时更换委员会是至关重要的。

A. 技术挑战和我们的贡献

动态 BFT 的正式处理。尽管需要动态 BFT,但到目前为止,还没有为动态 BFT 提供严格的形式化。虽然在崩溃故障模型 [11, 46] 和拜占庭故障模型 [20, 39, 40] 中定义了一些相关的原语,但对于具有可证明安全性的动态 BFT 缺乏良好的抽象。从现代的角度来看动态 BFT——在“区块链时代”——早就应该了。本文填补了这一空白,并提供了对动态 BFT 的正式处理。我们的规范涵盖了将 BFT 与成员服务分开的语法,这是一种源自 Schipper 为崩溃故障模型 [46] 所做的工作的方法。然而,我们对安全性的定义却发生了相当不同的转变,通过处理模糊不清的常规请求和成员请求。更重要的是,我们的处理具有以下两个特征:

• 在将安全定义提升到动态 BFT 时,我们定义了一个新属性(一致交付),我们认为该属性对动态 BFT 的安全性至关重要。我们展示了一些自然和替代交付属性无法正常工作。

• 我们的处理包括针对动态BFT 的不同“正确”概念的许多安全定义,每一个都有意义,从我们可以想象的最弱到最强。

识别动态 BFT 的(新)问题。尽管动态成员的长期工作(主要在崩溃容错系统中),我们发现了一些(新的)问题:

• 由于动态仲裁引起的问题(在第 IV 节中指定)。在动态 BFT 中,成员资格的变化会导致 quorum 大小的变化,从而产生各种活跃度问题。

• 由于视图更改(在第 IV 节中指定)引起的问题。在具有视图变化的动态 BFT(即领导者选举)中,也存在各种问题。例如,下一个领导者可能无法收集到足够多的视图更改消息,甚至可能不知道视图更改正在发生。更糟糕的是,多个副本可能会声称它们是同一视图中的领导者。

• 由于消息传递引起的问题(在第 III-E 节中指定)。

静态分布式系统有一个消息传递假设,即在正确的副本之间传输的消息最终会被传递。这个假设不适用于动态设置,因为一些正确的副本虽然在发送消息时是正确的,但可能会在将来的某些配置中离开系统。我们发现,即使是安全分布式计算社区中的一些经典协议(例如,[46])也只是假设跨配置的消息传递,并且这些协议的证明实际上是有缺陷的。

配置发现协议。我们的协议依赖于配置发现子协议,客户端和新副本在其中获得系统的成员资格。配置发现协议不仅从功能角度至关重要,而且对于我们动态 BFT 协议的正确性也很重要。我们提供了一种这样的协议,它使用显式成员发现。我们还在附录中介绍了两个使用隐式成员发现的替代协议。

结构、假设及其呈现。我们考虑两个不同的假设:标准仲裁假设(假设每个配置的最佳弹性)和 G 正确假设(假设一部分正确的副本永远不会离开系统)。基于每个假设,我们提供满足我们提出的不同安全定义的协议。我们首先介绍论文中的主要协议 Dyno。然后我们介绍 Dyno 的变体。我们正式证明了所有协议的安全性。

我们的目标之一是无缝处理会员变更。 Dyno 保留了底层 BFT 协议的全部效率,并且可以独立于视图更改来处理成员请求。然而,Dyno 确实对正常情况下的操作和底层 BFT 协议的视图更改机制进行了重大修改,同时没有增加性能开销。我们展示了 Dyno 在各种加入和离开场景下的高效和鲁棒性。

2 相关工作

BFT。作为一种容忍任意故障的通用方法,BFT 可以分为同步 BFT [1]、部分同步 BFT [10、14、15、50] 和异步 BFT [16、17、33]。在这项工作中,我们专注于部分同步 BFT。主分区与可分区成员服务。成员服务可以是主分区或可分区的 [11]。在主分区服务中,所有副本的视图都是完全有序的。在可分区视图中,视图是部分排序的,即多个不相交的视图可能同时存在。本文只研究主分区模型。

动态群组交流。组成员资格问题和视图同步通信问题首先由 Birman 和 Joseph [7] 讨论。组成员抽象提供了活动成员的动态但一致的视图。视图同步通信 [7, 47] 扩展组成员资格以支持视图成员内的可靠广播。扩展虚拟同步[37]扩展了虚拟同步,确保消息传递和所有副本的配置更改之间的关系保持一致。 Spread [5] 和 Secure Spread [4] 在碰撞故障模型中包含虚拟同步和扩展虚拟同步。 Secure Spread 通过身份验证、完整性、访问控制和机密性增强了 Spread。

Chockler 等人 [11] 对动态组通信系统进行了全面调查:首先定义组成员服务(用于添加和删除进程),而在第二步中指定通信原语(例如,可靠广播、原子广播) .在这些系统中,组成员服务是各种通信栈的基础层。相比之下,Schipper 的规范首先描述了通信原语,然后是成员更改,并允许所有成员更改来自对成员请求的显式调用 [46]。例如,为原子广播定义的原语称为动态原子广播,或简称为原子多播。 Schipper 认为,这种选择会导致更“自然”和更简单的规范。 Schiper [46] 还表明,他的规范在活性属性方面与 [11] 中调查的规范略有不同。

Guerraoui 等人最近提出了动态拜占庭可靠广播 (DBRB),其中副本可以动态地加入和离开系统 [20]。从定义的角度来看,DBRB 解决了与我们的(共识)相当不同的问题(广播),并专注于异步设置。从技术角度来看,DBRB 允许最终收敛到同一视图的不同视图路径。

Rampart [39] 和 SecureRing [25] 在拜占庭故障模型中实现状态机复制,并依靠拜占庭故障检测器来实现活性。

重新配置原子存储。动态原子读/写 (R/W) 存储可以是基于共识的 [19, 36, 44] 和无共识的。 Aguilera 等人在 DynaStore [2] 中证明,可以在异步设置中解决动态原子存储,而无需使用共识(或随机化)。

从 DynaStore 开始,已经提出了许多无共识的动态原子存储结构(例如,[3,18,23])。 Kuznetsov 和 Tonkikh 提出了具有拜占庭故障的异步原子存储 [28]。

SMR 的重新配置。 Lamport 在 Paxos 中建议将成员资格更改作为系统状态的一部分来管理 [30]。在成员请求达成协议后,副本等待 α 批请求执行,然后再安装新配置。 Lorch 等人提出了 SMART [34],其中系统的重新配置是通过创建一组额外的副本来管理的。两组副本运行并行 Paxos 实例,直到系统状态完全迁移到新组。对于主/备份复制,在崩溃故障设置中研究了重新配置的解决方案 [22, 49]。 Raft [38] 提出了一种用于重新配置的两阶段方法。第一阶段是一个过渡配置,称为联合共识。为了过渡到新的配置,两种配置中的副本都参与了联合共识,而共识是独立维护的。这种方法允许旧配置中的副本继续为客户端提供服务,并允许新配置中的副本赶上历史。只有在共同共识被提交后,系统才会转移到新的配置。 BFT-SMaRt 是一个支持重新配置的 BFT 系统 [50],其中成员资格请求被视为一种特殊类型的客户端请求并将所有请求排序在一起。我们的系统也使用这种策略。但是在不进一步修改协议的情况下单独这样做,可能会产生活性问题(零吞吐量),正如我们将在第 2 节中理论上展示的任何基于领导者的 BFT 协议一样。 并在第八节中对 BFT-SMaRt 进行了实验展示。

使用辅助主机重新配置。系统的重新配置(存储、SMR 或主备份复制)可以由辅助主服务器管理 [31、35、43]。例如,Vertical Paxos 显示(在崩溃故障设置中)使用 f + 1 个副本来构建管理 SMR 配置的配置主机就足够了。会员管理。动态 BFT 与成员管理形成鲜明对比,成员管理是一种管理分布式系统中节点的服务 [12、13、24、32、41、42、45、52]。该服务可以从独立的 SMR(例如,Apache Zookeeper [21]、Google Chubby [9])或通过成员的自我发现(例如,SWIM [13])构建。相比之下,动态 BFT 是一个根本不同的原语,可以被视为可自配置的 SMR。耐用性。持久性是在状态机复制系统崩溃或关闭时幸存下来并使正在恢复的副本保持最新的能力。该属性之前已在静态组的上下文中考虑 [6, 10],而我们从不同的角度考虑动态组的类似属性。

3 系统和威胁模型

A. 静态 BFT

传统的拜占庭容错 (BFT) 协议具有一组恒定的副本,其中一部分可能会任意失败(拜占庭故障)。在 BFT 中,副本传递请求,每个请求都由客户端提交。一个请求可以包括一个或多个操作。副本执行请求中的操作并向相应的客户端发送回复。客户端根据回复消息计算最终响应。

在具有 n 个副本的系统中,BFT 可以容忍 f ≤ b n−1 3 c 拜占庭式故障,这是最优的。 BFT 的正确性规定如下:

• 协议:如果一个正确的副本交付请求 m,那么每个正确的副本最终都会交付 m。

• 总顺序:如果一个正确的副本在传递m0 之前传递了一条消息m,那么另一个正确的副本只有在它传递了m 之后才传递一条消息m0。

• 活跃度:如果正确的客户端提交请求m,那么正确的副本最终会交付m。

• 完整性:没有正确的副本多次传递相同的消息m;如果一个正确的副本传递了一条消息 m 并且提交 m 的客户端是正确的,那么 m 之前是由客户端提交的。

总秩序和完整性是安全属性,而其他两个是活力属性。协议和活跃度一起意味着客户端最终会收到有效的响应。BFT 形式化可以显式地将序列号分配给客户端请求,并要求正确的副本根据顺序执行请求。

一般来说,部分同步的 BFT 协议依赖于视图更改(以领导者轮换的形式)来获得活跃性,因此在视图中进行。当领导者出现故障时(例如,PBFT [10])或根据某些策略(例如,Spinning [53],HotStuff [55])定期触发视图更改。然而,异步 BFT 协议没有视图更改机制。

B. 动态 BFT

我们考虑一个 BFT 系统,其副本取自有限集 Π = {p1, p2, ····}(也称为全域)。每个副本 pi ∈ Π 都有一个公钥/私钥对(pki,ski),为了简单起见,我们假设它的公钥被集合中的所有进程都知道,并用作 pi 的唯一标识符。动态 BFT 组由 Π 的一个子集组成。 BFT 组中的副本是该组的成员。我们使用配置的概念来表示 BFT 组的连续成员资格。令 Mc 是配置的成员资格(副本组),编号为整数 c,初始化为 0(初始配置)。副本通过配置安装更改其配置。我们引入以下定义: 定义 III.1。如果 p ∈ Mc,则副本 p 在配置 c 中。

定义 III.2。如果 p 已经安装了配置 c 但在 c 之后没有安装另一个配置,那么 p 的(当前)配置是 c。

定义 III.3。系统的最新配置是 c,如果至少有一个正确的副本安装了 c,并且没有正确的副本安装 c0,其中 c0 > c。

定义 III.4。一个副本 p 在配置 c 中是正确的,如果 p 安装了配置 c,并且 p 在 c 中是正确的(没有错误)。(注 p 在配置 c + 1 中可能有错,也可能没有错,但在 c 中没有错。)

定义 III.5。一个副本 p 是 c 正确的,如果 1) p 在配置 c 中是正确的,并且 2) 在 c 中没有正确的副本安装任何大于 c 的配置,或者 c 中的某些正确的副本在 c 和 p ∈ Mc 之后安装配置 c + 1 +1。 (如果 c 是 c 中所有正确副本的最新配置,则 p 是 c 正确的,或者 p 在 c 的下一个配置中。)

定义 III.6。如果 p ∈ Mc 并且 p 不是 c 正确的,则副本 p 是 c 错误的。 (副本 p 在配置 c 中可能是正确的,但 c 错误,例如,p 可能会在配置 c 之后但在配置 c + 1 之前从组中删除,并且永远不会在配置 c + 1 中。)

定义 III.7。副本 p 是 g 正确的,如果 1) p 是 0 正确的(其中 0 是系统的初始配置),并且 2) 不存在 c > 0 使得 p 不是 c 正确的。 (一个 g 正确的副本在其所有配置中都是正确的。)

定义 III.8。对于 c ≥ 0,副本 p 是 gc 正确的,如果 1) p 是 c 正确的,并且 2) 不存在 c0 使得 c0 > c 并且 p 不是 c0 正确的。 (gc 正确的副本在配置 c0 ≥ c 中是正确的。g0 正确的副本是 g 正确的。)

我们的配置概念(处理成员资格)独立于视图(在部分同步 BFT 的视图变化的意义上) .动态部分同步 BFT 可以同时具有配置的概念和视图的概念。请注意,静态 BFT 组是动态 BFT 模型的特例,具有固定数量的副本和单一配置。

C. 动态 BFT 的组成员资格更改

我们考虑两个可以修改成员资格的成员资格请求:将新副本添加到组的加入请求和从组中删除副本的离开请求。成员资格请求不同于不会更改成员资格的常规 BFT 请求(写入和读取请求)。我们不失一般性假设会员请求是修改会员的唯一方法。我们对谁可以发出会员请求没有任何限制。它们可以被任何授权的客户端(例如,加入或离开系统的副本、系统管理员、受信任的 CA、高级程序)调用。我们也不会讨论为什么要包含或排除副本,而只会介绍我们是如何做到的。在实践中,如第二节中的示例所示。我,在就谁将加入或离开小组以及为什么以及何时需要更改小组成员资格达成一致时通常没有歧义。

在配置 c 中的副本 pj 执行对 pi 的加入请求后,pj 的成员资格变为 Mc ∪ {pi}(并且相应地 pj 安装新配置)。在配置 c 中的副本 pj 执行对 pi 的离开请求时,其成员资格变为 Mc – {pi}。

对于 i < j 的两个配置成员 Mi 和 Mj,我们使用 Mj/Mi 表示存在于 Mj 中但不存在于 Mi 中的副本。例如,如果 Mi = {p2, p3, p4} 且 Mj = {p3, p4, p5, p6},则 Mj/Mi = {p5, p6}。设 nc 和 tc 分别是配置 c 中的副本数和 c-faulty 副本数。在配置 c 中,我们有 nc = |Mc|。

D. 假设

我们现在指定系统假设。

标准法定人数假设。我们假设这项工作中的最佳弹性模型。即,系统在配置 c 中可以容忍的最大故障数为 fc ≤ b nc-1 3 c。一个法定人数的副本至少由 d nc+fc+1 2 e 个副本组成。我们使用 Qc 来表示配置 c 中的仲裁大小。这是一个标准的和最优的假设。除非另有说明,我们考虑默认假设。

G-正确假设。我们还考虑了一个更强的假设,这不是必需的,但在某些情况下可能会产生一些(很多)更简单的协议。对于所有 c ≥ 0,让 F = max({fc}) + 1。G 正确假设要求至少存在 F 个在所有配置中都是正确的副本。换句话说,“足够”正确的副本永远不会离开系统。

此外,我们对动态成员资格做了两个标准假设(用于所有其他此类场景):首先,加入或离开系统的副本数量是有界的(一个自然的假设是从配置 c 到 c + 1,至少Qc c-正确的副本仍在 c+ 1) 中;其次,初始配置是宇宙 Π 中的所有副本都知道的。

E. 属性规范

在我们的形式化中,成员资格请求和常规 BFT 请求可以统称为请求。我们以与常规请求相同的方式处理会员请求。因此,在下面指定动态 BFT 的正确性时,请求 m 可以是会员请求或常规请求。特别是,加入或离开请求的调用只是对特殊客户端请求的调用。加入(或离开)请求的执行对应于请求的交付和通过请求中的添加(或删除)操作安装新配置。

• 协议:如果配置c 中的正确副本交付请求m,则配置c 中的每个正确副本最终都会交付m。

• 相同的配置交付:如果一个正确的副本 pi (resp.pj) 在配置 ci (resp. cj) 中传递 m,然后 ci = cj。

• 总顺序:如果配置c 中的一个正确副本在传递m0 之前传递了一条消息m,那么配置c 中的另一个正确副本只有在它传递了m 之后才传递一条消息m0。

• 活跃性:如果一个正确的客户端提交请求m,那么最终某个配置c 中的正确副本会交付m。

• 完整性:没有正确的副本多次传递相同的消息m;如果一个正确的副本在某个配置中传递了一条消息 m 并且提交 m 的客户端是正确的,那么 m 之前是由客户端提交的。

相同的配置交付属性是会员服务的自然要求,并且是先前定义的(例如,[11, 46])。 BFT 系统可以将递增的序列号分配给不同的客户端请求以订购交易。在这样的语法下,我们可以统一相同的配置交付属性和总订单属性:

• 增强的总订单:如果配置 c 中的一个正确副本交付具有序列号的请求 m,而配置 c0 中的另一个正确副本交付请求 m0具有相同的序列号,则 m = m0 和 c = c0。

一个实用、持久的 BFT 系统依赖于状态传输协议来更新正在恢复的副本或落后于其对等方的副本 [6, 10]。在动态 BFT 中,加入组的新副本也需要状态转移机制来赶上其他副本。新的副本或正在恢复的副本在获得系统状态之前可能被认为是有故障的。

一些(但不是全部)现有的 BFT 协议是在没有明确协议属性的情况下指定的,但这些协议可以轻松满足它。然而,动态 BFT 并非如此,因为达成一致并非易事。因此,我们在所有动态 BFT 结构中都明确考虑了一致性。

需要额外的属性。讨论了动态 BFT 属性自然地反映了静态 BFT 的属性,现在让我们激发对附加属性的需求。在静态 BFT 设置中,协议、总订单和我们的活跃度定义意味着正确的客户端将收到对其请求的回复。更具体地说,对于客户端请求 m,协议和活跃度保证所有正确的副本最终都会交付 m。由于有 n ≥ 3f + 1 个副本,客户端可以通过多数投票方法安全地传递响应,在收到 f +1 个匹配的回复后计算响应。事实上,静态 BFT 中活跃度的典型定义已经要求客户端最终会收到对其请求的回复,因此协议属性不是“需要的”。

经典定义不会立即适用于动态组。首先,由于不知道系统的成员身份或某些配置中的副本总数,客户端可能永远无法确定何时将回复传递给请求。其次,即使客户端知道成员资格信息,在处理消息时成员资格也可能已经改变。这两个因素激发了定义附加属性的需要。

尝试1。可以规避成员资格问题的“自然”增强活性可以定义如下: • 如果正确的客户端提交请求 m,则客户端最终会从副本传递响应。

不幸的是,该定义没有在动态 BFT 设置中捕获任何有意义的正确性保证。可以很容易地设计一个满足上述定义的简单协议,其中正确的客户端接收到不相关的响应。

尝试2。另一种选择是定义以下属性: • 成员身份发现:提交了 m 的正确客户端最终可以了解为其交付 m 的配置的成员身份。

成员发现属性要求客户端最终知道传递其消息的配置的成员信息(副本的身份)。它没有说明客户端是否可以或需要学习最新的(当前)成员,这在异步环境中具有挑战性(即使我们假设活动的部分同步模型)。实际上,即使客户获得了最新的会员信息,会员也可能在客户提交请求时或在处理请求时已更改。成员发现属性似乎涵盖了我们可以设想的许多场景,无论客户端是通过独立的子协议(在处理其请求之前或之后)获取成员信息,还是在协议运行时获取成员信息。

直观地说,成员发现属性,连同协议、活跃度和总顺序,将意味着客户端知道何时从相同的配置中收到足够的匹配回复,并且可以基于多数投票安全地传递响应。更准确地说,对于客户端请求 m,协议和活跃度保证了某些配置中的所有正确副本最终将传递客户端消息 m;总订单保证 m 必须在相同的配置中交付,例如 c;知道传递 m 的配置 c 的精确成员资格和配置 c 中的成员总数,客户端可以通过传统的多数投票方法安全地传递响应,在接收到配置 c 中的 fc + 1 个匹配回复后计算响应.

不幸的是,上述论点有一个重大缺陷。即使客户端了解了请求 m 为其传递的配置 c 的信息,即使我们假设通道完美,配置 c 中正确副本发送的回复消息也可能无法到达客户端。这是因为完美通道仅在发送者始终正确时才能保证消息传递,但发送者可能会在未来的某些配置中离开系统;事实上,由于网络异步,来自某个副本 pi 的回复消息可能在 pi 离开系统之前无法到达客户端。

我们评论说,虽然我们不采用成员发现的定义,但我们的构建确实是由这个想法驱动的。

最后的尝试。最后,我们定义以下属性: • 一致交付:提交 m 的正确客户端将交付正确响应,该响应与交付 m 的某些配置中的状态一致。

该物业有点不合常规,既包括活力又包括安全。然而,可以很容易地将属性划分为活性属性(正确的客户端最终会收到对其请求的回复)和安全属性(正确客户端传递的请求与传递请求的某些配置的状态一致) )。

为了正式定义一致的交付,我们使用状态机复制符号 [29, 48]。确定性状态机由以下值元组组成:一组状态、一组请求、一组回复、一个将请求和状态作为输入并输出更新状态的转换函数,以及一个输出函数将请求和状态作为输入并输出回复。请求由客户提交,回复被发送给客户。状态对系统状态进行编码(包括配置和保留的各种变量)。

如果回复 re 是由某个请求的输出函数和状态 st 生成的,则我们说回复 re 与正确状态机的状态 st 一致。当我们考虑确定性状态机时,并且由于所有正确的副本都实现了总顺序,相同的请求和相同的状态决定了正确副本的相同回复。


表 I:协议定义和结构概述。定义变体也可以应用于其他动态 BFT 属性,但它们不会(似乎)导致有趣的效率权衡。


请注意,正确的副本可能会在某些配置中生成回复(和相应的状态),但由于在此配置中某些回复可能永远不会到达客户端,因此客户端不会在此配置中传递回复。 (回想一下,在回复到达客户端之前,正确的副本可能已经离开系统。)但是,我们确实希望确保客户端最终会提供与系统维护的状态一致的回复。

另请注意,在传统的静态机器复制设置中,始终以相同的配置传递回复,因为有足够的正确副本。在这种情况下,不必定义这种额外的“一致交付”。

F 定义的变体

第 2 节中的定义有许多变体。 III-E。例如,为了达成一致,if 子句和 main 子句都讨论“c 中的正确副本”。我们在表 I 中总结了这些变体,上面详细描述的定义是 V2,这是我们可以想象的最强的一个。我们使用协议属性1 来说明它们的差异,不同的协议属性导致不同的结构,并具有有趣的效率权衡。

人们可以类似地描述其他属性的定义。这些属性的定义变体不会(似乎)导致更有效的构造。所以本文只提供具有不同协议定义的结构。


我们用图1来解释协议的定义。在这个例子中,有三个配置和七个副本。

复制体p1到p5是正确的,g1是正确的。复制体p6是1正确的,但2有问题,因为它在配置2之后离开了系统。复制件p7在1中是正确的,但在配置1后离开系统时是1个错误的。对于协议定义V,如果配置1中的正确副本p1传递了一个消息m2,任何其他g1正确的副本,包括p2到p5,最终都会传递m2。然而,复制体p6和p7可能会也可能不会传递m2。

对于协议定义V1,如果一个1正确的复制体p1交付了m1,任何其他1正确的复制体,包括p2到p6,都必须交付m1。对于V2,一个例子是m3。特别是,如果配置1中的正确副本p1交付了m3,配置1中的任何其他正确副本,包括p2到p7,将交付m3。V 0、V 01和V 02的属性相似,只是if子句需要c个正确的副本。

应该选择六个版本中的哪一个?每个版本中的 if 子句表示属性的条件:如果使用较弱的条件,我们将拥有更强的属性。

请注意,V (resp. V 0) 比 V1 (resp. V 01) 和 V2 (resp. V 02) 弱,因为 gc 正确的副本也是 c 正确的副本和正​​确的副本。此外,V1 (resp. V 01) 比 V2 (resp. V 02) 弱,因为某些配置 c 中的正确副本集包括 c 正确副本集。可以将我们的设置与针对崩溃故障的统一与非统一广播原语的设置进行比较,其中统一广播原语更强。

G. 与先前规范的比较

我们的语法遵循 Schiper 的语法,将动态 BFT 从其成员服务中分离出来 [46]。正如 Schiper 所说,这种治疗比 Chockler 等人 [46] 的治疗更自然、更简单。然而,我们对安全性(正确性)属性的规范与 Schipper [46] 的规范有很大不同。

首先,我们的规范处理拜占庭式故障,而 Schiper 的规范是为崩溃故障模型中的统一广播原语而设计的。

其次,虽然我们一起定义了常规请求和成员请求的属性,但 Schipper 分别定义了常规请求和成员请求的所有属性。特别是,Schipper 的工作首先描述了常规请求的总顺序,然后描述了成员请求的总顺序,两者都是传统意义上的请求总顺序。仅 Schiper 的总订单规范可能会导致以下“异常”,如图 2 所示:正确的副本 p1 可能在常规请求之前交付成员请求,而正确的副本 p2 在成员请求之前交付常规请求。这并不违反 Schiper 工作中定义的两个单独的总订单属性,但确实违反了我们定义的总订单保证。

图 2:不违反 Schiper 方案中的全序属性但违反我们的定义的示例。


也就是说,在 Schipper 的工作中定义的两个总顺序属性,即使结合起来,也比我们的要弱。然而,由于在Schiper的工作中为普通请求和会员请求额外定义了 “相同的配置交付 “属性,人们可以检查出 “异常 “不会发生。事实上,在 Schipper 的工作中定义的两个总订单属性和两个相同的配置交付属性,加在一起就等价于我们增强的总订单属性(它包含相同的配置交付属性)。因此,虽然我们的属性与 Schiper 的属性之间没有一一对应的关系,但我们的规范和 Schiper 的规范(对拜占庭故障进行了适当的修改)可以作为一个整体等效。然而,我们的定义看起来更简洁。

最后,Schipper 的工作没有定义对动态 BFT 的安全性至关重要的所需属性(一致交付)。

4 动态 BFT 的挑战

在构建动态 BFT 时,可以简单地将成员资格请求视为常规请求。然而,直观的方法会导致各种问题,使得动态 BFT 无法实现活性。我们在下面说明了基于领导者的 BFT 协议在部分同步环境中的视图变化的一些挑战。

正常情况下操作中的活性问题。协议属性,无论是部分同步还是异步假设,都要求如果正确的发送者在线保持足够长的时间,正确的接收者将接收到来自发送者的消息。然而,动态 BFT 并非如此。特别是,考虑一个 cq 正确的副本 pi,它在 cr > cq 之后立即离开系统。副本 pi 已在 cq 中交付 m 并在 cr 中删除(pi)。考虑另一个仍然在 cq 中的正确或 cq 正确的副本 pj。副本需要收集 Qcq 匹配消息来传递 m。然而,一些 cq 正确的副本(甚至除 pj 之外的所有 cq 正确的副本)可能不再正确,因为它们已经移动到 cr,例如,pi 已经离开系统。因此,正确的副本可能无法交付 m,从而产生一致性和活性问题。

视图更改的活性问题。我们总结了与视图更改相关的各种活性问题。

  1. 新视图中正确的领导者可能无法获得足够的视图更改消息来启动新视图。

  2. 新配置中的指定领导者可能不知道视图变化。这是因为副本处于不同的配置中,并且它们无法在最新配置中发送所有副本视图更改消息。

3)多个副本可能会在视图更改后声称他们是新的领导者。


图 3:视图变化的活跃度挑战。


我们在图 3 中展示了一个示例。副本从配置 c = 1 移动到 c = 3,其中在所有三个配置中,p5 都是领导者。在配置 c = 1 中,有五个副本,并且删除了 p3。副本 p2、p4、p5 安装配置 2,而 p1 仍停留在 c = 1 中。在配置 2 中,仲裁大小为 3,因此 p2、p4 和 p5 能够达成协议。在 c = 2 时,p6 请求加入系统。请求传递后,副本 p4、p5 和 p6 安装 c = 3,而 p2 仍停留在 c = 2。如果在此阶段发生视图更改,则副本 p6 是新视图中的指定领导者。由于 c = 3 中的 quorum 大小为 4,p6 必须收集 4 条消息才能启动新视图。然而,p1 和 p2 甚至不知道 p6。此外,副本 p1 可能认为它是新的领导者。因此,所有正确的副本将永远停止,因为副本在视图更改期间不会处理任何消息,并且副本可能永远不会恢复到正常情况下的操作。在静态系统中,可以通过使副本与其他副本同步来解决此问题。然而,在动态系统中,副本甚至可能不知道系统中当前副本的身份。

5 我们的协议概述

基于部分同步环境中的两个假设,我们提供了满足表 I 中各种动态 BFT 定义的安全结构。

A. Dyno-S:一种直观但低效的构造

Dyno-S 形式化的直觉是,每次处理成员资格请求时,都需要触发视图更改以防止副本丢失更新的配置。然而,使用这个想法构建这样一个具有可证明安全性的协议并非易事。该方法需要解决 Sec 中的挑战。 IV 并且需要实现一致的交付。

由于篇幅限制,我们将在全文中介绍该结构。该构造的主要缺点是每次视图更改都会导致吞吐量为零的窗口,因为副本在视图更改期间不处理任何请求。

B. Dyno、Dyno-C 和 Dyno-AC

Dyno 是我们的主要协议,可在成员变更期间保持其效率。在标准仲裁假设下,它在定义 V 的意义上是安全的,在更强的 G 正确假设下在 V1 的意义上也是安全的。

向前跃进,我们还提供了具有更强特性的动态 BFT 结构(总结在表 I 中)。 Dyno-A 建立在 Dyno 之上,另外还有一个简洁的附录 (A) 协议正在运行。 Dyno-C 与 Dyno 略有不同,使用了轻微的约束 ©。 Dyno-AC,顾名思义,包含了附录协议 (A) 和修改后的约束 ©。我们将在 Sec. 中描述附录协议和约束的含义。七。

下面,我们从高层次上描述 Dyno。在描述我们的成员方法时,我们定义了两个事件:init() 和 Deliver()。 init() 事件在当前视图中的主节点开始新一轮协议时触发。 Deliver() 事件表示在正常情况下操作期间请求已提交并准备好交付的事件。我们的成员协议具有以下关键组件,以确保正确性而不会中断性能。

我们将配置作为系统状态的一部分进行管理,类似于之前的工作(例如,Paxos、Schiper 的工作和 BFT-SMaRt)。

成员资格请求的处理方式与常规请求相同。副本在每一轮中就一批请求达成一致。如果批次包含常规请求和成员请求,则常规请求首先根据确定的顺序交付(与具有静态成员的 BFT 中的相同)。之后,会员请求被传递。然后所有副本都安装新配置。

临时会员管理。提交加入成员资格请求时,配置可能与提交请求时的配置不同。为了简化通知流程,我们引入了临时会员的概念。具体来说,每个新副本都充当学习者。

现有副本将正常情况下的操作消息发送到当前配置中的副本和所有临时成员。但是,仲裁大小仍与当前配置相同。在 Deliver() 事件中,成员资格被更新并与临时成员资格相同。这样做可以让我们拥有更有效的状态转移机制。

配置发现协议和一致交付。

我们设计配置发现协议,以便新副本和客户端了解当前系统的成员资格。我们提供隐式和显式实现目标的协议。这些协议对于实现一致的交付也很重要,因为客户端需要配置发现来验证系统中当前副本的回复。

我们还需要另外两种技术来实现一致的交付。首先,我们在配置之间强制达成一致,以确保所有正确的副本,而不仅仅是一小部分正确的副本,都是最新的。其次,副本维护执行历史和配置历史(执行历史的子集)的总顺序。执行历史记录包含每个请求的交付证明(以签名的形式,证明法定人数的副本已同意交付请求),以确保总订单和协议。配置历史记录仅包括会员请求的交付证明。

配置历史记录用于验证正确的副本是否安装了某些配置。配置历史允许客户端确定它是否已收到足够的匹配副本回复以在某些配置中安全地传递它们。

请注意,客户端可能无法在发出请求的配置中传递回复,但客户端将在未来的某些配置中传递它们。

精心设计的视图变化。为了确保新视图中的指定领导者接收到一定数量的视图更改消息,我们在视图更改期间引入了额外的工作流。具体来说,每个副本都在视图更改消息中包含其配置编号以及成员请求的有效传递证明。

对于配置 c 中的任何副本 pi,它将 c 与 c0 进行比较,其中 c0 是 pj 发送的视图更改消息中携带的配置号。如果 c0 更小,pi 将视图更改消息转发给 Mc/Mc0 中的所有副本。请注意,Mc/Mc0 就足够了,因为副本 pj(如果正确)必须已经将消息发送到 Mc0。另一方面,如果 c 较小,则有两种情况: pi 之前发送过视图更改消息; pi 之前没有发送过视图更改消息。在前一种情况下,pi 将其视图更改消息重新发送到 Mc0/Mc。在后一种情况下,pi 将其视图更改消息(如果适用)直接发送到 Mc0 中的所有副本。这确保了新视图中的副本能够收集足够多的视图更改消息以进入新视图。

6 DYNO 协议

我们现在介绍 Dyno,重点介绍如何处理会员请求和常规请求以及视图更改的工作流程。在整篇论文中,我们假设每条消息 m 都是唯一的。在本节中,我们将正常情况下的操作用作预言机,由 init() 和 Deliver() 事件表示,如第 2 节所述。 V. 特别是,我们使用 Bracha 的可靠广播 [8] 作为正常情况的操作,我们在附录 A 中讨论了如何触发 init() 和 Deliver() 事件的细节。我们使用 Bracha 的广播,因为它是一个原语达成一致,我们认为这对于动态 BFT 至关重要。对于每个请求,我们使用交付证明来表示请求可以安全交付的证明。在我们的例子中,这指的是 Bracha 广播的第二阶段中的 2f + 1 个匹配消息(或 PBFT 术语中的准备证书)或第三阶段中的 f + 1 个匹配消息(或 PBFT 术语中的 f + 1 个 hCOMMITi 消息) .

当我们描述协议时,我们考虑了一个通过获取配置 ig() 函数触发的配置发现协议。副本和客户端可以通过查询函数获取当前配置。配置发现的细节在 Sec. 中讨论。 VI-B。在本节中,我们忽略垃圾收集的细节,因为我们的系统可以使用传统的检查点协议。

A. 协议

客户定期提交请求。客户端能够通过ObtainConf ig() 函数获得配置c 和副本集Mc。为了提交请求,客户端首先向配置 c 中的所有副本广播一条消息 hSUBMIT, c, hREQUEST, cid, oii。请求 hREQUEST, cid, oi 是具有有效签名的常规请求,其中 cid 是客户端的 id,o 是操作。客户可能得到的答复有两种情况。 1) 如果客户端收到来自 Mc 中 fc + 1 个副本的回复,则完成请求。 2) 客户端可能会从 c0 中的副本获得回复,其中 c0 > c。在这种情况下,客户端会验证配置历史 chist(稍后会详细介绍)并检查 c0 是否为有效配置。如果 c0 有效,则请求完成。如果没有任何一种情况,客户端超时,客户端再次执行配置发现并提交请求,直到请求完成。


初始化 c {当前配置}
func submit() ” />
图 5:副本 pi 的正常情况操作。


图 6:查看副本 pi 上的更改协议。

在 deliver() 事件发生后,副本 pi 首先传递常规请求,然后传递成员资格请求。如果批次中包含成员请求,pi 安装新配置并将 c 加 1。对于每个 hADD、j、mi 消息,pi 将 pj 添加到 M,并开始向 pj 传输状态。对于每个 hREMOVE, j, mi 消息,pi 从 M 中删除 pj。如果 pj 传递了 REMOVE 请求,它就会离开系统。

任何请求加入系统的副本 pi 都充当学习者,被动地从正常情况操作中学习结果,即,它被系统中的副本添加到临时成员中。学习者按照与现有副本相同的规则处理正常情况的消息。在 pi 发送加入请求后,它等待直到它通过接受 2fc + 1 hHISTORY, s, h, C, Pi 消息完成状态转移。

之后,pi 参与正常情况下的操作。新副本的状态转移以赶上执行历史并维护历史请求的交付证明。

查看更改。我们现在勾勒出视图更改的主要工作流程,其伪代码如图 6 所示。为了开始视图更改,每个副本 pi 增加其视图编号并广播 hVIEW-CHANGE, v, c, s, C, PP, ii,其中 v 是视图编号,c 是配置编号,C 是稳定检查点,P 是自上次稳定检查点以来请求的一组交付证明,PP 是一组成员请求。

从副本 pj 收到 VIEW-CHANGE 消息后,副本将消息中携带的 c0 与其本地配置编号 c 进行比较。如果 c0 c,表示 replica pi 没有安装更新的配置。在这种情况下,pi 向 Mc0 广播一个 VIEW-CHANGE 消息。 Mc0 可以从 PP 获得,交货证明可以从 P 获得。

考虑 c 是由至少一个正确的副本安装的配置,并且没有正确的副本安装了大于 c 的配置,新的领导者可以通过 Mc[v mod |Mc|] 来识别。当新视图中指定的leader收集到2fc+1条有效的VIEW-CHANGE消息时,它通过广播一个hNEW-VIEW,v,c,V,Oi进入新视图,其中V是一组VIEW-CHANGE消息,O是一组 normalcase 操作消息。然后副本恢复正常情况下的操作并相应地处理 O 中的消息。

B.配置发现配置发现确保新副本和客户端了解现有系统的成员资格。我们在 Dyno 中提出的方法需要客户端和新副本来发现更新的配置(如果有的话)。在本节中,我们首先定义配置历史。然后,我们通过定义正常情况操作使用的接口,介绍我们在协议中使用的自我发现方法。我们在附录 B 中描述了两种替代结构。所有配置发现协议的证明显示在附录 C-A 中。

配置历史。我们将配置历史定义为一组根据配置编号按顺序排序的成员资格请求。配置历史是整个执行历史的一个子集。配置历史仅包括请求批次,其中每个批次至少包含一个成员资格请求。每条消息中对应的c号是按顺序排列的。我们还要求每个副本为每个成员资格请求维护相应的交付证明,即由 Mc 中的 Qc 副本签名的消息。单个配置历史可以被任何正确的副本验证以证明配置的存在。

图 7:配置发现:自我发现。

自我发现。默认情况下,我们使用图 7 所示的自我发现方法。为了获取系统的配置,副本(或客户端)pi 首先向 universe 发送 hDISCOVER,ci 请求,其中 c 是最新的配置 pi知道。定时器也启动。收到 hDISCOVER, c0i 请求后,副本回复 hCONF, c, Mc, chisti,其中 c 是其当前配置,Mc 是配置 c 的成员,chist 是配置历史记录。在收到带有有效 chist 的 CONF 消息后,pi 更新其本地配置编号、Mc 和 chist。在 Δ 超时后,配置发现完成并返回当前的 c 和 Mc。

定理 VI.1。在标准的法定人数假设下,Dyno 实现了协议 V、总订单、活跃度和一致交付。

Dyno 的正确性见附录 C-B。

七。 DYNO WITH STRONGER AGREEMENT PROPERTIES 我们研究了具有更强属性的 Dyno 变体,即 V1、V2、V 0、V 01 和 V 02。在本节中,我们介绍了 Dyno 实现 V1 协议属性的两种方法。我们首先通过更强的假设证明 Dyno 本身可以实现 V1。

然后,我们展示了 Dyno-A,一种基于 Dyno 的结构,它在标准群体假设下实现了 V1。然后我们介绍 Dyno-AC,它在 Dyno-A 之上添加了一个简单的约束以实现 V2。我们进一步表明,协议的结构对于 Dyno 保持不变,其中 V、V1 和 V2 分别实现 V 0、V 01 和 V 02。本节讨论的所有协议的证明见附录 C-C。

在 G 正确假设下,带 V1 的 Dyno。我们不改变协议的结构来实现正确性,而是假设第 2 节中的 G-correct 假设。三、由于我们不修改协议,因此总体顺序和活跃度遵循 Dyno。但是,协议属性可以大大简化。

定理 VII.1。在 G-correct 假设下,Dyno 实现了协议 V1、全序、活性和一致交付。

带V1的Dyno-A。假设总是存在至少f+1个g-正确的副本是不实际的,因为它要求人们知道max(f0, f1 – – ),即在系统的整个生命周期中错误副本的最大数量。相反,我们展示了另一种结构,在不改变系统假设的情况下实现了V1协议属性。特别是,我们在Dyno之上提供了一个附录协议来实现V1。


如图 8 所示,我们为每个落后的副本引入了额外的过程,以赶上更新配置的副本。特别是,在正常情况下的操作期间,每个副本 pi 仍会为其队列中的第一个请求设置一个计时器。如果在定时器超时之前请求没有被投递,不是直接触发视图变化,而是副本首先运行配置发现协议,获得一个新的配置号c0,以及副本列表Mc0。

如果 c0 = c,则副本根据 Dyno 中的过程开始视图更改。否则,如果 c0 大于 c,则副本向配置 c0 中的所有副本广播 hUPDATE, s, c, ii 消息,其中 s 是最后交付请求的序列号,c 是其当前配置。当 c0 中的副本 pi 收到 hUPDATE, s, c0, ji 消息时,它首先验证 pj 是否是配置 c0 中的有效副本。

如果 pi 的本地执行历史较长(即其最后提交请求的序列号大于 s),则 pi 将执行历史发送给 pj。在收到 fc0 + 1 匹配 hist 后,副本将发送 hist 中的请求。如果 hREMOVE, ii 请求已经传递,pi 直接离开系统。

否则,pi 继续参与协议。

定理 VII.2。在标准的群体假设下,Dyno-A 实现了协议 V1、全序、活性和一致交付。

附录协议的动机是让 c-correct 副本获得执行历史记录,即使副本落后。在副本超时的情况下,它会在开始视图更改之前执行配置发现协议。

如果副本落后,它会从其他副本获取执行历史记录。这确保任何 c-correct 副本在离开系统之前获得执行历史并交付请求(如果适用)。

带 V2 的 Dyno。基于具有 G-correct 假设的 Dyno 或 Dyno-A,我们可以进一步向副本添加更多约束,以便协议实现 V2,分别创建 Dyno-C 和 Dyno-AC。特别是,V2 进一步要求配置 c 中的任何正确副本也传递消息,如果 c 中的正确副本传递了消息。

附加约束非常简单:任何正确的副本 pi 仅在发送 hREMOVE, ii 请求后才离开系统(如果已提交离开请求)。该约束确保 c 中任何正确的副本都传递所有消息,即使它在 c 之后立即被删除。

因此,我们需要一个副本来发现更新的配置,并在它落后时获取执行历史记录。这样可以确保每个正确的副本都按照 V2 的要求传递它应该传递的所有请求。

定理 VII.3。在 G-correct 假设下,Dyno-C 实现了协议 V2、全序、活性和一致交付。在标准的群体假设下,Dyno-AC 实现了协议 V2、全序、活性和一致交付。

带有 V0、V01、V02 的测功机。无需更改协议规范即可实现 V 0、V 01 和 V 02。

即,Dyno 达到 V 0,Dyno-A(或 Gcorrect 假设下的 Dyno)达到 V 01,Dyno-C 和 Dyno-AC 达到 V 02。

8 实施与评估

概述。我们使用大约 10,000 LOC 在 Go 中实现 Dyno 变体。我们对 Dyno 进行了优化,其中加入系统的副本在传递成员资格请求后开始参与正常情况操作。状态转移是并行执行的。然而,在传递成员资格请求之后的所有请求都是在状态转移完成之后执行的。

我们的结果表明,Dyno-C 和 Dyno-AC 与 Dyno 实现了相似的性能,主要是因为附加约束和增编协议主要影响副本加入或离开系统的行为。因此,在本节中,我们将重点关注 Dyno 和 DynoS 的性能。我们将 Dyno 与 BFT-SMaRt [50] 进行了比较,BFT-SMaRt [50] 是一种用 Java 编写的 PBFT 协议变体的开源实现。 BFT-SMaRt 支持重新配置,其中成员请求由单独的视图管理器发出。

我们使用最多 30 台服务器在集群中部署协议。每台服务器都有 16 核 2.3GHz CPU。我们使用 f 来表示网络大小,我们在每个实验中使用 3f + 1 个副本。与以前主要关注小交易基准的协议不同,在我们的实验中,我们将所有交易和回复消息设置为 100 字节,因为 BFT 应用程序(例如区块链)中的交易通常至少为 100 字节。除了副本的数量,我们还改变了垃圾收集的频率(即检查点),表示为 cp,以及同时向系统提交事务的客户端数量。默认情况下,副本在每交付 100 批请求时执行检查点协议。



潜伏。我们评估了 Dyno 和 Dyno-S 的会员请求延迟。我们设置 f = 1 并让一个客户端连续提交定期请求。我们让副本在分别提交了 5000、10000 和 50000 个请求后提交成员请求(加入或离开)(在图中表示为 b)。我们仅在图 9d 中显示了协议的延迟。

Dyno 平均有 50 毫秒到 100 毫秒的延迟。结果与常规请求的结果类似。相比之下,由于 Dyno-S 在每次成员更改时都运行视图更改协议,因此延迟要高得多。 Dyno-S 的延迟分解如图 9a 所示。可以看出,视图更改是瓶颈,如果在视图更改之前处理更多请求,则延迟会更高。

由于每个新副本在加入系统后都会执行状态传输,因此我们还评估了每个实验的状态传输延迟。我们在图 9b 中显示了 Dyno 的结果。我们将状态传输(网络通信)的延迟和转换(副本处理历史客户端请求)的延迟分开。如图所示,随着 b 的增加,延迟明显变高。这是预料之中的,因为在状态转移期间需要同步大量请求。相比之下,协议延迟几乎可以忽略不计。

对于b=10000的实验,我们也改变了检查点的频率,并评估了一个连接请求的延时。 如图9c所示,检查点的频率对延迟没有直接影响。这是预料之中的,因为每个副本都会同步所有的历史事务,所以网络带宽的消耗是由状态传输主导的。

吞吐量和可扩展性。我们评估了 f = 1、f = 2 和 f = 5 时 Dyno 的吞吐量。如图 9e 所示,当 f = 1 时,Dyno 的峰值吞吐量为 76 ktx/s,在部分吞吐量中处于最高水平目前已知的同步 BFT。

当 f 增加时,性能会下降,正如几乎所有 BFT 协议所观察到的那样。我们在图 9f 中报告了 Dyno 和 BFT-SMaRt 的峰值吞吐量。 Dyno 实现了比 BFT-SMaRt 更高的峰值吞吐量,部分原因是底层实现的效率。

根据会员要求执行。我们评估 Dyno 的会员请求的性能。我们让 f = 1 并让 400 个客户端同时向系统提交常规请求。我们评估了三种不同的场景:1)加入请求下的性能; 2) 休假期间的表现; 3)加入和离开请求下的性能。

加入请求下的性能。我们让一个副本提交加入请求,并评估 g-correct 副本(即从时间 0 开始正确的副本)和新副本的吞吐量。如图 9g 所示,系统在加入请求时不会出现任何性能下降。

对于多个加入请求下的性能,我们从 4 个副本开始(f = 1)。然后我们定期发出成员请求并添加副本,直到系统有 8 个副本。我们展示了 g-correct 副本和加入系统的每个新副本的吞吐量。如图 9h 所示,系统在收到每个加入请求后都会出现性能下降,并在一段时间后恢复正常。例如,当第一个副本加入时,吞吐量从平均 50 ktx/s 下降到 30 ktx/s 左右,下降了 40%。这是预期的,因为新副本在处理常规请求时执行状态传输。然而,在状态传输完成后,吞吐量又回到 50-60 ktx/s。随着每个副本的加入,整个系统的吞吐量逐渐下降。这也是预料之中的,因为系统有更多的副本。当系统有 8 个副本时,整体吞吐量从 50-60 ktx/s 下降到 40-50 ktx/s。

我们匹配大部分系统配置参数,并在相同设置下评估 BFT-SMaRt 的性能。结果如图 9i 所示。与 Dyno 不同,在 BFT-SMaRt 中,加入系统的副本的吞吐量始终低于现有副本的吞吐量。此外,随着副本加入 Dyno,整体吞吐量下降始终低于 BFT-SMaRt。

休假请求下的表现。我们从 10 个副本(f = 3)开始,然后让 6 个副本一个接一个地离开。系统的吞吐量如图 9j 所示。与之前的情况相比,吞吐量更稳定,主要是因为副本可以在删除请求传递后直接离开系统。 BFT-SMaRt 的性能相似,如图 9k 所示,除了 BFT-SMaRt 的整体吞吐量比 Dyno 低约 30%-40%。

在多个加入和离开请求下的性能。我们还评估了加入和休假请求下的表现。特别是,我们在 30 秒的时间间隔内触发 3-5 个随机加入或离开请求。我们首先从 4 个副本开始,评估 Dyno 和 BFT-SMaRt 的性能。我们在图 9l 中展示了 g 校正副本的性能。性能类似于仅加入或离开请求下的性能。 BFT-SMaRt 在某些请求期间可能会达到低(接近 0)吞吐量。相比之下,Dyno 的性能总体上更稳定。

我们让系统一开始有 f = 3(10 个副本),然后再次进行相同的实验。我们在图 9m 中展示了 Dyno 的结果,在图 9n 中展示了 BFT-SMaRt 的结果。我们展示了 g 校正副本、加入系统的副本和离开系统的副本的性能。尽管吞吐量通常较低,但两种协议的结果与 f = 1 时的结果相似。

我们还在频繁的成员请求下评估 Dyno,我们从 10 个副本开始,让副本以随机间隔频繁加入和离开。如图 9o 所示,随着频繁的成员请求,系统的吞吐量趋于更加动荡,因为副本必须为新加入的副本执行频繁的状态转移。

9 结论

我们研究了动态拜占庭容错协议,其中副本可以加入和离开系统。我们正式定义了动态拜占庭容错的安全定义,并提出了不同但有意义的变体。我们介绍 Dyno,一种高效的动态拜占庭容错协议。我们表明,通过多达 30 台服务器的部署,Dyno 是高效的,能够以低成本处理会员请求。