类似Tendermint的共识协议,取消commit
阶段并使用leader
归票降低网络通信复杂度
docker build -t citacloud/consensus_bft .
$ consensus -h
consensus 6.6.0
Rivtower Technologies <contact@rivtower.com>
This doc string acts as a help message when the user runs '--help' as do all doc strings on fields
USAGE:
consensus <SUBCOMMAND>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
run run this service
运行consensus
服务。
$ consensus run -h
consensus-run
run this service
USAGE:
consensus run [OPTIONS]
OPTIONS:
-c, --config <CONFIG_PATH> Chain config path [default: config.toml]
-h, --help Print help information
-l, --log <LOG_FILE> log config path [default: consensus-log4rs.yaml]
参数:
-
微服务配置文件。
参见示例
example/config.toml
。其中:
consensus_port
为该服务监听的端口号。
-
日志配置文件。
参见示例
consensus-log4rs.yaml
。其中:
level
为日志等级。可选项有:Error
,Warn
,Info
,Debug
,Trace
,默认为Info
。appenders
为输出选项,类型为一个数组。可选项有:标准输出(stdout
)和滚动的日志文件(journey-service
),默认为同时输出到两个地方。
$ consensus run -c example/config.toml -l consensus-log4rs.yaml
2022-03-10T10:04:09.850581+08:00 INFO consensus - start consensus bft
2022-03-10T10:04:09.851129+08:00 INFO consensus - grpc port of this service: 50001
- Leader send new proposal success
- Leader send new proposal fail
- Leader retry send new proposal success
- When leader receive the Prevote vote from follower,if it has send the proposal, and collect above 2/3 Prevote votes then change to PrecommitWait
- ProposeWait timeout and leader has collect above 2/3 Prevote votes, then
- send Prevote vote with None hash
- start new round
- When leader receive the Precommit vote, and it has collect above 2/3 Precommit votes. If current leader isn't the (next height, init round) leader then change to CommitWait temporary and soon change to Commit else change to Commit
- Leader send message timeout and hasn't collect above 2/3 votes, change to NewView
- In the case below, change to Proposal
- CommitWait timeout and deal old height success
- Commit timeout and check and commit block failed, then start new round
- Leader has collect 2f NewView votes, start new round
- When leader receive Prevote, in the case below change to Proposal
- has collect 2f Prevote and self.round behind round, start new round
- hash in the voteset which is above 2/3 n is zero, start new round
- hasn't receive the Proposal yet which the hash is above 2/3 n, start new round
- When leader receive Precommit, in the case below change to Proposal
- hash in the voteset which is above 2/3 n is zero, start new round
- self.proposal not equal the hash in the voteset which is above 2/3 n, start new round
- else if check and commit block failed, then start new round
- Follower hasn't receive the Proposal
- Follower has receive the Proposal and add to proposals, hash_proposals , set proposal and send Prevote
- When receive the LeaderPrevote , check it, save to wal and send Precommit
- In the case below, change to CommitWait/Commit
- When receive the LeaderPrevote and change to PrecommitWait success, and if has receive LeaderPrecommit with above 2/3 Precommit from leader, then enter the follow case
- When follower receive the LeaderPrecommit with above 2/3 Precommit votes and save to wal, If current leader isn't the (next height, init round) leader then change to CommitWait temporary and soon change to Commit else change to Commit
- Follower receive Precommit whose hash is zero or check and commit block failed, start new round, change to Proposal
- Follower receive Prevote whose hash is zero, or hasn't receive the proposal , then start new round, change to Proposal
- In the case below, change to Proposal
- CommitWait timeout and deal old height success
- Commit timeout and check and commit block failed, then start new round
- Follower send message timeout and send NewView message, then change to NewView
- Follower has collect 2f NewView votes, start new round
-
启动
- 加载配置
- 创建
controller<->bft
,network<->bft
,timeout->bft
的通道channel
,并将通道channel
句柄放入bft_channels
- 初始化
bft
并开始select loop
- 启动
server
,添加uri
匹配规则,监听指定端口,并将匹配的uri
转发至相应的通道channel
-
运行
controller->bft
的reconfigure
及check_block
请求,做出相应处理,并返回处理结果reconfigure
- 更新
auth_manage
及is_consensus_node
- 如果当前节点是
(next height, init round)
的leader
,则请求controller
GetProposal
,根据结果值设置proposal
self_proposal
proposals
及相关值,并发送new proposal
- 更新
check_block
- 检查收到的
LeaderVote
中的vote
是否正确
- 检查收到的
network->bft
的消息会根据其VoteMsgtype
进行相应处理,并根据发送消息至其他节点Proposal
- 只有
follower
会收到该消息,在校验(height, round, step)
通过,请求controller
CheckProposal
,将其加入votes
- 上一步检查通过后,设置proposal self_proposal proposals,发送自己的Prevote消息,变更状态,设置超时时间
- 只有
Prevote
leader
收到消息校验(height, round, step)
及消息的发送节点的正确性后,将其加入votes
- 上一步检查通过后,检查
Prevote
数量进行相应处理,详见状态转换
Precommit
leader
收到消息校验(height, round, step)
及消息的发送节点的正确性后,将其加入votes
- 上一步检查通过后,检查
Precommit
数量进行相应处理,详见状态转换
LeaderPrevote
- follower收到消息校验
(height, round, step)
,消息的发送节点的正确性,及其票数是否超过2/3
后,将其加入votes
,并保存至wal
- 上一步检查通过后,做进一步处理,详见状态转换
- follower收到消息校验
LeaderPrecommit
follower
收到消息校验(height, round, step)
,消息的发送节点的正确性,及其票数是否超过2/3
后,将其加入votes
,并保存至wal
- 上一步检查通过后,做进一步处理,详见状态转换
NewView
- 收到消息校验
(height, round, step)
,消息的发送节点的正确性后,将其加入votes
- 上一步检查通过后,若当前节点收到
2f
个NewView
,发送NewView
消息,开始新的round
- 收到消息校验
timeout->bft
根据超时的消息类型及是否是对应height round
的leader
做相应处理