github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/tendermint/consensus/consensus_prevote.go (about)

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