github.com/okex/exchain@v1.8.0/libs/tendermint/consensus/consensus_new_round.go (about)

     1  package consensus
     2  
     3  import (
     4  	"fmt"
     5  	cstypes "github.com/okex/exchain/libs/tendermint/consensus/types"
     6  	"github.com/okex/exchain/libs/tendermint/types"
     7  	tmtime "github.com/okex/exchain/libs/tendermint/types/time"
     8  )
     9  
    10  //-----------------------------------------------------------------------------
    11  // State functions
    12  // Used internally by handleTimeout and handleMsg to make state transitions
    13  
    14  // Enter: `timeoutNewHeight` by startTime (R0PrevoteTime+timeoutCommit),
    15  //
    16  //	or, if SkipTimeoutCommit==true, after receiving all precommits from (height,round-1)
    17  //
    18  // Enter: `timeoutPrecommits` after any +2/3 precommits from (height,round-1)
    19  // Enter: +2/3 precommits for nil at (height,round-1)
    20  // Enter: +2/3 prevotes any or +2/3 precommits for block or any from (height, round)
    21  // NOTE: cs.StartTime was already set for height.
    22  func (cs *State) enterNewRound(height int64, round int) {
    23  	logger := cs.Logger.With("height", height, "round", round)
    24  	if cs.Height != height || round < cs.Round || (cs.Round == round && cs.Step != cstypes.RoundStepNewHeight) {
    25  		logger.Debug(fmt.Sprintf(
    26  			"enterNewRound(%v/%v): Invalid args. Current step: %v/%v/%v",
    27  			height,
    28  			round,
    29  			cs.Height,
    30  			cs.Round,
    31  			cs.Step))
    32  		return
    33  	}
    34  
    35  	cs.doNewRound(height, round, false, nil)
    36  }
    37  
    38  func (cs *State) doNewRound(height int64, round int, avc bool, val *types.Validator) {
    39  	logger := cs.Logger.With("height", height, "round", round)
    40  	cs.initNewHeight()
    41  	if !avc {
    42  		if now := tmtime.Now(); cs.StartTime.After(now) {
    43  			logger.Info("Need to set a buffer and log message here for sanity.", "startTime", cs.StartTime, "now", now)
    44  		}
    45  		logger.Info(fmt.Sprintf("enterNewRound(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
    46  
    47  		// Increment validators if necessary
    48  		validators := cs.Validators
    49  		if cs.Round < round {
    50  			validators = validators.Copy()
    51  			validators.IncrementProposerPriority(round - cs.Round)
    52  		}
    53  		cs.Validators = validators
    54  		cs.Votes.SetRound(round + 1) // also track next round (round+1) to allow round-skipping
    55  	} else {
    56  		cs.trc.Pin("NewRoundVC-%d", round)
    57  		logger.Info(fmt.Sprintf("enterNewRoundAVC(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
    58  
    59  		cs.Validators.Proposer = val
    60  		if cs.Votes.Round() == 0 {
    61  			cs.Votes.SetRound(1) // also track next round (round+1) to allow round-skipping
    62  		}
    63  	}
    64  
    65  	// Setup new round
    66  	// we don't fire newStep for this step,
    67  	// but we fire an event, so update the round step first
    68  	cs.updateRoundStep(round, cstypes.RoundStepNewRound)
    69  	cs.HasVC = avc
    70  	if round == 0 {
    71  		// We've already reset these upon new height,
    72  		// and meanwhile we might have received a proposal
    73  		// for round 0.
    74  	} else {
    75  		logger.Info("Resetting Proposal info")
    76  		cs.Proposal = nil
    77  		cs.ProposalBlock = nil
    78  		cs.ProposalBlockParts = nil
    79  	}
    80  
    81  	cs.TriggeredTimeoutPrecommit = false
    82  	cs.eventBus.PublishEventNewRound(cs.NewRoundEvent())
    83  	cs.metrics.Rounds.Set(float64(round))
    84  
    85  	// Wait for txs to be available in the mempool
    86  	// before we enterPropose in round 0. If the last block changed the app hash,
    87  	// we may need an empty "proof" block, and enterPropose immediately.
    88  	waitForTxs := cs.config.WaitForTxs() && round == 0 && !cs.needProofBlock(height)
    89  	if waitForTxs {
    90  		if cs.config.CreateEmptyBlocksInterval > 0 {
    91  			cs.scheduleTimeout(cs.config.CreateEmptyBlocksInterval, height, round,
    92  				cstypes.RoundStepNewRound)
    93  		}
    94  	} else {
    95  		cs.enterPropose(height, round)
    96  	}
    97  }
    98  
    99  func (cs *State) enterNewRoundAVC(height int64, round int, val *types.Validator) {
   100  	logger := cs.Logger.With("height", height, "round", round)
   101  	if round != 0 || cs.Round != 0 || cs.Height != height {
   102  		logger.Debug(fmt.Sprintf(
   103  			"enterNewRoundAVC(%v/%v): Invalid args. Current step: %v/%v/%v",
   104  			height,
   105  			round,
   106  			cs.Height,
   107  			cs.Round,
   108  			cs.Step))
   109  		return
   110  	}
   111  
   112  	cs.doNewRound(height, round, true, val)
   113  }
   114  
   115  // Enter: `timeoutNewHeight` by startTime (after timeoutCommit),
   116  func (cs *State) enterNewHeight(height int64) {
   117  	cs.Logger.Info("enterNewHeight", "vcMsg", cs.vcMsg, "proposer", cs.Validators.Proposer.Address)
   118  	if GetActiveVC() && cs.vcMsg != nil && cs.vcMsg.Validate(height, cs.Validators.Proposer.Address) {
   119  		_, val := cs.Validators.GetByAddress(cs.vcMsg.NewProposer)
   120  		cs.enterNewRoundAVC(height, 0, val)
   121  	} else {
   122  		cs.enterNewRound(height, 0)
   123  	}
   124  }