大致可以将consensus分为 自身状态机(由外部消息驱动和timeout驱动),其他节点状态机(由外部消息驱动)-驱动gossip,以及为了恢复状态的WAL。
自身状态机
自身状态机的实现基本如 tendermint算法描述。
其他peer状态机
其他节点状态机通过接受其他peer的消息,来更新其他peer的状态,同时维护3个协程(gossipData,gossipVotes,gossipMaj23)来帮助其他节点获取消息,
和1个广播协程来告知自身的状态。
consensus将消息分为:
-
stateChannel
, 用于通知其他节点本节点的状态。
NewRoundStep
用于更新peer的共识阶段,
NewValidBlockMessage
,当节点有validblock时,会告知其他节点的需要的blockParts。
HasVoteMessage
,告知其他节点已经含有的vote。
VoteSetMaj23Message
告知其他节点已经有maj23,收到的节点会发送voteSetBitsMessage
以进一步更新自己的状态,希望更准确获取votes。 -
dataChannel
, 主要是proposalMessage
和blockPartMessage
-
VoteChannel
, 包括prevote
和precommit
的vote。 -
voteSetBitsChannel
,voteSetsBitsMessage
用于更新节点已经有的voteBitArray,这样可以更准确地发送必要的votes给该peer。
WAL
为了防止节点异常故障退出导致状态丢失,每次timeout事件,newRoundStep
事件,proposalMessage
,blockPartMessage
, voteMessage
等都会写入
WAL,在启动时会play从特定高度后所有的消息,来恢复consensusState
的状态。
在节点启动时,上replay 上述WAL之前,会replay state db中的高度到blockstore
中更高高度的block。