@ -30,7 +30,7 @@ x * TestBadProposal - 2 vals, bad proposal (bad block state hash), should prevot
FullRoundSuite
x * TestFullRound1 - 1 val , full successful round
x * TestFullRoundNil - 1 val , full round of nil
x * TestFullRound2 - 2 vals , both required for fui ll round
x * TestFullRound2 - 2 vals , both required for full round
LockSuite
x * TestLockNoPOL - 2 vals , 4 rounds . one val locked , precommits nil every round except first .
x * TestLockPOLRelock - 4 vals , one precommits , other 3 polka at next round , so we unlock and precomit the polka
@ -66,15 +66,15 @@ func TestProposerSelection0(t *testing.T) {
// lets commit a block and ensure proposer for the next height is correct
prop := cs1 . GetRoundState ( ) . Validators . Proposer ( )
if ! bytes . Equal ( prop . Address , cs1 . privValidator . Address ) {
panic ( Fmt ( "expected proposer to be validator %d. Got %X" , 0 , prop . Address ) )
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
<- proposalCh
rs := cs1 . GetRoundState ( )
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , nil , vss [ 1 : ] ... )
signAddVotes ( cs1 , types . VoteTypePrecommit , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , vss [ 1 : ] ... )
// wait for new round so next validator is set
<- newRoundCh
@ -106,7 +106,7 @@ func TestProposerSelection2(t *testing.T) {
}
rs := cs1 . GetRoundState ( )
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , rs . ProposalBlockParts . Header ( ) , nil , vss [ 1 : ] ... )
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , rs . ProposalBlockParts . Header ( ) , vss [ 1 : ] ... )
<- newRoundCh // wait for the new round event each round
incrementRound ( vss [ 1 : ] ... )
@ -179,12 +179,14 @@ func TestEnterProposeYesPrivValidator(t *testing.T) {
func TestBadProposal ( t * testing . T ) {
cs1 , vss := randConsensusState ( 2 )
height , round := cs1 . Height , cs1 . Round
cs2 := vss [ 1 ]
vs2 := vss [ 1 ]
partSize := config . GetInt ( "block_part_size" )
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
voteCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringVote ( ) , 1 )
propBlock , _ := cs1 . createProposalBlock ( ) //changeProposer(t, cs1, c s2)
propBlock , _ := cs1 . createProposalBlock ( ) //changeProposer(t, cs1, v s2)
// make the second validator the proposer by incrementing round
round = round + 1
@ -197,10 +199,10 @@ func TestBadProposal(t *testing.T) {
}
stateHash [ 0 ] = byte ( ( stateHash [ 0 ] + 1 ) % 255 )
propBlock . AppHash = stateHash
propBlockParts := propBlock . MakePartSet ( )
proposal := types . NewProposal ( c s2. Height , round , propBlockParts . Header ( ) , - 1 )
if err := c s2. SignProposal ( config . GetString ( "chain_id" ) , proposal ) ; err != nil {
panic ( "failed to sign bad proposal: " + err . Error ( ) )
propBlockParts := propBlock . MakePartSet ( partSize )
proposal := types . NewProposal ( v s2. Height , round , propBlockParts . Header ( ) , - 1 , types . BlockID { } )
if err := v s2. SignProposal ( config . GetString ( "chain_id" ) , proposal ) ; err != nil {
t . Fatal ( "failed to sign bad proposal" , err )
}
// set the proposal block
@ -217,14 +219,15 @@ func TestBadProposal(t *testing.T) {
validatePrevote ( t , cs1 , round , vss [ 0 ] , nil )
// add bad prevote from cs2 and wait for it
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , propBlock . Hash ( ) , propBlock . MakePartSet ( ) . Header ( ) , voteCh )
// add bad prevote from vs2 and wait for it
signAddVotes ( cs1 , types . VoteTypePrevote , propBlock . Hash ( ) , propBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
<- voteCh
// wait for precommit
<- voteCh
validatePrecommit ( t , cs1 , round , 0 , vss [ 0 ] , nil , nil )
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , propBlock . Hash ( ) , propBlock . MakePartSet ( ) . Header ( ) , voteCh )
signAddVotes ( cs1 , types . VoteTypePrecommit , propBlock . Hash ( ) , propBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
}
//----------------------------------------------------------------------------------------------------
@ -281,7 +284,7 @@ func TestFullRoundNil(t *testing.T) {
// where the first validator has to wait for votes from the second
func TestFullRound2 ( t * testing . T ) {
cs1 , vss := randConsensusState ( 2 )
c s2 := vss [ 1 ]
v s2 := vss [ 1 ]
height , round := cs1 . Height , cs1 . Round
voteCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringVote ( ) , 1 )
@ -296,8 +299,9 @@ func TestFullRound2(t *testing.T) {
rs := cs1 . GetRoundState ( )
propBlockHash , propPartsHeader := rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( )
// prevote arrives from cs2:
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , propBlockHash , propPartsHeader , voteCh )
// prevote arrives from vs2:
signAddVotes ( cs1 , types . VoteTypePrevote , propBlockHash , propPartsHeader , vs2 )
<- voteCh
<- voteCh //precommit
@ -306,8 +310,9 @@ func TestFullRound2(t *testing.T) {
// we should be stuck in limbo waiting for more precommits
// precommit arrives from cs2:
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , propBlockHash , propPartsHeader , voteCh )
// precommit arrives from vs2:
signAddVotes ( cs1 , types . VoteTypePrecommit , propBlockHash , propPartsHeader , vs2 )
<- voteCh
// wait to finish commit, propose in next height
<- newBlockCh
@ -320,9 +325,11 @@ func TestFullRound2(t *testing.T) {
// two vals take turns proposing. val1 locks on first one, precommits nil on everything else
func TestLockNoPOL ( t * testing . T ) {
cs1 , vss := randConsensusState ( 2 )
c s2 := vss [ 1 ]
v s2 := vss [ 1 ]
height := cs1 . Height
partSize := config . GetInt ( "block_part_size" )
timeoutProposeCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutPropose ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
voteCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringVote ( ) , 1 )
@ -344,8 +351,9 @@ func TestLockNoPOL(t *testing.T) {
<- voteCh // prevote
// we should now be stuck in limbo forever, waiting for more prevotes
// prevote arrives from cs2:
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , voteCh )
// prevote arrives from vs2:
signAddVotes ( cs1 , types . VoteTypePrevote , cs1 . ProposalBlock . Hash ( ) , cs1 . ProposalBlockParts . Header ( ) , vs2 )
<- voteCh // prevote
<- voteCh // precommit
@ -358,7 +366,8 @@ func TestLockNoPOL(t *testing.T) {
hash := make ( [ ] byte , len ( theBlockHash ) )
copy ( hash , theBlockHash )
hash [ 0 ] = byte ( ( hash [ 0 ] + 1 ) % 255 )
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , hash , rs . ProposalBlock . MakePartSet ( ) . Header ( ) , voteCh )
signAddVotes ( cs1 , types . VoteTypePrecommit , hash , rs . ProposalBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
<- voteCh // precommit
// (note we're entering precommit for a second time this round)
// but with invalid args. then we enterPrecommitWait, and the timeout to new round
@ -372,7 +381,7 @@ func TestLockNoPOL(t *testing.T) {
Round2 ( cs1 , B ) // B B2
* /
incrementRound ( c s2)
incrementRound ( v s2)
// now we're on a new round and not the proposer, so wait for timeout
re = <- timeoutProposeCh
@ -389,7 +398,8 @@ func TestLockNoPOL(t *testing.T) {
validatePrevote ( t , cs1 , 1 , vss [ 0 ] , rs . LockedBlock . Hash ( ) )
// add a conflicting prevote from the other validator
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , hash , rs . ProposalBlock . MakePartSet ( ) . Header ( ) , voteCh )
signAddVotes ( cs1 , types . VoteTypePrevote , hash , rs . ProposalBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
<- voteCh
// now we're going to enter prevote again, but with invalid args
// and then prevote wait, which should timeout. then wait for precommit
@ -401,9 +411,10 @@ func TestLockNoPOL(t *testing.T) {
// we should precommit nil and be locked on the proposal
validatePrecommit ( t , cs1 , 1 , 0 , vss [ 0 ] , nil , theBlockHash )
// add conflicting precommit from c s2
// add conflicting precommit from v s2
// NOTE: in practice we should never get to a point where there are precommits for different blocks at the same round
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , hash , rs . ProposalBlock . MakePartSet ( ) . Header ( ) , voteCh )
signAddVotes ( cs1 , types . VoteTypePrecommit , hash , rs . ProposalBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
<- voteCh
// (note we're entering precommit for a second time this round, but with invalid args
// then we enterPrecommitWait and timeout into NewRound
@ -412,10 +423,10 @@ func TestLockNoPOL(t *testing.T) {
<- newRoundCh
log . Notice ( "#### ONTO ROUND 2" )
/ *
Round3 ( c s2, _ ) // B, B2
Round3 ( v s2, _ ) // B, B2
* /
incrementRound ( c s2)
incrementRound ( v s2)
re = <- proposalCh
rs = re . ( types . EventDataRoundState ) . RoundState . ( * RoundState )
@ -429,33 +440,36 @@ func TestLockNoPOL(t *testing.T) {
validatePrevote ( t , cs1 , 2 , vss [ 0 ] , rs . LockedBlock . Hash ( ) )
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , hash , rs . ProposalBlock . MakePartSet ( ) . Header ( ) , voteCh )
signAddVotes ( cs1 , types . VoteTypePrevote , hash , rs . ProposalBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
<- voteCh
<- timeoutWaitCh // prevote wait
<- voteCh // precommit
validatePrecommit ( t , cs1 , 2 , 0 , vss [ 0 ] , nil , theBlockHash ) // precommit nil but be locked on proposal
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , hash , rs . ProposalBlock . MakePartSet ( ) . Header ( ) , voteCh ) // NOTE: conflicting precommits at same height
validatePrecommit ( t , cs1 , 2 , 0 , vss [ 0 ] , nil , theBlockHash ) // precommit nil but be locked on proposal
signAddVotes ( cs1 , types . VoteTypePrecommit , hash , rs . ProposalBlock . MakePartSet ( partSize ) . Header ( ) , vs2 ) // NOTE: conflicting precommits at same height
<- voteCh
<- timeoutWaitCh
// before we time out into new round, set next proposal block
prop , propBlock := decideProposal ( cs1 , cs2 , c s2. Height , c s2. Round + 1 )
prop , propBlock := decideProposal ( cs1 , vs2 , v s2. Height , v s2. Round + 1 )
if prop == nil || propBlock == nil {
panic ( "Failed to create proposal block with c s2")
t . Fatal ( "Failed to create proposal block with v s2")
}
incrementRound ( c s2)
incrementRound ( v s2)
<- newRoundCh
log . Notice ( "#### ONTO ROUND 3" )
/ *
Round4 ( c s2, C ) // B C // B C
Round4 ( v s2, C ) // B C // B C
* /
// now we're on a new round and not the proposer
// so set the proposal block
cs1 . SetProposalAndBlock ( prop , propBlock , propBlock . MakePartSet ( ) , "" )
cs1 . SetProposalAndBlock ( prop , propBlock , propBlock . MakePartSet ( partSize ) , "" )
<- proposalCh
<- voteCh // prevote
@ -463,19 +477,24 @@ func TestLockNoPOL(t *testing.T) {
// prevote for locked block (not proposal)
validatePrevote ( t , cs1 , 0 , vss [ 0 ] , cs1 . LockedBlock . Hash ( ) )
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , propBlock . Hash ( ) , propBlock . MakePartSet ( ) . Header ( ) , voteCh )
signAddVotes ( cs1 , types . VoteTypePrevote , propBlock . Hash ( ) , propBlock . MakePartSet ( partSize ) . Header ( ) , vs2 )
<- voteCh
<- timeoutWaitCh
<- voteCh
validatePrecommit ( t , cs1 , 2 , 0 , vss [ 0 ] , nil , theBlockHash ) // precommit nil but locked on proposal
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , propBlock . Hash ( ) , propBlock . MakePartSet ( ) . Header ( ) , voteCh ) // NOTE: conflicting precommits at same height
validatePrecommit ( t , cs1 , 2 , 0 , vss [ 0 ] , nil , theBlockHash ) // precommit nil but locked on proposal
signAddVotes ( cs1 , types . VoteTypePrecommit , propBlock . Hash ( ) , propBlock . MakePartSet ( partSize ) . Header ( ) , vs2 ) // NOTE: conflicting precommits at same height
<- voteCh
}
// 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka
func TestLockPOLRelock ( t * testing . T ) {
cs1 , vss := randConsensusState ( 4 )
cs2 , cs3 , cs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
partSize := config . GetInt ( "block_part_size" )
timeoutProposeCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutPropose ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
@ -484,14 +503,14 @@ func TestLockPOLRelock(t *testing.T) {
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
newBlockCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewBlockHeader ( ) , 1 )
log . Debug ( "c s2 last round" , "lr" , c s2. PrivValidator . LastRound )
log . Debug ( "v s2 last round" , "lr" , v s2. PrivValidator . LastRound )
// everything done from perspective of cs1
/ *
Round1 ( cs1 , B ) // B B B B// B nil B nil
eg . cs2 and c s4 didn ' t see the 2 / 3 prevotes
eg . vs2 and v s4 didn ' t see the 2 / 3 prevotes
* /
// start round and wait for propose and prevote
@ -501,26 +520,27 @@ func TestLockPOLRelock(t *testing.T) {
re := <- proposalCh
rs := re . ( types . EventDataRoundState ) . RoundState . ( * RoundState )
theBlockHash := rs . ProposalBlock . Hash ( )
theBlockPartsHeader := rs . ProposalBlockParts . Header ( )
<- voteCh // prevote
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , theBlockHash , theBlockPartsHeader , voteCh , cs2 , cs3 , cs4 )
signAddVotes ( cs1 , types . VoteTypePrevote , cs1 . ProposalBlock . Hash ( ) , cs1 . ProposalBlockParts . Header ( ) , vs2 , vs3 , vs4 )
_ , _ , _ = <- voteCh , <- voteCh , <- voteCh // prevotes
<- voteCh // our precommit
// the proposed block should now be locked and our precommit added
validatePrecommit ( t , cs1 , 0 , 0 , vss [ 0 ] , theBlockHash , theBlockHash )
// add precommits from the rest
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , types . PartSetHeader { } , voteCh , cs2 , cs4 )
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs3 , theBlockHash , theBlockPartsHeader , voteCh )
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 , vs4 )
signAddVotes ( cs1 , types . VoteTypePrecommit , cs1 . ProposalBlock . Hash ( ) , cs1 . ProposalBlockParts . Header ( ) , vs3 )
_ , _ , _ = <- voteCh , <- voteCh , <- voteCh // precommits
// before we timeout to the new round set the new proposal
prop , propBlock := decideProposal ( cs1 , cs2 , c s2. Height , c s2. Round + 1 )
propBlockParts := propBlock . MakePartSet ( )
prop , propBlock := decideProposal ( cs1 , vs2 , v s2. Height , v s2. Round + 1 )
propBlockParts := propBlock . MakePartSet ( partSize )
propBlockHash := propBlock . Hash ( )
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
// timeout to new round
<- timeoutWaitCh
@ -532,7 +552,7 @@ func TestLockPOLRelock(t *testing.T) {
log . Notice ( "### ONTO ROUND 1" )
/ *
Round2 ( c s2, C ) // B C C C // C C C _)
Round2 ( v s2, C ) // B C C C // C C C _)
cs1 changes lock !
* /
@ -550,7 +570,8 @@ func TestLockPOLRelock(t *testing.T) {
validatePrevote ( t , cs1 , 0 , vss [ 0 ] , theBlockHash )
// now lets add prevotes from everyone else for the new block
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , propBlockHash , propBlockParts . Header ( ) , voteCh , cs2 , cs3 , cs4 )
signAddVotes ( cs1 , types . VoteTypePrevote , propBlockHash , propBlockParts . Header ( ) , vs2 , vs3 , vs4 )
_ , _ , _ = <- voteCh , <- voteCh , <- voteCh // prevotes
// now either we go to PrevoteWait or Precommit
select {
@ -564,7 +585,8 @@ func TestLockPOLRelock(t *testing.T) {
// we should have unlocked and locked on the new block
validatePrecommit ( t , cs1 , 1 , 1 , vss [ 0 ] , propBlockHash , propBlockHash )
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , propBlockHash , propBlockParts . Header ( ) , voteCh , cs2 , cs3 )
signAddVotes ( cs1 , types . VoteTypePrecommit , propBlockHash , propBlockParts . Header ( ) , vs2 , vs3 )
_ , _ = <- voteCh , <- voteCh
be := <- newBlockCh
b := be . ( types . EventDataNewBlockHeader )
@ -582,14 +604,16 @@ func TestLockPOLRelock(t *testing.T) {
// 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka
func TestLockPOLUnlock ( t * testing . T ) {
cs1 , vss := randConsensusState ( 4 )
cs2 , cs3 , cs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
partSize := config . GetInt ( "block_part_size" )
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
timeoutProposeCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutPropose ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
unlockCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringUnlock ( ) , 1 )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . Address )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . GetAddress ( ) )
// everything done from perspective of cs1
@ -608,7 +632,7 @@ func TestLockPOLUnlock(t *testing.T) {
<- voteCh // prevote
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , nil , cs2 , cs3 , c s4)
signAddVotes ( cs1 , types . VoteTypePrevote , cs1 . ProposalBlock . Hash ( ) , cs1 . ProposalBlockParts . Header ( ) , vs2 , vs3 , v s4)
<- voteCh //precommit
@ -618,14 +642,14 @@ func TestLockPOLUnlock(t *testing.T) {
rs = cs1 . GetRoundState ( )
// add precommits from the rest
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , types . PartSetHeader { } , nil , cs2 , c s4)
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs3 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , nil )
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 , v s4)
signAddVotes ( cs1 , types . VoteTypePrecommit , cs1 . ProposalBlock . Hash ( ) , cs1 . ProposalBlockParts . Header ( ) , vs3 )
// before we time out into new round, set next proposal block
prop , propBlock := decideProposal ( cs1 , cs2 , c s2. Height , c s2. Round + 1 )
propBlockParts := propBlock . MakePartSet ( )
prop , propBlock := decideProposal ( cs1 , vs2 , v s2. Height , v s2. Round + 1 )
propBlockParts := propBlock . MakePartSet ( partSize )
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
// timeout to new round
re = <- timeoutWaitCh
@ -638,7 +662,7 @@ func TestLockPOLUnlock(t *testing.T) {
<- newRoundCh
log . Notice ( "#### ONTO ROUND 1" )
/ *
Round2 ( c s2, C ) // B nil nil nil // nil nil nil _
Round2 ( v s2, C ) // B nil nil nil // nil nil nil _
cs1 unlocks !
* /
@ -655,7 +679,7 @@ func TestLockPOLUnlock(t *testing.T) {
<- voteCh
validatePrevote ( t , cs1 , 0 , vss [ 0 ] , lockedBlockHash )
// now lets add prevotes from everyone else for nil (a polka!)
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , nil , types . PartSetHeader { } , nil , cs2 , cs3 , c s4)
signAddVotes ( cs1 , types . VoteTypePrevote , nil , types . PartSetHeader { } , vs2 , vs3 , v s4)
// the polka makes us unlock and precommit nil
<- unlockCh
@ -665,7 +689,7 @@ func TestLockPOLUnlock(t *testing.T) {
// NOTE: since we don't relock on nil, the lock round is 0
validatePrecommit ( t , cs1 , 1 , 0 , vss [ 0 ] , nil , nil )
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , types . PartSetHeader { } , nil , cs2 , c s3)
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 , v s3)
<- newRoundCh
}
@ -675,13 +699,15 @@ func TestLockPOLUnlock(t *testing.T) {
// then we see the polka from round 1 but shouldn't unlock
func TestLockPOLSafety1 ( t * testing . T ) {
cs1 , vss := randConsensusState ( 4 )
cs2 , cs3 , cs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
partSize := config . GetInt ( "block_part_size" )
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
timeoutProposeCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutPropose ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . Address )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . GetAddress ( ) )
// start round and wait for propose and prevote
startTestRound ( cs1 , cs1 . Height , 0 )
@ -695,7 +721,7 @@ func TestLockPOLSafety1(t *testing.T) {
validatePrevote ( t , cs1 , 0 , vss [ 0 ] , propBlock . Hash ( ) )
// the others sign a polka but we don't see it
prevotes := signVoteMany ( types . VoteTypePrevote , propBlock . Hash ( ) , propBlock . MakePartSet ( ) . Header ( ) , cs2 , cs3 , c s4)
prevotes := signVotes ( types . VoteTypePrevote , propBlock . Hash ( ) , propBlock . MakePartSet ( partSize ) . Header ( ) , vs2 , vs3 , v s4)
// before we time out into new round, set next proposer
// and next proposal block
@ -709,13 +735,13 @@ func TestLockPOLSafety1(t *testing.T) {
log . Warn ( "old prop" , "hash" , fmt . Sprintf ( "%X" , propBlock . Hash ( ) ) )
// we do see them precommit nil
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , types . PartSetHeader { } , nil , cs2 , cs3 , c s4)
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 , vs3 , v s4)
prop , propBlock := decideProposal ( cs1 , cs2 , c s2. Height , c s2. Round + 1 )
prop , propBlock := decideProposal ( cs1 , vs2 , v s2. Height , v s2. Round + 1 )
propBlockHash := propBlock . Hash ( )
propBlockParts := propBlock . MakePartSet ( )
propBlockParts := propBlock . MakePartSet ( partSize )
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
//XXX: this isnt gauranteed to get there before the timeoutPropose ...
cs1 . SetProposalAndBlock ( prop , propBlock , propBlockParts , "some peer" )
@ -746,18 +772,18 @@ func TestLockPOLSafety1(t *testing.T) {
validatePrevote ( t , cs1 , 1 , vss [ 0 ] , propBlockHash )
// now we see the others prevote for it, so we should lock on it
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , propBlockHash , propBlockParts . Header ( ) , nil , cs2 , cs3 , c s4)
signAddVotes ( cs1 , types . VoteTypePrevote , propBlockHash , propBlockParts . Header ( ) , vs2 , vs3 , v s4)
<- voteCh // precommit
// we should have precommitted
validatePrecommit ( t , cs1 , 1 , 1 , vss [ 0 ] , propBlockHash , propBlockHash )
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , types . PartSetHeader { } , nil , cs2 , c s3)
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 , v s3)
<- timeoutWaitCh
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
<- newRoundCh
@ -778,7 +804,7 @@ func TestLockPOLSafety1(t *testing.T) {
newStepCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRoundStep ( ) , 1 )
// add prevotes from the earlier round
addVoteToFromMany ( cs1 , prevotes , cs2 , cs3 , cs4 )
addVotes ( cs1 , prevotes ... )
log . Warn ( "Done adding prevotes!" )
@ -794,30 +820,33 @@ func TestLockPOLSafety1(t *testing.T) {
// dont see P0, lock on P1 at R1, dont unlock using P0 at R2
func TestLockPOLSafety2 ( t * testing . T ) {
cs1 , vss := randConsensusState ( 4 )
cs2 , cs3 , cs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
partSize := config . GetInt ( "block_part_size" )
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
timeoutProposeCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutPropose ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
unlockCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringUnlock ( ) , 1 )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . Address )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . GetAddress ( ) )
// the block for R0: gets polkad but we miss it
// (even though we signed it, shhh)
_ , propBlock0 := decideProposal ( cs1 , vss [ 0 ] , cs1 . Height , cs1 . Round )
propBlockHash0 := propBlock0 . Hash ( )
propBlockParts0 := propBlock0 . MakePartSet ( )
propBlockParts0 := propBlock0 . MakePartSet ( partSize )
// the others sign a polka but we don't see it
prevotes := signVoteMany ( types . VoteTypePrevote , propBlockHash0 , propBlockParts0 . Header ( ) , cs2 , cs3 , c s4)
prevotes := signVotes ( types . VoteTypePrevote , propBlockHash0 , propBlockParts0 . Header ( ) , vs2 , vs3 , v s4)
// the block for round 1
prop1 , propBlock1 := decideProposal ( cs1 , cs2 , c s2. Height , c s2. Round + 1 )
prop1 , propBlock1 := decideProposal ( cs1 , vs2 , v s2. Height , v s2. Round + 1 )
propBlockHash1 := propBlock1 . Hash ( )
propBlockParts1 := propBlock1 . MakePartSet ( )
propBlockParts1 := propBlock1 . MakePartSet ( partSize )
propBlockID1 := types . BlockID { propBlockHash1 , propBlockParts1 . Header ( ) }
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
cs1 . updateRoundStep ( 0 , RoundStepPrecommitWait )
@ -832,28 +861,30 @@ func TestLockPOLSafety2(t *testing.T) {
<- voteCh // prevote
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , propBlockHash1 , propBlockParts1 . Header ( ) , nil , cs2 , cs3 , c s4)
signAddVotes ( cs1 , types . VoteTypePrevote , propBlockHash1 , propBlockParts1 . Header ( ) , vs2 , vs3 , v s4)
<- voteCh // precommit
// the proposed block should now be locked and our precommit added
validatePrecommit ( t , cs1 , 1 , 1 , vss [ 0 ] , propBlockHash1 , propBlockHash1 )
// add precommits from the rest
signAddVoteToFromMany ( types . VoteTypePrecommit , cs1 , nil , types . PartSetHeader { } , nil , cs2 , c s4)
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs3 , propBlockHash1 , propBlockParts1 . Header ( ) , nil )
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 , v s4)
signAddVotes ( cs1 , types . VoteTypePrecommit , propBlockHash1 , propBlockParts1 . Header ( ) , vs3 )
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
// timeout of precommit wait to new round
<- timeoutWaitCh
// in round 2 we see the polkad block from round 0
newProp := types . NewProposal ( height , 2 , propBlockParts0 . Header ( ) , 0 )
if err := c s3. SignProposal ( config . GetString ( "chain_id" ) , newProp ) ; err != nil {
panic ( err )
newProp := types . NewProposal ( height , 2 , propBlockParts0 . Header ( ) , 0 , propBlockID1 )
if err := v s3. SignProposal ( config . GetString ( "chain_id" ) , newProp ) ; err != nil {
t . Fatal ( err )
}
cs1 . SetProposalAndBlock ( newProp , propBlock0 , propBlockParts0 , "some peer" )
addVoteToFromMany ( cs1 , prevotes , cs2 , cs3 , cs4 ) // add the pol votes
// Add the pol votes
addVotes ( cs1 , prevotes ... )
<- newRoundCh
log . Notice ( "### ONTO Round 2" )
@ -884,13 +915,13 @@ func TestLockPOLSafety2(t *testing.T) {
/ *
func TestSlashingPrevotes ( t * testing . T ) {
cs1 , vss := randConsensusState ( 2 )
c s2 := vss [ 1 ]
v s2 := vss [ 1 ]
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . Address )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . GetAddress ( ) )
// start round and wait for propose and prevote
startTestRound ( cs1 , cs1 . Height , 0 )
@ -904,7 +935,7 @@ func TestSlashingPrevotes(t *testing.T) {
// add one for a different block should cause us to go into prevote wait
hash := rs . ProposalBlock . Hash ( )
hash [ 0 ] = byte ( hash [ 0 ] + 1 ) % 255
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , hash , rs . ProposalBlockParts . Header ( ) , nil )
signAddVotes ( cs1 , types . VoteTypePrevote , hash , rs . ProposalBlockParts . Header ( ) , vs2 )
<- timeoutWaitCh
@ -912,20 +943,20 @@ func TestSlashingPrevotes(t *testing.T) {
// away and ignore more prevotes (and thus fail to slash!)
// add the conflicting vote
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , nil )
signAddVotes ( cs1 , types . VoteTypePrevote , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , vs2 )
// XXX: Check for existence of Dupeout info
}
func TestSlashingPrecommits ( t * testing . T ) {
cs1 , vss := randConsensusState ( 2 )
c s2 := vss [ 1 ]
v s2 := vss [ 1 ]
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . Address )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . GetAddress ( ) )
// start round and wait for propose and prevote
startTestRound ( cs1 , cs1 . Height , 0 )
@ -933,8 +964,8 @@ func TestSlashingPrecommits(t *testing.T) {
re := <- proposalCh
<- voteCh // prevote
// add prevote from c s2
signAddVoteToFrom ( types . VoteTypePrevote , cs1 , cs2 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , nil )
// add prevote from v s2
signAddVotes ( cs1 , types . VoteTypePrevote , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , vs2 )
<- voteCh // precommit
@ -942,13 +973,13 @@ func TestSlashingPrecommits(t *testing.T) {
// add one for a different block should cause us to go into prevote wait
hash := rs . ProposalBlock . Hash ( )
hash [ 0 ] = byte ( hash [ 0 ] + 1 ) % 255
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , hash , rs . ProposalBlockParts . Header ( ) , nil )
signAddVotes ( cs1 , types . VoteTypePrecommit , hash , rs . ProposalBlockParts . Header ( ) , vs2 )
// NOTE: we have to send the vote for different block first so we don't just go into precommit round right
// away and ignore more prevotes (and thus fail to slash!)
// add precommit from c s2
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , nil )
// add precommit from v s2
signAddVotes ( cs1 , types . VoteTypePrecommit , rs . ProposalBlock . Hash ( ) , rs . ProposalBlockParts . Header ( ) , vs2 )
// XXX: Check for existence of Dupeout info
}
@ -964,13 +995,15 @@ func TestSlashingPrecommits(t *testing.T) {
// we receive a final precommit after going into next round, but others might have gone to commit already!
func TestHalt1 ( t * testing . T ) {
cs1 , vss := randConsensusState ( 4 )
cs2 , cs3 , cs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
vs2 , vs3 , vs4 := vss [ 1 ] , vss [ 2 ] , vss [ 3 ]
partSize := config . GetInt ( "block_part_size" )
proposalCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringCompleteProposal ( ) , 1 )
timeoutWaitCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringTimeoutWait ( ) , 1 )
newRoundCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewRound ( ) , 1 )
newBlockCh := subscribeToEvent ( cs1 . evsw , "tester" , types . EventStringNewBlock ( ) , 1 )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . Address )
voteCh := subscribeToVoter ( cs1 , cs1 . privValidator . GetAddress ( ) )
// start round and wait for propose and prevote
startTestRound ( cs1 , cs1 . Height , 0 )
@ -978,23 +1011,23 @@ func TestHalt1(t *testing.T) {
re := <- proposalCh
rs := re . ( types . EventDataRoundState ) . RoundState . ( * RoundState )
propBlock := rs . ProposalBlock
propBlockParts := propBlock . MakePartSet ( )
propBlockParts := propBlock . MakePartSet ( partSize )
<- voteCh // prevote
signAddVoteToFromMany ( types . VoteTypePrevote , cs1 , propBlock . Hash ( ) , propBlockParts . Header ( ) , nil , cs3 , c s4)
signAddVotes ( cs1 , types . VoteTypePrevote , propBlock . Hash ( ) , propBlockParts . Header ( ) , vs3 , v s4)
<- voteCh // precommit
// the proposed block should now be locked and our precommit added
validatePrecommit ( t , cs1 , 0 , 0 , vss [ 0 ] , propBlock . Hash ( ) , propBlock . Hash ( ) )
// add precommits from the rest
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs2 , nil , types . PartSetHeader { } , nil ) // didnt receive proposal
signAddVoteToFrom ( types . VoteTypePrecommit , cs1 , cs3 , propBlock . Hash ( ) , propBlockParts . Header ( ) , nil )
// we receive this later, but c s3 might receive it earlier and with ours will go to commit!
precommit4 := signVote ( c s4, types . VoteTypePrecommit , propBlock . Hash ( ) , propBlockParts . Header ( ) )
signAddVotes ( cs1 , types . VoteTypePrecommit , nil , types . PartSetHeader { } , vs2 ) // didnt receive proposal
signAddVotes ( cs1 , types . VoteTypePrecommit , propBlock . Hash ( ) , propBlockParts . Header ( ) , vs3 )
// we receive this later, but v s3 might receive it earlier and with ours will go to commit!
precommit4 := signVote ( v s4, types . VoteTypePrecommit , propBlock . Hash ( ) , propBlockParts . Header ( ) )
incrementRound ( cs2 , cs3 , c s4)
incrementRound ( vs2 , vs3 , v s4)
// timeout to new round
<- timeoutWaitCh
@ -1012,7 +1045,7 @@ func TestHalt1(t *testing.T) {
validatePrevote ( t , cs1 , 0 , vss [ 0 ] , rs . LockedBlock . Hash ( ) )
// now we receive the precommit from the previous round
addVoteToFrom ( cs1 , cs4 , precommit4 )
addVotes ( cs1 , precommit4 )
// receiving that precommit should take us straight to commit
<- newBlockCh