深入 Tendermint —— 共识算法

​PPIO 是为开发者打造的去中心化存储与分发平台,让数据更便宜、更高速、更隐私。官方网站是 https://pp.io。

深入 Tendermint —— 共识算法_第1张图片在之前的分享中,我们有整体介绍过 Tendermint 实现跨链的整个流程,以及他的易使用,易理解,高性能的相关特点(可参考之前的文章《Tendermint 介绍及实战分析》)。并且简要的介绍了Tendermint 共识算法,状态机复制及 ABCI 接口的相关知识。基于上次的分享,今天我们从根本原理上,来着重剖析 Tendermint 业务逻辑中最复杂,也是最重要的环节——共识算法。

我们知道分布式一致性算法一般可以分为两类:拜占庭容错和非拜占庭容错。非拜占庭容错算法如 Paxos, Raft 等在当前的分布式系统中已经广泛使用,而拜占庭容错算法的实际应用范围相对来说小很多(特别是在区块链问世之前)。Tendermint 属于拜占庭容错算法,它针对传统的PBFT算法做了优化,只需要有两轮投票即可达成共识,目前 Tendermint 算法主要应用在区块链系统中。

Round-based协议

首先我们先说一下Round-based协议。在Tendermint中一共有三种类型的投票:prevote,precommit和commit。当一个block被全网络commit的话,意味着这个block已经被全网超过2/3的Validator签名并广播了。

vote数据结构如下:

深入 Tendermint —— 共识算法_第2张图片

在链达到一个新的 Height 时候,系统会运行一个 round-based 协议来决定下一个block。round-based 协议由以下三个步骤构成:proposal,prevote,precommit。以及两个特殊步骤:commit,NewHeight。其中 propose,prevote 和 precommit 会分别占用整个 round 1/3时间。每一 round 的时间会比上一 round 的时间长一点,这是为了让网络在部分同步的情况下最终达成一致性共识。

round-based 协议运行过程如下:

深入 Tendermint —— 共识算法_第3张图片

round-based 协议是一个状态机,主要有 NewHeigh -> Propose -> Prevote -> Precommit -> Commit 一共 5 个状态。上述每个状态都被称为一个 Step。首尾的 NewHeigh 和 Commit ,这两个 Steps 被称为特殊的 Step。而中间循环三个 Steps 则被称为一个 Round,是共识阶段,也是算法的核心原理所在。一个块的最终提交(Commit)可能需要多个 Round 过程,这是因为有许多原因可能会导致当前 Round 不成功(比如出块节点 Offline,提出的块是无效块,收到的 Prevote 或者 Precommit 票数不够 +2/3 等等)。出现这些情况的话,解决方案就是移步到下一轮,或者增加 timeout 时间。

当区块链达到一个新的高度时进入 NewHeight 阶段。接下来 Propose 阶段会提交一个 proposal ,prevote 阶段会对收到的 proposal 进行 prevote 投票。在 precommit 阶段收集到+⅔ prevote 投票后,对 block 进行 precommit 投票。如果收集到+⅔ precommit 投票后则进入 commit 阶段,如果没有收集到+⅔ precommit 投票,会再次进入 propose 阶段。在共识阶段期间如果收到+⅔ commit 投票那么直接进入 commit 阶段。

以上就是算法运行的整体过程,接下来分阶段来阐述各个阶段。

Proposal

在每一轮开始前会通过 round-robin 方式选出一个 proposer,选出的  proposal  会提交这一轮的  proposal。proposer 的选择规则请查看之前的一篇文章《出块节点选择》

proposal  的数据结构如下:

深入 Tendermint —— 共识算法_第4张图片

Prevote

在 Prevote 开始阶段,每个 Validator 会判断自己是否锁定在上一轮的 proposed 区块上,如果锁定在之前的 proposal 区块中,那么在本轮中继续为之前锁定的 proposal 区块签名并广播 prevote 投票。否则为当前轮中接收到的 proposal 区块签名并广播prevote 投票。如果由于某些原因当前 Validator 并没有收到任何 proposal 区块,那么签名并广播一个空的 prevote 投票。

Precommit

在  precommit  开始阶段,每个  Validator  会判断,如果收集到了超过 2/3 prevote 投票,那么为这个区块签名并广播  precommit  投票,并且当前  Validator  会锁定在这个区块上,同时释放之前锁定的区块。。一个 Validator 一次只能锁定在一个区块上。如果一个 Validator 收集到超过2/3空区块(nil)的  prevote  投票,那么释放之前锁定的区块。处于锁定状态的  Validator  会为锁定的区块收集  prevote  投票,并把这些投票打成包放入 proof-of-lock  中,proof-of-lock 会在之后的propose阶段用到。如果一个  Validator 没有收集到超过2/3的  prevote  投票,那么它不会锁定在任何区块上。这里,介绍一个重要概念:PoLC,全称为 Proof of Lock Change,表示在某个特定的高度和轮数(height, round),对某个块或 nil (空块)超过总结点 2/3 的 Prevote 投票集合。简单来说 PoLC 就是 Prevote 的投票集。

在 precommit 阶段后期,如果  Validator  收集到超过2/3的  precommit  投票,那么 Validator  进入到  commit  阶段。否则进入下一轮的 propose 阶段。

Commit

commit  阶段分为两个并行的步骤:

  1. Validator 收到了被全网  commit  的区块,Validator  会为这个区块广播一个commit 投票。

  2. Validator 需要为被全网络precommit的区块,收集到超过 ⅔ commit投票。

一旦两个条件全部满足了,节点会将 commitTime 设置到当前时间上,并且会进入NewHeight 阶段。

在整个共识过程的任何阶段,一旦节点收到超过⅔ commit 投票,那么它会立刻进入到commit 阶段。

为什么不会分叉?

如果小于1/3节点是拜占庭节点(如果大于等于1/3,那么共识就没法达成了)。当validator commit 了区块 B,那么表示有大于2/3的节点在R轮投了 precommit,这表示至少有大于1/3节点(大于1/3节点哪儿来的呢?就是大于2/3减去小于⅓。为什么是这么算呢?

有人说不是有大于2/3的节点投了 precommit ,那么这些人不都是诚实的节点吗?当然不是了,拜占庭节点的意思它工作随性,有时候正确有时候失败。假设这个时候所有的拜占庭节点正确的工作了,所以都算在在+2/3节点内,所以这么算了)被 lock在了 R‘>R。如果这个时候有针对同一区块高度的投票,那么由于这+1/3节点被 lock在了 R’ 轮,所以不会有+2/3的节点投 prevote,也就不会在同一高度达成一个新的共识区块,所以就不会分叉。

所以 Tendermint 不分叉是基于它是 BFT 共识,然后加上 PoLC 共同完成。

今天我们带大家一起深入学习了,Tendermint 中的共识算法部分。重点介绍了 round-based 协议运行过程,以及在运行过程中 Propose 、 Prevote 、Precommit 和 Commit 环节的具体实现步骤。相信通过这两期文章,大家应该对 Tendermint 技术有了更深入的了解。

今后我们还会和大家探讨更多区块链技术方面的知识,如果您想更进一步的和我们一起学习探索,就快来关注 PPIO 公众号,加入 PPIO 开发者社区或 Discord 群组,和我们一起创造精彩。

 

想了解更多有关 PPIO 的信息,可以移步官网:pp.io

如果你想更进一步了解项目,欢迎加入我们的微信讨论群,后台回复“PPIO讨论群” 获取入群二维码

你可能感兴趣的:(PPIO,block)