概览
BFT的节点根据是否参与投票可以区分为验证节点和非验证节点,其中验证节点需要参与每一个区块的投票。 这里有几个关键的特定词:
- Epoch : 每个epoch中包含多个round,单个epoch中验证者列表是固定的,这个列表不会随时变动否则会影响投票递进。
- Round : 每一轮Round有一个Leader,这个Leader会根据收到的交易打包出新的待投票的区块。
- Voting Power : 这个一般根据质押的代币数量来决定当前节点的VP。
共识层的代码会收到别的节点打包好发过来的消息,验证者需要单独的验证消息的内容。一般在单个节点的本地在新的Round 开始的时候会设置一个计时器,这个计时器的作用就是保证每个Round都能按照一定的周期推进。 投票的内容可以区分为3大类
- TC : 本次Round的Leader没有在规定的时间范围之内打包好区块并且广播出去
- NEC : 本地节点对区块的内容投票不背书
- QC : QC的生成需要投票背书VP达到总量的>= 2/3 + 1
TC的详细流程
待添加中…
QC的详细流程
通过一段RUST实现的BFT,可以详细梳理下整个QC的流程:
pub fn process_vote<VT>(
&mut self,
author: &NodeId<SCT::NodeIdPubKey>,
vote_msg: &VoteMessage<SCT>,
validators: &VT,
validator_mapping: &ValidatorMapping<
SCT::NodeIdPubKey,
SignatureCollectionKeyPairType<SCT>,
>,
) -> (Option<QuorumCertificate<SCT>>, Vec<VoteStateCommand>)
参数内容:
- author:这个消息的发送节点
- vote_msg: 发送的消息内容,包含投票的Round和Vote内容
- validators: 当前Epoch中包含的验证者列表
当本地节点收到投票消息之后:
- 首先需要验证Round是否已经过期(由于网络延迟等原因造成),过期消息不再被处理
- 本地节点需要存储当前Round收到的所有消息,包含节点ID(author)和投票内容
- 然后将本次的内容插入到上诉的消息列表中,然后我们就得到了当前Round的所有投票内容
- 这时我们就可以开始计算VP,当VP >= 总VP * 2/3 + 1的时候,当前节点就可以为本轮Round生成QC
- 在生成QC之前本地节点还需要循环每个消息去验证签名信息,如果有非法的签名,就把这个签名的节点信息移出pending的消息列表,当移出之后再次检查VP的数量是否能够满足上诉的条件
- 一般情况下签名的内容应该都是合法的,否则签名的节点会受到相应的处罚。
- 当所有签名合法之后开始生成QC,并且更新本地的Round到Round+1
NEC的详细流程
待添加中…