github.com/okex/exchain@v1.8.0/libs/tendermint/consensus/consensus_prevote.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/libs/automation"
     7  	"github.com/okex/exchain/libs/tendermint/types"
     8  )
     9  
    10  // Enter: `timeoutPropose` after entering Propose.
    11  // Enter: proposal block and POL is ready.
    12  // Prevote for LockedBlock if we're locked, or ProposalBlock if valid.
    13  // Otherwise vote nil.
    14  func (cs *State) enterPrevote(height int64, round int) {
    15  	if cs.Height != height || round < cs.Round || (cs.Round == round && cstypes.RoundStepPrevote <= cs.Step) {
    16  		cs.Logger.Debug(fmt.Sprintf(
    17  			"enterPrevote(%v/%v): Invalid args. Current step: %v/%v/%v",
    18  			height,
    19  			round,
    20  			cs.Height,
    21  			cs.Round,
    22  			cs.Step))
    23  		return
    24  	}
    25  
    26  	cs.initNewHeight()
    27  	cs.trc.Pin("Prevote-%d", round)
    28  
    29  	defer func() {
    30  		// Done enterPrevote:
    31  		cs.updateRoundStep(round, cstypes.RoundStepPrevote)
    32  		cs.newStep()
    33  	}()
    34  
    35  	cs.Logger.Info(fmt.Sprintf("enterPrevote(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
    36  
    37  	// Sign and broadcast vote as necessary
    38  	cs.doPrevote(height, round)
    39  
    40  	// Once `addVote` hits any +2/3 prevotes, we will go to PrevoteWait
    41  	// (so we have more time to try and collect +2/3 prevotes for a single block)
    42  }
    43  
    44  func (cs *State) defaultDoPrevote(height int64, round int) {
    45  	logger := cs.Logger.With("height", height, "round", round)
    46  
    47  	if automation.PrevoteNil(height, round) {
    48  		cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{})
    49  		return
    50  	}
    51  
    52  	// If a block is locked, prevote that.
    53  	if cs.LockedBlock != nil {
    54  		logger.Info("enterPrevote: Block was locked")
    55  		cs.signAddVote(types.PrevoteType, cs.LockedBlock.Hash(), cs.LockedBlockParts.Header())
    56  		return
    57  	}
    58  
    59  	// If ProposalBlock is nil, prevote nil.
    60  	if cs.ProposalBlock == nil {
    61  		logger.Info("enterPrevote: ProposalBlock is nil")
    62  		cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{})
    63  		return
    64  	}
    65  
    66  	// Validate proposal block
    67  	err := cs.blockExec.ValidateBlock(cs.state, cs.ProposalBlock)
    68  	if err != nil {
    69  		// ProposalBlock is invalid, prevote nil.
    70  		logger.Error("enterPrevote: ProposalBlock is invalid", "err", err)
    71  		cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{})
    72  		return
    73  	}
    74  
    75  	// Prevote cs.ProposalBlock
    76  	// NOTE: the proposal signature is validated when it is received,
    77  	// and the proposal block parts are validated as they are received (against the merkle hash in the proposal)
    78  	logger.Info("enterPrevote: ProposalBlock is valid")
    79  	cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header())
    80  }
    81  
    82  // Enter: any +2/3 prevotes at next round.
    83  func (cs *State) enterPrevoteWait(height int64, round int) {
    84  	logger := cs.Logger.With("height", height, "round", round)
    85  
    86  	if cs.Height != height || round < cs.Round || (cs.Round == round && cstypes.RoundStepPrevoteWait <= cs.Step) {
    87  		logger.Debug(fmt.Sprintf(
    88  			"enterPrevoteWait(%v/%v): Invalid args. Current step: %v/%v/%v",
    89  			height,
    90  			round,
    91  			cs.Height,
    92  			cs.Round,
    93  			cs.Step))
    94  		return
    95  	}
    96  
    97  	cs.initNewHeight()
    98  	cs.trc.Pin("PrevoteWait-%d", round)
    99  
   100  	if !cs.Votes.Prevotes(round).HasTwoThirdsAny() {
   101  		panic(fmt.Sprintf("enterPrevoteWait(%v/%v), but Prevotes does not have any +2/3 votes", height, round))
   102  	}
   103  	logger.Info(fmt.Sprintf("enterPrevoteWait(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
   104  
   105  	defer func() {
   106  		// Done enterPrevoteWait:
   107  		cs.updateRoundStep(round, cstypes.RoundStepPrevoteWait)
   108  		cs.newStep()
   109  	}()
   110  
   111  	// Wait for some more prevotes; enterPrecommit
   112  	cs.scheduleTimeout(cs.config.Prevote(round), height, round, cstypes.RoundStepPrevoteWait)
   113  }