mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-14 13:51:21 +00:00
rearrange common_test.go; EnsureDir for privVal
This commit is contained in:
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@ -28,6 +29,9 @@ import (
|
|||||||
var config cfg.Config // NOTE: must be reset for each _test.go file
|
var config cfg.Config // NOTE: must be reset for each _test.go file
|
||||||
var ensureTimeout = time.Duration(2)
|
var ensureTimeout = time.Duration(2)
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// validator stub (a dummy consensus peer we control)
|
||||||
|
|
||||||
type validatorStub struct {
|
type validatorStub struct {
|
||||||
Index int // Validator index. NOTE: we don't assume validator set changes.
|
Index int // Validator index. NOTE: we don't assume validator set changes.
|
||||||
Height int
|
Height int
|
||||||
@ -57,9 +61,6 @@ func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartS
|
|||||||
return vote, err
|
return vote, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
|
||||||
// Convenience functions
|
|
||||||
|
|
||||||
// Sign vote for type/hash/header
|
// Sign vote for type/hash/header
|
||||||
func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
||||||
v, err := vs.signVote(voteType, hash, header)
|
v, err := vs.signVote(voteType, hash, header)
|
||||||
@ -69,6 +70,34 @@ func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSe
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func signVotes(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.Vote {
|
||||||
|
votes := make([]*types.Vote, len(vss))
|
||||||
|
for i, vs := range vss {
|
||||||
|
votes[i] = signVote(vs, voteType, hash, header)
|
||||||
|
}
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
||||||
|
func incrementHeight(vss ...*validatorStub) {
|
||||||
|
for _, vs := range vss {
|
||||||
|
vs.Height += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func incrementRound(vss ...*validatorStub) {
|
||||||
|
for _, vs := range vss {
|
||||||
|
vs.Round += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Functions for transitioning the consensus state
|
||||||
|
|
||||||
|
func startTestRound(cs *ConsensusState, height, round int) {
|
||||||
|
cs.enterNewRound(height, round)
|
||||||
|
cs.startRoutines(0)
|
||||||
|
}
|
||||||
|
|
||||||
// Create proposal block from cs1 but sign it with vs
|
// Create proposal block from cs1 but sign it with vs
|
||||||
func decideProposal(cs1 *ConsensusState, vs *validatorStub, height, round int) (proposal *types.Proposal, block *types.Block) {
|
func decideProposal(cs1 *ConsensusState, vs *validatorStub, height, round int) (proposal *types.Proposal, block *types.Block) {
|
||||||
block, blockParts := cs1.createProposalBlock()
|
block, blockParts := cs1.createProposalBlock()
|
||||||
@ -91,41 +120,11 @@ func addVotes(to *ConsensusState, votes ...*types.Vote) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func signVotes(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.Vote {
|
|
||||||
votes := make([]*types.Vote, len(vss))
|
|
||||||
for i, vs := range vss {
|
|
||||||
votes[i] = signVote(vs, voteType, hash, header)
|
|
||||||
}
|
|
||||||
return votes
|
|
||||||
}
|
|
||||||
|
|
||||||
func signAddVotes(to *ConsensusState, voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) {
|
func signAddVotes(to *ConsensusState, voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) {
|
||||||
votes := signVotes(voteType, hash, header, vss...)
|
votes := signVotes(voteType, hash, header, vss...)
|
||||||
addVotes(to, votes...)
|
addVotes(to, votes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureNoNewStep(stepCh chan interface{}) {
|
|
||||||
timeout := time.NewTicker(ensureTimeout * time.Second)
|
|
||||||
select {
|
|
||||||
case <-timeout.C:
|
|
||||||
break
|
|
||||||
case <-stepCh:
|
|
||||||
panic("We should be stuck waiting for more votes, not moving to the next step")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func incrementHeight(vss ...*validatorStub) {
|
|
||||||
for _, vs := range vss {
|
|
||||||
vs.Height += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func incrementRound(vss ...*validatorStub) {
|
|
||||||
for _, vs := range vss {
|
|
||||||
vs.Round += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) {
|
func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) {
|
||||||
prevotes := cs.Votes.Prevotes(round)
|
prevotes := cs.Votes.Prevotes(round)
|
||||||
var vote *types.Vote
|
var vote *types.Vote
|
||||||
@ -192,24 +191,39 @@ func validatePrevoteAndPrecommit(t *testing.T, cs *ConsensusState, thisRound, lo
|
|||||||
cs.mtx.Unlock()
|
cs.mtx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixedConsensusState() *ConsensusState {
|
// genesis
|
||||||
stateDB := dbm.NewMemDB()
|
func subscribeToVoter(cs *ConsensusState, addr []byte) chan interface{} {
|
||||||
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
|
voteCh0 := subscribeToEvent(cs.evsw, "tester", types.EventStringVote(), 1)
|
||||||
privValidatorFile := config.GetString("priv_validator_file")
|
voteCh := make(chan interface{})
|
||||||
privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
|
go func() {
|
||||||
privValidator.Reset()
|
for {
|
||||||
cs := newConsensusState(state, privValidator, counter.NewCounterApplication(true))
|
v := <-voteCh0
|
||||||
return cs
|
vote := v.(types.EventDataVote)
|
||||||
|
// we only fire for our own votes
|
||||||
|
if bytes.Equal(addr, vote.Vote.ValidatorAddress) {
|
||||||
|
voteCh <- v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return voteCh
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixedConsensusStateDummy() *ConsensusState {
|
func readVotes(ch chan interface{}, reads int) chan struct{} {
|
||||||
stateDB := dbm.NewMemDB()
|
wg := make(chan struct{})
|
||||||
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
|
go func() {
|
||||||
privValidatorFile := config.GetString("priv_validator_file")
|
for i := 0; i < reads; i++ {
|
||||||
privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
|
<-ch // read the precommit event
|
||||||
privValidator.Reset()
|
}
|
||||||
cs := newConsensusState(state, privValidator, dummy.NewDummyApplication())
|
close(wg)
|
||||||
return cs
|
}()
|
||||||
|
return wg
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// consensus states
|
||||||
|
|
||||||
|
func newConsensusState(state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState {
|
||||||
|
return newConsensusStateWithConfig(config, state, pv, app)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConsensusStateWithConfig(thisConfig cfg.Config, state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState {
|
func newConsensusStateWithConfig(thisConfig cfg.Config, state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState {
|
||||||
@ -235,8 +249,28 @@ func newConsensusStateWithConfig(thisConfig cfg.Config, state *sm.State, pv *typ
|
|||||||
return cs
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConsensusState(state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState {
|
func loadPrivValidator(config cfg.Config) *types.PrivValidator {
|
||||||
return newConsensusStateWithConfig(config, state, pv, app)
|
privValidatorFile := config.GetString("priv_validator_file")
|
||||||
|
EnsureDir(path.Dir(privValidatorFile), 0700)
|
||||||
|
privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
|
||||||
|
privValidator.Reset()
|
||||||
|
return privValidator
|
||||||
|
}
|
||||||
|
|
||||||
|
func fixedConsensusState() *ConsensusState {
|
||||||
|
stateDB := dbm.NewMemDB()
|
||||||
|
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
|
||||||
|
privValidator := loadPrivValidator(config)
|
||||||
|
cs := newConsensusState(state, privValidator, counter.NewCounterApplication(true))
|
||||||
|
return cs
|
||||||
|
}
|
||||||
|
|
||||||
|
func fixedConsensusStateDummy() *ConsensusState {
|
||||||
|
stateDB := dbm.NewMemDB()
|
||||||
|
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
|
||||||
|
privValidator := loadPrivValidator(config)
|
||||||
|
cs := newConsensusState(state, privValidator, dummy.NewDummyApplication())
|
||||||
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
|
func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
|
||||||
@ -256,6 +290,21 @@ func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
|
|||||||
return cs, vss
|
return cs, vss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func ensureNoNewStep(stepCh chan interface{}) {
|
||||||
|
timeout := time.NewTicker(ensureTimeout * time.Second)
|
||||||
|
select {
|
||||||
|
case <-timeout.C:
|
||||||
|
break
|
||||||
|
case <-stepCh:
|
||||||
|
panic("We should be stuck waiting for more votes, not moving to the next step")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// consensus nets
|
||||||
|
|
||||||
func randConsensusNet(nValidators int, testName string, tickerFunc func() TimeoutTicker, appFunc func() tmsp.Application) []*ConsensusState {
|
func randConsensusNet(nValidators int, testName string, tickerFunc func() TimeoutTicker, appFunc func() tmsp.Application) []*ConsensusState {
|
||||||
genDoc, privVals := randGenesisDoc(nValidators, false, 10)
|
genDoc, privVals := randGenesisDoc(nValidators, false, 10)
|
||||||
css := make([]*ConsensusState, nValidators)
|
css := make([]*ConsensusState, nValidators)
|
||||||
@ -296,40 +345,18 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF
|
|||||||
return css
|
return css
|
||||||
}
|
}
|
||||||
|
|
||||||
func subscribeToVoter(cs *ConsensusState, addr []byte) chan interface{} {
|
func getSwitchIndex(switches []*p2p.Switch, peer *p2p.Peer) int {
|
||||||
voteCh0 := subscribeToEvent(cs.evsw, "tester", types.EventStringVote(), 1)
|
for i, s := range switches {
|
||||||
voteCh := make(chan interface{})
|
if bytes.Equal(peer.NodeInfo.PubKey.Address(), s.NodeInfo().PubKey.Address()) {
|
||||||
go func() {
|
return i
|
||||||
for {
|
|
||||||
v := <-voteCh0
|
|
||||||
vote := v.(types.EventDataVote)
|
|
||||||
// we only fire for our own votes
|
|
||||||
if bytes.Equal(addr, vote.Vote.ValidatorAddress) {
|
|
||||||
voteCh <- v
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
return voteCh
|
panic("didnt find peer in switches")
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func readVotes(ch chan interface{}, reads int) chan struct{} {
|
//-------------------------------------------------------------------------------
|
||||||
wg := make(chan struct{})
|
// genesis
|
||||||
go func() {
|
|
||||||
for i := 0; i < reads; i++ {
|
|
||||||
<-ch // read the precommit event
|
|
||||||
}
|
|
||||||
close(wg)
|
|
||||||
}()
|
|
||||||
return wg
|
|
||||||
}
|
|
||||||
|
|
||||||
func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) {
|
|
||||||
genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
|
|
||||||
db := dbm.NewMemDB()
|
|
||||||
s0 := sm.MakeGenesisState(db, genDoc)
|
|
||||||
s0.Save()
|
|
||||||
return s0, privValidators
|
|
||||||
}
|
|
||||||
|
|
||||||
func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []*types.PrivValidator) {
|
func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []*types.PrivValidator) {
|
||||||
validators := make([]types.GenesisValidator, numValidators)
|
validators := make([]types.GenesisValidator, numValidators)
|
||||||
@ -348,28 +375,18 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G
|
|||||||
ChainID: config.GetString("chain_id"),
|
ChainID: config.GetString("chain_id"),
|
||||||
Validators: validators,
|
Validators: validators,
|
||||||
}, privValidators
|
}, privValidators
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startTestRound(cs *ConsensusState, height, round int) {
|
func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) {
|
||||||
cs.enterNewRound(height, round)
|
genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
|
||||||
cs.startRoutines(0)
|
db := dbm.NewMemDB()
|
||||||
}
|
s0 := sm.MakeGenesisState(db, genDoc)
|
||||||
|
s0.Save()
|
||||||
//--------------------------------
|
return s0, privValidators
|
||||||
// reactor stuff
|
|
||||||
|
|
||||||
func getSwitchIndex(switches []*p2p.Switch, peer *p2p.Peer) int {
|
|
||||||
for i, s := range switches {
|
|
||||||
if bytes.Equal(peer.NodeInfo.PubKey.Address(), s.NodeInfo().PubKey.Address()) {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("didnt find peer in switches")
|
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
// mock ticker
|
||||||
|
|
||||||
func newMockTickerFunc(onlyOnce bool) func() TimeoutTicker {
|
func newMockTickerFunc(onlyOnce bool) func() TimeoutTicker {
|
||||||
return func() TimeoutTicker {
|
return func() TimeoutTicker {
|
||||||
|
Reference in New Issue
Block a user