0%

深入Tendermint --- 出块节点选择

Tendermint本身是BFT+POS共识,在BFT之前需要先通过POS方法选出一个proposer来进行提案,proposer是从Validator节点中选出的,Validator是在创世区块(genesis.json)中配置的。

这里有两个概念区分一下: - validator:所有参与共识验证的节点 - proposer:出块节点,validator中选出来的出块节点

Proposer选择规则

validator可以配置一个或多个,但只会有一个Validator被选中作为proposer出块,那么如何选择proposer呢?Tendermint采取round-robin策略选择proposer。round-robin是什么意思呢?当Validator初始化完成后,全网每个节点会存储一份Validator副本,放在一个循环数据中,当链上区块达到一个新的高度后,就会进行一次proposer选举,一般一个区块高度(height)大部分情况下只需要一轮(round)就能产生,网络不好的时候可能要多轮才能出一个块,无论如何,每一轮都会有一个新的validator作为proposer, 轮换规则就是很简单的依次递增,第一轮,会选择数组中第0个validator作为proposer, 第二轮选择第1个validator,以此类推,当到达最后一个后重置为0,这样无限循环。这种round-robin策略,能有效的略过超时的proposer节点,使算法能自动进行下去。

上面提到proposer是通过round-robin方式从Validator数据组选出来的,那么Validator数组中的Validator是以什么规则被选中的呢?proposer选择顺序与Validato的votingPower(投票力)有关,谁的VotingPower大谁优先被选中为proposer。如果每一轮都选择votingPower最大的,那么会不会出现votingPower大的Validator会一直被选中,而其他votingPower小的Validator会一直没有机会称为proposer呢?为了解决这个问题Tendermint提供了一个votingPower更新算法,算法的规则如下:

  • Validator的初始votingPower与其stake是相等的,stake是什么?之前提到过Tendermint的共识算法是POS+BFT,这里的stake就是POS算法的权重,类似于POW算法的算力,用来衡量一个节点的权重的。如果Validator A在创世块中的stake是1,那么它的votingPower也会被初始化为1
  • 每一轮结束后都会对Validator的votingPower做一次更新
    • 如果一个Validator在当前轮中没有被选中为proposer,那么它的votingPower将增加,增加的值为它初始的stake,例如Validator A的初始化stake为1,如果A没有被选中为proposer,那么它的votingPower=pre_votingPower+stake。
    • 如果一个Validator在当前轮中被选中为proposer,那么它的votingPower将减少,减少的值为数组中其他Validator的stake之和,例如:Validator集合={A:1,B:2,C:3},如果C被选中为proposer,那么C的votingPower=pre_votingPower-(stake_a+stake_b)

例子演示

到此为止,关于出块节点的选择方式已经介绍完了,接下来将通过一个例子让大家直观地感受一下在Tendermint中出块节点的选择过程,下面这张图演示了如何选择proposer的过程:

validators

例:Validator集合={A:1,B:2,C:3}

首先假设我们在创世块中一个配置了三个Validator分别是A,B,C他们的stake分别是1,2,3,因此这三个Validator的votingPower也分别为:1,2,3。

在第一轮中,根据上文介绍的规则,Tendermint会选择votingPower最大的Validator作为proposer,所以在第一轮中proposer为C,就是上图中第一列中标红的方块。根据规则,每一轮结束后会对所有的Validator的votingPower做一次更新,所以从上图可以看出在第二轮中A,B,C的votingPower分别变成2,4,0。

以此类推,大家有兴趣可以推算一下第二轮,第三轮,第四轮中A,B,C各自的votingPower的变化。

从上图中可以看出,Validator C 在四轮中有两次被选中为proposer,这是由于每个Validator称为proposer的比率是与它的stake占所有Validator的stake比率有关,Validator C 的stake是3,其中总的stake为6,所以C称为proposer的比率是50%。

总结

Tendermint在创世块中有一组Validator,当链上区块达到一个新的高度时会首先触发Proposer选举,Proposer选举是通过round-robin这种轮询的方式产生的,每一轮结束后Tendermint会调整一次votingPower,每一个Validator节点出块比例与它的stake占总的stake有关。

优缺点总结:

  • 优点: Proposer的选择方式是与stake相关的,所以应用层可以实现自己的共识(如:DPOS),在应用层将计算好Validator的权重传递给Tendermint,Tendermint就会按照应用层需要的方式选择Proposer。

  • 缺点: Round-robin 策略太简单了,容易被坏人预测到下一个validator是谁,于是可以提前布局,对validator发起DDoS攻击或别的攻击。Tendermint的解决方法就是,把validator节点,全部放在 Sentry Node后面,对外不暴露IP地址。