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 }