Skip to content

Commit

Permalink
[Cherry-pick #1175]: remove logic to unlock block on +2/3 prevote for…
Browse files Browse the repository at this point in the history
… nil (#19)

* cp #1175: remove logic to unlock block on +2/3 prevote for nil

* fix lint

* fix test
  • Loading branch information
teddyding authored Sep 6, 2023
1 parent 23effc2 commit c72272c
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 259 deletions.
13 changes: 3 additions & 10 deletions consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,13 +510,6 @@ func ensureNoNewRoundStep(stepCh <-chan cmtpubsub.Message) {
"We should be stuck waiting, not receiving NewRoundStep event")
}

func ensureNoNewUnlock(unlockCh <-chan cmtpubsub.Message) {
ensureNoNewEvent(
unlockCh,
ensureTimeout,
"We should be stuck waiting, not receiving Unlock event")
}

func ensureNoNewTimeout(stepCh <-chan cmtpubsub.Message, timeout int64) {
timeoutDuration := time.Duration(timeout*10) * time.Nanosecond
ensureNoNewEvent(
Expand Down Expand Up @@ -629,9 +622,9 @@ func ensureNewBlockHeader(blockCh <-chan cmtpubsub.Message, height int64, blockH
}
}

func ensureNewUnlock(unlockCh <-chan cmtpubsub.Message, height int64, round int32) {
ensureNewEvent(unlockCh, height, round, ensureTimeout,
"Timeout expired while waiting for NewUnlock event")
func ensureLock(lockCh <-chan cmtpubsub.Message, height int64, round int32) {
ensureNewEvent(lockCh, height, round, ensureTimeout,
"Timeout expired while waiting for LockValue event")
}

func ensureProposal(proposalCh <-chan cmtpubsub.Message, height int64, round int32, propID types.BlockID) {
Expand Down
68 changes: 14 additions & 54 deletions consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,6 @@ func (cs *State) enterPrevoteWait(height int64, round int32) {
// Enter: `timeoutPrecommit` after any +2/3 precommits.
// Enter: +2/3 precomits for block or nil.
// Lock & precommit the ProposalBlock if we have enough prevotes for it (a POL in this round)
// else, unlock an existing lock and precommit nil if +2/3 of prevotes were nil,
// else, precommit nil otherwise.
func (cs *State) enterPrecommit(height int64, round int32) {
logger := cs.Logger.With("height", height, "round", round)
Expand Down Expand Up @@ -1464,21 +1463,9 @@ func (cs *State) enterPrecommit(height int64, round int32) {
panic(fmt.Sprintf("this POLRound should be %v but got %v", round, polRound))
}

// +2/3 prevoted nil. Unlock and precommit nil.
if len(blockID.Hash) == 0 {
if cs.LockedBlock == nil {
logger.Debug("precommit step; +2/3 prevoted for nil")
} else {
logger.Debug("precommit step; +2/3 prevoted for nil; unlocking")
cs.LockedRound = -1
cs.LockedBlock = nil
cs.LockedBlockParts = nil

if err := cs.eventBus.PublishEventUnlock(cs.RoundStateEvent()); err != nil {
logger.Error("failed publishing event unlock", "err", err)
}
}

// +2/3 prevoted nil. Precommit nil.
if blockID.IsNil() {
logger.Debug("precommit step; +2/3 prevoted for nil")
cs.signAddVote(cmtproto.PrecommitType, nil, types.PartSetHeader{})
return
}
Expand All @@ -1498,7 +1485,9 @@ func (cs *State) enterPrecommit(height int64, round int32) {
return
}

// If +2/3 prevoted for proposal block, stage and precommit it
// If greater than 2/3 of the voting power on the network prevoted for
// the proposed block, update our locked block to this block and issue a
// precommit vote for it.
if cs.ProposalBlock.HashesTo(blockID.Hash) {
logger.Debug("precommit step; +2/3 prevoted proposal block; locking", "hash", blockID.Hash)

Expand All @@ -1520,23 +1509,14 @@ func (cs *State) enterPrecommit(height int64, round int32) {
}

// There was a polka in this round for a block we don't have.
// Fetch that block, unlock, and precommit nil.
// The +2/3 prevotes for this round is the POL for our unlock.
// Fetch that block, and precommit nil.
logger.Debug("precommit step; +2/3 prevotes for a block we do not have; voting nil", "block_id", blockID)

cs.LockedRound = -1
cs.LockedBlock = nil
cs.LockedBlockParts = nil

if !cs.ProposalBlockParts.HasHeader(blockID.PartSetHeader) {
cs.ProposalBlock = nil
cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartSetHeader)
}

if err := cs.eventBus.PublishEventUnlock(cs.RoundStateEvent()); err != nil {
logger.Error("failed publishing event unlock", "err", err)
}

cs.signAddVote(cmtproto.PrecommitType, nil, types.PartSetHeader{})
}

Expand Down Expand Up @@ -1644,7 +1624,7 @@ func (cs *State) tryFinalizeCommit(height int64) {
}

blockID, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
if !ok || len(blockID.Hash) == 0 {
if !ok || blockID.IsNil() {
logger.Error("failed attempt to finalize commit; there was no +2/3 majority or +2/3 was for nil")
return
}
Expand Down Expand Up @@ -2019,7 +1999,7 @@ func (cs *State) handleCompleteProposal(blockHeight int64) {
// Update Valid* if we can.
prevotes := cs.Votes.Prevotes(cs.Round)
blockID, hasTwoThirds := prevotes.TwoThirdsMajority()
if hasTwoThirds && !blockID.IsZero() && (cs.ValidRound < cs.Round) {
if hasTwoThirds && !blockID.IsNil() && (cs.ValidRound < cs.Round) {
if cs.ProposalBlock.HashesTo(blockID.Hash) {
cs.Logger.Debug(
"updating valid block to new proposal block",
Expand Down Expand Up @@ -2172,33 +2152,13 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error
prevotes := cs.Votes.Prevotes(vote.Round)
cs.Logger.Debug("added vote to prevote", "vote", vote, "prevotes", prevotes.StringShort())

// If +2/3 prevotes for a block or nil for *any* round:
if blockID, ok := prevotes.TwoThirdsMajority(); ok {
// There was a polka!
// If we're locked but this is a recent polka, unlock.
// If it matches our ProposalBlock, update the ValidBlock

// Unlock if `cs.LockedRound < vote.Round <= cs.Round`
// NOTE: If vote.Round > cs.Round, we'll deal with it when we get to vote.Round
if (cs.LockedBlock != nil) &&
(cs.LockedRound < vote.Round) &&
(vote.Round <= cs.Round) &&
!cs.LockedBlock.HashesTo(blockID.Hash) {

cs.Logger.Debug("unlocking because of POL", "locked_round", cs.LockedRound, "pol_round", vote.Round)

cs.LockedRound = -1
cs.LockedBlock = nil
cs.LockedBlockParts = nil

if err := cs.eventBus.PublishEventUnlock(cs.RoundStateEvent()); err != nil {
return added, err
}
}
// Check to see if >2/3 of the voting power on the network voted for any non-nil block.
if blockID, ok := prevotes.TwoThirdsMajority(); ok && !blockID.IsNil() {
// Greater than 2/3 of the voting power on the network voted for some
// non-nil block

// Update Valid* if we can.
// NOTE: our proposal block may be nil or not what received a polka..
if len(blockID.Hash) != 0 && (cs.ValidRound < vote.Round) && (vote.Round == cs.Round) {
if cs.ValidRound < vote.Round && vote.Round == cs.Round {
if cs.ProposalBlock.HashesTo(blockID.Hash) {
cs.Logger.Debug("updating valid block because of POL", "valid_round", cs.ValidRound, "pol_round", vote.Round)
cs.ValidRound = vote.Round
Expand Down
Loading

0 comments on commit c72272c

Please sign in to comment.