|
|
@ -17,75 +17,50 @@ import ( |
|
|
|
) |
|
|
|
|
|
|
|
func TestRollback(t *testing.T) { |
|
|
|
stateStore := state.NewStore(dbm.NewMemDB()) |
|
|
|
blockStore := &mocks.BlockStore{} |
|
|
|
var ( |
|
|
|
height int64 = 100 |
|
|
|
appVersion uint64 = 10 |
|
|
|
height int64 = 100 |
|
|
|
nextHeight int64 = 101 |
|
|
|
) |
|
|
|
blockStore := &mocks.BlockStore{} |
|
|
|
stateStore := setupStateStore(t, height) |
|
|
|
initialState, err := stateStore.Load() |
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
valSet, _ := types.RandValidatorSet(5, 10) |
|
|
|
|
|
|
|
params := types.DefaultConsensusParams() |
|
|
|
params.Version.AppVersion = appVersion |
|
|
|
// perform the rollback over a version bump
|
|
|
|
newParams := types.DefaultConsensusParams() |
|
|
|
newParams.Block.MaxBytes = 10000 |
|
|
|
|
|
|
|
initialState := state.State{ |
|
|
|
Version: tmstate.Version{ |
|
|
|
Consensus: tmversion.Consensus{ |
|
|
|
Block: version.BlockProtocol, |
|
|
|
App: 10, |
|
|
|
}, |
|
|
|
Software: version.TMCoreSemVer, |
|
|
|
}, |
|
|
|
ChainID: "test-chain", |
|
|
|
InitialHeight: 10, |
|
|
|
LastBlockID: makeBlockIDRandom(), |
|
|
|
AppHash: tmhash.Sum([]byte("app_hash")), |
|
|
|
LastResultsHash: tmhash.Sum([]byte("last_results_hash")), |
|
|
|
LastBlockHeight: height, |
|
|
|
LastValidators: valSet, |
|
|
|
Validators: valSet.CopyIncrementProposerPriority(1), |
|
|
|
NextValidators: valSet.CopyIncrementProposerPriority(2), |
|
|
|
LastHeightValidatorsChanged: height + 1, |
|
|
|
ConsensusParams: *params, |
|
|
|
LastHeightConsensusParamsChanged: height + 1, |
|
|
|
} |
|
|
|
require.NoError(t, stateStore.Bootstrap(initialState)) |
|
|
|
|
|
|
|
height++ |
|
|
|
block := &types.BlockMeta{ |
|
|
|
Header: types.Header{ |
|
|
|
Height: height, |
|
|
|
AppHash: initialState.AppHash, |
|
|
|
LastBlockID: initialState.LastBlockID, |
|
|
|
LastResultsHash: initialState.LastResultsHash, |
|
|
|
}, |
|
|
|
} |
|
|
|
blockStore.On("LoadBlockMeta", height).Return(block) |
|
|
|
|
|
|
|
appVersion++ |
|
|
|
newParams.Version.AppVersion = appVersion |
|
|
|
newParams.Version.AppVersion = 11 |
|
|
|
newParams.Block.MaxBytes = 1000 |
|
|
|
nextState := initialState.Copy() |
|
|
|
nextState.LastBlockHeight = height |
|
|
|
nextState.Version.Consensus.App = appVersion |
|
|
|
nextState.LastBlockHeight = nextHeight |
|
|
|
nextState.Version.Consensus.App = 11 |
|
|
|
nextState.LastBlockID = makeBlockIDRandom() |
|
|
|
nextState.AppHash = tmhash.Sum([]byte("next_app_hash")) |
|
|
|
nextState.AppHash = tmhash.Sum([]byte("app_hash")) |
|
|
|
nextState.LastValidators = initialState.Validators |
|
|
|
nextState.Validators = initialState.NextValidators |
|
|
|
nextState.NextValidators = initialState.NextValidators.CopyIncrementProposerPriority(1) |
|
|
|
nextState.ConsensusParams = *newParams |
|
|
|
nextState.LastHeightConsensusParamsChanged = height + 1 |
|
|
|
nextState.LastHeightValidatorsChanged = height + 1 |
|
|
|
nextState.LastHeightConsensusParamsChanged = nextHeight + 1 |
|
|
|
nextState.LastHeightValidatorsChanged = nextHeight + 1 |
|
|
|
|
|
|
|
// update the state
|
|
|
|
require.NoError(t, stateStore.Save(nextState)) |
|
|
|
|
|
|
|
block := &types.BlockMeta{ |
|
|
|
BlockID: initialState.LastBlockID, |
|
|
|
Header: types.Header{ |
|
|
|
Height: initialState.LastBlockHeight, |
|
|
|
AppHash: initialState.AppHash, |
|
|
|
LastBlockID: makeBlockIDRandom(), |
|
|
|
LastResultsHash: initialState.LastResultsHash, |
|
|
|
}, |
|
|
|
} |
|
|
|
blockStore.On("LoadBlockMeta", initialState.LastBlockHeight).Return(block) |
|
|
|
blockStore.On("Height").Return(nextHeight) |
|
|
|
|
|
|
|
// rollback the state
|
|
|
|
rollbackHeight, rollbackHash, err := state.Rollback(blockStore, stateStore) |
|
|
|
require.NoError(t, err) |
|
|
|
require.EqualValues(t, int64(100), rollbackHeight) |
|
|
|
require.EqualValues(t, height, rollbackHeight) |
|
|
|
require.EqualValues(t, initialState.AppHash, rollbackHash) |
|
|
|
blockStore.AssertExpectations(t) |
|
|
|
|
|
|
@ -105,19 +80,34 @@ func TestRollbackNoState(t *testing.T) { |
|
|
|
} |
|
|
|
|
|
|
|
func TestRollbackNoBlocks(t *testing.T) { |
|
|
|
stateStore := state.NewStore(dbm.NewMemDB()) |
|
|
|
const height = int64(100) |
|
|
|
stateStore := setupStateStore(t, height) |
|
|
|
blockStore := &mocks.BlockStore{} |
|
|
|
var ( |
|
|
|
height int64 = 100 |
|
|
|
appVersion uint64 = 10 |
|
|
|
) |
|
|
|
blockStore.On("Height").Return(height) |
|
|
|
blockStore.On("LoadBlockMeta", height-1).Return(nil) |
|
|
|
|
|
|
|
_, _, err := state.Rollback(blockStore, stateStore) |
|
|
|
require.Error(t, err) |
|
|
|
require.Contains(t, err.Error(), "block at height 99 not found") |
|
|
|
} |
|
|
|
|
|
|
|
func TestRollbackDifferentStateHeight(t *testing.T) { |
|
|
|
const height = int64(100) |
|
|
|
stateStore := setupStateStore(t, height) |
|
|
|
blockStore := &mocks.BlockStore{} |
|
|
|
blockStore.On("Height").Return(height + 2) |
|
|
|
|
|
|
|
_, _, err := state.Rollback(blockStore, stateStore) |
|
|
|
require.Error(t, err) |
|
|
|
require.Equal(t, err.Error(), "statestore height (100) is not one below or equal to blockstore height (102)") |
|
|
|
} |
|
|
|
|
|
|
|
func setupStateStore(t *testing.T, height int64) state.Store { |
|
|
|
stateStore := state.NewStore(dbm.NewMemDB()) |
|
|
|
valSet, _ := types.RandValidatorSet(5, 10) |
|
|
|
|
|
|
|
params := types.DefaultConsensusParams() |
|
|
|
params.Version.AppVersion = appVersion |
|
|
|
newParams := types.DefaultConsensusParams() |
|
|
|
newParams.Block.MaxBytes = 10000 |
|
|
|
params.Version.AppVersion = 10 |
|
|
|
|
|
|
|
initialState := state.State{ |
|
|
|
Version: tmstate.Version{ |
|
|
@ -140,12 +130,8 @@ func TestRollbackNoBlocks(t *testing.T) { |
|
|
|
ConsensusParams: *params, |
|
|
|
LastHeightConsensusParamsChanged: height + 1, |
|
|
|
} |
|
|
|
require.NoError(t, stateStore.Save(initialState)) |
|
|
|
blockStore.On("LoadBlockMeta", height).Return(nil) |
|
|
|
|
|
|
|
_, _, err := state.Rollback(blockStore, stateStore) |
|
|
|
require.Error(t, err) |
|
|
|
require.Contains(t, err.Error(), "block at height 100 not found") |
|
|
|
require.NoError(t, stateStore.Bootstrap(initialState)) |
|
|
|
return stateStore |
|
|
|
} |
|
|
|
|
|
|
|
func makeBlockIDRandom() types.BlockID { |
|
|
|