Browse Source

state machine cleanup

pull/96/head
Jae Kwon 10 years ago
parent
commit
4d5fda7516
1 changed files with 39 additions and 34 deletions
  1. +39
    -34
      consensus/state.go

+ 39
- 34
consensus/state.go View File

@ -5,59 +5,64 @@ Consensus State Machine Overview:
* NewHeight, NewRound, Propose, Prevote, Precommit represent state machine steps. (aka RoundStep). * NewHeight, NewRound, Propose, Prevote, Precommit represent state machine steps. (aka RoundStep).
* To "prevote/precommit" something means to broadcast a prevote/precommit vote for something. * To "prevote/precommit" something means to broadcast a prevote/precommit vote for something.
* During NewHeight/NewRound/Propose/Prevote/Precommit: * During NewHeight/NewRound/Propose/Prevote/Precommit:
* Nodes gossip the locked proposal, if locked on a proposal.
* Nodes gossip the proposal proposed by the designated proposer for that round.
* Nodes gossip the proposal block proposed by the designated proposer for that round.
* Nodes gossip prevotes/precommits for rounds [0...currentRound+1] (currentRound+1 for catch-up) * Nodes gossip prevotes/precommits for rounds [0...currentRound+1] (currentRound+1 for catch-up)
* Nodes also gossip prevotes for the proposal's POL (proof-of-lock) round if proposed.
* Upon each state transition, the height/round/step is broadcast to neighboring peers. * Upon each state transition, the height/round/step is broadcast to neighboring peers.
* The set of +2/3 of precommits from the same round for a block "commits the block".
* The set of +2/3 of precommits at the same round for the same block is called a Commit, or Validation.
* A block contains the last block's Validation, which includes the Commit precommits.
While all the precommits in the Validation are from the same height & round (ordered by validator index),
some precommits may be nil (if the validator's precommit vote didn't reach the proposer in time),
or some precommits may be for different blockhashes for the last block hash (which is fine).
* NewRound:
* Set up new round. --> Then, goto Propose
* NewRound(height:H,round:R):
* Set up new round. --> goto Propose(H,R)
* NOTE: Not much happens in this step. It exists for clarity.
* Propose:
* Propose(height:H,round:R):
* Upon entering Propose: * Upon entering Propose:
* The designated proposer proposes a block.
* The designated proposer proposes a block for (H,R).
* The Propose step ends: * The Propose step ends:
* After `timeoutPropose` after entering Propose. --> Then, goto Prevote
* After receiving proposal block and POL prevotes are ready. --> Then, goto Prevote
* After any +2/3 prevotes received for the next round. --> Then, goto Prevote next round
* After any +2/3 precommits received for the next round. --> Then, goto Precommit next round
* After +2/3 precommits received for a particular block. --> Then, goto Commit
* After `timeoutPropose` after entering Propose. --> goto Prevote(H,R)
* After receiving proposal block and all POL prevotes. --> goto Prevote(H,R)
* After any +2/3 prevotes received for (H,R+1). --> goto Prevote(H,R+1)
* After any +2/3 precommits received for (H,R+1). --> goto Precommit(H,R+1)
* After +2/3 precommits received for a particular block. --> goto Commit(H)
* Prevote:
* Prevote(height:H,round:R):
* Upon entering Prevote, each validator broadcasts its prevote vote. * Upon entering Prevote, each validator broadcasts its prevote vote.
* If the validator is locked on a block, it prevotes that. * If the validator is locked on a block, it prevotes that.
* Else, if the proposed block from the previous step is good, it prevotes that.
* Else, if the proposed block from Propose(H,R) is good, it prevotes that.
* Else, if the proposal is invalid or wasn't received on time, it prevotes <nil>. * Else, if the proposal is invalid or wasn't received on time, it prevotes <nil>.
* The Prevote step ends: * The Prevote step ends:
* After +2/3 prevotes for a particular block or <nil>. --> Then, goto Precommit
* After `timeoutPrevote` after receiving any +2/3 prevotes. --> Then, goto Precommit
* After any +2/3 prevotes received for the next round. --> Then, goto Prevote next round
* After any +2/3 precommits received for the next round. --> Then, goto Precommit next round
* After +2/3 precommits received for a particular block. --> Then, goto Commit
* After +2/3 prevotes for a particular block or <nil>. --> goto Precommit(H,R)
* After `timeoutPrevote` after receiving any +2/3 prevotes. --> goto Precommit(H,R)
* After any +2/3 prevotes received for (H,R+1). --> goto Prevote(H,R+1)
* After any +2/3 precommits received for (H,R+1). --> goto Precommit(H,R+1)
* After +2/3 precommits received for a particular block. --> goto Commit(H)
* Precommit:
* Precommit(height:H,round:R):
* Upon entering Precommit, each validator broadcasts its precommit vote. * Upon entering Precommit, each validator broadcasts its precommit vote.
* If the validator had seen +2/3 of prevotes for a particular block,
* If the validator had seen +2/3 of prevotes for a particular block from Prevote(H,R),
it locks (changes lock to) that block and precommits that block. it locks (changes lock to) that block and precommits that block.
* Else, if the validator had seen +2/3 of prevotes for nil, it unlocks and precommits <nil>.
* Else, if +2/3 of prevotes for a particular block or nil is not received on time,
* Else, if the validator had seen +2/3 of prevotes for <nil>, it unlocks and precommits <nil>.
* Else, if +2/3 of prevotes for a particular block or <nil> is not received on time,
it precommits what it's locked on, or <nil>. it precommits what it's locked on, or <nil>.
* The Precommit step ends: * The Precommit step ends:
* After +2/3 precommits for a particular block. --> Then, goto Commit
* After +2/3 precommits for <nil>. --> Then, goto NewRound next round
* After `timeoutPrecommit` after receiving any +2/3 precommits. --> Then, goto NewRound next round
* After any +2/3 prevotes received for the next round. --> Then, goto Prevote next round
* After any +2/3 precommits received for the next round. --> Then, goto Precommit next round
* After +2/3 precommits for a particular block. --> goto Commit(H)
* After +2/3 precommits for <nil>. --> goto NewRound(H,R+1)
* After `timeoutPrecommit` after receiving any +2/3 precommits. --> goto NewRound(H,R+1)
* After any +2/3 prevotes received for (H,R+1). --> goto Prevote(H,R+1)
* After any +2/3 precommits received for (H,R+1). --> goto Precommit(H,R+1)
* Commit:
* Commit(height:H):
* Set CommitTime = now * Set CommitTime = now
* Wait until block is received, then goto NewHeight
* Wait until block is received. --> goto NewHeight(H+1)
* NewHeight:
* Upon entering NewHeight,
* Move Precommits to LastCommit and increment height.
* Wait until `CommitTime+timeoutCommit` to receive straggler commits. --> Then, goto NewRound round 0
* NewHeight(height:H):
* Move Precommits to LastCommit and increment height.
* Set StartTime = CommitTime+timeoutCommit
* Wait until `StartTime` to receive straggler commits. --> goto NewRound(H,0)
* Proof of Safety: * Proof of Safety:
If a good validator commits at round R, it's because it saw +2/3 of precommits for round R. If a good validator commits at round R, it's because it saw +2/3 of precommits for round R.


Loading…
Cancel
Save