fix: rollback command don't actually delete multistore versions (#11361)

* rollback command don't actually delete multistore versions

Closes: #11333

- add unit tests
- use LoadVersionForOverwriting
- update tendermint dependency to 0.35.x release branch

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

flushMetadata after rollback

Update server/rollback.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

fix build

gofumpt

* fix unit test
This commit is contained in:
yihuang
2022-08-30 05:50:00 +00:00
committed by GitHub
co-authored by Aleksandr Bezobchuk
parent f8b55ff8ee
commit 51d2de582d
10 changed files with 116 additions and 28 deletions
+69
View File
@@ -0,0 +1,69 @@
package rootmulti_test
import (
"fmt"
"testing"
"github.com/cosmos/cosmos-sdk/simapp"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
)
func TestRollback(t *testing.T) {
db := dbm.NewMemDB()
options := simapp.SetupOptions{
Logger: log.NewNopLogger(),
DB: db,
AppOpts: simtestutil.NewAppOptionsWithFlagHome(simapp.DefaultNodeHome),
}
app := simapp.NewSimappWithCustomOptions(t, false, options)
app.Commit()
ver0 := app.LastBlockHeight()
// commit 10 blocks
for i := int64(1); i <= 10; i++ {
header := tmproto.Header{
Height: ver0 + i,
AppHash: app.LastCommitID().Hash,
}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := app.NewContext(false, header)
store := ctx.KVStore(app.GetKey("bank"))
store.Set([]byte("key"), []byte(fmt.Sprintf("value%d", i)))
app.Commit()
}
require.Equal(t, ver0+10, app.LastBlockHeight())
store := app.NewContext(true, tmproto.Header{}).KVStore(app.GetKey("bank"))
require.Equal(t, []byte("value10"), store.Get([]byte("key")))
// rollback 5 blocks
target := ver0 + 5
require.NoError(t, app.CommitMultiStore().RollbackToVersion(target))
require.Equal(t, target, app.LastBlockHeight())
// recreate app to have clean check state
app = simapp.NewSimApp(options.Logger, options.DB, nil, true, simtestutil.NewAppOptionsWithFlagHome(simapp.DefaultNodeHome))
store = app.NewContext(true, tmproto.Header{}).KVStore(app.GetKey("bank"))
require.Equal(t, []byte("value5"), store.Get([]byte("key")))
// commit another 5 blocks with different values
for i := int64(6); i <= 10; i++ {
header := tmproto.Header{
Height: ver0 + i,
AppHash: app.LastCommitID().Hash,
}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := app.NewContext(false, header)
store := ctx.KVStore(app.GetKey("bank"))
store.Set([]byte("key"), []byte(fmt.Sprintf("VALUE%d", i)))
app.Commit()
}
require.Equal(t, ver0+10, app.LastBlockHeight())
store = app.NewContext(true, tmproto.Header{}).KVStore(app.GetKey("bank"))
require.Equal(t, []byte("VALUE10"), store.Get([]byte("key")))
}
+16 -19
View File
@@ -933,29 +933,26 @@ func (rs *Store) buildCommitInfo(version int64) *types.CommitInfo {
}
// RollbackToVersion delete the versions after `target` and update the latest version.
func (rs *Store) RollbackToVersion(target int64) int64 {
if target < 0 {
panic("Negative rollback target")
}
current := getLatestVersion(rs.db)
if target >= current {
return current
}
for ; current > target; current-- {
rs.pruningManager.HandleHeight(current)
}
if err := rs.pruneStores(); err != nil {
panic(err)
func (rs *Store) RollbackToVersion(target int64) error {
if target <= 0 {
return fmt.Errorf("invalid rollback height target: %d", target)
}
// update latest height
bz, err := gogotypes.StdInt64Marshal(current)
if err != nil {
panic(err)
for key, store := range rs.stores {
if store.GetStoreType() == types.StoreTypeIAVL {
// If the store is wrapped with an inter-block cache, we must first unwrap
// it to get the underlying IAVL store.
store = rs.GetCommitKVStore(key)
_, err := store.(*iavl.Store).LoadVersionForOverwriting(target)
if err != nil {
return err
}
}
}
rs.db.Set([]byte(latestVersionKey), bz)
return current
rs.flushMetadata(rs.db, target, rs.buildCommitInfo(target))
return rs.LoadLatestVersion()
}
func (rs *Store) flushMetadata(db dbm.DB, version int64, cInfo *types.CommitInfo) {