From 1d6f00859dd46beae036146782f0f088b2e50e63 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 28 Dec 2017 18:26:13 -0500 Subject: [PATCH] fixes from review --- blockchain/reactor_test.go | 12 ++++-------- consensus/common_test.go | 9 +++------ consensus/replay.go | 6 +----- consensus/replay_file.go | 4 +--- consensus/replay_test.go | 5 ++--- consensus/wal_generator.go | 2 +- evidence/pool.go | 3 +-- node/node.go | 15 +++++---------- state/execution.go | 35 +++++++++++++++++++++-------------- state/execution_test.go | 11 +---------- state/state.go | 2 +- state/state_test.go | 4 ++-- state/{db.go => store.go} | 29 +++++++++++++++++++++++++---- 13 files changed, 68 insertions(+), 69 deletions(-) rename state/{db.go => store.go} (90%) diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index 2edff18bb..fcb8a6f86 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -10,6 +10,7 @@ import ( cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/proxy" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" ) @@ -17,12 +18,7 @@ import ( func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore) { config := cfg.ResetTestRoot("blockchain_reactor_test") blockStore := NewBlockStore(dbm.NewMemDB()) - - // Get State - stateDB := dbm.NewMemDB() - state, _ := sm.GetState(stateDB, config.GenesisFile()) - sm.SaveState(stateDB, state) - + state, _ := sm.LoadStateFromDBOrGenesisFile(dbm.NewMemDB(), config.GenesisFile()) return state, blockStore } @@ -31,8 +27,8 @@ func newBlockchainReactor(logger log.Logger, maxBlockHeight int64) *BlockchainRe // Make the blockchainReactor itself fastSync := true - blockExec := sm.NewBlockExecutor(dbm.NewMemDB(), log.TestingLogger(), - types.NopEventBus{}, nil, types.MockMempool{}, types.MockEvidencePool{}) + var nilApp proxy.AppConnConsensus + blockExec := sm.NewBlockExecutor(dbm.NewMemDB(), log.TestingLogger(), nilApp, types.MockMempool{}, types.MockEvidencePool{}) bcReactor := NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync) bcReactor.SetLogger(logger.With("module", "blockchain")) diff --git a/consensus/common_test.go b/consensus/common_test.go index 1516365e7..eb574a219 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -265,8 +265,7 @@ func newConsensusStateWithConfigAndBlockStore(thisConfig *cfg.Config, state sm.S // Make ConsensusReactor stateDB := dbm.NewMemDB() // XXX !! - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), - types.NopEventBus{}, proxyAppConnCon, mempool, evpool) + blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyAppConnCon, mempool, evpool) cs := NewConsensusState(thisConfig.Consensus, state, blockExec, blockStore, mempool, evpool) cs.SetLogger(log.TestingLogger()) cs.SetPrivValidator(pv) @@ -356,8 +355,7 @@ func randConsensusNet(nValidators int, testName string, tickerFunc func() Timeou logger := consensusLogger() for i := 0; i < nValidators; i++ { stateDB := dbm.NewMemDB() // each state needs its own db - state, _ := sm.MakeGenesisState(genDoc) - sm.SaveState(stateDB, state) + state, _ := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc) thisConfig := ResetConfig(cmn.Fmt("%s_%d", testName, i)) for _, opt := range configOpts { opt(thisConfig) @@ -381,8 +379,7 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF logger := consensusLogger() for i := 0; i < nPeers; i++ { stateDB := dbm.NewMemDB() // each state needs its own db - state, _ := sm.MakeGenesisState(genDoc) - sm.SaveState(stateDB, state) + state, _ := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc) thisConfig := ResetConfig(cmn.Fmt("%s_%d", testName, i)) ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal var privVal types.PrivValidator diff --git a/consensus/replay.go b/consensus/replay.go index 55c291783..784e8bd6e 100644 --- a/consensus/replay.go +++ b/consensus/replay.go @@ -363,14 +363,10 @@ func (h *Handshaker) replayBlocks(state sm.State, proxyApp proxy.AppConns, appBl // ApplyBlock on the proxyApp with the last block. func (h *Handshaker) replayBlock(state sm.State, height int64, proxyApp proxy.AppConnConsensus) (sm.State, error) { - mempool := types.MockMempool{} - evpool := types.MockEvidencePool{} - block := h.store.LoadBlock(height) meta := h.store.LoadBlockMeta(height) - blockExec := sm.NewBlockExecutor(h.stateDB, h.logger, - types.NopEventBus{}, proxyApp, mempool, evpool) + blockExec := sm.NewBlockExecutor(h.stateDB, h.logger, proxyApp, types.MockMempool{}, types.MockEvidencePool{}) var err error state, err = blockExec.ApplyBlock(state, meta.BlockID, block) diff --git a/consensus/replay_file.go b/consensus/replay_file.go index 4e490ccba..26b8baebf 100644 --- a/consensus/replay_file.go +++ b/consensus/replay_file.go @@ -305,9 +305,7 @@ func newConsensusStateForReplay(config cfg.BaseConfig, csConfig *cfg.ConsensusCo } mempool, evpool := types.MockMempool{}, types.MockEvidencePool{} - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), - types.NopEventBus{}, proxyApp.Consensus(), - mempool, evpool) + blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool) consensusState := NewConsensusState(csConfig, state.Copy(), blockExec, blockStore, mempool, evpool) diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 4647ff3d6..c497ed546 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -53,7 +53,7 @@ func init() { func startNewConsensusStateAndWaitForBlock(t *testing.T, lastBlockHeight int64, blockDB dbm.DB, stateDB dbm.DB) { logger := log.TestingLogger() - state, _ := sm.GetState(stateDB, consensusReplayConfig.GenesisFile()) + state, _ := sm.LoadStateFromDBOrGenesisFile(stateDB, consensusReplayConfig.GenesisFile()) privValidator := loadPrivValidator(consensusReplayConfig) cs := newConsensusStateWithConfigAndBlockStore(consensusReplayConfig, state, privValidator, dummy.NewDummyApplication(), blockDB) cs.SetLogger(logger) @@ -394,8 +394,7 @@ func testHandshakeReplay(t *testing.T, nBlocks int, mode uint) { func applyBlock(stateDB dbm.DB, st sm.State, blk *types.Block, proxyApp proxy.AppConns) sm.State { testPartSize := st.ConsensusParams.BlockPartSizeBytes - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), - types.NopEventBus{}, proxyApp.Consensus(), mempool, evpool) + blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool) blkID := types.BlockID{blk.Hash(), blk.MakePartSet(testPartSize).Header()} newState, err := blockExec.ApplyBlock(st, blkID, blk) diff --git a/consensus/wal_generator.go b/consensus/wal_generator.go index c4171b129..45609e568 100644 --- a/consensus/wal_generator.go +++ b/consensus/wal_generator.go @@ -67,7 +67,7 @@ func WALWithNBlocks(numBlocks int) (data []byte, err error) { defer eventBus.Stop() mempool := types.MockMempool{} evpool := types.MockEvidencePool{} - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), types.NopEventBus{}, proxyApp.Consensus(), mempool, evpool) + blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool) consensusState := NewConsensusState(config.Consensus, state.Copy(), blockExec, blockStore, mempool, evpool) consensusState.SetLogger(logger) consensusState.SetEventBus(eventBus) diff --git a/evidence/pool.go b/evidence/pool.go index cdc01398c..4d706da81 100644 --- a/evidence/pool.go +++ b/evidence/pool.go @@ -27,8 +27,7 @@ func NewEvidencePool(params types.EvidenceParams, evidenceStore *EvidenceStore, params: params, logger: log.NewNopLogger(), evidenceStore: evidenceStore, - // state: *state, - evidenceChan: make(chan types.Evidence), + evidenceChan: make(chan types.Evidence), } return evpool } diff --git a/node/node.go b/node/node.go index cd1e63206..2eea4ed26 100644 --- a/node/node.go +++ b/node/node.go @@ -138,6 +138,7 @@ func NewNode(config *cfg.Config, } // Get genesis doc + // TODO: move to state package? genDoc, err := loadGenesisDoc(stateDB) if err != nil { genDoc, err = genesisDocProvider() @@ -149,13 +150,9 @@ func NewNode(config *cfg.Config, saveGenesisDoc(stateDB, genDoc) } - state := sm.LoadState(stateDB) - if state.IsEmpty() { - state, err = sm.MakeGenesisState(genDoc) - if err != nil { - return nil, err - } - sm.SaveState(stateDB, state) + state, err := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc) + if err != nil { + return nil, err } // Create the proxyApp, which manages connections (consensus, mempool, query) @@ -218,9 +215,7 @@ func NewNode(config *cfg.Config, blockExecLogger := logger.With("module", "state") // make block executor for consensus and blockchain reactors to execute blocks - blockExec := sm.NewBlockExecutor(stateDB, blockExecLogger, - types.NopEventBus{}, proxyApp.Consensus(), - mempool, evidencePool) + blockExec := sm.NewBlockExecutor(stateDB, blockExecLogger, proxyApp.Consensus(), mempool, evidencePool) // Make BlockchainReactor bcReactor := bc.NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync) diff --git a/state/execution.go b/state/execution.go index ce45e4c43..68cb13bd7 100644 --- a/state/execution.go +++ b/state/execution.go @@ -20,34 +20,41 @@ import ( // BlockExecutor provides the context and accessories for properly executing a block. type BlockExecutor struct { - db dbm.DB - logger log.Logger + // save state, validators, consensus params, abci responses here + db dbm.DB + + // execute the app against this + proxyApp proxy.AppConnConsensus + // tx events txEventPublisher types.TxEventPublisher - proxyApp proxy.AppConnConsensus + // update these with block results after commit mempool types.Mempool evpool types.EvidencePool -} -func (blockExec *BlockExecutor) SetTxEventPublisher(txEventPublisher types.TxEventPublisher) { - blockExec.txEventPublisher = txEventPublisher + logger log.Logger } // NewBlockExecutor returns a new BlockExecutor. -func NewBlockExecutor(db dbm.DB, logger log.Logger, - txEventer types.TxEventPublisher, proxyApp proxy.AppConnConsensus, +func NewBlockExecutor(db dbm.DB, logger log.Logger, proxyApp proxy.AppConnConsensus, mempool types.Mempool, evpool types.EvidencePool) *BlockExecutor { return &BlockExecutor{ - db, - logger, - txEventer, - proxyApp, - mempool, - evpool, + db: db, + proxyApp: proxyApp, + txEventPublisher: types.NopEventBus{}, + mempool: mempool, + evpool: evpool, + logger: logger, } } +// SetTxEventPublisher - set the transaction event publisher. If not called, +// it defaults to types.NopEventBus. +func (blockExec *BlockExecutor) SetTxEventPublisher(txEventPublisher types.TxEventPublisher) { + blockExec.txEventPublisher = txEventPublisher +} + // ApplyBlock validates the block against the state, executes it against the app, // commits it, and saves the block and state. It's the only function that needs to be called // from outside this package to process and commit an entire block. diff --git a/state/execution_test.go b/state/execution_test.go index 1a63d3ed0..9db269116 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -32,8 +32,7 @@ func TestApplyBlock(t *testing.T) { state, stateDB := state(), dbm.NewMemDB() - blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), - types.NopEventBus{}, proxyApp.Consensus(), + blockExec := NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), types.MockMempool{}, types.MockEvidencePool{}) block := makeBlock(state, 1) @@ -56,14 +55,6 @@ func TestBeginBlockAbsentValidators(t *testing.T) { state := state() - // there were 2 validators - /*val1PrivKey := crypto.GenPrivKeyEd25519() - val2PrivKey := crypto.GenPrivKeyEd25519() - lastValidators := types.NewValidatorSet([]*types.Validator{ - types.NewValidator(val1PrivKey.PubKey(), 10), - types.NewValidator(val2PrivKey.PubKey(), 5), - })*/ - prevHash := state.LastBlockID.Hash prevParts := types.PartSetHeader{} prevBlockID := types.BlockID{prevHash, prevParts} diff --git a/state/state.go b/state/state.go index 7ffa56edc..575a1630e 100644 --- a/state/state.go +++ b/state/state.go @@ -23,7 +23,7 @@ var ( // including the last validator set and the consensus params. // All fields are exposed so the struct can be easily serialized, // but none of them should be mutated directly. -// Instead, use state.Copy() ro state.NextState(...). +// Instead, use state.Copy() or state.NextState(...). // NOTE: not goroutine-safe. type State struct { // Immutable diff --git a/state/state_test.go b/state/state_test.go index 7e9ed2cf8..61b3167b3 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -23,8 +23,8 @@ import ( func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, State) { config := cfg.ResetTestRoot("state_") stateDB := dbm.NewDB("state", config.DBBackend, config.DBDir()) - state, err := GetState(stateDB, config.GenesisFile()) - assert.NoError(t, err, "expected no error on GetState") + state, err := LoadStateFromDBOrGenesisFile(stateDB, config.GenesisFile()) + assert.NoError(t, err, "expected no error on LoadStateFromDBOrGenesisFile") tearDown := func(t *testing.T) {} diff --git a/state/db.go b/state/store.go similarity index 90% rename from state/db.go rename to state/store.go index fbe99863b..de2d4d67c 100644 --- a/state/db.go +++ b/state/store.go @@ -25,14 +25,31 @@ func calcABCIResponsesKey(height int64) []byte { return []byte(cmn.Fmt("abciResponsesKey:%v", height)) } -// GetState loads the most recent state from the database, -// or creates a new one from the given genesisFile and persists the result +// LoadStateFromDBOrGenesisFile loads the most recent state from the database, +// or creates a new one from the given genesisFilePath and persists the result // to the database. -func GetState(stateDB dbm.DB, genesisFile string) (State, error) { +func LoadStateFromDBOrGenesisFile(stateDB dbm.DB, genesisFilePath string) (State, error) { state := LoadState(stateDB) if state.IsEmpty() { var err error - state, err = MakeGenesisStateFromFile(genesisFile) + state, err = MakeGenesisStateFromFile(genesisFilePath) + if err != nil { + return state, err + } + SaveState(stateDB, state) + } + + return state, nil +} + +// LoadStateFromDBOrGenesisDoc loads the most recent state from the database, +// or creates a new one from the given genesisDoc and persists the result +// to the database. +func LoadStateFromDBOrGenesisDoc(stateDB dbm.DB, genesisDoc *types.GenesisDoc) (State, error) { + state := LoadState(stateDB) + if state.IsEmpty() { + var err error + state, err = MakeGenesisState(genesisDoc) if err != nil { return state, err } @@ -67,6 +84,10 @@ func loadState(db dbm.DB, key []byte) (state State) { // SaveState persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database. func SaveState(db dbm.DB, s State) { + saveState(db, s, stateKey) +} + +func saveState(db dbm.DB, s State, key []byte) { nextHeight := s.LastBlockHeight + 1 saveValidatorsInfo(db, nextHeight, s.LastHeightValidatorsChanged, s.Validators) saveConsensusParamsInfo(db, nextHeight, s.LastHeightConsensusParamsChanged, s.ConsensusParams)