|
|
@ -88,20 +88,20 @@ var ( |
|
|
|
) |
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// RoundStep enum type
|
|
|
|
// RoundStepType enum type
|
|
|
|
|
|
|
|
type RoundStep uint8 |
|
|
|
type RoundStepType uint8 // These must be numeric, ordered.
|
|
|
|
|
|
|
|
const ( |
|
|
|
RoundStepNewHeight = RoundStep(0x00) // Round0 for new height started, wait til CommitTime + Delta
|
|
|
|
RoundStepNewRound = RoundStep(0x01) // Pseudostep, immediately goes to RoundStepPropose
|
|
|
|
RoundStepPropose = RoundStep(0x10) // Did propose, gossip proposal
|
|
|
|
RoundStepPrevote = RoundStep(0x11) // Did prevote, gossip prevotes
|
|
|
|
RoundStepPrecommit = RoundStep(0x12) // Did precommit, gossip precommits
|
|
|
|
RoundStepCommit = RoundStep(0x20) // Entered commit state machine
|
|
|
|
RoundStepNewHeight = RoundStepType(0x01) // Round0 for new height started, wait til CommitTime + Delta
|
|
|
|
RoundStepNewRound = RoundStepType(0x02) // Pseudostep, immediately goes to RoundStepPropose
|
|
|
|
RoundStepPropose = RoundStepType(0x03) // Did propose, gossip proposal
|
|
|
|
RoundStepPrevote = RoundStepType(0x04) // Did prevote, gossip prevotes
|
|
|
|
RoundStepPrecommit = RoundStepType(0x05) // Did precommit, gossip precommits
|
|
|
|
RoundStepCommit = RoundStepType(0x06) // Entered commit state machine
|
|
|
|
) |
|
|
|
|
|
|
|
func (rs RoundStep) String() string { |
|
|
|
func (rs RoundStepType) String() string { |
|
|
|
switch rs { |
|
|
|
case RoundStepNewHeight: |
|
|
|
return "RoundStepNewHeight" |
|
|
@ -123,15 +123,15 @@ func (rs RoundStep) String() string { |
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// RoundAction enum type
|
|
|
|
|
|
|
|
type RoundActionType uint8 |
|
|
|
type RoundActionType string |
|
|
|
|
|
|
|
const ( |
|
|
|
RoundActionPropose = RoundActionType(0xA0) // Propose and goto RoundStepPropose
|
|
|
|
RoundActionPrevote = RoundActionType(0xA1) // Prevote and goto RoundStepPrevote
|
|
|
|
RoundActionPrecommit = RoundActionType(0xA2) // Precommit and goto RoundStepPrecommit
|
|
|
|
RoundActionTryCommit = RoundActionType(0xC0) // Goto RoundStepCommit, or RoundStepPropose for next round.
|
|
|
|
RoundActionCommit = RoundActionType(0xC1) // Goto RoundStepCommit upon +2/3 commits
|
|
|
|
RoundActionTryFinalize = RoundActionType(0xC2) // Maybe goto RoundStepPropose for next round.
|
|
|
|
RoundActionPropose = RoundActionType("PR") // Propose and goto RoundStepPropose
|
|
|
|
RoundActionPrevote = RoundActionType("PV") // Prevote and goto RoundStepPrevote
|
|
|
|
RoundActionPrecommit = RoundActionType("PC") // Precommit and goto RoundStepPrecommit
|
|
|
|
RoundActionTryCommit = RoundActionType("TC") // Goto RoundStepCommit, or RoundStepPropose for next round.
|
|
|
|
RoundActionCommit = RoundActionType("CM") // Goto RoundStepCommit upon +2/3 commits
|
|
|
|
RoundActionTryFinalize = RoundActionType("TF") // Maybe goto RoundStepPropose for next round.
|
|
|
|
) |
|
|
|
|
|
|
|
func (rat RoundActionType) String() string { |
|
|
@ -171,7 +171,7 @@ func (ra RoundAction) String() string { |
|
|
|
type RoundState struct { |
|
|
|
Height uint // Height we are working on
|
|
|
|
Round uint |
|
|
|
Step RoundStep |
|
|
|
Step RoundStepType |
|
|
|
StartTime time.Time |
|
|
|
CommitTime time.Time // Time when +2/3 commits were found
|
|
|
|
Validators *sm.ValidatorSet |
|
|
@ -187,7 +187,6 @@ type RoundState struct { |
|
|
|
Precommits *VoteSet |
|
|
|
Commits *VoteSet |
|
|
|
LastCommits *VoteSet |
|
|
|
PrivValidator *sm.PrivValidator |
|
|
|
} |
|
|
|
|
|
|
|
func (rs *RoundState) String() string { |
|
|
@ -241,6 +240,7 @@ type ConsensusState struct { |
|
|
|
|
|
|
|
blockStore *bc.BlockStore |
|
|
|
mempoolReactor *mempl.MempoolReactor |
|
|
|
privValidator *sm.PrivValidator |
|
|
|
runActionCh chan RoundAction |
|
|
|
newStepCh chan *RoundState |
|
|
|
|
|
|
@ -318,6 +318,7 @@ func (cs *ConsensusState) stepTransitionRoutine() { |
|
|
|
// For clarity, all state transitions that happen after some timeout are here.
|
|
|
|
// Schedule the next action by pushing a RoundAction{} to cs.runActionCh.
|
|
|
|
scheduleNextAction := func() { |
|
|
|
// NOTE: rs must be fetched in the same callstack as the caller.
|
|
|
|
rs := cs.getRoundState() |
|
|
|
go func() { |
|
|
|
// NOTE: We can push directly to runActionCh because
|
|
|
@ -491,7 +492,12 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) { |
|
|
|
cs.Round = 0 |
|
|
|
cs.Step = RoundStepNewHeight |
|
|
|
if cs.CommitTime.IsZero() { |
|
|
|
cs.StartTime = state.LastBlockTime.Add(newHeightDelta) |
|
|
|
// "Now" makes it easier to sync up dev nodes.
|
|
|
|
// We add newHeightDelta to allow transactions
|
|
|
|
// to be gathered for the first block.
|
|
|
|
// And alternative solution that relies on clocks:
|
|
|
|
// cs.StartTime = state.LastBlockTime.Add(newHeightDelta)
|
|
|
|
cs.StartTime = time.Now().Add(newHeightDelta) |
|
|
|
} else { |
|
|
|
cs.StartTime = cs.CommitTime.Add(newHeightDelta) |
|
|
|
} |
|
|
@ -521,12 +527,12 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) { |
|
|
|
} |
|
|
|
|
|
|
|
// If we've timed out, then send rebond tx.
|
|
|
|
if cs.PrivValidator != nil && cs.state.UnbondingValidators.HasAddress(cs.PrivValidator.Address) { |
|
|
|
if cs.privValidator != nil && cs.state.UnbondingValidators.HasAddress(cs.privValidator.Address) { |
|
|
|
rebondTx := &types.RebondTx{ |
|
|
|
Address: cs.PrivValidator.Address, |
|
|
|
Address: cs.privValidator.Address, |
|
|
|
Height: cs.Height + 1, |
|
|
|
} |
|
|
|
err := cs.PrivValidator.SignRebondTx(rebondTx) |
|
|
|
err := cs.privValidator.SignRebondTx(rebondTx) |
|
|
|
if err == nil { |
|
|
|
log.Info("Signed and broadcast RebondTx", "height", cs.Height, "round", cs.Round, "tx", rebondTx) |
|
|
|
cs.mempoolReactor.BroadcastTx(rebondTx) |
|
|
@ -565,7 +571,7 @@ func (cs *ConsensusState) setupNewRound(round uint) { |
|
|
|
func (cs *ConsensusState) SetPrivValidator(priv *sm.PrivValidator) { |
|
|
|
cs.mtx.Lock() |
|
|
|
defer cs.mtx.Unlock() |
|
|
|
cs.PrivValidator = priv |
|
|
|
cs.privValidator = priv |
|
|
|
} |
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
@ -598,14 +604,14 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) { |
|
|
|
}() |
|
|
|
|
|
|
|
// Nothing to do if it's not our turn.
|
|
|
|
if cs.PrivValidator == nil { |
|
|
|
if cs.privValidator == nil { |
|
|
|
return |
|
|
|
} |
|
|
|
if !bytes.Equal(cs.Validators.Proposer().Address, cs.PrivValidator.Address) { |
|
|
|
log.Debug("Not our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.PrivValidator) |
|
|
|
if !bytes.Equal(cs.Validators.Proposer().Address, cs.privValidator.Address) { |
|
|
|
log.Debug("Not our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.privValidator) |
|
|
|
return |
|
|
|
} else { |
|
|
|
log.Debug("Our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.PrivValidator) |
|
|
|
log.Debug("Our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.privValidator) |
|
|
|
} |
|
|
|
|
|
|
|
var block *types.Block |
|
|
@ -673,7 +679,7 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) { |
|
|
|
|
|
|
|
// Make proposal
|
|
|
|
proposal := NewProposal(cs.Height, cs.Round, blockParts.Header(), polParts.Header()) |
|
|
|
err := cs.PrivValidator.SignProposal(proposal) |
|
|
|
err := cs.privValidator.SignProposal(proposal) |
|
|
|
if err == nil { |
|
|
|
log.Info("Signed and set proposal", "height", cs.Height, "round", cs.Round, "proposal", proposal) |
|
|
|
log.Debug(Fmt("Signed and set proposal block: %v", block)) |
|
|
@ -1059,7 +1065,7 @@ func (cs *ConsensusState) stageBlock(block *types.Block, blockParts *types.PartS |
|
|
|
} |
|
|
|
|
|
|
|
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.PartSetHeader) *types.Vote { |
|
|
|
if cs.PrivValidator == nil || !cs.Validators.HasAddress(cs.PrivValidator.Address) { |
|
|
|
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.Address) { |
|
|
|
return nil |
|
|
|
} |
|
|
|
vote := &types.Vote{ |
|
|
@ -1069,10 +1075,10 @@ func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.Part |
|
|
|
BlockHash: hash, |
|
|
|
BlockParts: header, |
|
|
|
} |
|
|
|
err := cs.PrivValidator.SignVote(vote) |
|
|
|
err := cs.privValidator.SignVote(vote) |
|
|
|
if err == nil { |
|
|
|
log.Info("Signed and added vote", "height", cs.Height, "round", cs.Round, "vote", vote) |
|
|
|
cs.addVote(cs.PrivValidator.Address, vote) |
|
|
|
cs.addVote(cs.privValidator.Address, vote) |
|
|
|
return vote |
|
|
|
} else { |
|
|
|
log.Warn("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "error", err) |
|
|
|