深刻 Tendermint —— 共识算法

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

在以前的分享中,咱们有总体介绍过 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数据结构以下:

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

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

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 的数据结构以下:

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讨论群” 获取入群二维码


相关文章
相关标签/搜索