diff --git a/store/CHANGELOG.md b/store/CHANGELOG.md index c49c88668fea..bc16c71f122a 100644 --- a/store/CHANGELOG.md +++ b/store/CHANGELOG.md @@ -25,13 +25,14 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] -## Features +### Features * [#14645](https://github.com/cosmos/cosmos-sdk/pull/14645) Add limit to the length of key and value. +* [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. ## [v0.1.0-alpha.1](https://github.com/cosmos/cosmos-sdk/releases/tag/store%2Fv0.1.0-alpha.1) - 2023-03-17 ### Features * [#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. -* [#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. +* [#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 55ee77e39432..f20902e4d7bd 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -529,6 +529,8 @@ func (rs *Store) CacheMultiStore() types.CacheMultiStore { // iterating at past heights. func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStore, error) { cachedStores := make(map[types.StoreKey]types.CacheWrapper) + var commitInfo *types.CommitInfo + storeInfos := map[string]bool{} for key, store := range rs.stores { var cacheStore types.KVStore switch store.GetStoreType() { @@ -541,9 +543,30 @@ func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStor // version does not exist or is pruned, an error should be returned. var err error cacheStore, err = store.(*iavl.Store).GetImmutable(version) + // if we got error from loading a module store + // we fetch commit info of this version + // we use commit info to check if the store existed at this version or not if err != nil { - return nil, err + if commitInfo == nil { + var errCommitInfo error + commitInfo, errCommitInfo = rs.GetCommitInfo(version) + + if errCommitInfo != nil { + return nil, errCommitInfo + } + + for _, storeInfo := range commitInfo.StoreInfos { + storeInfos[storeInfo.Name] = true + } + } + + // If the store existed at this version, it means there's actually an error + // getting the root store at this version. + if storeInfos[key.Name()] { + return nil, err + } } + default: cacheStore = store } diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index ae589c907790..5557a33fb343 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -96,6 +96,17 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { require.NotNil(t, kvStore) require.Equal(t, kvStore.Get(k), v) + // add new module stores (store4 and store5) to multi stores and commit + ms.MountStoreWithDB(types.NewKVStoreKey("store4"), types.StoreTypeIAVL, nil) + ms.MountStoreWithDB(types.NewKVStoreKey("store5"), types.StoreTypeIAVL, nil) + err = ms.LoadLatestVersionAndUpgrade(&types.StoreUpgrades{Added: []string{"store4", "store5"}}) + require.NoError(t, err) + ms.Commit() + + // cache multistore of version before adding store4 should works + _, err = ms.CacheMultiStoreWithVersion(1) + require.NoError(t, err) + // require we cannot commit (write) to a cache-versioned multi-store require.Panics(t, func() { kvStore.Set(k, []byte("newValue"))