From 32811c3f861e31788611a39e15f96d98589bce60 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 25 Jun 2015 12:52:16 -0700 Subject: [PATCH] comment cleanup --- consensus/reactor.go | 2 +- consensus/state.go | 53 ++++++++++++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/consensus/reactor.go b/consensus/reactor.go index c8cce2d79..9b515ac44 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -353,7 +353,7 @@ OUTER_LOOP: } // If the peer is on a previous height, help catch up. - if 0 < prs.Height && prs.Height < rs.Height { + if (0 < prs.Height) && (prs.Height < rs.Height) { //log.Debug("Data catchup", "height", rs.Height, "peerHeight", prs.Height, "peerProposalBlockParts", prs.ProposalBlockParts) if index, ok := prs.ProposalBlockParts.Not().PickRandom(); ok { // Ensure that the peer's PartSetHeader is correct diff --git a/consensus/state.go b/consensus/state.go index a1be04d15..cd22ac233 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1,31 +1,35 @@ /* - Consensus State Machine Overview: + 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: - * Nodes gossip the proposal block proposed by the designated proposer at round. - * Nodes gossip prevotes/precommits at rounds [0...currentRound+1] (currentRound+1 to allow round-skipping) - * Nodes gossip prevotes for the proposal's POL (proof-of-lock) round if proposed. - * Nodes gossip to late nodes (lagging in height) with precommits of the commit round (aka catchup) + During NewHeight/NewRound/Propose/Prevote/Precommit: + * Nodes gossip the proposal block proposed by the designated proposer at round. + * Nodes gossip prevotes/precommits at rounds [0...currentRound+1] (currentRound+1 to allow round-skipping) + * Nodes gossip prevotes for the proposal's POL (proof-of-lock) round if proposed. + * Nodes gossip to late nodes (lagging in height) with precommits of the commit round (aka catchup) - 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 at the same round for the same block is called a Commit, or Validation. + 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 (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). + 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 (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). - Each unlock/change-of-lock should be justifiable by an POL where +2/3 prevoted for - some block or at some round. + Each unlock/change-of-lock should be justifiable by an POL where +2/3 prevoted for + some block or at some round. - POL = Proof-of-Lock = +2/3 prevotes for block B (or +2/3 prevotes for ) at (H,R) - lockRound < POLRound <= unlockOrChangeLockRound + POL = Proof-of-Lock = +2/3 prevotes for block B (or +2/3 prevotes for ) at (H,R) + lockRound < POLRound <= unlockOrChangeLockRound + + Without the POLRound <= unlockOrChangeLockRound condition, an unlock would be possible from a + future condition that hasn't happened yet, so it destroys deterministic accountability. + With lockRound < POLRound <= unlockOrChangeLockRound, blame can be shifted to lower rounds. * NewRound(height:H,round:R): * Set up new round. --> goto Propose(H,R) @@ -89,6 +93,13 @@ are fixed, so eventually we'll be able to "fully gossip" the block & POL. TODO: cap the block.size at something reasonable. Lemma 2: If a good node is at round R, neighboring good nodes will soon catch up to round R. + Lemma 3: If a node at (H,R) receives +2/3 prevotes for a block (or +2/3 for ) at (H,R+1), + it will enter NewRound(H,R+1). + Lemma 4: Terminal conditions imply the existence of deterministic accountability, for + a synchronous (fixed-duration) protocol extension (judgement). + TODO: define terminal conditions (fork and non-decision). + TODO: define new assumptions for the synchronous judgement period. + +-------------------------------------+ v |(Wait til `CommmitTime+timeoutCommit`) @@ -1019,7 +1030,11 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote, peerKey stri prevotes := cs.Votes.Prevotes(vote.Round) log.Debug(Fmt("Added to prevotes: %v", prevotes.StringShort())) // First, unlock if prevotes is a valid POL. - if cs.LockedBlock != nil && cs.LockedRound < vote.Round { + // >> lockRound < POLRound <= unlockOrChangeLockRound (see spec) + // NOTE: If (lockRound < POLRound) but !(POLRound <= unlockOrChangeLockRound), + // we'll still EnterNewRound(H,vote.R) and EnterPrecommit(H,vote.R) to process it + // there. + if (cs.LockedBlock != nil) && (cs.LockedRound < vote.Round) && (vote.Round <= cs.Round) { hash, _, ok := prevotes.TwoThirdsMajority() if ok && !cs.LockedBlock.HashesTo(hash) { log.Info("Unlocking because of POL.", "lockedRound", cs.LockedRound, "POLRound", vote.Round)