Exonum中的共识算法

来源:互联网 发布:c语言数组删除指定元素 编辑:程序博客网 时间:2024/06/04 18:56

Exonum中的共识

本文属于译文,原文地址:
https://exonum.com/doc/architecture/consensus/

一般而言,共识算法(consensus algorithm)就是一个处理程序——获取由参与者组成的小组共同认可的结果。在Exonum中共识算法是用来对添加到区块链中的区块交易列表达成共识。此算法的另一个目的是确保交易执行的结果会被在区块链网络中的所有其他节点以相同的方式理解。

Exonum中的共识算法使用了在Tendermint中被提议的算法的某些思想,但是对比此算法以及区块链中其他的共识算法,Exonum中的共识算法还是有几个出众的特点。

设想

Exonum共识算法假设共识的参与者都是可以被辨认的。因此,相对于无需许可的区块链,此算法更适用于Exonum倾向的需许可的区块链。

并不是区块链网络中的所有节点都要积极的参与到共识算法中。相反,积极的共识参与者是个特殊的角色——验证人或验证人的节点。例如,在 consortium区块链中,验证人是被参与 consortium的公司所管理的。

共识算法必须在有故障产生时能采取行动,也就是,当参与者有异常行为时。Exonum共识算法假设最坏的情况会发生——在区块链网络中的一个节点或者一个组的节点会产生故障或者像资源丰富的敌手妥协(比如黑客或腐败的管理者)时Exonum的共识算法就会采取行动。这种威胁模型在计算机科学中被称为拜占庭错误(Byzantine faults),因此,Exonum共识算法是拜占庭容错的(Byzantine fault tolerant)。

从计算机科学的角度,Exonum共识算法设想了几种常见的情况:

  • 验证人的节点是部分同步的,即他们的运算能力没有很大的差别

  • 网络也是部分同步,即所有的信息都会在有限的时间内被分发出去,具体多长时间无法提前得知

  • 每个验证者都可以访问本地的计时器来确定时间间隔。另一方面,在系统中没有全局的时间同步

  • 使用公钥加密的方式对验证者身份进行认证,因此,验证者之间的通信是也都是通过认证的

PBFT(被大家所熟知的拜占庭共识)和它的继承者们也假设了上面提到的相同设想。

算法概述

达成下一个区块(在区块链中的高度为H)的共识处理过程包含了几个回合,从回合1开始。当验证者提交了高度为H-1的区块时,第一回合就开始了。首回合是由一个固定的时间表来决定的:回合开始于一定的间隔时间。由于系统中没有全局的时间,所以对于每个验证者而言回合的开始时间可能是不同的。

当处理到了回合R时,前面的回合还没完成。也就是回合R意味着验证者只能处理小于等于R回合的相关数据。验证者的当前状态可以用一个数组来表示(H,R),对于每个验证者而言,可能R的数值是不同的,但是通常情况下H都是相同的。如果某个验证者滞后了(例如,在首次同步的时候或者被关闭了一段时间),他的区块高度(H的值)可能会低一些。在这种情况下,验证者为了快速和整个网络进行同步,可以向其他的验证者或者整个节点请求丢失的区块。

稻草人版本(非完善版本)

为了更加简单的叙述处理过程,回合的处理如下:

  1. 每个回合都有一个领导节点,领导节点会为下一个区块提出 投标(proposal) 并广播到网络中。选择领导节点的原理在分离算法中说过
  2. 验证者们可以通过广播 预投票(prevote) 信息来为投标进行表决。一个预投票意味着验证者已经能解析投标以及拥有投标中的所有交易
  3. 当一个验证者从大多数其他验证者那里收集到了足够的预投票,他开始处理已预投票的投标中交易,并且广播 预提交(precommit) 信息。预提交信息包含了投标的执行结果,执行结果是用 新状态哈希值 进行表示的。预提交信息表示发送者已准备好将相应的投标区块提交到区块链上,但是为了确保成功,需要看看其他的验证者对此有何看法
  4. 最后,如果验证者收集到了大多数有着相同 新状态哈希值 的预提交(这些预提交属于同一个投标),则投标就会被加入到区块链中

非稻草人版本(完善版本)

注意:在下面的描述中, +2/3 代表着大于三分之二的验证者,-1/3 代表着小于三分之一的验证者

上面的算法过于简化了:

  • 由于网络的延迟验证者收到信息的顺序是不可保证的。例如,验证者收到了一个自己并不知道的区块投标的预投票或者预提交信息。

  • 也有可能会出现不按照共识算法来操作的验证者。验证者可能会下线,或者被敌手腐败了。为了让这个设想更加形式化,假设 -1/3 验证者在任意时刻出现了异常行为(这种验证者在计算机科学中称为拜占庭),而其他的验证者都是诚实的。

上面所说的三阶段共识(投标,预投票,预提交)可以让共识算法在这种情况下还能正常运行。更精确的来说,此算法要求保证安全性和活跃性。

  • 安全性是指当一个诚实的验证者提交了一个区块之后,在区块链中的相同高度上再也不会有其他诚实验证者提交任何区块

  • 活跃性是指诚实的验证者会一直保持着时不时的往区块链上提交新的区块

拜占庭验证者也许会给不同的验证者发送不同的信息。为了在这种情况下保证安全性,Exonum共识算法使用了锁(lock)的概念。

当验证者在某个投标上收集到了+2/3的预投票,则验证者就被锁定在此投标上。被锁定的验证者除了能给被锁定的投标投票之外是不可以给其他任何投标进行投票的。当一个新的回合开始时,被锁定的验证者会立刻发送一个预投票信息表明自己被锁定在某个投标上。如果其他的验证者在本地没有锁的信息时,会发送一个预投票信息给被锁的验证者从而获取锁的信息。

例子:验证者A获得了验证者B和验证者C的预投票,由于连接的问题他们不会从彼此那里获取预投票,然后验证者B和验证者C可以通过验证者A来获取彼此的预投票

锁是可改变的:如果A锁定在了一个投标上,而在下个回合的时候其他的验证者都被锁定在了另一个投标上,A最终还是会更新自己的锁

请求

由于共识信息可能会丢失或信息顺序错乱,Exonum共识使用请求机制从其他验证者来获取自己所不知道的信息。当验证者与对端验证者通信的时候发现对端拥有自己不知道但需要知道的信息时,验证者就会发送一个请求给对端

例子:当一个节点接收到了一个比自己本地高度要高的共识信息时,则节点就会发送一个A**请求**。对端应该发送在区块中已被认可的交易相关信息,附带交易确实被区块认可的相关证明(也就是+2/3验证者的预提交)。

对于各种共识信息,都有相应的请求:投标,预投票,预提交。因为共识信息是用数字签名来认证的,所以它们可以直接发送对请求的响应。

节点状态概述

在投标算法中状态的顺序如下:

提交(Commit) ->循环(Round)+ ->提交(Commit) -> 。。。。。

在时间轴上,状态看起来像下面这样(其中一个验证者的状态):

  提交: | H |                               |H+1|                                  …
回合1: |     | R1                                  | R1                            …
回合2: |             | R2                                  | R2                    …
回合3: |                     | R3                                  | R3            …
回合4: |                            | R4                                   | R4    …
………
————————————————————————–> Time

注意回合是有一个固定的开始时间的,但是没有一个确定的结束时间(当接受到下一个区块时结束)。这与部分同步共识算法的通常行为不同,他们通常会有一个确定的结束(即在回合R产生的数据只能在回合R期间处理)。

网络通信

小窍门:可以通过看源代码来了解共识信息更加详细的技术细节。

信息

共识算法一共提供了几种不同类型的信息。所有的信息都是使用公钥数字签名来进行认证的,所以信息的发送者都是明确的知道而且不可被伪造的。而且,数字签名(替代了了比如 HMACs)也保证了信息可以随性的在网络中重发。除此之外,负载均衡器就可以完成信息的重发,即使不知道信息的内容到底是什么。

投标(Propose)

投标信息就是一系列被回合领导者提出要加入到下一个区块中的交易。投标信息是使用交易的哈希值来代替整个的交易明细。接收到投标信息的验证者可以发送请求给对端来获取自己没有的交易明细。

如果所有的验证者都按照规定进行操作,那么投标只会被回合领导者发送。

预投票(Prevote)

预投票是对投标信息进行表决。一个预投票信息意味着验证者已经可以正确的构成投标以及投标中包含的交易。预投票是广播给所有的验证者的。

预提交(Precommit)

预提交信息代表验证者已经准备好把投标加入到区块链的下一个区块中。预提交也是广播给所有的验证者。

状态(Status)

状态是一个关于当前区块高度的通知信息。它根据写入到全局配置参数status_timeout中的值来进行周期性发送的。

区块(Block)

一个区块信息包含着区块(在区块链中的含义)以及一系列允许此区块被接受的预提交信息。区块信息是根据请求来发送的。

请求信息(Request Messages)

请求信息都是为了获取交易,投标,以及预投票信息的。请求信息的产生以及处理规则都是相当明显的。

例:投标请求信息会在如下的情况下产生:当一个验证者接收到了一个自己并不知道的指示某个投标的共识信息(预投票或预提交)时,他就会发送出一个投标请求信息,收到投标请求信息的验证者会响应请求的投标给请求者。

与众不同的特征

与其他的拜占庭算法相比,Exonum的共识算法具有以下与众不同的特点:

无限制的回合

回合都是具有一个固定的开始时间但是没有一个确定的结束时间(只有当接收到下一个区块的时候一个回合才结束)。当验证者之间网络连接不稳定时这有效的减小了延迟。

假设某个回合的共识信息必须要在此回合之内处理完成,如果网络的状态不是很好的情况下,可能等到回合结束的时候才接收到了投标信息。那么在下个回合的时候,提出一个投标以及表决投标的整个处理过程可能又需要重新开始。在网络连接性比较差的情况下可能需要增加下个回合的超时时间才能让区块在新的超时时间内被接收到。这种已经完成的工作还需要重复的再次开始以及增加超时时间都会让接收区块投标产生额外的延时。

对于上面讨论的情况相反情况下,Exonum中的回合没有固定的结束时间让可以允许接收投标有一个必要的最小延迟时间。

工作分工

投标信息只包含了交易的哈希值(交易明细的本身是直接包含在区块信息中的)。另外,交易的执行是延后的,只有当节点被锁在一个投标上的时候交易才会被执行。

延迟交易处理能减少恶意节点对系统吞吐量和延迟的负面影响,实际上,在算法的各个阶段将交易的处理都分割开了:

  • 在预投票阶段验证者只需要保证投标上的所有交易都是正确的(验证者已经检查过投标上的所有交易都存在在本节点上。交易的正确性在交易被接收的时候就已经验证过了,节点是不会存储不正确的交易的)

  • 在预提交阶段验证者执行交易到当前区块链的状态

  • 在提交阶段验证者确保在执行完交易之后他们达到相同的状态

如果拜占庭验证者发送拥有不同交易列表的投标给不同的验证者,验证者是不需要在预投票的阶段花费时间来检查列表以及执行交易的。从其他的验证者那里接收到预投票信息时,比较投标哈希值(propose_hash)则交易列表的不同会很容易被检测到,投标哈希值存在于投标信息中(接收到投标时就会接收到投标哈希值)

因此,工作的分工能减少拜占庭节点对于整个系统性能负面影响。

请求算法

请求算法允许验证者存储从其他验证者那里获取的任何共识信息。这对于系统的活跃性有很好的积极影响。

原创粉丝点击