mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-05 13:05:09 +00:00
* cli: add --hard flag to rollback command to remove block as well (#9261)
Co-authored-by: Levi Aul <levi@leviaul.com>
(cherry picked from commit e84d43ec93)
* Fix lint
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Co-authored-by: Callum Waters <cmwaters19@gmail.com>
Co-authored-by: Thane Thomson <connect@thanethomson.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package state_test
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/state/mocks"
|
||||
"github.com/tendermint/tendermint/store"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
@@ -50,6 +52,7 @@ func TestRollback(t *testing.T) {
|
||||
BlockID: initialState.LastBlockID,
|
||||
Header: types.Header{
|
||||
Height: initialState.LastBlockHeight,
|
||||
Time: initialState.LastBlockTime,
|
||||
AppHash: crypto.CRandBytes(tmhash.Size),
|
||||
LastBlockID: makeBlockIDRandom(),
|
||||
LastResultsHash: initialState.LastResultsHash,
|
||||
@@ -61,6 +64,7 @@ func TestRollback(t *testing.T) {
|
||||
Height: nextState.LastBlockHeight,
|
||||
AppHash: initialState.AppHash,
|
||||
LastBlockID: block.BlockID,
|
||||
Time: nextState.LastBlockTime,
|
||||
LastResultsHash: nextState.LastResultsHash,
|
||||
},
|
||||
}
|
||||
@@ -69,7 +73,7 @@ func TestRollback(t *testing.T) {
|
||||
blockStore.On("Height").Return(nextHeight)
|
||||
|
||||
// rollback the state
|
||||
rollbackHeight, rollbackHash, err := state.Rollback(blockStore, stateStore)
|
||||
rollbackHeight, rollbackHash, err := state.Rollback(blockStore, stateStore, false)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, height, rollbackHeight)
|
||||
require.EqualValues(t, initialState.AppHash, rollbackHash)
|
||||
@@ -81,6 +85,122 @@ func TestRollback(t *testing.T) {
|
||||
require.EqualValues(t, initialState, loadedState)
|
||||
}
|
||||
|
||||
func TestRollbackHard(t *testing.T) {
|
||||
const height int64 = 100
|
||||
blockStore := store.NewBlockStore(dbm.NewMemDB())
|
||||
stateStore := state.NewStore(dbm.NewMemDB(), state.StoreOptions{DiscardABCIResponses: false})
|
||||
|
||||
valSet, _ := types.RandValidatorSet(5, 10)
|
||||
|
||||
params := types.DefaultConsensusParams()
|
||||
params.Version.App = 10
|
||||
now := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
block := &types.Block{
|
||||
Header: types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
ChainID: "test-chain",
|
||||
Time: now,
|
||||
Height: height,
|
||||
AppHash: crypto.CRandBytes(tmhash.Size),
|
||||
LastBlockID: makeBlockIDRandom(),
|
||||
LastCommitHash: crypto.CRandBytes(tmhash.Size),
|
||||
DataHash: crypto.CRandBytes(tmhash.Size),
|
||||
ValidatorsHash: valSet.Hash(),
|
||||
NextValidatorsHash: valSet.CopyIncrementProposerPriority(1).Hash(),
|
||||
ConsensusHash: params.Hash(),
|
||||
LastResultsHash: crypto.CRandBytes(tmhash.Size),
|
||||
EvidenceHash: crypto.CRandBytes(tmhash.Size),
|
||||
ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
|
||||
},
|
||||
LastCommit: &types.Commit{Height: height - 1},
|
||||
}
|
||||
|
||||
partSet, err := block.MakePartSet(types.BlockPartSizeBytes)
|
||||
require.NoError(t, err)
|
||||
blockStore.SaveBlock(block, partSet, &types.Commit{Height: block.Height})
|
||||
|
||||
currState := state.State{
|
||||
Version: tmstate.Version{
|
||||
Consensus: block.Header.Version,
|
||||
Software: version.TMCoreSemVer,
|
||||
},
|
||||
LastBlockHeight: block.Height,
|
||||
LastBlockTime: block.Time,
|
||||
AppHash: crypto.CRandBytes(tmhash.Size),
|
||||
LastValidators: valSet,
|
||||
Validators: valSet.CopyIncrementProposerPriority(1),
|
||||
NextValidators: valSet.CopyIncrementProposerPriority(2),
|
||||
ConsensusParams: *params,
|
||||
LastHeightConsensusParamsChanged: height + 1,
|
||||
LastHeightValidatorsChanged: height + 1,
|
||||
LastResultsHash: crypto.CRandBytes(tmhash.Size),
|
||||
}
|
||||
require.NoError(t, stateStore.Bootstrap(currState))
|
||||
|
||||
nextBlock := &types.Block{
|
||||
Header: types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
ChainID: block.ChainID,
|
||||
Time: block.Time,
|
||||
Height: currState.LastBlockHeight + 1,
|
||||
AppHash: currState.AppHash,
|
||||
LastBlockID: types.BlockID{Hash: block.Hash(), PartSetHeader: partSet.Header()},
|
||||
LastCommitHash: crypto.CRandBytes(tmhash.Size),
|
||||
DataHash: crypto.CRandBytes(tmhash.Size),
|
||||
ValidatorsHash: valSet.CopyIncrementProposerPriority(1).Hash(),
|
||||
NextValidatorsHash: valSet.CopyIncrementProposerPriority(2).Hash(),
|
||||
ConsensusHash: params.Hash(),
|
||||
LastResultsHash: currState.LastResultsHash,
|
||||
EvidenceHash: crypto.CRandBytes(tmhash.Size),
|
||||
ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
|
||||
},
|
||||
LastCommit: &types.Commit{Height: currState.LastBlockHeight},
|
||||
}
|
||||
|
||||
nextPartSet, err := nextBlock.MakePartSet(types.BlockPartSizeBytes)
|
||||
require.NoError(t, err)
|
||||
blockStore.SaveBlock(nextBlock, nextPartSet, &types.Commit{Height: nextBlock.Height})
|
||||
|
||||
rollbackHeight, rollbackHash, err := state.Rollback(blockStore, stateStore, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, rollbackHeight, currState.LastBlockHeight)
|
||||
require.Equal(t, rollbackHash, currState.AppHash)
|
||||
|
||||
// state should not have been changed
|
||||
loadedState, err := stateStore.Load()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, currState, loadedState)
|
||||
|
||||
// resave the same block
|
||||
blockStore.SaveBlock(nextBlock, nextPartSet, &types.Commit{Height: nextBlock.Height})
|
||||
|
||||
params.Version.App = 11
|
||||
|
||||
nextState := state.State{
|
||||
Version: tmstate.Version{
|
||||
Consensus: block.Header.Version,
|
||||
Software: version.TMCoreSemVer,
|
||||
},
|
||||
LastBlockHeight: nextBlock.Height,
|
||||
LastBlockTime: nextBlock.Time,
|
||||
AppHash: crypto.CRandBytes(tmhash.Size),
|
||||
LastValidators: valSet.CopyIncrementProposerPriority(1),
|
||||
Validators: valSet.CopyIncrementProposerPriority(2),
|
||||
NextValidators: valSet.CopyIncrementProposerPriority(3),
|
||||
ConsensusParams: *params,
|
||||
LastHeightConsensusParamsChanged: nextBlock.Height + 1,
|
||||
LastHeightValidatorsChanged: nextBlock.Height + 1,
|
||||
LastResultsHash: crypto.CRandBytes(tmhash.Size),
|
||||
}
|
||||
require.NoError(t, stateStore.Save(nextState))
|
||||
|
||||
rollbackHeight, rollbackHash, err = state.Rollback(blockStore, stateStore, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, rollbackHeight, currState.LastBlockHeight)
|
||||
require.Equal(t, rollbackHash, currState.AppHash)
|
||||
}
|
||||
|
||||
func TestRollbackNoState(t *testing.T) {
|
||||
stateStore := state.NewStore(dbm.NewMemDB(),
|
||||
state.StoreOptions{
|
||||
@@ -88,7 +208,7 @@ func TestRollbackNoState(t *testing.T) {
|
||||
})
|
||||
blockStore := &mocks.BlockStore{}
|
||||
|
||||
_, _, err := state.Rollback(blockStore, stateStore)
|
||||
_, _, err := state.Rollback(blockStore, stateStore, false)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "no state found")
|
||||
}
|
||||
@@ -101,7 +221,7 @@ func TestRollbackNoBlocks(t *testing.T) {
|
||||
blockStore.On("LoadBlockMeta", height).Return(nil)
|
||||
blockStore.On("LoadBlockMeta", height-1).Return(nil)
|
||||
|
||||
_, _, err := state.Rollback(blockStore, stateStore)
|
||||
_, _, err := state.Rollback(blockStore, stateStore, false)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "block at height 99 not found")
|
||||
}
|
||||
@@ -112,7 +232,7 @@ func TestRollbackDifferentStateHeight(t *testing.T) {
|
||||
blockStore := &mocks.BlockStore{}
|
||||
blockStore.On("Height").Return(height + 2)
|
||||
|
||||
_, _, err := state.Rollback(blockStore, stateStore)
|
||||
_, _, err := state.Rollback(blockStore, stateStore, false)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err.Error(), "statestore height (100) is not one below or equal to blockstore height (102)")
|
||||
}
|
||||
@@ -138,6 +258,7 @@ func setupStateStore(t *testing.T, height int64) state.Store {
|
||||
AppHash: tmhash.Sum([]byte("app_hash")),
|
||||
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
|
||||
LastBlockHeight: height,
|
||||
LastBlockTime: time.Now(),
|
||||
LastValidators: valSet,
|
||||
Validators: valSet.CopyIncrementProposerPriority(1),
|
||||
NextValidators: valSet.CopyIncrementProposerPriority(2),
|
||||
|
||||
Reference in New Issue
Block a user