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 }