Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return empty store tree on non-existing version #7415

Merged
merged 27 commits into from
Oct 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
085ab67
Registered upgrade module tx commands
RiccardoM May 27, 2020
8c75acf
Merge remote-tracking branch 'origin/master'
RiccardoM Jul 21, 2020
4f2c638
Merge remote-tracking branch 'origin/master'
RiccardoM Aug 17, 2020
f16c094
Merge remote-tracking branch 'origin/master'
RiccardoM Sep 10, 2020
c9e1464
Merge branch 'master' of github.com:cosmos/cosmos-sdk
RiccardoM Sep 30, 2020
30193c8
Return empty store tree on non-existing version
RiccardoM Sep 30, 2020
8d51054
Return empty store tree on non-existing version
RiccardoM Sep 30, 2020
de349ad
Improving the loading of new stores
RiccardoM Oct 1, 2020
8fa352c
Merge remote-tracking branch 'riccardo/upgrade-fix' into upgrade-fix
RiccardoM Oct 1, 2020
8c0bc0b
Moved the SetInitialVersion after the load
RiccardoM Oct 1, 2020
508457f
Improved the StoreUpgrades object adding the Added modules
RiccardoM Oct 2, 2020
40b2caf
Rolled back version error and moved int64 to uint64 conversion
RiccardoM Oct 5, 2020
28d866a
Fixed the loading of stores after an on-chain upgrade
RiccardoM Sep 30, 2020
e865488
Added back empty tree return on missing version
RiccardoM Oct 8, 2020
67fde03
Merge remote-tracking branch 'riccardo/upgrade-fix' into upgrade-fix
RiccardoM Oct 8, 2020
95b0361
Added back empty tree return on missing version and fixed some bugs
RiccardoM Oct 8, 2020
691aeaf
Fixed the loading of stores after an on-chain upgrade
RiccardoM Sep 30, 2020
230839c
Added back empty tree return on missing version
RiccardoM Oct 8, 2020
0deaf8a
Added back empty tree return on missing version and fixed some bugs
RiccardoM Oct 8, 2020
308b7f0
Added CHANGELOG entry
RiccardoM Oct 9, 2020
fe79634
Fixed rootmulti tests to not fail when an invalid height is queried. …
RiccardoM Oct 9, 2020
4fc58f4
Fixed store tests
RiccardoM Oct 9, 2020
9cbb46c
Fixed failing test
RiccardoM Oct 12, 2020
4467d50
Update store/types/store.go
RiccardoM Oct 12, 2020
1c91c46
Merge remote-tracking branch 'riccardo/upgrade-fix' into upgrade-fix
RiccardoM Oct 13, 2020
3d0612a
Fixed build error
RiccardoM Oct 13, 2020
dd6e2a2
Merge branch 'master' into upgrade-fix
alexanderbez Oct 13, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ invalid or incomplete requests.
* (x/genutil) [\#5938](https://github.com/cosmos/cosmos-sdk/pull/5938) Fix `InitializeNodeValidatorFiles` error handling.
* (x/staking) [\#5949](https://github.com/cosmos/cosmos-sdk/pull/5949) Skip staking `HistoricalInfoKey` in simulations as headers are not exported.
* (client) [\#5964](https://github.com/cosmos/cosmos-sdk/issues/5964) `--trust-node` is now false by default - for real. Users must ensure it is set to true if they don't want to enable the verifier.
* (kvstore) [\#7415](https://github.com/cosmos/cosmos-sdk/pull/7415) Allow new stores to be registered during on-chain upgrades.

### State Machine Breaking

Expand Down
2 changes: 1 addition & 1 deletion baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func TestLoadVersionPruning(t *testing.T) {

for _, v := range []int64{1, 2, 4} {
_, err = app.cms.CacheMultiStoreWithVersion(v)
require.Error(t, err)
require.NoError(t, err)
}

for _, v := range []int64{3, 5, 6, 7} {
Expand Down
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module github.com/cosmos/cosmos-sdk

require (
github.com/99designs/keyring v1.1.6
github.com/DataDog/zstd v1.4.5 // indirect
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
github.com/armon/go-metrics v0.3.4
github.com/bgentry/speakeasy v0.1.0
github.com/btcsuite/btcd v0.21.0-beta
Expand All @@ -12,11 +13,15 @@ require (
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d
github.com/cosmos/iavl v0.15.0-rc3
github.com/cosmos/ledger-cosmos-go v0.11.1
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect
github.com/dgraph-io/ristretto v0.0.3 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25
github.com/gogo/gateway v1.1.0
github.com/gogo/protobuf v1.3.1
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.4.2
github.com/golang/snappy v0.0.2 // indirect
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.15.2
Expand All @@ -43,6 +48,8 @@ require (
github.com/tendermint/tendermint v0.34.0-rc4.0.20201005135527-d7d0ffea13c6
github.com/tendermint/tm-db v0.6.2
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.25.0
Expand Down
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
Expand Down Expand Up @@ -139,13 +141,19 @@ github.com/dgraph-io/badger/v2 v2.0.3 h1:inzdf6VF/NZ+tJ8RwwYMjJMvsOALTHYdozn0qSl
github.com/dgraph-io/badger/v2 v2.0.3/go.mod h1:3KY8+bsP8wI0OEnQJAKpd4wIJW/Mm32yw2j/9FUVnIM=
github.com/dgraph-io/badger/v2 v2.2007.1 h1:t36VcBCpo4SsmAD5M8wVv1ieVzcALyGfaJ92z4ccULM=
github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k=
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3 h1:MQLRM35Pp0yAyBYksjbj1nZI/w6eyRY/mWoM1sFf4kU=
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI=
github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
Expand Down Expand Up @@ -228,6 +236,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
Expand Down Expand Up @@ -681,6 +691,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo=
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -729,6 +741,8 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
Expand Down
16 changes: 11 additions & 5 deletions store/iavl/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ type Store struct {
// store's version (id) from the provided DB. An error is returned if the version
// fails to load.
func LoadStore(db dbm.DB, id types.CommitID, lazyLoading bool) (types.CommitKVStore, error) {
tree, err := iavl.NewMutableTree(db, defaultIAVLCacheSize)
return LoadStoreWithInitialVersion(db, id, lazyLoading, 0)
}

// LoadStore returns an IAVL Store as a CommitKVStore setting its initialVersion
// to the one given. Internally, it will load the store's version (id) from the
// provided DB. An error is returned if the version fails to load.
func LoadStoreWithInitialVersion(db dbm.DB, id types.CommitID, lazyLoading bool, initialVersion uint64) (types.CommitKVStore, error) {
Copy link
Contributor

@erikgrinaker erikgrinaker Oct 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this will probably have to be modified once IAVL 0.15 is released. In 0.14, loading a missing version from an empty tree (no versions) does not error, which has been changed/fixed for the 0.15 line: cosmos/iavl#317

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. We'll just have to update this once that version is released.

tree, err := iavl.NewMutableTreeWithOpts(db, defaultIAVLCacheSize, &iavl.Options{InitialVersion: initialVersion})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -78,11 +85,11 @@ func UnsafeNewStore(tree *iavl.MutableTree) *Store {
// GetImmutable returns a reference to a new store backed by an immutable IAVL
// tree at a specific version (height) without any pruning options. This should
// be used for querying and iteration only. If the version does not exist or has
// been pruned, an error will be returned. Any mutable operations executed will
// result in a panic.
// been pruned, an empty immutable IAVL tree will be used.
// Any mutable operations executed will result in a panic.
func (st *Store) GetImmutable(version int64) (*Store, error) {
if !st.VersionExists(version) {
return nil, iavl.ErrVersionDoesNotExist
return &Store{tree: &immutableTree{&iavl.ImmutableTree{}}}, nil
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
}

iTree, err := st.tree.GetImmutable(version)
Expand Down Expand Up @@ -153,7 +160,6 @@ func (st *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.Ca

// Implements types.KVStore.
func (st *Store) Set(key, value []byte) {
defer telemetry.MeasureSince(time.Now(), "store", "iavl", "set")
types.AssertValidKey(key)
types.AssertValidValue(value)
st.tree.Set(key, value)
Expand Down
58 changes: 57 additions & 1 deletion store/iavl/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,62 @@ func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) {
return tree, types.CommitID{Version: ver, Hash: hash}
}

func TestLoadStore(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newAlohaTree(t, db)
store := UnsafeNewStore(tree)

// Create non-pruned height H
require.True(t, tree.Set([]byte("hello"), []byte("hallo")))
hash, verH, err := tree.SaveVersion()
cIDH := types.CommitID{Version: verH, Hash: hash}
require.Nil(t, err)

// Create pruned height Hp
require.True(t, tree.Set([]byte("hello"), []byte("hola")))
hash, verHp, err := tree.SaveVersion()
cIDHp := types.CommitID{Version: verHp, Hash: hash}
require.Nil(t, err)

// TODO: Prune this height

// Create current height Hc
require.True(t, tree.Set([]byte("hello"), []byte("ciao")))
hash, verHc, err := tree.SaveVersion()
cIDHc := types.CommitID{Version: verHc, Hash: hash}
require.Nil(t, err)

// Querying an existing store at some previous non-pruned height H
hStore, err := store.GetImmutable(verH)
require.NoError(t, err)
require.Equal(t, string(hStore.Get([]byte("hello"))), "hallo")

// Querying an existing store at some previous pruned height Hp
hpStore, err := store.GetImmutable(verHp)
require.NoError(t, err)
require.Equal(t, string(hpStore.Get([]byte("hello"))), "hola")

// Querying an existing store at current height Hc
hcStore, err := store.GetImmutable(verHc)
require.NoError(t, err)
require.Equal(t, string(hcStore.Get([]byte("hello"))), "ciao")

// Querying a new store at some previous non-pruned height H
newHStore, err := LoadStore(db, cIDH, false)
require.NoError(t, err)
require.Equal(t, string(newHStore.Get([]byte("hello"))), "hallo")

// Querying a new store at some previous pruned height Hp
newHpStore, err := LoadStore(db, cIDHp, false)
require.NoError(t, err)
require.Equal(t, string(newHpStore.Get([]byte("hello"))), "hola")

// Querying a new store at current height H
newHcStore, err := LoadStore(db, cIDHc, false)
require.NoError(t, err)
require.Equal(t, string(newHcStore.Get([]byte("hello"))), "ciao")
}

func TestGetImmutable(t *testing.T) {
db := dbm.NewMemDB()
tree, cID := newAlohaTree(t, db)
Expand All @@ -61,7 +117,7 @@ func TestGetImmutable(t *testing.T) {
require.Nil(t, err)

_, err = store.GetImmutable(cID.Version + 1)
require.Error(t, err)
require.NoError(t, err)

newStore, err := store.GetImmutable(cID.Version - 1)
require.NoError(t, err)
Expand Down
26 changes: 21 additions & 5 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,14 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error {
var newStores = make(map[types.StoreKey]types.CommitKVStore)

for key, storeParams := range rs.storesParams {
store, err := rs.loadCommitStoreFromParams(key, rs.getCommitID(infos, key.Name()), storeParams)
commitID := rs.getCommitID(infos, key.Name())

// If it has been added, set the initial version
if upgrades.IsAdded(key.Name()) {
storeParams.initialVersion = uint64(ver) + 1
}

store, err := rs.loadCommitStoreFromParams(key, commitID, storeParams)
if err != nil {
return errors.Wrap(err, "failed to load store")
}
Expand Down Expand Up @@ -813,7 +820,15 @@ func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID
panic("recursive MultiStores not yet supported")

case types.StoreTypeIAVL:
store, err := iavl.LoadStore(db, id, rs.lazyLoading)
var store types.CommitKVStore
var err error

if params.initialVersion == 0 {
store, err = iavl.LoadStore(db, id, rs.lazyLoading)
} else {
store, err = iavl.LoadStoreWithInitialVersion(db, id, rs.lazyLoading, params.initialVersion)
}
Comment on lines +826 to +830
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check isn't strictly necessary, since LoadStore() is equivalent to LoadStoreWithInitialVersion(..., 0). But might be good to be explicit about it anyway.


if err != nil {
return nil, err
}
Expand Down Expand Up @@ -868,9 +883,10 @@ func (rs *Store) buildCommitInfo(version int64) *types.CommitInfo {
}

type storeParams struct {
key types.StoreKey
db dbm.DB
typ types.StoreType
key types.StoreKey
db dbm.DB
typ types.StoreType
initialVersion uint64
}

func getLatestVersion(db dbm.DB) int64 {
Expand Down
39 changes: 33 additions & 6 deletions store/rootmulti/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ func TestCacheMultiStoreWithVersion(t *testing.T) {
cID := ms.Commit()
require.Equal(t, int64(1), cID.Version)

// require failure when given an invalid or pruned version
// require no failure when given an invalid or pruned version
_, err = ms.CacheMultiStoreWithVersion(cID.Version + 1)
require.Error(t, err)
require.NoError(t, err)

// require a valid version can be cache-loaded
cms, err := ms.CacheMultiStoreWithVersion(cID.Version)
Expand Down Expand Up @@ -192,6 +192,9 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) {
require.NotNil(t, s3)
s3.Set(k3, v3)

s4, _ := store.getStoreByName("store4").(types.KVStore)
require.Nil(t, s4)

// do one commit
commitID := store.Commit()
expectedCommitID := getExpectedCommitID(store, 1)
Expand Down Expand Up @@ -231,6 +234,24 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) {
require.NotNil(t, s3)
require.Nil(t, s3.Get(k3)) // data was deleted

// store4 is mounted, with empty data
s4, _ = restore.getStoreByName("store4").(types.KVStore)
require.NotNil(t, s4)

iterator := s4.Iterator(nil, nil)

values := 0
for ; iterator.Valid(); iterator.Next() {
values += 1
}
require.Zero(t, values)

require.NoError(t, iterator.Close())

// write something inside store4
k4, v4 := []byte("fourth"), []byte("created")
s4.Set(k4, v4)

// store2 is no longer mounted
st2 := restore.getStoreByName("store2")
require.Nil(t, st2)
Expand Down Expand Up @@ -258,12 +279,16 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) {
require.NotNil(t, rl2)
require.Equal(t, v2, rl2.Get(k2))

rl4, _ := reload.getStoreByName("store4").(types.KVStore)
require.NotNil(t, rl4)
require.Equal(t, v4, rl4.Get(k4))

// check commitInfo in storage
ci, err = getCommitInfo(db, 2)
require.NoError(t, err)
require.Equal(t, int64(2), ci.Version)
require.Equal(t, 3, len(ci.StoreInfos), ci.StoreInfos)
checkContains(t, ci.StoreInfos, []string{"store1", "restore2", "store3"})
require.Equal(t, 4, len(ci.StoreInfos), ci.StoreInfos)
checkContains(t, ci.StoreInfos, []string{"store1", "restore2", "store3", "store4"})
}

func TestParsePath(t *testing.T) {
Expand Down Expand Up @@ -474,7 +499,7 @@ func TestMultiStore_Pruning(t *testing.T) {

for _, v := range tc.deleted {
_, err := ms.CacheMultiStoreWithVersion(v)
require.Error(t, err, "expected error when loading height: %d", v)
require.NoError(t, err, "expected error when loading height: %d", v)
}
})
}
Expand Down Expand Up @@ -510,7 +535,7 @@ func TestMultiStore_PruningRestart(t *testing.T) {

for _, v := range pruneHeights {
_, err := ms.CacheMultiStoreWithVersion(v)
require.Error(t, err, "expected error when loading height: %d", v)
require.NoError(t, err, "expected error when loading height: %d", v)
}
}

Expand Down Expand Up @@ -796,8 +821,10 @@ func newMultiStoreWithModifiedMounts(db dbm.DB, pruningOpts types.PruningOptions
store.MountStoreWithDB(types.NewKVStoreKey("store1"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB(types.NewKVStoreKey("restore2"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB(types.NewKVStoreKey("store3"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB(types.NewKVStoreKey("store4"), types.StoreTypeIAVL, nil)

upgrades := &types.StoreUpgrades{
Added: []string{"store4"},
Renamed: []types.StoreRename{{
OldKey: "store2",
NewKey: "restore2",
Expand Down
10 changes: 10 additions & 0 deletions store/types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/types/kv"
tmstrings "github.com/tendermint/tendermint/libs/strings"
)

type Store interface {
Expand Down Expand Up @@ -44,6 +45,7 @@ type Queryable interface {

// StoreUpgrades defines a series of transformations to apply the multistore db upon load
type StoreUpgrades struct {
Added []string `json:"added"`
Renamed []StoreRename `json:"renamed"`
Deleted []string `json:"deleted"`
}
Expand All @@ -63,6 +65,14 @@ type StoreRename struct {
NewKey string `json:"new_key"`
}

// IsDeleted returns true if the given key should be added
func (s *StoreUpgrades) IsAdded(key string) bool {
if s == nil {
return false
}
return tmstrings.StringInSlice(key, s.Added)
}

// IsDeleted returns true if the given key should be deleted
func (s *StoreUpgrades) IsDeleted(key string) bool {
if s == nil {
Expand Down