152 lines
4.6 KiB
Go

package consensus
import (
"bytes"
"fmt"
"testing"
"time"
bc "github.com/tendermint/tendermint/blockchain"
dbm "github.com/tendermint/tendermint/db"
mempl "github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/p2p"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
//-------------------------------------------------------------------------------
// utils
func addVoteToFrom(to, from *ConsensusState, vote *types.Vote) {
valIndex, _ := to.Validators.GetByAddress(from.privValidator.Address)
added, err := to.TryAddVote(to.GetRoundState(), vote, valIndex, "")
if _, ok := err.(*types.ErrVoteConflictingSignature); ok {
// let it fly
} else if !added {
panic("Failed to add vote")
} else if err != nil {
panic(fmt.Sprintln("Failed to add vote:", err))
}
}
func signVote(from *ConsensusState, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
vote, err := from.signVote(voteType, hash, header)
if err != nil {
panic(fmt.Sprintln("Failed to sign vote", err))
}
return vote
}
// add vote to one cs from another
func signAddVoteToFrom(voteType byte, to, from *ConsensusState, hash []byte, header types.PartSetHeader) *types.Vote {
vote := signVote(from, voteType, hash, header)
addVoteToFrom(to, from, vote)
return vote
}
func ensureNoNewStep(t *testing.T, cs *ConsensusState) {
timeout := time.NewTicker(2 * time.Second)
select {
case <-timeout.C:
break
case <-cs.NewStepCh():
panic("We should be stuck waiting for more votes, not moving to the next step")
}
}
func ensureNewStep(t *testing.T, cs *ConsensusState) {
timeout := time.NewTicker(2 * time.Second)
select {
case <-timeout.C:
panic("We should have gone to the next step, not be stuck waiting")
case <-cs.NewStepCh():
break
}
}
func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *types.PrivValidator, blockHash []byte) {
prevotes := cs.Votes.Prevotes(round)
var vote *types.Vote
if vote = prevotes.GetByAddress(privVal.Address); vote == nil {
panic("Failed to find prevote from validator")
}
if blockHash == nil {
if vote.BlockHash != nil {
panic(fmt.Sprintf("Expected prevote to be for nil, got %X", vote.BlockHash))
}
} else {
if !bytes.Equal(vote.BlockHash, blockHash) {
panic(fmt.Sprintf("Expected prevote to be for %X, got %X", blockHash, vote.BlockHash))
}
}
}
func validatePrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *types.PrivValidator, votedBlockHash, lockedBlockHash []byte) {
precommits := cs.Votes.Precommits(thisRound)
var vote *types.Vote
if vote = precommits.GetByAddress(privVal.Address); vote == nil {
panic("Failed to find precommit from validator")
}
if votedBlockHash == nil {
if vote.BlockHash != nil {
panic("Expected precommit to be for nil")
}
} else {
if !bytes.Equal(vote.BlockHash, votedBlockHash) {
panic("Expected precommit to be for proposal block")
}
}
if lockedBlockHash == nil {
if cs.LockedRound != lockRound || cs.LockedBlock != nil {
panic(fmt.Sprintf("Expected to be locked on nil at round %d. Got locked at round %d with block %v", lockRound, cs.LockedRound, cs.LockedBlock))
}
} else {
if cs.LockedRound != lockRound || !bytes.Equal(cs.LockedBlock.Hash(), lockedBlockHash) {
panic(fmt.Sprintf("Expected block to be locked on round %d, got %d. Got locked block %X, expected %X", lockRound, cs.LockedRound, cs.LockedBlock.Hash(), lockedBlockHash))
}
}
}
func simpleConsensusState(nValidators int) ([]*ConsensusState, []*types.PrivValidator) {
// Get State
state, privAccs, privVals := sm.RandGenesisState(10, true, 1000, nValidators, false, 10)
_, _ = privAccs, privVals
fmt.Println(state.BondedValidators)
css := make([]*ConsensusState, nValidators)
for i := 0; i < nValidators; i++ {
// Get BlockStore
blockDB := dbm.NewMemDB()
blockStore := bc.NewBlockStore(blockDB)
// Make MempoolReactor
mempool := mempl.NewMempool(state.Copy())
mempoolReactor := mempl.NewMempoolReactor(mempool)
mempoolReactor.SetSwitch(p2p.NewSwitch())
// Make ConsensusReactor
cs := NewConsensusState(state, blockStore, mempoolReactor)
// read off the NewHeightStep
<-cs.NewStepCh()
css[i] = cs
}
return css, privVals
}
func randConsensusState() (*ConsensusState, []*types.PrivValidator) {
state, _, privValidators := sm.RandGenesisState(20, false, 1000, 10, false, 1000)
blockStore := bc.NewBlockStore(dbm.NewMemDB())
mempool := mempl.NewMempool(state)
mempoolReactor := mempl.NewMempoolReactor(mempool)
cs := NewConsensusState(state, blockStore, mempoolReactor)
return cs, privValidators
}