This commit is contained in:
Sam Ricotta
2022-07-29 15:46:28 +02:00
parent 7a024d012d
commit 426e9f9cf9
7 changed files with 116 additions and 58 deletions

View File

@@ -42,7 +42,9 @@ func TestApplyBlock(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, _ := makeState(1, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
mmock.Mempool{}, sm.EmptyEvidencePool{}, blockStore)
@@ -67,7 +69,9 @@ func TestBeginBlockValidators(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // no need to check error again
state, stateDB, _ := makeState(2, 2)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
prevHash := state.LastBlockID.Hash
prevParts := types.PartSetHeader{}
@@ -130,7 +134,9 @@ func TestBeginBlockByzantineValidators(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, privVals := makeState(1, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
privVal := privVals[state.Validators.Validators[0].Address.String()]
@@ -355,7 +361,9 @@ func TestEndBlockValidatorUpdates(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, _ := makeState(1, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(
@@ -428,7 +436,9 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, _ := makeState(1, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(
stateStore,

View File

@@ -111,7 +111,9 @@ func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValida
})
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
if err := stateStore.Save(s); err != nil {
panic(err)
}

View File

@@ -78,7 +78,10 @@ func TestRollback(t *testing.T) {
}
func TestRollbackNoState(t *testing.T) {
stateStore := state.NewStore(dbm.NewMemDB(), false)
stateStore := state.NewStore(dbm.NewMemDB(),
state.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := &mocks.BlockStore{}
_, _, err := state.Rollback(blockStore, stateStore)
@@ -111,7 +114,7 @@ func TestRollbackDifferentStateHeight(t *testing.T) {
}
func setupStateStore(t *testing.T, height int64) state.Store {
stateStore := state.NewStore(dbm.NewMemDB(), false)
stateStore := state.NewStore(dbm.NewMemDB(), state.StoreOptions{DiscardABCIResponses: false})
valSet, _ := factory.RandValidatorSet(5, 10)
params := types.DefaultConsensusParams()

View File

@@ -32,7 +32,9 @@ func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, sm.State) {
dbType := dbm.BackendType(cfg.DBBackend)
stateDB, err := dbm.NewDB("state", dbType, cfg.DBDir())
require.NoError(t, err)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, err := stateStore.Load()
require.NoError(t, err)
require.Empty(t, state)
@@ -82,7 +84,9 @@ func TestMakeGenesisStateNilValidators(t *testing.T) {
func TestStateSaveLoad(t *testing.T) {
tearDown, stateDB, state := setupTestCase(t)
defer tearDown(t)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
assert := assert.New(t)
state.LastBlockHeight++
@@ -101,7 +105,9 @@ func TestStateSaveLoad(t *testing.T) {
func TestABCIResponsesSaveLoad1(t *testing.T) {
tearDown, stateDB, state := setupTestCase(t)
defer tearDown(t)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
assert := assert.New(t)
state.LastBlockHeight++
@@ -134,7 +140,9 @@ func TestABCIResponsesSaveLoad2(t *testing.T) {
defer tearDown(t)
assert := assert.New(t)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
cases := [...]struct {
// Height is implied to equal index+2,
@@ -222,7 +230,9 @@ func TestValidatorSimpleSaveLoad(t *testing.T) {
defer tearDown(t)
assert := assert.New(t)
statestore := sm.NewStore(stateDB, false)
statestore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
// Can't load anything for height 0.
_, err := statestore.LoadValidators(0)
@@ -255,7 +265,9 @@ func TestValidatorSimpleSaveLoad(t *testing.T) {
func TestOneValidatorChangesSaveLoad(t *testing.T) {
tearDown, stateDB, state := setupTestCase(t)
defer tearDown(t)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
// Change vals at these heights.
changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}
@@ -907,7 +919,9 @@ func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) {
const valSetSize = 2
tearDown, stateDB, state := setupTestCase(t)
t.Cleanup(func() { tearDown(t) })
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state.Validators = genValSet(valSetSize)
state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
err := stateStore.Save(state)
@@ -932,7 +946,9 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) {
const valSetSize = 7
tearDown, stateDB, state := setupTestCase(t)
defer tearDown(t)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
require.Equal(t, int64(0), state.LastBlockHeight)
state.Validators = genValSet(valSetSize)
state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
@@ -996,7 +1012,9 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) {
tearDown, stateDB, state := setupTestCase(t)
defer tearDown(t)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
// Change vals at these heights.
changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}

View File

@@ -88,7 +88,7 @@ type Store interface {
LoadValidators(int64) (*types.ValidatorSet, error)
// LoadABCIResponses loads the abciResponse for a given height
LoadABCIResponses(int64) (*tmstate.ABCIResponses, error)
//LoadLastABCIResponse loads the last abciResponse for a given height
// LoadLastABCIResponse loads the last abciResponse for a given height
LoadLastABCIResponse(int64) (*tmstate.ABCIResponses, error)
// LoadConsensusParams loads the consensus params for a given height
LoadConsensusParams(int64) (types.ConsensusParams, error)
@@ -110,16 +110,24 @@ type Store interface {
type dbStore struct {
db dbm.DB
// discardABCIResponses determines if all
// ABCI responses are persisted or just the last
discardABCIResponses bool
StoreOptions
}
type StoreOptions struct {
// DiscardABCIResponses determines whether or not the store
// retains all ABCIResponses. If DiscardABCiResponses is enabled,
// the store will maintain only the response object from the latest
// height.
DiscardABCIResponses bool
}
var _ Store = (*dbStore)(nil)
// NewStore creates the dbStore of the state pkg.
func NewStore(db dbm.DB, discardABCIResponses bool) Store {
return dbStore{db, discardABCIResponses}
func NewStore(db dbm.DB, options StoreOptions) Store {
return dbStore{db, options}
}
// LoadState loads the State from the database.
@@ -423,7 +431,7 @@ func ABCIResponsesResultsHash(ar *tmstate.ABCIResponses) []byte {
// database. If the node has DiscardABCIResponses set to true, ErrABCIResponsesNotPersisted
// is persisted. If not found, ErrNoABCIResponsesForHeight is returned.
func (store dbStore) LoadABCIResponses(height int64) (*tmstate.ABCIResponses, error) {
if store.discardABCIResponses {
if store.DiscardABCIResponses {
return nil, ErrABCIResponsesNotPersisted
}
@@ -440,19 +448,19 @@ func (store dbStore) LoadABCIResponses(height int64) (*tmstate.ABCIResponses, er
if err != nil {
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
tmos.Exit(fmt.Sprintf(`LoadABCIResponses: Data has been corrupted or its spec has
changed: %v\n`, err))
changed: %v\n`, err))
}
// TODO: ensure that buf is completely read.
return abciResponses, nil
}
// LoadLastABCIResponses loads the last ABCI response specifically after a crash
// We conduct a sanity check here which compares the height from the last ABCIResponse to the
// height that is given
// LoadLastABCIResponses loads the ABCIResponses from the most recent height.
// The height parameter is used to ensure that the response corresponds to the latest height.
// If not, an error is returned.
//
// This is used for recovering from crashes where we called app.Commit and
// before we called s.Save()
// This method is used for recovering in the case that we called the Commit ABCI
// method on the application but crashed before persisting the results.
func (store dbStore) LoadLastABCIResponse(height int64) (*tmstate.ABCIResponses, error) {
bz, err := store.db.Get(lastABCIResponseKey)
if err != nil {
@@ -466,12 +474,11 @@ func (store dbStore) LoadLastABCIResponse(height int64) (*tmstate.ABCIResponses,
abciResponse := new(tmstate.ABCIResponsesInfo)
err = abciResponse.Unmarshal(bz)
if err != nil {
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
tmos.Exit(fmt.Sprintf(`LoadLastABCIResponses: Data has been corrupted or its spec has
changed: %v\n`, err))
}
//Here we sanitize by comparing the height from the height that is given to the last ABCIResponse
// Here we validate the result by comparing its height to the expected height.
if height != abciResponse.GetHeight() {
return nil, errors.New("expected height %d but last stored abci responses was at height %d")
}
@@ -484,7 +491,7 @@ func (store dbStore) LoadLastABCIResponse(height int64) (*tmstate.ABCIResponses,
// Responses are indexed by height so they can also be loaded later to produce
// Merkle proofs.
//
// CONTRACT: height must be monotonically increasing every time this is called
//CONTRACT: height must be monotonically increasing every time this is called.
func (store dbStore) SaveABCIResponses(height int64, abciResponses *tmstate.ABCIResponses) error {
var dtxs []*abci.ResponseDeliverTx
// strip nil values,
@@ -497,7 +504,7 @@ func (store dbStore) SaveABCIResponses(height int64, abciResponses *tmstate.ABCI
// If the flag is false then we save the ABCIResponse. This can be used for the /BlockResults
// query or to reindex an event using the command line.
if !store.discardABCIResponses {
if !store.DiscardABCIResponses {
bz, err := abciResponses.Marshal()
if err != nil {
return err
@@ -505,7 +512,6 @@ func (store dbStore) SaveABCIResponses(height int64, abciResponses *tmstate.ABCI
if err := store.db.Set(abciResponsesKey(height), bz); err != nil {
return err
}
}
// We always save the last ABCI response incase we crash after app.Commit and before s.Save(.)

View File

@@ -26,7 +26,9 @@ const (
func TestStoreBootstrap(t *testing.T) {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
val, _ := factory.RandValidator(true, 10)
val2, _ := factory.RandValidator(true, 10)
val3, _ := factory.RandValidator(true, 10)
@@ -52,7 +54,9 @@ func TestStoreBootstrap(t *testing.T) {
func TestStoreLoadValidators(t *testing.T) {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
val, _ := factory.RandValidator(true, 10)
val2, _ := factory.RandValidator(true, 10)
val3, _ := factory.RandValidator(true, 10)
@@ -107,7 +111,9 @@ func BenchmarkLoadValidators(b *testing.B) {
dbType := dbm.BackendType(cfg.DBBackend)
stateDB, err := dbm.NewDB("state", dbType, cfg.DBDir())
require.NoError(b, err)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state, err := sm.MakeGenesisStateFromFile(cfg.GenesisFile())
if err != nil {
b.Fatal(err)
@@ -141,7 +147,9 @@ func BenchmarkLoadValidators(b *testing.B) {
func TestStoreLoadConsensusParams(t *testing.T) {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
err := stateStore.Save(makeRandomStateFromConsensusParams(types.DefaultConsensusParams(), 1, 1))
require.NoError(t, err)
params, err := stateStore.LoadConsensusParams(1)
@@ -184,7 +192,9 @@ func TestPruneStates(t *testing.T) {
t.Run(name, func(t *testing.T) {
db := dbm.NewMemDB()
stateStore := sm.NewStore(db, false)
stateStore := sm.NewStore(db, sm.StoreOptions{
DiscardABCIResponses: false,
})
pk := ed25519.GenPrivKey().PubKey()
// Generate a bunch of state data. Validators change for heights ending with 3, and
@@ -308,15 +318,16 @@ func TestABCIResponsesResultsHash(t *testing.T) {
}
func TestLastABCIResponses(t *testing.T) {
//if the state store is empty
// if the state store is empty
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
responses, err := stateStore.LoadABCIResponses(1)
require.Error(t, err)
require.Nil(t, responses)
fmt.Println(responses)
//stub the abciresponses
// stub the abciresponses
response1 := &tmstate.ABCIResponses{
BeginBlock: &abci.ResponseBeginBlock{},
DeliverTxs: []*abci.ResponseDeliverTx{
@@ -324,29 +335,29 @@ func TestLastABCIResponses(t *testing.T) {
},
EndBlock: &abci.ResponseEndBlock{},
}
//Create new db and state store and set discard abciresponses to false
// create new db and state store and set discard abciresponses to false
stateDB = dbm.NewMemDB()
stateStore = sm.NewStore(stateDB, false)
stateStore = sm.NewStore(stateDB, sm.StoreOptions{DiscardABCIResponses: false})
height := int64(10)
//save the last abci response
// save the last abci response
err = stateStore.SaveABCIResponses(height, response1)
require.NoError(t, err)
//search for the last abciresponse and check if it has saved
// search for the last abciresponse and check if it has saved
lastResponse, err := stateStore.LoadLastABCIResponse(height)
require.NoError(t, err)
//check to see if the saved response height is the same as the loaded height
// check to see if the saved response height is the same as the loaded height
assert.Equal(t, lastResponse, response1)
// use an incorret height to make sure the state store errors
_, err = stateStore.LoadLastABCIResponse(height + 1)
assert.Error(t, err)
//check if the abci response didnt save in the abciresponses
// check if the abci response didnt save in the abciresponses
responses, err = stateStore.LoadABCIResponses(height)
require.NoError(t, err, responses)
require.Equal(t, response1, responses)
//stub the second abciresponse
// stub the second abciresponse
response2 := &tmstate.ABCIResponses{
BeginBlock: &abci.ResponseBeginBlock{},
DeliverTxs: []*abci.ResponseDeliverTx{
@@ -355,15 +366,17 @@ func TestLastABCIResponses(t *testing.T) {
EndBlock: &abci.ResponseEndBlock{},
}
//create a new statestore with the responses on
stateStore = sm.NewStore(stateDB, true)
// create a new statestore with the responses on
stateStore = sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: true,
})
// save an additional response
err = stateStore.SaveABCIResponses(height+1, response2)
require.NoError(t, err)
//check to see if the response saved by calling the last response
// check to see if the response saved by calling the last response
lastResponse2, err := stateStore.LoadLastABCIResponse(height + 1)
require.NoError(t, err)
//check to see if the saved response height is the same as the loaded height
// check to see if the saved response height is the same as the loaded height
assert.Equal(t, response2, lastResponse2)
// should error as we are no longer saving the response

View File

@@ -33,7 +33,9 @@ func TestValidateBlockHeader(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, privVals := makeState(3, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(
stateStore,
@@ -120,7 +122,9 @@ func TestValidateBlockCommit(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, privVals := makeState(1, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(
stateStore,
@@ -241,7 +245,9 @@ func TestValidateBlockEvidence(t *testing.T) {
defer proxyApp.Stop() //nolint:errcheck // ignore for tests
state, stateDB, privVals := makeState(4, 1)
stateStore := sm.NewStore(stateDB, false)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
blockStore := store.NewBlockStore(dbm.NewMemDB())
defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)