diff --git a/CHANGELOG.md b/CHANGELOG.md index 479145c22569..ce4ca804cb75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. * (x/evidence) [#14757](https://github.com/cosmos/cosmos-sdk/pull/14757) Evidence messages do not need to implement a `.Type()` anymore. * (x/auth/tx) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove `.Type()` and `Route()` methods from all msgs and `legacytx.LegacyMsg` interface. * [#14691](https://github.com/cosmos/cosmos-sdk/pull/14691) Change behavior of `sdk.StringifyEvents` to not flatten events attributes by events type. diff --git a/store/CHANGELOG.md b/store/CHANGELOG.md index 2b6a94c78aca..f94f225911b8 100644 --- a/store/CHANGELOG.md +++ b/store/CHANGELOG.md @@ -27,4 +27,5 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features -* (store) [14746](https://github.com/cosmos/cosmos-sdk/pull/14746) The `store` module is extracted to have a separate go.mod file which allows it be a standalone module. \ No newline at end of file +* (store) [14746](https://github.com/cosmos/cosmos-sdk/pull/14746) The `store` module is extracted to have a separate go.mod file which allows it be a standalone module. +* (store) [14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. \ No newline at end of file diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 43c6cac99381..a969d0c507d5 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -156,11 +156,7 @@ func (rs *Store) MountStoreWithDB(key types.StoreKey, typ types.StoreType, db db if _, ok := rs.keysByName[key.Name()]; ok { panic(fmt.Sprintf("store duplicate store key name %v", key)) } - rs.storesParams[key] = storeParams{ - key: key, - typ: typ, - db: db, - } + rs.storesParams[key] = newStoreParams(key, db, typ, 0) rs.keysByName[key.Name()] = key } @@ -254,8 +250,10 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error { commitID := rs.getCommitID(infos, key.Name()) // If it has been added, set the initial version - if upgrades.IsAdded(key.Name()) { + if upgrades.IsAdded(key.Name()) || upgrades.RenamedFrom(key.Name()) != "" { storeParams.initialVersion = uint64(ver) + 1 + } else if commitID.Version != ver && storeParams.typ == types.StoreTypeIAVL { + return fmt.Errorf("version of store %s mismatch root store's version; expected %d got %d", key.Name(), ver, commitID.Version) } store, err := rs.loadCommitStoreFromParams(key, commitID, storeParams) @@ -275,8 +273,7 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error { // handle renames specially // make an unregistered key to satisfy loadCommitStore params oldKey := types.NewKVStoreKey(oldName) - oldParams := storeParams - oldParams.key = oldKey + oldParams := newStoreParams(oldKey, storeParams.db, storeParams.typ, 0) // load from the old name oldStore, err := rs.loadCommitStoreFromParams(oldKey, rs.getCommitID(infos, oldName), oldParams) @@ -1039,6 +1036,15 @@ type storeParams struct { initialVersion uint64 } +func newStoreParams(key types.StoreKey, db dbm.DB, typ types.StoreType, initialVersion uint64) storeParams { // nolint + return storeParams{ + key: key, + db: db, + typ: typ, + initialVersion: initialVersion, + } +} + func GetLatestVersion(db dbm.DB) int64 { bz, err := db.Get([]byte(latestVersionKey)) if err != nil { diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index f27263eddc57..8a117f68d2f8 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -271,6 +271,12 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) { require.Equal(t, migratedID.Version, int64(2)) reload, _ := newMultiStoreWithModifiedMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) + // unmount store3 since store3 was deleted + unmountStore(reload, "store3") + + rs3, _ := reload.GetStoreByName("store3").(types.KVStore) + require.Nil(t, rs3) + err = reload.LoadLatestVersion() require.Nil(t, err) require.Equal(t, migratedID, reload.LastCommitID()) @@ -606,6 +612,32 @@ func TestMultiStore_PruningRestart(t *testing.T) { } } +// TestUnevenStoresHeightCheck tests if loading root store correctly errors when +// there's any module store with the wrong height +func TestUnevenStoresHeightCheck(t *testing.T) { + var db dbm.DB = dbm.NewMemDB() + store := newMultiStoreWithMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) + err := store.LoadLatestVersion() + require.Nil(t, err) + + // commit to increment store's height + store.Commit() + + // mount store4 to root store + store.MountStoreWithDB(types.NewKVStoreKey("store4"), types.StoreTypeIAVL, nil) + + // load the stores without upgrades + err = store.LoadLatestVersion() + require.Error(t, err) + + // now, let's load with upgrades... + upgrades := &types.StoreUpgrades{ + Added: []string{"store4"}, + } + err = store.LoadLatestVersionAndUpgrade(upgrades) + require.Nil(t, err) +} + func TestSetInitialVersion(t *testing.T) { db := dbm.NewMemDB() multi := newMultiStoreWithMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) @@ -866,6 +898,13 @@ func newMultiStoreWithModifiedMounts(db dbm.DB, pruningOpts pruningtypes.Pruning return store, upgrades } +func unmountStore(rootStore *Store, storeKeyName string) { + sk := rootStore.keysByName[storeKeyName] + delete(rootStore.stores, sk) + delete(rootStore.storesParams, sk) + delete(rootStore.keysByName, storeKeyName) +} + func checkStore(t *testing.T, store *Store, expect, got types.CommitID) { require.Equal(t, expect, got) require.Equal(t, expect, store.LastCommitID()) diff --git a/x/upgrade/types/storeloader_test.go b/x/upgrade/types/storeloader_test.go index a408e605eaf7..244c33a40a99 100644 --- a/x/upgrade/types/storeloader_test.go +++ b/x/upgrade/types/storeloader_test.go @@ -147,11 +147,6 @@ func TestSetLoader(t *testing.T) { res := app.Commit() require.NotNil(t, res.Data) - // checking the case of the store being renamed - if tc.setLoader != nil { - checkStore(t, db, upgradeHeight, tc.origStoreKey, k, nil) - } - // check db is properly updated checkStore(t, db, upgradeHeight, tc.loadStoreKey, k, v) })