Browse Source

consensus: reduce shared state in tests (#6313)

pull/6324/head
Sam Kleinman 3 years ago
committed by GitHub
parent
commit
dbfd6fc613
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 279 additions and 211 deletions
  1. +2
    -2
      consensus/byzantine_test.go
  2. +42
    -22
      consensus/common_test.go
  3. +2
    -2
      consensus/invalid_test.go
  4. +10
    -10
      consensus/mempool_test.go
  5. +12
    -9
      consensus/reactor_test.go
  6. +84
    -43
      consensus/replay_test.go
  7. +127
    -123
      consensus/state_test.go

+ 2
- 2
consensus/byzantine_test.go View File

@ -28,7 +28,7 @@ import (
// Byzantine node sends two different prevotes (nil and blockID) to the same
// validator.
func TestByzantinePrevoteEquivocation(t *testing.T) {
configSetup(t)
config := configSetup(t)
nValidators := 4
prevoteHeight := int64(2)
@ -36,7 +36,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
tickerFunc := newMockTickerFunc(true)
appFunc := newCounter
genDoc, privVals := randGenesisDoc(nValidators, false, 30)
genDoc, privVals := randGenesisDoc(config, nValidators, false, 30)
states := make([]*State, nValidators)
for i := 0; i < nValidators; i++ {


+ 42
- 22
consensus/common_test.go View File

@ -42,24 +42,21 @@ import (
const (
testSubscriber = "test-client"
// genesis, chain_id, priv_val
ensureTimeout = time.Millisecond * 200
)
// A cleanupFunc cleans up any config / test files created for a particular
// test.
type cleanupFunc func()
// genesis, chain_id, priv_val
var (
config *cfg.Config // NOTE: must be reset for each _test.go file
consensusReplayConfig *cfg.Config
ensureTimeout = time.Millisecond * 200
)
func configSetup(t *testing.T) {
func configSetup(t *testing.T) *cfg.Config {
t.Helper()
config = ResetConfig("consensus_reactor_test")
consensusReplayConfig = ResetConfig("consensus_replay_test")
config := ResetConfig("consensus_reactor_test")
consensusReplayConfig := ResetConfig("consensus_replay_test")
configStateTest := ResetConfig("consensus_state_test")
configMempoolTest := ResetConfig("consensus_mempool_test")
configByzantineTest := ResetConfig("consensus_byzantine_test")
@ -71,6 +68,7 @@ func configSetup(t *testing.T) {
os.RemoveAll(configMempoolTest.RootDir)
os.RemoveAll(configByzantineTest.RootDir)
})
return config
}
func ensureDir(dir string, mode os.FileMode) {
@ -94,7 +92,7 @@ type validatorStub struct {
VotingPower int64
}
var testMinPower int64 = 10
const testMinPower int64 = 10
func newValidatorStub(privValidator types.PrivValidator, valIndex int32) *validatorStub {
return &validatorStub{
@ -105,6 +103,7 @@ func newValidatorStub(privValidator types.PrivValidator, valIndex int32) *valida
}
func (vs *validatorStub) signVote(
config *cfg.Config,
voteType tmproto.SignedMsgType,
hash []byte,
header types.PartSetHeader) (*types.Vote, error) {
@ -131,8 +130,14 @@ func (vs *validatorStub) signVote(
}
// Sign vote for type/hash/header
func signVote(vs *validatorStub, voteType tmproto.SignedMsgType, hash []byte, header types.PartSetHeader) *types.Vote {
v, err := vs.signVote(voteType, hash, header)
func signVote(
vs *validatorStub,
config *cfg.Config,
voteType tmproto.SignedMsgType,
hash []byte,
header types.PartSetHeader) *types.Vote {
v, err := vs.signVote(config, voteType, hash, header)
if err != nil {
panic(fmt.Errorf("failed to sign vote: %v", err))
}
@ -140,13 +145,14 @@ func signVote(vs *validatorStub, voteType tmproto.SignedMsgType, hash []byte, he
}
func signVotes(
config *cfg.Config,
voteType tmproto.SignedMsgType,
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)
votes[i] = signVote(vs, config, voteType, hash, header)
}
return votes
}
@ -237,13 +243,14 @@ func addVotes(to *State, votes ...*types.Vote) {
}
func signAddVotes(
config *cfg.Config,
to *State,
voteType tmproto.SignedMsgType,
hash []byte,
header types.PartSetHeader,
vss ...*validatorStub,
) {
votes := signVotes(voteType, hash, header, vss...)
votes := signVotes(config, voteType, hash, header, vss...)
addVotes(to, votes...)
}
@ -440,9 +447,9 @@ func loadPrivValidator(config *cfg.Config) *privval.FilePV {
return privValidator
}
func randState(nValidators int) (*State, []*validatorStub) {
func randState(config *cfg.Config, nValidators int) (*State, []*validatorStub) {
// Get State
state, privVals := randGenesisState(nValidators, false, 10)
state, privVals := randGenesisState(config, nValidators, false, 10)
vss := make([]*validatorStub, nValidators)
@ -694,6 +701,7 @@ func consensusLogger() log.Logger {
}
func randConsensusState(
config *cfg.Config,
nValidators int,
testName string,
tickerFunc func() TimeoutTicker,
@ -701,7 +709,7 @@ func randConsensusState(
configOpts ...func(*cfg.Config),
) ([]*State, cleanupFunc) {
genDoc, privVals := randGenesisDoc(nValidators, false, 30)
genDoc, privVals := randGenesisDoc(config, nValidators, false, 30)
css := make([]*State, nValidators)
logger := consensusLogger()
@ -748,15 +756,17 @@ func randConsensusState(
// nPeers = nValidators + nNotValidator
func randConsensusNetWithPeers(
config *cfg.Config,
nValidators,
nPeers int,
testName string,
tickerFunc func() TimeoutTicker,
appFunc func(string) abci.Application,
) ([]*State, *types.GenesisDoc, *cfg.Config, cleanupFunc) {
genDoc, privVals := randGenesisDoc(nValidators, false, testMinPower)
genDoc, privVals := randGenesisDoc(config, nValidators, false, testMinPower)
css := make([]*State, nPeers)
logger := consensusLogger()
var peer0Config *cfg.Config
configRootDirs := make([]string, 0, nPeers)
for i := 0; i < nPeers; i++ {
@ -808,7 +818,12 @@ func randConsensusNetWithPeers(
}
}
func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []types.PrivValidator) {
func randGenesisDoc(
config *cfg.Config,
numValidators int,
randPower bool,
minPower int64) (*types.GenesisDoc, []types.PrivValidator) {
validators := make([]types.GenesisValidator, numValidators)
privValidators := make([]types.PrivValidator, numValidators)
for i := 0; i < numValidators; i++ {
@ -829,8 +844,13 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G
}, privValidators
}
func randGenesisState(numValidators int, randPower bool, minPower int64) (sm.State, []types.PrivValidator) {
genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
func randGenesisState(
config *cfg.Config,
numValidators int,
randPower bool,
minPower int64) (sm.State, []types.PrivValidator) {
genDoc, privValidators := randGenesisDoc(config, numValidators, randPower, minPower)
s0, _ := sm.MakeGenesisState(genDoc)
return s0, privValidators
}


+ 2
- 2
consensus/invalid_test.go View File

@ -15,10 +15,10 @@ import (
)
func TestReactorInvalidPrecommit(t *testing.T) {
configSetup(t)
config := configSetup(t)
n := 4
states, cleanup := randConsensusState(n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
states, cleanup := randConsensusState(config, n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
t.Cleanup(cleanup)
for i := 0; i < 4; i++ {


+ 10
- 10
consensus/mempool_test.go View File

@ -25,13 +25,13 @@ func assertMempool(txn txNotifier) mempl.Mempool {
}
func TestMempoolNoProgressUntilTxsAvailable(t *testing.T) {
configSetup(t)
baseConfig := configSetup(t)
config := ResetConfig("consensus_mempool_txs_available_test")
t.Cleanup(func() { _ = os.RemoveAll(config.RootDir) })
config.Consensus.CreateEmptyBlocks = false
state, privVals := randGenesisState(1, false, 10)
state, privVals := randGenesisState(baseConfig, 1, false, 10)
cs := newStateWithConfig(config, state, privVals[0], NewCounterApplication())
assertMempool(cs.txNotifier).EnableTxsAvailable()
height, round := cs.Height, cs.Round
@ -47,13 +47,13 @@ func TestMempoolNoProgressUntilTxsAvailable(t *testing.T) {
}
func TestMempoolProgressAfterCreateEmptyBlocksInterval(t *testing.T) {
configSetup(t)
baseConfig := configSetup(t)
config := ResetConfig("consensus_mempool_txs_available_test")
t.Cleanup(func() { _ = os.RemoveAll(config.RootDir) })
config.Consensus.CreateEmptyBlocksInterval = ensureTimeout
state, privVals := randGenesisState(1, false, 10)
state, privVals := randGenesisState(baseConfig, 1, false, 10)
cs := newStateWithConfig(config, state, privVals[0], NewCounterApplication())
assertMempool(cs.txNotifier).EnableTxsAvailable()
@ -67,13 +67,13 @@ func TestMempoolProgressAfterCreateEmptyBlocksInterval(t *testing.T) {
}
func TestMempoolProgressInHigherRound(t *testing.T) {
configSetup(t)
baseConfig := configSetup(t)
config := ResetConfig("consensus_mempool_txs_available_test")
t.Cleanup(func() { _ = os.RemoveAll(config.RootDir) })
config.Consensus.CreateEmptyBlocks = false
state, privVals := randGenesisState(1, false, 10)
state, privVals := randGenesisState(baseConfig, 1, false, 10)
cs := newStateWithConfig(config, state, privVals[0], NewCounterApplication())
assertMempool(cs.txNotifier).EnableTxsAvailable()
height, round := cs.Height, cs.Round
@ -119,9 +119,9 @@ func deliverTxsRange(cs *State, start, end int) {
}
func TestMempoolTxConcurrentWithCommit(t *testing.T) {
configSetup(t)
config := configSetup(t)
state, privVals := randGenesisState(1, false, 10)
state, privVals := randGenesisState(config, 1, false, 10)
blockDB := dbm.NewMemDB()
stateStore := sm.NewStore(blockDB)
cs := newStateWithConfigAndBlockStore(config, state, privVals[0], NewCounterApplication(), blockDB)
@ -145,9 +145,9 @@ func TestMempoolTxConcurrentWithCommit(t *testing.T) {
}
func TestMempoolRmBadTx(t *testing.T) {
configSetup(t)
config := configSetup(t)
state, privVals := randGenesisState(1, false, 10)
state, privVals := randGenesisState(config, 1, false, 10)
app := NewCounterApplication()
blockDB := dbm.NewMemDB()
stateStore := sm.NewStore(blockDB)


+ 12
- 9
consensus/reactor_test.go View File

@ -246,10 +246,10 @@ func waitForBlockWithUpdatedValsAndValidateIt(
}
func TestReactorBasic(t *testing.T) {
configSetup(t)
config := configSetup(t)
n := 4
states, cleanup := randConsensusState(n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
states, cleanup := randConsensusState(config, n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
t.Cleanup(cleanup)
rts := setup(t, n, states, 100) // buffer must be large enough to not deadlock
@ -274,14 +274,14 @@ func TestReactorBasic(t *testing.T) {
}
func TestReactorWithEvidence(t *testing.T) {
configSetup(t)
config := configSetup(t)
n := 4
testName := "consensus_reactor_test"
tickerFunc := newMockTickerFunc(true)
appFunc := newCounter
genDoc, privVals := randGenesisDoc(n, false, 30)
genDoc, privVals := randGenesisDoc(config, n, false, 30)
states := make([]*State, n)
logger := consensusLogger()
@ -369,10 +369,11 @@ func TestReactorWithEvidence(t *testing.T) {
}
func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) {
configSetup(t)
config := configSetup(t)
n := 4
states, cleanup := randConsensusState(
config,
n,
"consensus_reactor_test",
newMockTickerFunc(true),
@ -409,10 +410,10 @@ func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) {
}
func TestReactorRecordsVotesAndBlockParts(t *testing.T) {
configSetup(t)
config := configSetup(t)
n := 4
states, cleanup := randConsensusState(n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
states, cleanup := randConsensusState(config, n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
t.Cleanup(cleanup)
rts := setup(t, n, states, 100) // buffer must be large enough to not deadlock
@ -466,10 +467,11 @@ func TestReactorRecordsVotesAndBlockParts(t *testing.T) {
}
func TestReactorVotingPowerChange(t *testing.T) {
configSetup(t)
config := configSetup(t)
n := 4
states, cleanup := randConsensusState(
config,
n,
"consensus_voting_power_changes_test",
newMockTickerFunc(true),
@ -565,11 +567,12 @@ func TestReactorVotingPowerChange(t *testing.T) {
}
func TestReactorValidatorSetChanges(t *testing.T) {
configSetup(t)
config := configSetup(t)
nPeers := 7
nVals := 4
states, _, _, cleanup := randConsensusNetWithPeers(
config,
nVals,
nPeers,
"consensus_val_set_changes_test",


+ 84
- 43
consensus/replay_test.go View File

@ -6,6 +6,7 @@ import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"runtime"
@ -276,25 +277,21 @@ func (w *crashingWAL) Stop() error { return w.next.Stop() }
func (w *crashingWAL) Wait() { w.next.Wait() }
//------------------------------------------------------------------------------------------
type testSim struct {
type simulatorTestSuite struct {
GenesisState sm.State
Config *cfg.Config
Chain []*types.Block
Commits []*types.Commit
CleanupFunc cleanupFunc
Mempool mempl.Mempool
Evpool sm.EvidencePool
}
const (
numBlocks = 6
)
var (
mempool = emptyMempool{}
evpool = sm.EmptyEvidencePool{}
sim testSim
)
//---------------------------------------
// Test handshake/replay
@ -305,12 +302,20 @@ var (
var modes = []uint{0, 1, 2, 3}
// This is actually not a test, it's for storing validator change tx data for testHandshakeReplay
func TestSimulateValidatorsChange(t *testing.T) {
configSetup(t)
func setupSimulator(t *testing.T) *simulatorTestSuite {
t.Helper()
config := configSetup(t)
sim := &simulatorTestSuite{
Mempool: emptyMempool{},
Evpool: sm.EmptyEvidencePool{},
}
nPeers := 7
nVals := 4
css, genDoc, config, cleanup := randConsensusNetWithPeers(
config,
nVals,
nPeers,
"replay_test",
@ -337,7 +342,11 @@ func TestSimulateValidatorsChange(t *testing.T) {
ensureNewRound(newRoundCh, height, 0)
ensureNewProposal(proposalCh, height, round)
rs := css[0].GetRoundState()
signAddVotes(css[0], tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:nVals]...)
signAddVotes(sim.Config, css[0], tmproto.PrecommitType,
rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(),
vss[1:nVals]...)
ensureNewRound(newRoundCh, height+1, 0)
// HEIGHT 2
@ -367,7 +376,9 @@ func TestSimulateValidatorsChange(t *testing.T) {
}
ensureNewProposal(proposalCh, height, round)
rs = css[0].GetRoundState()
signAddVotes(css[0], tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:nVals]...)
signAddVotes(sim.Config, css[0], tmproto.PrecommitType,
rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(),
vss[1:nVals]...)
ensureNewRound(newRoundCh, height+1, 0)
// HEIGHT 3
@ -397,7 +408,9 @@ func TestSimulateValidatorsChange(t *testing.T) {
}
ensureNewProposal(proposalCh, height, round)
rs = css[0].GetRoundState()
signAddVotes(css[0], tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:nVals]...)
signAddVotes(sim.Config, css[0], tmproto.PrecommitType,
rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(),
vss[1:nVals]...)
ensureNewRound(newRoundCh, height+1, 0)
// HEIGHT 4
@ -463,7 +476,9 @@ func TestSimulateValidatorsChange(t *testing.T) {
if i == selfIndex {
continue
}
signAddVotes(css[0], tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), newVss[i])
signAddVotes(sim.Config, css[0],
tmproto.PrecommitType, rs.ProposalBlock.Hash(),
rs.ProposalBlockParts.Header(), newVss[i])
}
ensureNewRound(newRoundCh, height+1, 0)
@ -482,7 +497,9 @@ func TestSimulateValidatorsChange(t *testing.T) {
if i == selfIndex {
continue
}
signAddVotes(css[0], tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), newVss[i])
signAddVotes(sim.Config, css[0],
tmproto.PrecommitType, rs.ProposalBlock.Hash(),
rs.ProposalBlockParts.Header(), newVss[i])
}
ensureNewRound(newRoundCh, height+1, 0)
@ -517,7 +534,9 @@ func TestSimulateValidatorsChange(t *testing.T) {
if i == selfIndex {
continue
}
signAddVotes(css[0], tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), newVss[i])
signAddVotes(sim.Config, css[0],
tmproto.PrecommitType, rs.ProposalBlock.Hash(),
rs.ProposalBlockParts.Header(), newVss[i])
}
ensureNewRound(newRoundCh, height+1, 0)
@ -527,61 +546,67 @@ func TestSimulateValidatorsChange(t *testing.T) {
sim.Chain = append(sim.Chain, css[0].blockStore.LoadBlock(int64(i)))
sim.Commits = append(sim.Commits, css[0].blockStore.LoadBlockCommit(int64(i)))
}
if sim.CleanupFunc != nil {
t.Cleanup(sim.CleanupFunc)
}
return sim
}
// Sync from scratch
func TestHandshakeReplayAll(t *testing.T) {
configSetup(t)
sim := setupSimulator(t)
for _, m := range modes {
testHandshakeReplay(t, config, 0, m, false)
testHandshakeReplay(t, sim, 0, m, false)
}
for _, m := range modes {
testHandshakeReplay(t, config, 0, m, true)
testHandshakeReplay(t, sim, 0, m, true)
}
}
// Sync many, not from scratch
func TestHandshakeReplaySome(t *testing.T) {
configSetup(t)
sim := setupSimulator(t)
for _, m := range modes {
testHandshakeReplay(t, config, 2, m, false)
testHandshakeReplay(t, sim, 2, m, false)
}
for _, m := range modes {
testHandshakeReplay(t, config, 2, m, true)
testHandshakeReplay(t, sim, 2, m, true)
}
}
// Sync from lagging by one
func TestHandshakeReplayOne(t *testing.T) {
configSetup(t)
sim := setupSimulator(t)
for _, m := range modes {
testHandshakeReplay(t, config, numBlocks-1, m, false)
testHandshakeReplay(t, sim, numBlocks-1, m, false)
}
for _, m := range modes {
testHandshakeReplay(t, config, numBlocks-1, m, true)
testHandshakeReplay(t, sim, numBlocks-1, m, true)
}
}
// Sync from caught up
func TestHandshakeReplayNone(t *testing.T) {
configSetup(t)
sim := setupSimulator(t)
for _, m := range modes {
testHandshakeReplay(t, config, numBlocks, m, false)
testHandshakeReplay(t, sim, numBlocks, m, false)
}
for _, m := range modes {
testHandshakeReplay(t, config, numBlocks, m, true)
testHandshakeReplay(t, sim, numBlocks, m, true)
}
}
// Test mockProxyApp should not panic when app return ABCIResponses with some empty ResponseDeliverTx
func TestMockProxyApp(t *testing.T) {
configSetup(t)
sim := setupSimulator(t) // setup config and simulator
config := sim.Config
assert.NotNil(t, config)
sim.CleanupFunc() // clean the test env created in TestSimulateValidatorsChange
logger := log.TestingLogger()
var validTxs, invalidTxs = 0, 0
txIndex := 0
@ -648,12 +673,15 @@ func tempWALWithData(data []byte) string {
// Make some blocks. Start a fresh app and apply nBlocks blocks.
// Then restart the app and sync it up with the remaining blocks
func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uint, testValidatorsChange bool) {
func testHandshakeReplay(t *testing.T, sim *simulatorTestSuite, nBlocks int, mode uint, testValidatorsChange bool) {
var chain []*types.Block
var commits []*types.Commit
var store *mockBlockStore
var stateDB dbm.DB
var genesisState sm.State
config := sim.Config
if testValidatorsChange {
testConfig := ResetConfig(fmt.Sprintf("%s_%v_m", t.Name(), mode))
defer func() { _ = os.RemoveAll(testConfig.RootDir) }()
@ -698,12 +726,12 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin
state := genesisState.Copy()
// run the chain through state.ApplyBlock to build up the tendermint state
state = buildTMStateFromChain(config, stateStore, state, chain, nBlocks, mode)
state = buildTMStateFromChain(config, sim.Mempool, sim.Evpool, stateStore, state, chain, nBlocks, mode)
latestAppHash := state.AppHash
// make a new client creator
kvstoreApp := kvstore.NewPersistentKVStoreApplication(
filepath.Join(config.DBDir(), fmt.Sprintf("replay_test_%d_%d_a", nBlocks, mode)))
filepath.Join(config.DBDir(), fmt.Sprintf("replay_test_%d_%d_a_r%d", nBlocks, mode, rand.Int())))
t.Cleanup(func() { require.NoError(t, kvstoreApp.Close()) })
clientCreator2 := proxy.NewLocalClientCreator(kvstoreApp)
@ -715,7 +743,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin
stateStore := sm.NewStore(stateDB1)
err := stateStore.Save(genesisState)
require.NoError(t, err)
buildAppStateFromChain(proxyApp, stateStore, genesisState, chain, nBlocks, mode)
buildAppStateFromChain(proxyApp, stateStore, sim.Mempool, sim.Evpool, genesisState, chain, nBlocks, mode)
}
// Prune block store if requested
@ -775,7 +803,12 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin
}
}
func applyBlock(stateStore sm.Store, st sm.State, blk *types.Block, proxyApp proxy.AppConns) sm.State {
func applyBlock(stateStore sm.Store,
mempool mempl.Mempool,
evpool sm.EvidencePool,
st sm.State,
blk *types.Block,
proxyApp proxy.AppConns) sm.State {
testPartSize := types.BlockPartSizeBytes
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool)
@ -787,8 +820,14 @@ func applyBlock(stateStore sm.Store, st sm.State, blk *types.Block, proxyApp pro
return newState
}
func buildAppStateFromChain(proxyApp proxy.AppConns, stateStore sm.Store,
state sm.State, chain []*types.Block, nBlocks int, mode uint) {
func buildAppStateFromChain(
proxyApp proxy.AppConns,
stateStore sm.Store,
mempool mempl.Mempool,
evpool sm.EvidencePool,
state sm.State,
chain []*types.Block,
nBlocks int, mode uint) {
// start a new app without handshake, play nBlocks blocks
if err := proxyApp.Start(); err != nil {
panic(err)
@ -809,18 +848,18 @@ func buildAppStateFromChain(proxyApp proxy.AppConns, stateStore sm.Store,
case 0:
for i := 0; i < nBlocks; i++ {
block := chain[i]
state = applyBlock(stateStore, state, block, proxyApp)
state = applyBlock(stateStore, mempool, evpool, state, block, proxyApp)
}
case 1, 2, 3:
for i := 0; i < nBlocks-1; i++ {
block := chain[i]
state = applyBlock(stateStore, state, block, proxyApp)
state = applyBlock(stateStore, mempool, evpool, state, block, proxyApp)
}
if mode == 2 || mode == 3 {
// update the kvstore height and apphash
// as if we ran commit but not
state = applyBlock(stateStore, state, chain[nBlocks-1], proxyApp)
state = applyBlock(stateStore, mempool, evpool, state, chain[nBlocks-1], proxyApp)
}
default:
panic(fmt.Sprintf("unknown mode %v", mode))
@ -830,6 +869,8 @@ func buildAppStateFromChain(proxyApp proxy.AppConns, stateStore sm.Store,
func buildTMStateFromChain(
config *cfg.Config,
mempool mempl.Mempool,
evpool sm.EvidencePool,
stateStore sm.Store,
state sm.State,
chain []*types.Block,
@ -861,19 +902,19 @@ func buildTMStateFromChain(
case 0:
// sync right up
for _, block := range chain {
state = applyBlock(stateStore, state, block, proxyApp)
state = applyBlock(stateStore, mempool, evpool, state, block, proxyApp)
}
case 1, 2, 3:
// sync up to the penultimate as if we stored the block.
// whether we commit or not depends on the appHash
for _, block := range chain[:len(chain)-1] {
state = applyBlock(stateStore, state, block, proxyApp)
state = applyBlock(stateStore, mempool, evpool, state, block, proxyApp)
}
// apply the final block to a state copy so we can
// get the right next appHash but keep the state back
applyBlock(stateStore, state, chain[len(chain)-1], proxyApp)
applyBlock(stateStore, mempool, evpool, state, chain[len(chain)-1], proxyApp)
default:
panic(fmt.Sprintf("unknown mode %v", mode))
}


+ 127
- 123
consensus/state_test.go View File

@ -56,9 +56,9 @@ x * TestHalt1 - if we see +2/3 precommits after timing out into new round, we sh
// ProposeSuite
func TestStateProposerSelection0(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
height, round := cs1.Height, cs1.Round
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
@ -82,7 +82,7 @@ func TestStateProposerSelection0(t *testing.T) {
ensureNewProposal(proposalCh, height, round)
rs := cs1.GetRoundState()
signAddVotes(cs1, tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:]...)
signAddVotes(config, cs1, tmproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:]...)
// Wait for new round so next validator is set.
ensureNewRound(newRoundCh, height+1, 0)
@ -98,9 +98,9 @@ func TestStateProposerSelection0(t *testing.T) {
// Now let's do it all again, but starting from round 2 instead of 0
func TestStateProposerSelection2(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4) // test needs more work for more than 3 validators
cs1, vss := randState(config, 4) // test needs more work for more than 3 validators
height := cs1.Height
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
@ -128,7 +128,7 @@ func TestStateProposerSelection2(t *testing.T) {
}
rs := cs1.GetRoundState()
signAddVotes(cs1, tmproto.PrecommitType, nil, rs.ProposalBlockParts.Header(), vss[1:]...)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, rs.ProposalBlockParts.Header(), vss[1:]...)
ensureNewRound(newRoundCh, height, i+round+1) // wait for the new round event each round
incrementRound(vss[1:]...)
}
@ -137,9 +137,9 @@ func TestStateProposerSelection2(t *testing.T) {
// a non-validator should timeout into the prevote round
func TestStateEnterProposeNoPrivValidator(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs, _ := randState(1)
cs, _ := randState(config, 1)
cs.SetPrivValidator(nil)
height, round := cs.Height, cs.Round
@ -158,9 +158,9 @@ func TestStateEnterProposeNoPrivValidator(t *testing.T) {
// a validator should not timeout of the prevote round (TODO: unless the block is really big!)
func TestStateEnterProposeYesPrivValidator(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs, _ := randState(1)
cs, _ := randState(config, 1)
height, round := cs.Height, cs.Round
// Listen for propose timeout event
@ -190,9 +190,9 @@ func TestStateEnterProposeYesPrivValidator(t *testing.T) {
}
func TestStateBadProposal(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(2)
cs1, vss := randState(config, 2)
height, round := cs1.Height, cs1.Round
vs2 := vss[1]
@ -240,19 +240,19 @@ func TestStateBadProposal(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], nil)
// add bad prevote from vs2 and wait for it
signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
ensurePrevote(voteCh, height, round)
// wait for precommit
ensurePrecommit(voteCh, height, round)
validatePrecommit(t, cs1, round, -1, vss[0], nil, nil)
signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
}
func TestStateOversizedBlock(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(2)
cs1, vss := randState(config, 2)
cs1.state.ConsensusParams.Block.MaxBytes = 2000
height, round := cs1.Height, cs1.Round
vs2 := vss[1]
@ -302,11 +302,11 @@ func TestStateOversizedBlock(t *testing.T) {
// precommit on it
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], nil)
signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
ensurePrevote(voteCh, height, round)
ensurePrecommit(voteCh, height, round)
validatePrecommit(t, cs1, round, -1, vss[0], nil, nil)
signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
}
//----------------------------------------------------------------------------------------------------
@ -314,9 +314,9 @@ func TestStateOversizedBlock(t *testing.T) {
// propose, prevote, and precommit a block
func TestStateFullRound1(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs, vss := randState(1)
cs, vss := randState(config, 1)
height, round := cs.Height, cs.Round
// NOTE: buffer capacity of 0 ensures we can validate prevote and last commit
@ -356,9 +356,9 @@ func TestStateFullRound1(t *testing.T) {
// nil is proposed, so prevote and precommit nil
func TestStateFullRoundNil(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs, vss := randState(1)
cs, vss := randState(config, 1)
height, round := cs.Height, cs.Round
voteCh := subscribeUnBuffered(cs.eventBus, types.EventQueryVote)
@ -376,9 +376,9 @@ func TestStateFullRoundNil(t *testing.T) {
// run through propose, prevote, precommit commit with two validators
// where the first validator has to wait for votes from the second
func TestStateFullRound2(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(2)
cs1, vss := randState(config, 2)
vs2 := vss[1]
height, round := cs1.Height, cs1.Round
@ -395,7 +395,7 @@ func TestStateFullRound2(t *testing.T) {
propBlockHash, propPartSetHeader := rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header()
// prevote arrives from vs2:
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propPartSetHeader, vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propPartSetHeader, vs2)
ensurePrevote(voteCh, height, round) // prevote
ensurePrecommit(voteCh, height, round) // precommit
@ -405,7 +405,7 @@ func TestStateFullRound2(t *testing.T) {
// we should be stuck in limbo waiting for more precommits
// precommit arrives from vs2:
signAddVotes(cs1, tmproto.PrecommitType, propBlockHash, propPartSetHeader, vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlockHash, propPartSetHeader, vs2)
ensurePrecommit(voteCh, height, round)
// wait to finish commit, propose in next height
@ -418,9 +418,9 @@ func TestStateFullRound2(t *testing.T) {
// two validators, 4 rounds.
// two vals take turns proposing. val1 locks on first one, precommits nil on everything else
func TestStateLockNoPOL(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(2)
cs1, vss := randState(config, 2)
vs2 := vss[1]
height, round := cs1.Height, cs1.Round
@ -451,7 +451,7 @@ func TestStateLockNoPOL(t *testing.T) {
// we should now be stuck in limbo forever, waiting for more prevotes
// prevote arrives from vs2:
signAddVotes(cs1, tmproto.PrevoteType, theBlockHash, thePartSetHeader, vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, theBlockHash, thePartSetHeader, vs2)
ensurePrevote(voteCh, height, round) // prevote
ensurePrecommit(voteCh, height, round) // precommit
@ -463,7 +463,7 @@ func TestStateLockNoPOL(t *testing.T) {
hash := make([]byte, len(theBlockHash))
copy(hash, theBlockHash)
hash[0] = (hash[0] + 1) % 255
signAddVotes(cs1, tmproto.PrecommitType, hash, thePartSetHeader, vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, hash, thePartSetHeader, vs2)
ensurePrecommit(voteCh, height, round) // precommit
// (note we're entering precommit for a second time this round)
@ -496,7 +496,7 @@ func TestStateLockNoPOL(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash())
// add a conflicting prevote from the other validator
signAddVotes(cs1, tmproto.PrevoteType, hash, rs.LockedBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, hash, rs.LockedBlock.MakePartSet(partSize).Header(), vs2)
ensurePrevote(voteCh, height, round)
// now we're going to enter prevote again, but with invalid args
@ -509,7 +509,7 @@ func TestStateLockNoPOL(t *testing.T) {
validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash)
// add conflicting precommit from vs2
signAddVotes(cs1, tmproto.PrecommitType, hash, rs.LockedBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, hash, rs.LockedBlock.MakePartSet(partSize).Header(), vs2)
ensurePrecommit(voteCh, height, round)
// (note we're entering precommit for a second time this round, but with invalid args
@ -539,7 +539,7 @@ func TestStateLockNoPOL(t *testing.T) {
ensurePrevote(voteCh, height, round) // prevote
validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash())
signAddVotes(cs1, tmproto.PrevoteType, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2)
ensurePrevote(voteCh, height, round)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds())
@ -548,6 +548,7 @@ func TestStateLockNoPOL(t *testing.T) {
validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // precommit nil but be locked on proposal
signAddVotes(
config,
cs1,
tmproto.PrecommitType,
hash,
@ -557,7 +558,7 @@ func TestStateLockNoPOL(t *testing.T) {
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds())
cs2, _ := randState(2) // needed so generated block is different than locked block
cs2, _ := randState(config, 2) // needed so generated block is different than locked block
// before we time out into new round, set next proposal block
prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1)
if prop == nil || propBlock == nil {
@ -585,7 +586,7 @@ func TestStateLockNoPOL(t *testing.T) {
validatePrevote(t, cs1, 3, vss[0], cs1.LockedBlock.Hash())
// prevote for proposed block
signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
ensurePrevote(voteCh, height, round)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds())
@ -593,6 +594,7 @@ func TestStateLockNoPOL(t *testing.T) {
validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // precommit nil but locked on proposal
signAddVotes(
config,
cs1,
tmproto.PrecommitType,
propBlock.Hash(),
@ -606,9 +608,9 @@ func TestStateLockNoPOL(t *testing.T) {
// in round two: v1 prevotes the same block that the node is locked on
// the others prevote a new block hence v1 changes lock and precommits the new block with the others
func TestStateLockPOLRelock(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -642,14 +644,14 @@ func TestStateLockPOLRelock(t *testing.T) {
ensurePrevote(voteCh, height, round) // prevote
signAddVotes(cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round) // our precommit
// the proposed block should now be locked and our precommit added
validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash)
// add precommits from the rest
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// before we timeout to the new round set the new proposal
cs2 := newState(cs1.state, vs2, counter.NewApplication(true))
@ -690,14 +692,14 @@ func TestStateLockPOLRelock(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], theBlockHash)
// now lets add prevotes from everyone else for the new block
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// we should have unlocked and locked on the new block, sending a precommit for this new block
validatePrecommit(t, cs1, round, round, vss[0], propBlockHash, propBlockHash)
// more prevote creating a majority on the new block and this is then committed
signAddVotes(cs1, tmproto.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3)
ensureNewBlockHeader(newBlockCh, height, propBlockHash)
ensureNewRound(newRoundCh, height+1, 0)
@ -705,9 +707,9 @@ func TestStateLockPOLRelock(t *testing.T) {
// 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka
func TestStateLockPOLUnlock(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -741,15 +743,15 @@ func TestStateLockPOLUnlock(t *testing.T) {
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], theBlockHash)
signAddVotes(cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// the proposed block should now be locked and our precommit added
validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash)
// add precommits from the rest
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs4)
signAddVotes(cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3)
// before we time out into new round, set next proposal block
prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
@ -780,7 +782,7 @@ func TestStateLockPOLUnlock(t *testing.T) {
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], lockedBlockHash)
// now lets add prevotes from everyone else for nil (a polka!)
signAddVotes(cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// the polka makes us unlock and precommit nil
ensureNewUnlock(unlockCh, height, round)
@ -790,7 +792,7 @@ func TestStateLockPOLUnlock(t *testing.T) {
// NOTE: since we don't relock on nil, the lock round is -1
validatePrecommit(t, cs1, round, -1, vss[0], nil, nil)
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3)
ensureNewRound(newRoundCh, height, round+1)
}
@ -799,9 +801,9 @@ func TestStateLockPOLUnlock(t *testing.T) {
// v1 should unlock and precommit nil. In the third round another block is proposed, all vals
// prevote and now v1 can lock onto the third block and precommit that
func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -831,14 +833,14 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
ensurePrevote(voteCh, height, round) // prevote
signAddVotes(cs1, tmproto.PrevoteType, firstBlockHash, firstBlockParts, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, firstBlockHash, firstBlockParts, vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round) // our precommit
// the proposed block should now be locked and our precommit added
validatePrecommit(t, cs1, round, round, vss[0], firstBlockHash, firstBlockHash)
// add precommits from the rest
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// before we timeout to the new round set the new proposal
cs2 := newState(cs1.state, vs2, counter.NewApplication(true))
@ -871,7 +873,7 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], firstBlockHash)
// now lets add prevotes from everyone else for the new block
signAddVotes(cs1, tmproto.PrevoteType, secondBlockHash, secondBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, secondBlockHash, secondBlockParts.Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// we should have unlocked and locked on the new block, sending a precommit for this new block
@ -882,7 +884,7 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
}
// more prevote creating a majority on the new block and this is then committed
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// before we timeout to the new round set the new proposal
cs3 := newState(cs1.state, vs3, counter.NewApplication(true))
@ -915,7 +917,7 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
// we are no longer locked to the first block so we should be able to prevote
validatePrevote(t, cs1, round, vss[0], thirdPropBlockHash)
signAddVotes(cs1, tmproto.PrevoteType, thirdPropBlockHash, thirdPropBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, thirdPropBlockHash, thirdPropBlockParts.Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// we have a majority, now vs1 can change lock to the third block
@ -927,9 +929,9 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
// then a polka at round 2 that we lock on
// then we see the polka from round 1 but shouldn't unlock
func TestStateLockPOLSafety1(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -956,12 +958,14 @@ func TestStateLockPOLSafety1(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], propBlock.Hash())
// the others sign a polka but we don't see it
prevotes := signVotes(tmproto.PrevoteType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4)
prevotes := signVotes(config, tmproto.PrevoteType,
propBlock.Hash(), propBlock.MakePartSet(partSize).Header(),
vs2, vs3, vs4)
t.Logf("old prop hash %v", fmt.Sprintf("%X", propBlock.Hash()))
// we do see them precommit nil
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// cs1 precommit nil
ensurePrecommit(voteCh, height, round)
@ -1001,13 +1005,13 @@ func TestStateLockPOLSafety1(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], propBlockHash)
// now we see the others prevote for it, so we should lock on it
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// we should have precommitted
validatePrecommit(t, cs1, round, round, vss[0], propBlockHash, propBlockHash)
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds())
@ -1048,9 +1052,9 @@ func TestStateLockPOLSafety1(t *testing.T) {
// What we want:
// dont see P0, lock on P1 at R1, dont unlock using P0 at R2
func TestStateLockPOLSafety2(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1073,7 +1077,7 @@ func TestStateLockPOLSafety2(t *testing.T) {
propBlockID0 := types.BlockID{Hash: propBlockHash0, PartSetHeader: propBlockParts0.Header()}
// the others sign a polka but we don't see it
prevotes := signVotes(tmproto.PrevoteType, propBlockHash0, propBlockParts0.Header(), vs2, vs3, vs4)
prevotes := signVotes(config, tmproto.PrevoteType, propBlockHash0, propBlockParts0.Header(), vs2, vs3, vs4)
// the block for round 1
prop1, propBlock1 := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
@ -1096,15 +1100,15 @@ func TestStateLockPOLSafety2(t *testing.T) {
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], propBlockHash1)
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash1, propBlockParts1.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash1, propBlockParts1.Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// the proposed block should now be locked and our precommit added
validatePrecommit(t, cs1, round, round, vss[0], propBlockHash1, propBlockHash1)
// add precommits from the rest
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs4)
signAddVotes(cs1, tmproto.PrecommitType, propBlockHash1, propBlockParts1.Header(), vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlockHash1, propBlockParts1.Header(), vs3)
incrementRound(vs2, vs3, vs4)
@ -1147,9 +1151,9 @@ func TestStateLockPOLSafety2(t *testing.T) {
// What we want:
// P0 proposes B0 at R3.
func TestProposeValidBlock(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1178,13 +1182,13 @@ func TestProposeValidBlock(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], propBlockHash)
// the others sign a polka
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// we should have precommitted
validatePrecommit(t, cs1, round, round, vss[0], propBlockHash, propBlockHash)
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds())
@ -1201,7 +1205,7 @@ func TestProposeValidBlock(t *testing.T) {
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], propBlockHash)
signAddVotes(cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
ensureNewUnlock(unlockCh, height, round)
@ -1212,7 +1216,7 @@ func TestProposeValidBlock(t *testing.T) {
incrementRound(vs2, vs3, vs4)
incrementRound(vs2, vs3, vs4)
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
round += 2 // moving to the next round
@ -1239,9 +1243,9 @@ func TestProposeValidBlock(t *testing.T) {
// What we want:
// P0 miss to lock B but set valid block to B after receiving delayed prevote.
func TestSetValidBlockOnDelayedPrevote(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1270,10 +1274,10 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) {
validatePrevote(t, cs1, round, vss[0], propBlockHash)
// vs2 send prevote for propBlock
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2)
// vs3 send prevote nil
signAddVotes(cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs3)
signAddVotes(config, cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs3)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds())
@ -1288,7 +1292,7 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) {
assert.True(t, rs.ValidRound == -1)
// vs2 send (delayed) prevote for propBlock
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs4)
ensureNewValidBlock(validBlockCh, height, round)
@ -1303,9 +1307,9 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) {
// P0 miss to lock B as Proposal Block is missing, but set valid block to B after
// receiving delayed Block Proposal.
func TestSetValidBlockOnDelayedProposal(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1337,7 +1341,7 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) {
propBlockParts := propBlock.MakePartSet(partSize)
// vs2, vs3 and vs4 send prevote for propBlock
signAddVotes(cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
ensureNewValidBlock(validBlockCh, height, round)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds())
@ -1361,9 +1365,9 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) {
// What we want:
// P0 waits for timeoutPrecommit before starting next round
func TestWaitingTimeoutOnNilPolka(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1374,7 +1378,7 @@ func TestWaitingTimeoutOnNilPolka(t *testing.T) {
startTestRound(cs1, height, round)
ensureNewRound(newRoundCh, height, round)
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds())
ensureNewRound(newRoundCh, height, round+1)
@ -1384,9 +1388,9 @@ func TestWaitingTimeoutOnNilPolka(t *testing.T) {
// What we want:
// P0 waits for timeoutPropose in the next round before entering prevote
func TestWaitingTimeoutProposeOnNewRound(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1404,7 +1408,7 @@ func TestWaitingTimeoutProposeOnNewRound(t *testing.T) {
ensurePrevote(voteCh, height, round)
incrementRound(vss[1:]...)
signAddVotes(cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
round++ // moving to the next round
ensureNewRound(newRoundCh, height, round)
@ -1422,9 +1426,9 @@ func TestWaitingTimeoutProposeOnNewRound(t *testing.T) {
// What we want:
// P0 jump to higher round, precommit and start precommit wait
func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1442,7 +1446,7 @@ func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) {
ensurePrevote(voteCh, height, round)
incrementRound(vss[1:]...)
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
round++ // moving to the next round
ensureNewRound(newRoundCh, height, round)
@ -1460,9 +1464,9 @@ func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) {
// What we want:
// P0 wait for timeoutPropose to expire before sending prevote.
func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, int32(1)
@ -1478,7 +1482,7 @@ func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) {
ensureNewRound(newRoundCh, height, round)
incrementRound(vss[1:]...)
signAddVotes(cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds())
@ -1489,9 +1493,9 @@ func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) {
// What we want:
// P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet
func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, int32(1)
@ -1511,7 +1515,7 @@ func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) {
ensureNewRound(newRoundCh, height, round)
// vs2, vs3 and vs4 send precommit for propBlock
signAddVotes(cs1, tmproto.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
ensureNewValidBlock(validBlockCh, height, round)
rs := cs1.GetRoundState()
@ -1525,9 +1529,9 @@ func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) {
// P0 receives 2/3+ Precommit for B for round 0, while being in round 1. It emits NewValidBlock event.
// After receiving block, it executes block and moves to the next height.
func TestCommitFromPreviousRound(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, int32(1)
@ -1546,7 +1550,7 @@ func TestCommitFromPreviousRound(t *testing.T) {
ensureNewRound(newRoundCh, height, round)
// vs2, vs3 and vs4 send precommit for propBlock for the previous round
signAddVotes(cs1, tmproto.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
ensureNewValidBlock(validBlockCh, height, round)
@ -1580,10 +1584,10 @@ func (n *fakeTxNotifier) Notify() {
// and third precommit arrives which leads to the commit of that header and the correct
// start of the next round
func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) {
configSetup(t)
config := configSetup(t)
config.Consensus.SkipTimeoutCommit = false
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
cs1.txNotifier = &fakeTxNotifier{ch: make(chan struct{})}
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
@ -1612,15 +1616,15 @@ func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) {
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], theBlockHash)
signAddVotes(cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// the proposed block should now be locked and our precommit added
validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash)
// add precommits
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2)
signAddVotes(cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3)
// wait till timeout occurs
ensurePrecommitTimeout(precommitTimeoutCh)
@ -1628,7 +1632,7 @@ func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) {
ensureNewRound(newRoundCh, height, round+1)
// majority is now reached
signAddVotes(cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs4)
ensureNewBlockHeader(newBlockHeader, height, theBlockHash)
@ -1643,10 +1647,10 @@ func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) {
}
func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) {
configSetup(t)
config := configSetup(t)
config.Consensus.SkipTimeoutCommit = false
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
@ -1674,15 +1678,15 @@ func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) {
ensurePrevote(voteCh, height, round)
validatePrevote(t, cs1, round, vss[0], theBlockHash)
signAddVotes(cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, theBlockHash, theBlockParts, vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash)
// add precommits
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2)
signAddVotes(cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3)
signAddVotes(cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs4)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2)
signAddVotes(config, cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, theBlockHash, theBlockParts, vs4)
ensureNewBlockHeader(newBlockHeader, height, theBlockHash)
@ -1787,9 +1791,9 @@ func TestStateSlashingPrecommits(t *testing.T) {
// 4 vals.
// we receive a final precommit after going into next round, but others might have gone to commit already!
func TestStateHalt1(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs1, vss := randState(4)
cs1, vss := randState(config, 4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
height, round := cs1.Height, cs1.Round
partSize := types.BlockPartSizeBytes
@ -1814,17 +1818,17 @@ func TestStateHalt1(t *testing.T) {
ensurePrevote(voteCh, height, round)
signAddVotes(cs1, tmproto.PrevoteType, propBlock.Hash(), propBlockParts.Header(), vs2, vs3, vs4)
signAddVotes(config, cs1, tmproto.PrevoteType, propBlock.Hash(), propBlockParts.Header(), vs2, vs3, vs4)
ensurePrecommit(voteCh, height, round)
// the proposed block should now be locked and our precommit added
validatePrecommit(t, cs1, round, round, vss[0], propBlock.Hash(), propBlock.Hash())
// add precommits from the rest
signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2) // didnt receive proposal
signAddVotes(cs1, tmproto.PrecommitType, propBlock.Hash(), propBlockParts.Header(), vs3)
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2) // didnt receive proposal
signAddVotes(config, cs1, tmproto.PrecommitType, propBlock.Hash(), propBlockParts.Header(), vs3)
// we receive this later, but vs3 might receive it earlier and with ours will go to commit!
precommit4 := signVote(vs4, tmproto.PrecommitType, propBlock.Hash(), propBlockParts.Header())
precommit4 := signVote(vs4, config, tmproto.PrecommitType, propBlock.Hash(), propBlockParts.Header())
incrementRound(vs2, vs3, vs4)
@ -1856,10 +1860,10 @@ func TestStateHalt1(t *testing.T) {
}
func TestStateOutputsBlockPartsStats(t *testing.T) {
configSetup(t)
config := configSetup(t)
// create dummy peer
cs, _ := randState(1)
cs, _ := randState(config, 1)
peer := p2pmock.NewPeer(nil)
// 1) new block part
@ -1901,15 +1905,15 @@ func TestStateOutputsBlockPartsStats(t *testing.T) {
}
func TestStateOutputVoteStats(t *testing.T) {
configSetup(t)
config := configSetup(t)
cs, vss := randState(2)
cs, vss := randState(config, 2)
// create dummy peer
peer := p2pmock.NewPeer(nil)
randBytes := tmrand.Bytes(tmhash.Size)
vote := signVote(vss[1], tmproto.PrecommitType, randBytes, types.PartSetHeader{})
vote := signVote(vss[1], config, tmproto.PrecommitType, randBytes, types.PartSetHeader{})
voteMessage := &VoteMessage{vote}
cs.handleMsg(msgInfo{voteMessage, peer.ID()})
@ -1923,7 +1927,7 @@ func TestStateOutputVoteStats(t *testing.T) {
// sending the vote for the bigger height
incrementHeight(vss[1])
vote = signVote(vss[1], tmproto.PrecommitType, randBytes, types.PartSetHeader{})
vote = signVote(vss[1], config, tmproto.PrecommitType, randBytes, types.PartSetHeader{})
cs.handleMsg(msgInfo{&VoteMessage{vote}, peer.ID()})


Loading…
Cancel
Save