diff --git a/consensus/state.go b/consensus/state.go index 6374e7d7e..6352769bb 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -317,7 +317,8 @@ 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(rs *RoundState) { + scheduleNextAction := func() { + rs := cs.getRoundState() go func() { // NOTE: We can push directly to runActionCh because // we're running in a separate goroutine, which avoids deadlocks. @@ -350,14 +351,19 @@ func (cs *ConsensusState) stepTransitionRoutine() { // There's nothing to scheudle, we're waiting for // ProposalBlockParts.IsComplete() && // Commits.HasTwoThirdsMajority() - //panic("The next action from RoundStepCommit is not scheduled by time") + panic("The next action from RoundStepCommit is not scheduled by time") default: panic("Should not happen") } }() } - scheduleNextAction(cs.getRoundState()) + if cs.getRoundState().Step < RoundStepCommit { + scheduleNextAction() + } else { + // Race condition with receipt of commits, maybe. + // We shouldn't have to schedule anything. + } // NOTE: All ConsensusState.RunAction*() calls come from here. // Since only one routine calls them, it is safe to assume that @@ -396,7 +402,7 @@ ACTION_LOOP: continue ACTION_LOOP } cs.RunActionPropose(rs.Height, rs.Round) - scheduleNextAction(rs) + scheduleNextAction() continue ACTION_LOOP case RoundActionPrevote: @@ -404,7 +410,7 @@ ACTION_LOOP: continue ACTION_LOOP } cs.RunActionPrevote(rs.Height, rs.Round) - scheduleNextAction(rs) + scheduleNextAction() continue ACTION_LOOP case RoundActionPrecommit: @@ -412,7 +418,7 @@ ACTION_LOOP: continue ACTION_LOOP } cs.RunActionPrecommit(rs.Height, rs.Round) - scheduleNextAction(rs) + scheduleNextAction() continue ACTION_LOOP case RoundActionTryCommit: @@ -427,7 +433,7 @@ ACTION_LOOP: // Could not commit, move onto next round. cs.SetupNewRound(rs.Height, rs.Round+1) // cs.Step is now at RoundStepNewRound - scheduleNextAction(rs) + scheduleNextAction() continue ACTION_LOOP } @@ -449,7 +455,7 @@ ACTION_LOOP: cs.evsw.FireEvent(types.EventStringNewBlock(), newBlock) cs.evc.Flush() }() - scheduleNextAction(rs) + scheduleNextAction() continue ACTION_LOOP } else { // do not schedule next action. @@ -539,11 +545,8 @@ func (cs *ConsensusState) setupNewRound(round uint) { } // Increment all the way to round. - log.Debug(Fmt("Validators prior to IncrementAccum: %v, %v-%v", cs.Validators.String(), - round, cs.Round)) validators := cs.Validators.Copy() validators.IncrementAccum(round - cs.Round) - log.Debug(Fmt("Validators after IncrementAccum: %v", validators.String())) cs.Round = round cs.Step = RoundStepNewRound diff --git a/state/execution.go b/state/execution.go index c34076314..33eb160ab 100644 --- a/state/execution.go +++ b/state/execution.go @@ -151,10 +151,7 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade } // Increment validator AccumPowers - log.Debug(Fmt("Bonded Validators prior to IncrementAccum: %v", s.BondedValidators.String())) s.BondedValidators.IncrementAccum(1) - log.Debug(Fmt("Bonded Validators after IncrementAccum: %v", s.BondedValidators.String())) - s.LastBlockHeight = block.Height s.LastBlockHash = block.Hash() s.LastBlockParts = blockPartsHeader diff --git a/state/validator_set.go b/state/validator_set.go index 817e52293..6220f2667 100644 --- a/state/validator_set.go +++ b/state/validator_set.go @@ -45,6 +45,9 @@ func NewValidatorSet(vals []*Validator) *ValidatorSet { // TODO: mind the overflow when times and votingPower shares too large. func (valSet *ValidatorSet) IncrementAccum(times uint) { + log.Debug("IncrementAccum", "times", times) + + log.Debug(Fmt("IncrementAccum prior to accum: %v\n", valSet)) // Add VotingPower * times to each validator and order into heap. validatorsHeap := NewHeap() @@ -53,15 +56,20 @@ func (valSet *ValidatorSet) IncrementAccum(times uint) { validatorsHeap.Push(val, accumComparable(val.Accum)) } + log.Debug(Fmt("IncrementAccum after accum: %v\n", valSet)) + // Decrement the validator with most accum, times times. for i := uint(0); i < times; i++ { mostest := validatorsHeap.Peek().(*Validator) + if i == times-1 { + valSet.proposer = mostest + } mostest.Accum -= int64(valSet.TotalVotingPower()) validatorsHeap.Update(mostest, accumComparable(mostest.Accum)) } - // The next proposer is the next most accums remaining - valSet.proposer = validatorsHeap.Peek().(*Validator) + log.Debug(Fmt("IncrementAccum after decrements: %v\n", valSet)) + log.Debug(Fmt("IncrementAccum chose proposer: %v\n", valSet.proposer)) } func (valSet *ValidatorSet) Copy() *ValidatorSet { @@ -293,5 +301,5 @@ type accumComparable uint64 // We want to find the validator with the greatest accum. func (ac accumComparable) Less(o interface{}) bool { - return uint64(ac) > uint64(o.(accumComparable)) + return uint64(ac) < uint64(o.(accumComparable)) }