You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.3 KiB

  1. package state_test
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/require"
  5. dbm "github.com/tendermint/tm-db"
  6. "github.com/tendermint/tendermint/internal/state"
  7. "github.com/tendermint/tendermint/internal/state/mocks"
  8. "github.com/tendermint/tendermint/internal/test/factory"
  9. "github.com/tendermint/tendermint/types"
  10. "github.com/tendermint/tendermint/version"
  11. )
  12. func TestRollback(t *testing.T) {
  13. var (
  14. height int64 = 100
  15. appVersion uint64 = 10
  16. )
  17. blockStore := &mocks.BlockStore{}
  18. stateStore := setupStateStore(t, height)
  19. initialState, err := stateStore.Load()
  20. require.NoError(t, err)
  21. height++
  22. block := &types.BlockMeta{
  23. Header: types.Header{
  24. Height: height,
  25. AppHash: initialState.AppHash,
  26. LastBlockID: initialState.LastBlockID,
  27. LastResultsHash: initialState.LastResultsHash,
  28. },
  29. }
  30. blockStore.On("LoadBlockMeta", height).Return(block)
  31. blockStore.On("Height").Return(height)
  32. // perform the rollback over a version bump
  33. appVersion++
  34. newParams := types.DefaultConsensusParams()
  35. newParams.Version.AppVersion = appVersion
  36. newParams.Block.MaxBytes = 1000
  37. nextState := initialState.Copy()
  38. nextState.LastBlockHeight = height
  39. nextState.Version.Consensus.App = appVersion
  40. nextState.LastBlockID = factory.MakeBlockID()
  41. nextState.AppHash = factory.RandomHash()
  42. nextState.LastValidators = initialState.Validators
  43. nextState.Validators = initialState.NextValidators
  44. nextState.NextValidators = initialState.NextValidators.CopyIncrementProposerPriority(1)
  45. nextState.ConsensusParams = *newParams
  46. nextState.LastHeightConsensusParamsChanged = height + 1
  47. nextState.LastHeightValidatorsChanged = height + 1
  48. // update the state
  49. require.NoError(t, stateStore.Save(nextState))
  50. // rollback the state
  51. rollbackHeight, rollbackHash, err := state.Rollback(blockStore, stateStore)
  52. require.NoError(t, err)
  53. require.EqualValues(t, int64(100), rollbackHeight)
  54. require.EqualValues(t, initialState.AppHash, rollbackHash)
  55. blockStore.AssertExpectations(t)
  56. // assert that we've recovered the prior state
  57. loadedState, err := stateStore.Load()
  58. require.NoError(t, err)
  59. require.EqualValues(t, initialState, loadedState)
  60. }
  61. func TestRollbackNoState(t *testing.T) {
  62. stateStore := state.NewStore(dbm.NewMemDB())
  63. blockStore := &mocks.BlockStore{}
  64. _, _, err := state.Rollback(blockStore, stateStore)
  65. require.Error(t, err)
  66. require.Contains(t, err.Error(), "no state found")
  67. }
  68. func TestRollbackNoBlocks(t *testing.T) {
  69. const height = int64(100)
  70. stateStore := setupStateStore(t, height)
  71. blockStore := &mocks.BlockStore{}
  72. blockStore.On("Height").Return(height)
  73. blockStore.On("LoadBlockMeta", height).Return(nil)
  74. _, _, err := state.Rollback(blockStore, stateStore)
  75. require.Error(t, err)
  76. require.Contains(t, err.Error(), "block at height 100 not found")
  77. }
  78. func TestRollbackDifferentStateHeight(t *testing.T) {
  79. const height = int64(100)
  80. stateStore := setupStateStore(t, height)
  81. blockStore := &mocks.BlockStore{}
  82. blockStore.On("Height").Return(height + 2)
  83. _, _, err := state.Rollback(blockStore, stateStore)
  84. require.Error(t, err)
  85. require.Equal(t, err.Error(), "statestore height (100) is not one below or equal to blockstore height (102)")
  86. }
  87. func setupStateStore(t *testing.T, height int64) state.Store {
  88. stateStore := state.NewStore(dbm.NewMemDB())
  89. valSet, _ := factory.RandValidatorSet(5, 10)
  90. params := types.DefaultConsensusParams()
  91. params.Version.AppVersion = 10
  92. initialState := state.State{
  93. Version: state.Version{
  94. Consensus: version.Consensus{
  95. Block: version.BlockProtocol,
  96. App: 10,
  97. },
  98. Software: version.TMVersion,
  99. },
  100. ChainID: factory.DefaultTestChainID,
  101. InitialHeight: 10,
  102. LastBlockID: factory.MakeBlockID(),
  103. AppHash: factory.RandomHash(),
  104. LastResultsHash: factory.RandomHash(),
  105. LastBlockHeight: height,
  106. LastValidators: valSet,
  107. Validators: valSet.CopyIncrementProposerPriority(1),
  108. NextValidators: valSet.CopyIncrementProposerPriority(2),
  109. LastHeightValidatorsChanged: height + 1,
  110. ConsensusParams: *params,
  111. LastHeightConsensusParamsChanged: height + 1,
  112. }
  113. require.NoError(t, stateStore.Bootstrap(initialState))
  114. return stateStore
  115. }