41  
共识协议
作者: 姜天雨 于 2021年07月20日 发布在分类 / 底层框架资料 / GoQuorum 下,并于 2021年07月20日 编辑

共识协议

GoQuorum 实施以下权威证明共识协议:

IBFT 共识概述

一个 PBFT 启发的共识算法,由 AMIS 提供,具有即时交易终结性。请参阅此 technical web article .

介绍

Istanbul Byzantine Fault Tolerant (IBFT)  共识的灵感来自   Castro-Liskov 99 paper .

IBFT 通过使用三阶段共识, PRE-PREPARE, PREPARE COMMIT 继承了原始 PBFT 。系统最多可以容忍 N 个验证者网络中的  F  个故障节点,其中 N = 3F + 1.

执行

术语

Validator: :区块验证参与者。

Proposer :被选中在共识轮中提议区块的区块验证参与者。

Round :共识回合。一轮以提议者创建区块提议开始,以区块提交或轮次更改结束。

Proposal :正在进行共识处理的新区块生成提案。

Sequence :提案的序号。一个序列号应该大于所有以前的序列号。目前,每个提议的区块高度都是其关联的序列号。

Backlog :保存未来共识消息的存储。

Round state :特定顺序和轮次的共识消息,包括预准备消息、准备消息和提交消息。

Consensus proof :一个区块的承诺签名,可以证明该区块已经经过了共识过程。

Snapshot :上一纪元的验证者投票状态。

共识

Istanbul BFT 共识协议从第 轮开始,验证者以循环方式从自己中挑选提议者。然后提议者将提议一个新的区块提议并将其与 PRE-PREPARE 消息一起广播。在收到来自提议者的 PRE-PREPARE  消息后,其他验证者验证传入的提议并进入 PRE-PREPARE 状态并广播 PREPARED 消息。这一步是为了确保所有验证节点都在同一序列和同一轮中工作。当验证节点从其他验证节点接收到 ceil(2N/3) PREPARE 消息时,验证节点切换到 PREPARE  状态并广播 COMMIT   消息。这一步是通知其他验证节点它接受提议的块并将将该块插入链中。最后,验证者等待 ceil(2N/3)  COMMIT   消息进入 COMMITTED 状态,然后将块附加到链中。

 Istanbul BFT  协议中的块是最终的,这意味着没有分叉,任何有效的块都必须在主链中的某个位置。为了防止故障节点生成与主链完全不同的链,每个验证节点在将其插入链之前,将收到的 COMMIT 签名的 ceil(2N/3)  附加到标头中的 extraData 字段。因此,所有块都是可自我验证的。但是,动态 extraData  会导致块哈希计算出现问题。由于来自不同验证者的同一个区块可以有不同的 COMMIT 签名集,因此同一个区块也可以有不同的区块哈希。为了解决这个问题,我们通过排除 COMMIT  签名部分来计算块哈希。因此,我们仍然可以保持块 / 块哈希的一致性,并将共识证明放在标题中。

共识状态

Istanbul BFT  是一种状态机复制算法。 每个验证节点都维护一个状态机副本,以达成区块共识。 IBFT 共识中的各种状态是,

NEW ROUND :提议者发送新的区块提议。 验证者等待 PRE-PREPARE  消息。

PRE-PREPARED :验证者已收到 PRE-PREPARE  消息并广播 PREPARE 消息。 然后它等待 ceil(2N/3) PREPARE  COMMIT 消息。

PREPARED :验证节点已收到 ceil(2N/3)  PREPARE 消息并广播   COMMIT  消息。 然后它等待 ceil(2N/3)  COMMIT  消息。

COMMITTED :验证节点已收到 ceil(2N/3)  COMMIT  消息,并且能够将提议的块插入到区块链中。

FINAL COMMITTED :一个新块成功插入区块链,验证者准备好进行下一轮。

ROUND CHANGE :验证节点正在等待相同提议的轮数上的 ROUND CHANGE   消息的 ceil(2N/3)

粘贴图片

NEW ROUND -> PRE-PREPARED:

  • 提议者 txpool 收集交易。

  • 提议者 生成一个区块提议并将其广播给验证者。然后它进入 PRE-PREPARED  状态。

  • 每个 验证者 在收到 PRE-PREPARED  消息后进入 PRE-PREPARED  ,条件如下:

            1.区块提议来自有效提议者。

            2.  区块头有效。

            3.  区块提议的顺序和轮次与 验证者 的状态相匹配。

  • 验证者 向其他验证节点广播 PREPARE 消息。

PRE-PREPARED -> PREPARED

  • 验证者 接收 ceil(2N/3)  个有效的 PREPARE  消息以进入 PREPARE  状态。有效消息符合以下条件:

            1.匹配的顺序和回合。

             2.匹配的块哈希。

            3. 消息来自已知的验证者。

            4. 验证者在进入 PREPARE   状态时广播 COMMIT  消息。

PREPARED -> COMMITTED

  • 验证者 收到有效 COMMIT 消息的 ceil(2N/3) 以进入 COMMITTED 状态。有效消息符合以下条件:

            1. 匹配的顺序和回合。

             2. 匹配的块哈希。

            3. 消息来自已知的验证者。

COMMITTED -> FINAL COMMITTED

验证者 ceil(2N/3) 承诺签名附加到 extraData 并尝试将块插入区块链。

当插入成功时,验证者进入  FINAL COMMITTED  状态。

FINAL COMMITTED -> NEW ROUND

验证者 选择一个新的 提议者 并开始新的一轮计时器。

轮换流程

1.三个条件可以触发 ROUND CHANGE

  • 回合更改计时器到期。

  • 无效的 PREPREPARE  消息。

  • 块插入失败。

2.当验证者注意到上述条件之一适用时,它会广播 ROUND CHANGE  消息以及提议的轮数,并等待来自其他验证者的 ROUND CHANGE 消息。根据以下条件选择建议的轮数:

  • 如果验证节点已收到来自其对等方的 ROUND CHANGE 消息,则它会选择具有 F + 1 ROUND CHANGE 消息的最大轮数。

  • 否则,它选择 1 + 当前轮数作为建议的轮数。

  • 每当验证者收到 F + 1 条关于相同提议轮数的 ROUND CHANGE 消息时,它会将收到的消息与自己的消息进行比较。如果接收到的更大,则验证节点再次使用接收到的数字广播 ROUND CHANGE  消息。

  • 在收到相同提议轮数的 ceil(2N/3)  ROUND CHANGE 消息后,验证者退出轮次变更循环,计算新的提议者,然后进入 NEW ROUND 状态。

  • 验证者跳出轮次更改循环的另一个条件是当它通过对等同步接收到已验证的块时。

推荐人选择

目前我们支持两种策略: 轮询 粘性提议者

轮询 轮询 是默认的提议者选择策略。在此设置中,提议者将在每个区块和轮次更改中更改。

粘性提议者:在粘性提议者设置中,提议者仅在发生轮次更改时才会更改。

验证人名单投票

Istanbul BFT  使用与 Clique 类似的验证节点投票机制,并从 Clique EIP   复制大部分内容。每个纪元交易都会重置验证人投票,这意味着任何用于添加 / 删除验证人的未决投票都会被重置。

对于所有交易块:

  • 提议者可以投一票来提议更改验证者列表。

  • 只有每个目标受益人的最新提案才会保存在单个验证者中。

  • 随着链的进展,投票会实时统计(允许并发提案)。

  • 达成多数共识 VALIDATOR_LIMIT 的提案立即生效。

  • 无效的提案不会因为客户端实现的简单性而受到惩罚。

  • 一项生效的提案需要放弃对该提案的所有未决投票(支持和反对)。

未来的消息和 储存

在异步网络环境中,人们可能会收到在当前状态下无法处理的未来消息。例如,验证者可以在 NEW ROUND 上接收 COMMIT  消息。我们称这种信息为 未来信息 。当验证者收到一条未来的消息时,它会将消息放入其 backlog 中,并在可能的情况下尝试稍后处理。

常数  

Istanbul BFT 定义了以下常量

  • EPOCH_LENGTH :默认值: 30000 块。检查点和重置未决投票之前的块数。

  • REQUEST_TIMEOUT :每轮共识超时在以毫秒为单位发射回合之前。

  • BLOCK_PERIOD :两个连续块之间的最小时间戳差异(以秒为单位)。

  • PROPOSER_POLICY :提议者选择策略,默认为 轮询

  • ISTANBUL_DIGEST :修复了用于 Istanbul 区块识别的区块头中 mixDigest 的幻数 0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365 

  • DEFAULT_DIFFICULTY :默认区块难度,设置为 0x0000000000000001

  • EXTRA_VANITY:为提议者虚荣保留的固定数量的额外数据前缀字节。

            1. 建议保留 32 字节以保留当前的额外数据限额。

  • NONCE_AUTH:Magic nonce number 0xffffffffffffffff用于投票添加验证者。

  • NONCE_DROP:Magic nonce number  0x0000000000000000 用于投票删除验证者。

  • UNCLE_HASH: 总是 Keccak256(RLP([]))作为叔节点在 PoW 之外毫无意义。

  • PREPREPARE_MSG_CODE:固定数字0。PREPREPARE消息的消息代码。

  • PREPARE_MSG_CODE:固定数字1。PREPARE 消息的消息代码。

  • COMMIT_MSG_CODE:固定编号2。COMMIT消息的消息代码。

  • ROUND_CHANGE_MSG_CODE:固定数字 3 . ROUND CHANGE 消息的消息代码

  • VALIDATOR_LIMIT:通过授权或取消授权提案的验证者数量。

            1. 必须是  floor(N / 2) + 1才能在链上强制执行多数共识。

区块头字段

Istanbul BFT 不会添加新的区块 头部字段 。相反,它遵循 Clique 重新调整 ethash  标头字段的用途,如下所示:

  • nonce :关于受益人字段定义的帐户的提案人提案。

            1. 应为 NONCE_DROP   以提议取消受益人作为现有验证人的授权。

            2. 应该是 NONCE_AUTH 提议授权受益人作为新的验证人。

            3. 必须用零填充, NONCE_DROP   NONCE_AUTH

  • mixHash :修正了用于 Istanbul 区块识别的幻数 0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365

  • ommersHash:必须是UNCLE_HASH,因为叔节点在 PoW 之外毫无意义。

  • timestamp:必须至少是父级时间戳 +  BLOCK_PERIOD

  • difficulty:必须填写 0x0000000000000001。

  • extraData:签名者vanity 和 RLP 编码的Istanbul 额外数据的组合字段,其中Istanbul 额外数据包含验证者列表、提议者印章和提交印章。伊斯坦布尔额外数据定义如下:

粘贴图片

因此, extraData 的形式为 EXTRA_VANITY | ISTANBUL_EXTRA | 表示用于 separate vanity and Istanbul extra data 的固定索引(不是分隔符的实际字符)。

  • 第一个 EXTRA_VANITY  字节(固定)可能包含任意提议者 vanity data

  • ISTANBUL_EXTRA  字节是从 RLP(IstanbulExtra)  计算得到的 RLP 编码的 IstanbulExtra  数据,其中 RLP() RLP 编码函数, IstanbulExtra 是伊斯坦布尔额外数据。

  •             1.Validators :验证节点列表,必须按升序排列。

                2.Seal :提议人签名盖章。

                3.CommittedSeal :作为共识证明的承诺签名印章列表。

    区块哈希、提议者密封和承诺密封

    由于以下原因, Istanbul 区块哈希计算与 ethash 区块哈希计算不同:

    1.  提议者需要将提议者的印章放在 extraData 中,以证明该区块是由选定的提议者签署的。

    验证者需要在 extraData 中放入 ceil(2N/3) commited seals 作为共识证明,以证明区块已经达成共识。

    计算仍然类似于 ethash 块哈希计算,只是我们需要处理 extraData 。我们计算字段如下:

    提议者印章计算

    到提议者印章计算时,这些待发印章仍然未知,所以我们计算那些未知的印章为空。计算如下:

    • Proposer seal: SignECDSA(Keccak256(RLP(Header)), PrivateKey)

    • PrivateKey :提议者的私钥。

    • Header: ethash 标头相同,只是具有不同的 extraData

    • extraData: vanity | RLP(IstanbulExtra) ,其中在 IstanbulExtra  中, CommittedSeal   Seal  是空数组。

    块哈希计算

    在计算区块哈希时,我们需要排除已提交的印章,因为数据在不同验证节点之间是动态的。因此,我们在计算哈希时将 CommittedSeal 设为空数组。计算是:

    • Header :与 ethash  标头相同,只是具有不同的 extraData

    • extraData: vanity | RLP(IstanbulExtra) ,其中在 IstanbulExtra  中, CommittedSeal 是一个空数组。

    共识证明

    在将区块插入区块链之前,每个验证者需要从其他验证者那里收集 ceil(2N/3) 提交的印章以组成共识证明。一旦它收到足够多的 committed seals ,它就会填充 IstanbulExtra 中的 CommittedSeal  ,重新计算 extraData ,然后将区块插入到区块链中。请注意,由于提交的印章可能因不同的来源而异,因此我们在计算块哈希时排除了该部分,如上一节所述。

    承诺密封计算:

    承诺印章由每个验证者签署哈希及其私钥的 COMMIT_MSG_CODE  消息代码来计算。计算如下:

    • Committed seal: SignECDSA(Keccak256(CONCAT(Hash, COMMIT_MSG_CODE)), PrivateKey).

    • CONCAT(Hash, COMMIT_MSG_CODE):  连接块哈希和 COMMIT_MSG_CODE 字节。

    • PrivateKey: 签名验证者的私钥。

    出处

    GoQuorum 中的 Istanbul BFT 实现基于 EIP 650 。自 EIP 开放以来,它已经更新,以通过引入锁定来解决安全问题。






     推荐知识

     历史版本

    修改日期 修改人 备注
    2021-07-20 13:53:19[当前版本] 姜天雨 修改内容
    2021-07-20 13:52:07 姜天雨 创建版本

     附件

    附件类型

    PNGPNG

      目录
      区块链服务网络发展联盟