diff --git a/CHANGELOG.md b/CHANGELOG.md index bacbedec7033..56c5c0ebefb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Improvements + +* (store) [#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. + ### Bug Fixes * (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index fae4f1d88938..c0bf40f24363 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -571,9 +571,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 = getCommitInfo(rs.db, 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 2b5deafcc0a5..2719df5b852a 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -101,19 +101,16 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { require.Equal(t, kvStore.Get(k), v) // add new module stores (store4 and store5) to multi stores and commit - key4, key5 := types.NewKVStoreKey("store4"), types.NewKVStoreKey("store5") - ms.MountStoreWithDB(key4, types.StoreTypeIAVL, nil) - ms.MountStoreWithDB(key5, types.StoreTypeIAVL, nil) + 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 - cms2, err := ms.CacheMultiStoreWithVersion(1) + _, err = ms.CacheMultiStoreWithVersion(1) require.NoError(t, err) - require.Empty(t, cms2.GetKVStore(key4).Get([]byte("key"))) - // require we cannot commit (write) to a cache-versioned multi-store require.Panics(t, func() { kvStore.Set(k, []byte("newValue"))