@ -8,14 +8,18 @@ import (
"time"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/abci/example/kvstore"
abcitypes "github.com/tendermint/tendermint/abci/types"
abcimocks "github.com/tendermint/tendermint/abci/types/mocks"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/crypto/tmhash"
cstypes "github.com/tendermint/tendermint/internal/consensus/types"
cstypes "github.com/tendermint/tendermint/internal/consensus/types"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/eventbus"
tmpubsub "github.com/tendermint/tendermint/internal/pubsub"
tmpubsub "github.com/tendermint/tendermint/internal/pubsub"
tmquery "github.com/tendermint/tendermint/internal/pubsub/query"
tmquery "github.com/tendermint/tendermint/internal/pubsub/query"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/log"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmtime "github.com/tendermint/tendermint/libs/time"
tmtime "github.com/tendermint/tendermint/libs/time"
@ -68,9 +72,8 @@ func TestStateProposerSelection0(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
newRoundCh := subscribe ( ctx , t , cs1 . eventBus , types . EventQueryNewRound )
newRoundCh := subscribe ( ctx , t , cs1 . eventBus , types . EventQueryNewRound )
@ -110,11 +113,10 @@ func TestStateProposerSelection0(t *testing.T) {
// Now let's do it all again, but starting from round 2 instead of 0
// Now let's do it all again, but starting from round 2 instead of 0
func TestStateProposerSelection2 ( t * testing . T ) {
func TestStateProposerSelection2 ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 ) // test needs more work for more than 3 validators
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } ) // test needs more work for more than 3 validators
height := cs1 . Height
height := cs1 . Height
newRoundCh := subscribe ( ctx , t , cs1 . eventBus , types . EventQueryNewRound )
newRoundCh := subscribe ( ctx , t , cs1 . eventBus , types . EventQueryNewRound )
@ -149,11 +151,10 @@ func TestStateProposerSelection2(t *testing.T) {
// a non-validator should timeout into the prevote round
// a non-validator should timeout into the prevote round
func TestStateEnterProposeNoPrivValidator ( t * testing . T ) {
func TestStateEnterProposeNoPrivValidator ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs , _ := makeState ( ctx , t , config , logger , 1 )
cs , _ := makeState ( ctx , t , makeStateArgs { config : config , validators : 1 } )
cs . SetPrivValidator ( ctx , nil )
cs . SetPrivValidator ( ctx , nil )
height , round := cs . Height , cs . Round
height , round := cs . Height , cs . Round
@ -173,11 +174,10 @@ func TestStateEnterProposeNoPrivValidator(t *testing.T) {
// a validator should not timeout of the prevote round (TODO: unless the block is really big!)
// a validator should not timeout of the prevote round (TODO: unless the block is really big!)
func TestStateEnterProposeYesPrivValidator ( t * testing . T ) {
func TestStateEnterProposeYesPrivValidator ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs , _ := makeState ( ctx , t , config , logger , 1 )
cs , _ := makeState ( ctx , t , makeStateArgs { config : config , validators : 1 } )
height , round := cs . Height , cs . Round
height , round := cs . Height , cs . Round
// Listen for propose timeout event
// Listen for propose timeout event
@ -208,11 +208,10 @@ func TestStateEnterProposeYesPrivValidator(t *testing.T) {
func TestStateBadProposal ( t * testing . T ) {
func TestStateBadProposal ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 2 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
vs2 := vss [ 1 ]
vs2 := vss [ 1 ]
@ -270,11 +269,10 @@ func TestStateBadProposal(t *testing.T) {
func TestStateOversizedBlock ( t * testing . T ) {
func TestStateOversizedBlock ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 2 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
cs1 . state . ConsensusParams . Block . MaxBytes = 2000
cs1 . state . ConsensusParams . Block . MaxBytes = 2000
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
vs2 := vss [ 1 ]
vs2 := vss [ 1 ]
@ -336,11 +334,10 @@ func TestStateOversizedBlock(t *testing.T) {
// propose, prevote, and precommit a block
// propose, prevote, and precommit a block
func TestStateFullRound1 ( t * testing . T ) {
func TestStateFullRound1 ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs , vss := makeState ( ctx , t , config , logger , 1 )
cs , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 1 } )
height , round := cs . Height , cs . Round
height , round := cs . Height , cs . Round
voteCh := subscribe ( ctx , t , cs . eventBus , types . EventQueryVote )
voteCh := subscribe ( ctx , t , cs . eventBus , types . EventQueryVote )
@ -367,11 +364,10 @@ func TestStateFullRound1(t *testing.T) {
// nil is proposed, so prevote and precommit nil
// nil is proposed, so prevote and precommit nil
func TestStateFullRoundNil ( t * testing . T ) {
func TestStateFullRoundNil ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs , _ := makeState ( ctx , t , config , logger , 1 )
cs , _ := makeState ( ctx , t , makeStateArgs { config : config , validators : 1 } )
height , round := cs . Height , cs . Round
height , round := cs . Height , cs . Round
voteCh := subscribe ( ctx , t , cs . eventBus , types . EventQueryVote )
voteCh := subscribe ( ctx , t , cs . eventBus , types . EventQueryVote )
@ -387,11 +383,10 @@ func TestStateFullRoundNil(t *testing.T) {
// where the first validator has to wait for votes from the second
// where the first validator has to wait for votes from the second
func TestStateFullRound2 ( t * testing . T ) {
func TestStateFullRound2 ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 2 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
vs2 := vss [ 1 ]
vs2 := vss [ 1 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -432,11 +427,10 @@ func TestStateFullRound2(t *testing.T) {
// two vals take turns proposing. val1 locks on first one, precommits nil on everything else
// two vals take turns proposing. val1 locks on first one, precommits nil on everything else
func TestStateLock_NoPOL ( t * testing . T ) {
func TestStateLock_NoPOL ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 2 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
vs2 := vss [ 1 ]
vs2 := vss [ 1 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -580,7 +574,9 @@ func TestStateLock_NoPOL(t *testing.T) {
ensureNewTimeout ( t , timeoutWaitCh , height , round , cs1 . config . Precommit ( round ) . Nanoseconds ( ) )
ensureNewTimeout ( t , timeoutWaitCh , height , round , cs1 . config . Precommit ( round ) . Nanoseconds ( ) )
cs2 , _ := makeState ( ctx , t , config , logger , 2 ) // needed so generated block is different than locked block
// cs1 is locked on a block at this point, so we must generate a new consensus
// state to force a new proposal block to be generated.
cs2 , _ := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
// before we time out into new round, set next proposal block
// before we time out into new round, set next proposal block
prop , propBlock := decideProposal ( ctx , t , cs2 , vs2 , vs2 . Height , vs2 . Round + 1 )
prop , propBlock := decideProposal ( ctx , t , cs2 , vs2 , vs2 . Height , vs2 . Round + 1 )
require . NotNil ( t , propBlock , "Failed to create proposal block with vs2" )
require . NotNil ( t , propBlock , "Failed to create proposal block with vs2" )
@ -643,7 +639,7 @@ func TestStateLock_POLUpdateLock(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , logger : logger } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -751,9 +747,8 @@ func TestStateLock_POLRelock(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -851,9 +846,8 @@ func TestStateLock_PrevoteNilWhenLockedAndMissProposal(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -942,7 +936,7 @@ func TestStateLock_PrevoteNilWhenLockedAndDifferentProposal(t *testing.T) {
state .
state .
* /
* /
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , logger : logger } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1044,7 +1038,7 @@ func TestStateLock_POLDoesNotUnlock(t *testing.T) {
state .
state .
* /
* /
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , logger : logger } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1178,7 +1172,7 @@ func TestStateLock_MissingProposalWhenPOLSeenDoesNotUpdateLock(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , logger : logger } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1267,9 +1261,8 @@ func TestStateLock_DoesNotLockOnOldProposal(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1347,7 +1340,7 @@ func TestStateLock_POLSafety1(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , logger : logger } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1464,11 +1457,10 @@ func TestStateLock_POLSafety1(t *testing.T) {
// dont see P0, lock on P1 at R1, dont unlock using P0 at R2
// dont see P0, lock on P1 at R1, dont unlock using P0 at R2
func TestStateLock_POLSafety2 ( t * testing . T ) {
func TestStateLock_POLSafety2 ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1564,7 +1556,7 @@ func TestState_PrevotePOLFromPreviousRound(t *testing.T) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
logger := log . NewNopLogger ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config , logger : logger } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1702,12 +1694,11 @@ func TestState_PrevotePOLFromPreviousRound(t *testing.T) {
// What we want:
// What we want:
// P0 proposes B0 at R3.
// P0 proposes B0 at R3.
func TestProposeValidBlock ( t * testing . T ) {
func TestProposeValidBlock ( t * testing . T ) {
cfg := configSetup ( t )
logger := log . NewNopLogger ( )
config := configSetup ( t )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , cfg , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1739,14 +1730,14 @@ func TestProposeValidBlock(t *testing.T) {
ensurePrevoteMatch ( t , voteCh , height , round , blockID . Hash )
ensurePrevoteMatch ( t , voteCh , height , round , blockID . Hash )
// the others sign a polka
// the others sign a polka
signAddVotes ( ctx , t , cs1 , tmproto . PrevoteType , cfg . ChainID ( ) , blockID , vs2 , vs3 , vs4 )
signAddVotes ( ctx , t , cs1 , tmproto . PrevoteType , con fi g . ChainID ( ) , blockID , vs2 , vs3 , vs4 )
ensurePrecommit ( t , voteCh , height , round )
ensurePrecommit ( t , voteCh , height , round )
// we should have precommitted the proposed block in this round.
// we should have precommitted the proposed block in this round.
validatePrecommit ( ctx , t , cs1 , round , round , vss [ 0 ] , blockID . Hash , blockID . Hash )
validatePrecommit ( ctx , t , cs1 , round , round , vss [ 0 ] , blockID . Hash , blockID . Hash )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , cfg . ChainID ( ) , types . BlockID { } , vs2 , vs3 , vs4 )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , con fi g . ChainID ( ) , types . BlockID { } , vs2 , vs3 , vs4 )
ensureNewTimeout ( t , timeoutWaitCh , height , round , cs1 . config . Precommit ( round ) . Nanoseconds ( ) )
ensureNewTimeout ( t , timeoutWaitCh , height , round , cs1 . config . Precommit ( round ) . Nanoseconds ( ) )
@ -1762,7 +1753,7 @@ func TestProposeValidBlock(t *testing.T) {
// We did not see a valid proposal within this round, so prevote nil.
// We did not see a valid proposal within this round, so prevote nil.
ensurePrevoteMatch ( t , voteCh , height , round , nil )
ensurePrevoteMatch ( t , voteCh , height , round , nil )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , cfg . ChainID ( ) , types . BlockID { } , vs2 , vs3 , vs4 )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , con fi g . ChainID ( ) , types . BlockID { } , vs2 , vs3 , vs4 )
ensurePrecommit ( t , voteCh , height , round )
ensurePrecommit ( t , voteCh , height , round )
// we should have precommitted nil during this round because we received
// we should have precommitted nil during this round because we received
@ -1772,7 +1763,7 @@ func TestProposeValidBlock(t *testing.T) {
incrementRound ( vs2 , vs3 , vs4 )
incrementRound ( vs2 , vs3 , vs4 )
incrementRound ( vs2 , vs3 , vs4 )
incrementRound ( vs2 , vs3 , vs4 )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , cfg . ChainID ( ) , types . BlockID { } , vs2 , vs3 , vs4 )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , con fi g . ChainID ( ) , types . BlockID { } , vs2 , vs3 , vs4 )
round += 2 // increment by multiple rounds
round += 2 // increment by multiple rounds
@ -1798,11 +1789,10 @@ func TestProposeValidBlock(t *testing.T) {
// P0 miss to lock B but set valid block to B after receiving delayed prevote.
// P0 miss to lock B but set valid block to B after receiving delayed prevote.
func TestSetValidBlockOnDelayedPrevote ( t * testing . T ) {
func TestSetValidBlockOnDelayedPrevote ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1868,11 +1858,10 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) {
// receiving delayed Block Proposal.
// receiving delayed Block Proposal.
func TestSetValidBlockOnDelayedProposal ( t * testing . T ) {
func TestSetValidBlockOnDelayedProposal ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1928,6 +1917,54 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) {
assert . True ( t , rs . ValidRound == round )
assert . True ( t , rs . ValidRound == round )
}
}
func TestProcessProposalAccept ( t * testing . T ) {
for _ , testCase := range [ ] struct {
name string
accept bool
expectedNilPrevote bool
} {
{
name : "accepted block is prevoted" ,
accept : true ,
expectedNilPrevote : false ,
} ,
{
name : "rejected block is not prevoted" ,
accept : false ,
expectedNilPrevote : true ,
} ,
} {
t . Run ( testCase . name , func ( t * testing . T ) {
config := configSetup ( t )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
m := abcimocks . NewBaseMock ( )
m . On ( "ProcessProposal" , mock . Anything ) . Return ( abcitypes . ResponseProcessProposal { Accept : testCase . accept } )
cs1 , _ := makeState ( ctx , t , makeStateArgs { config : config , application : m } )
height , round := cs1 . Height , cs1 . Round
proposalCh := subscribe ( ctx , t , cs1 . eventBus , types . EventQueryCompleteProposal )
newRoundCh := subscribe ( ctx , t , cs1 . eventBus , types . EventQueryNewRound )
pv1 , err := cs1 . privValidator . GetPubKey ( ctx )
require . NoError ( t , err )
addr := pv1 . Address ( )
voteCh := subscribeToVoter ( ctx , t , cs1 , addr )
startTestRound ( ctx , cs1 , cs1 . Height , round )
ensureNewRound ( t , newRoundCh , height , round )
ensureNewProposal ( t , proposalCh , height , round )
rs := cs1 . GetRoundState ( )
var prevoteHash tmbytes . HexBytes
if ! testCase . expectedNilPrevote {
prevoteHash = rs . ProposalBlock . Hash ( )
}
ensurePrevoteMatch ( t , voteCh , height , round , prevoteHash )
} )
}
}
// 4 vals, 3 Nil Precommits at P0
// 4 vals, 3 Nil Precommits at P0
// What we want:
// What we want:
// P0 waits for timeoutPrecommit before starting next round
// P0 waits for timeoutPrecommit before starting next round
@ -1935,9 +1972,8 @@ func TestWaitingTimeoutOnNilPolka(t *testing.T) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1959,11 +1995,10 @@ func TestWaitingTimeoutOnNilPolka(t *testing.T) {
// P0 waits for timeoutPropose in the next round before entering prevote
// P0 waits for timeoutPropose in the next round before entering prevote
func TestWaitingTimeoutProposeOnNewRound ( t * testing . T ) {
func TestWaitingTimeoutProposeOnNewRound ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -1999,11 +2034,10 @@ func TestWaitingTimeoutProposeOnNewRound(t *testing.T) {
// P0 jump to higher round, precommit and start precommit wait
// P0 jump to higher round, precommit and start precommit wait
func TestRoundSkipOnNilPolkaFromHigherRound ( t * testing . T ) {
func TestRoundSkipOnNilPolkaFromHigherRound ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -2040,11 +2074,10 @@ func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) {
// P0 wait for timeoutPropose to expire before sending prevote.
// P0 wait for timeoutPropose to expire before sending prevote.
func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound ( t * testing . T ) {
func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , int32 ( 1 )
height , round := cs1 . Height , int32 ( 1 )
@ -2071,11 +2104,10 @@ func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) {
// P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet
// P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet
func TestEmitNewValidBlockEventOnCommitWithoutBlock ( t * testing . T ) {
func TestEmitNewValidBlockEventOnCommitWithoutBlock ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , int32 ( 1 )
height , round := cs1 . Height , int32 ( 1 )
@ -2114,11 +2146,10 @@ func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) {
// After receiving block, it executes block and moves to the next height.
// After receiving block, it executes block and moves to the next height.
func TestCommitFromPreviousRound ( t * testing . T ) {
func TestCommitFromPreviousRound ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , int32 ( 1 )
height , round := cs1 . Height , int32 ( 1 )
@ -2176,12 +2207,11 @@ func (n *fakeTxNotifier) Notify() {
// start of the next round
// start of the next round
func TestStartNextHeightCorrectlyAfterTimeout ( t * testing . T ) {
func TestStartNextHeightCorrectlyAfterTimeout ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config . Consensus . SkipTimeoutCommit = false
config . Consensus . SkipTimeoutCommit = false
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
cs1 . txNotifier = & fakeTxNotifier { ch : make ( chan struct { } ) }
cs1 . txNotifier = & fakeTxNotifier { ch : make ( chan struct { } ) }
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
@ -2243,12 +2273,11 @@ func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) {
func TestResetTimeoutPrecommitUponNewHeight ( t * testing . T ) {
func TestResetTimeoutPrecommitUponNewHeight ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
config . Consensus . SkipTimeoutCommit = false
config . Consensus . SkipTimeoutCommit = false
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
@ -2313,12 +2342,11 @@ func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) {
// 4 vals.
// 4 vals.
// we receive a final precommit after going into next round, but others might have gone to commit already!
// we receive a final precommit after going into next round, but others might have gone to commit already!
func TestStateHalt1 ( t * testing . T ) {
func TestStateHalt1 ( t * testing . T ) {
cfg := configSetup ( t )
logger := log . NewNopLogger ( )
config := configSetup ( t )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , cfg , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
partSize := types . BlockPartSizeBytes
partSize := types . BlockPartSizeBytes
@ -2348,17 +2376,17 @@ func TestStateHalt1(t *testing.T) {
ensurePrevote ( t , voteCh , height , round )
ensurePrevote ( t , voteCh , height , round )
signAddVotes ( ctx , t , cs1 , tmproto . PrevoteType , cfg . ChainID ( ) , blockID , vs2 , vs3 , vs4 )
signAddVotes ( ctx , t , cs1 , tmproto . PrevoteType , con fi g . ChainID ( ) , blockID , vs2 , vs3 , vs4 )
ensurePrecommit ( t , voteCh , height , round )
ensurePrecommit ( t , voteCh , height , round )
// the proposed block should now be locked and our precommit added
// the proposed block should now be locked and our precommit added
validatePrecommit ( ctx , t , cs1 , round , round , vss [ 0 ] , propBlock . Hash ( ) , propBlock . Hash ( ) )
validatePrecommit ( ctx , t , cs1 , round , round , vss [ 0 ] , propBlock . Hash ( ) , propBlock . Hash ( ) )
// add precommits from the rest
// add precommits from the rest
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , cfg . ChainID ( ) , types . BlockID { } , vs2 ) // didnt receive proposal
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , cfg . ChainID ( ) , blockID , vs3 )
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , con fi g . ChainID ( ) , types . BlockID { } , vs2 ) // didnt receive proposal
signAddVotes ( ctx , t , cs1 , tmproto . PrecommitType , con fi g . ChainID ( ) , blockID , vs3 )
// we receive this later, but vs3 might receive it earlier and with ours will go to commit!
// we receive this later, but vs3 might receive it earlier and with ours will go to commit!
precommit4 := signVote ( ctx , t , vs4 , tmproto . PrecommitType , cfg . ChainID ( ) , blockID )
precommit4 := signVote ( ctx , t , vs4 , tmproto . PrecommitType , con fi g . ChainID ( ) , blockID )
incrementRound ( vs2 , vs3 , vs4 )
incrementRound ( vs2 , vs3 , vs4 )
@ -2389,12 +2417,11 @@ func TestStateHalt1(t *testing.T) {
func TestStateOutputsBlockPartsStats ( t * testing . T ) {
func TestStateOutputsBlockPartsStats ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
// create dummy peer
// create dummy peer
cs , _ := makeState ( ctx , t , config , logger , 1 )
cs , _ := makeState ( ctx , t , makeStateArgs { config : config , validators : 1 } )
peerID , err := types . NewNodeID ( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" )
peerID , err := types . NewNodeID ( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" )
require . NoError ( t , err )
require . NoError ( t , err )
@ -2438,11 +2465,10 @@ func TestStateOutputsBlockPartsStats(t *testing.T) {
func TestStateOutputVoteStats ( t * testing . T ) {
func TestStateOutputVoteStats ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs , vss := makeState ( ctx , t , config , logger , 2 )
cs , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
// create dummy peer
// create dummy peer
peerID , err := types . NewNodeID ( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" )
peerID , err := types . NewNodeID ( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" )
require . NoError ( t , err )
require . NoError ( t , err )
@ -2480,11 +2506,10 @@ func TestStateOutputVoteStats(t *testing.T) {
func TestSignSameVoteTwice ( t * testing . T ) {
func TestSignSameVoteTwice ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
_ , vss := makeState ( ctx , t , config , logger , 2 )
_ , vss := makeState ( ctx , t , makeStateArgs { config : config , validators : 2 } )
randBytes := tmrand . Bytes ( tmhash . Size )
randBytes := tmrand . Bytes ( tmhash . Size )
@ -2521,11 +2546,10 @@ func TestSignSameVoteTwice(t *testing.T) {
// corresponding proposal message.
// corresponding proposal message.
func TestStateTimestamp_ProposalNotMatch ( t * testing . T ) {
func TestStateTimestamp_ProposalNotMatch ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
@ -2570,11 +2594,10 @@ func TestStateTimestamp_ProposalNotMatch(t *testing.T) {
// corresponding proposal message.
// corresponding proposal message.
func TestStateTimestamp_ProposalMatch ( t * testing . T ) {
func TestStateTimestamp_ProposalMatch ( t * testing . T ) {
config := configSetup ( t )
config := configSetup ( t )
logger := log . NewNopLogger ( )
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
defer cancel ( )
cs1 , vss := makeState ( ctx , t , config , logger , 4 )
cs1 , vss := makeState ( ctx , t , makeStateArgs { config : config } )
height , round := cs1 . Height , cs1 . Round
height , round := cs1 . Height , cs1 . Round
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]