mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-19 14:34:17 +00:00
Pull out consensus liveness fix, which went to #1815
This commit is contained in:
@@ -7,7 +7,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -18,14 +17,14 @@ import (
|
||||
bc "github.com/tendermint/tendermint/blockchain"
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
cstypes "github.com/tendermint/tendermint/consensus/types"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
mempl "github.com/tendermint/tendermint/mempool"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
"github.com/tendermint/tendermint/abci/example/counter"
|
||||
"github.com/tendermint/tendermint/abci/example/kvstore"
|
||||
@@ -326,30 +325,6 @@ func ensureNewStep(stepCh <-chan interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func ensureVote(voteCh chan interface{}, height int64, round int, voteType byte) {
|
||||
timer := time.NewTimer(ensureTimeout)
|
||||
select {
|
||||
case <-timer.C:
|
||||
break
|
||||
case v := <-voteCh:
|
||||
edv, ok := v.(types.EventDataVote)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("expected a *types.Vote, got %v. wrong subscription channel?",
|
||||
reflect.TypeOf(v)))
|
||||
}
|
||||
vote := edv.Vote
|
||||
if vote.Height != height {
|
||||
panic(fmt.Sprintf("expected height %v, got %v", height, vote.Height))
|
||||
}
|
||||
if vote.Round != round {
|
||||
panic(fmt.Sprintf("expected round %v, got %v", round, vote.Round))
|
||||
}
|
||||
if vote.Type != voteType {
|
||||
panic(fmt.Sprintf("expected type %v, got %v", voteType, vote.Type))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// consensus nets
|
||||
|
||||
|
||||
+6
-11
@@ -1014,11 +1014,9 @@ func (cs *ConsensusState) enterPrevoteWait(height int64, round int) {
|
||||
logger.Debug(cmn.Fmt("enterPrevoteWait(%v/%v): Invalid args. Current step: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
|
||||
return
|
||||
}
|
||||
/*
|
||||
if !cs.Votes.Prevotes(round).HasTwoThirdsAny() {
|
||||
cmn.PanicSanity(cmn.Fmt("enterPrevoteWait(%v/%v), but Prevotes does not have any +2/3 votes", height, round))
|
||||
}
|
||||
*/
|
||||
if !cs.Votes.Prevotes(round).HasTwoThirdsAny() {
|
||||
cmn.PanicSanity(cmn.Fmt("enterPrevoteWait(%v/%v), but Prevotes does not have any +2/3 votes", height, round))
|
||||
}
|
||||
logger.Info(cmn.Fmt("enterPrevoteWait(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step))
|
||||
|
||||
defer func() {
|
||||
@@ -1587,7 +1585,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
||||
if prevotes.HasTwoThirdsMajority() {
|
||||
cs.enterPrecommit(height, vote.Round)
|
||||
} else {
|
||||
cs.enterPropose(height, vote.Round) // we can't prevote until we wait for the proposal.
|
||||
cs.enterPrevote(height, vote.Round) // if the vote is ahead of us
|
||||
cs.enterPrevoteWait(height, vote.Round)
|
||||
}
|
||||
} else if cs.Proposal != nil && 0 <= cs.Proposal.POLRound && cs.Proposal.POLRound == vote.Round {
|
||||
@@ -1603,9 +1601,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
||||
blockID, ok := precommits.TwoThirdsMajority()
|
||||
if ok {
|
||||
if len(blockID.Hash) == 0 {
|
||||
cs.enterNewRound(height, vote.Round)
|
||||
cs.enterPrecommit(height, vote.Round)
|
||||
cs.enterPrecommitWait(height, vote.Round)
|
||||
cs.enterNewRound(height, vote.Round+1)
|
||||
} else {
|
||||
cs.enterNewRound(height, vote.Round)
|
||||
cs.enterPrecommit(height, vote.Round)
|
||||
@@ -1621,8 +1617,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
||||
}
|
||||
} else if cs.Round <= vote.Round && precommits.HasTwoThirdsAny() {
|
||||
cs.enterNewRound(height, vote.Round)
|
||||
cs.enterPrevote(height, vote.Round)
|
||||
cs.enterPrevoteWait(height, vote.Round)
|
||||
cs.enterPrecommit(height, vote.Round)
|
||||
cs.enterPrecommitWait(height, vote.Round)
|
||||
}
|
||||
default:
|
||||
|
||||
+11
-15
@@ -64,22 +64,22 @@ func TestStateProposerSelection0(t *testing.T) {
|
||||
|
||||
startTestRound(cs1, height, round)
|
||||
|
||||
// Wait for new round so proposer is set.
|
||||
// wait for new round so proposer is set
|
||||
<-newRoundCh
|
||||
|
||||
// Commit a block and ensure proposer for the next height is correct.
|
||||
// lets commit a block and ensure proposer for the next height is correct
|
||||
prop := cs1.GetRoundState().Validators.GetProposer()
|
||||
if !bytes.Equal(prop.Address, cs1.privValidator.GetAddress()) {
|
||||
t.Fatalf("expected proposer to be validator %d. Got %X", 0, prop.Address)
|
||||
}
|
||||
|
||||
// Wait for complete proposal.
|
||||
// wait for complete proposal
|
||||
<-proposalCh
|
||||
|
||||
rs := cs1.GetRoundState()
|
||||
signAddVotes(cs1, types.VoteTypePrecommit, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:]...)
|
||||
|
||||
// Wait for new round so next validator is set.
|
||||
// wait for new round so next validator is set
|
||||
<-newRoundCh
|
||||
|
||||
prop = cs1.GetRoundState().Validators.GetProposer()
|
||||
@@ -718,8 +718,6 @@ func TestStateLockPOLUnlock(t *testing.T) {
|
||||
func TestStateLockPOLSafety1(t *testing.T) {
|
||||
cs1, vss := randConsensusState(4)
|
||||
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
|
||||
h := cs1.GetRoundState().Height
|
||||
r := cs1.GetRoundState().Round
|
||||
|
||||
partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
|
||||
|
||||
@@ -736,7 +734,7 @@ func TestStateLockPOLSafety1(t *testing.T) {
|
||||
rs := re.(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
|
||||
propBlock := rs.ProposalBlock
|
||||
|
||||
ensureVote(voteCh, h, r, types.VoteTypePrevote)
|
||||
<-voteCh // prevote
|
||||
|
||||
validatePrevote(t, cs1, 0, vss[0], propBlock.Hash())
|
||||
|
||||
@@ -757,11 +755,6 @@ func TestStateLockPOLSafety1(t *testing.T) {
|
||||
// we do see them precommit nil
|
||||
signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs3, vs4)
|
||||
|
||||
ensureVote(voteCh, h, r, types.VoteTypePrecommit)
|
||||
|
||||
<-newRoundCh
|
||||
t.Log("### ONTO ROUND 1")
|
||||
|
||||
prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
|
||||
propBlockHash := propBlock.Hash()
|
||||
propBlockParts := propBlock.MakePartSet(partSize)
|
||||
@@ -772,6 +765,9 @@ func TestStateLockPOLSafety1(t *testing.T) {
|
||||
if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
<-newRoundCh
|
||||
t.Log("### ONTO ROUND 1")
|
||||
/*Round2
|
||||
// we timeout and prevote our lock
|
||||
// a polka happened but we didn't see it!
|
||||
@@ -792,13 +788,13 @@ func TestStateLockPOLSafety1(t *testing.T) {
|
||||
}
|
||||
t.Logf("new prop hash %v", fmt.Sprintf("%X", propBlockHash))
|
||||
// go to prevote, prevote for proposal block
|
||||
ensureVote(voteCh, h, r+1, types.VoteTypePrevote)
|
||||
<-voteCh
|
||||
validatePrevote(t, cs1, 1, vss[0], propBlockHash)
|
||||
|
||||
// now we see the others prevote for it, so we should lock on it
|
||||
signAddVotes(cs1, types.VoteTypePrevote, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
|
||||
|
||||
ensureVote(voteCh, h, r+1, types.VoteTypePrecommit)
|
||||
<-voteCh // precommit
|
||||
|
||||
// we should have precommitted
|
||||
validatePrecommit(t, cs1, 1, 1, vss[0], propBlockHash, propBlockHash)
|
||||
@@ -820,7 +816,7 @@ func TestStateLockPOLSafety1(t *testing.T) {
|
||||
<-timeoutProposeCh
|
||||
|
||||
// finish prevote
|
||||
ensureVote(voteCh, h, r+2, types.VoteTypePrevote)
|
||||
<-voteCh
|
||||
|
||||
// we should prevote what we're locked on
|
||||
validatePrevote(t, cs1, 2, vss[0], propBlockHash)
|
||||
|
||||
Reference in New Issue
Block a user