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

feat: state migration from IAVL to SMT (ADR-040) #10962

Merged
merged 41 commits into from
Mar 20, 2022
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4cc992f
feat: add migration for adr40
Jan 18, 2022
df0dc4f
chore: removed sort from migration func
Jan 19, 2022
fca170d
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 21, 2022
79583ec
chore: address the pr comments
Jan 27, 2022
bcfeff1
Merge branch 'sai/migration_for_adr40' of github.com:vulcanize/cosmos…
Jan 27, 2022
d511fa3
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 27, 2022
00b99a7
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 27, 2022
0eaec31
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 28, 2022
9f496e9
test: add test for migrationv2
Jan 29, 2022
39b303b
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 29, 2022
8b16dad
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 31, 2022
b305280
chore: change the `MigrationV2`
Jan 31, 2022
ebc1d3b
Merge branch 'master' into sai/migration_for_adr40
gsk967 Jan 31, 2022
64e1cb4
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 1, 2022
39d51cf
chore: refactored the migrationV2
Feb 1, 2022
242939e
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 1, 2022
a9fa647
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 2, 2022
ada2859
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 3, 2022
38527f7
chore: address the pr review comments
Feb 15, 2022
1e884cf
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 15, 2022
1b79269
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 17, 2022
00b6360
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 22, 2022
dc57212
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 25, 2022
4695365
fix: fix the build issue
Feb 25, 2022
3a5bdf0
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 25, 2022
c103f16
Merge branch 'master' into sai/migration_for_adr40
gsk967 Feb 28, 2022
4a9feb5
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 4, 2022
677639e
chore: address the pr comments
Mar 4, 2022
074da95
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 4, 2022
a05f72e
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 6, 2022
6eb51d1
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 9, 2022
c16dc89
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 10, 2022
119b77a
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 11, 2022
a97ed5a
address the pr comments
Mar 11, 2022
179743c
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 15, 2022
bb61b5d
address the pr comments
Mar 15, 2022
f381e09
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 16, 2022
7eec931
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 17, 2022
1af9b3b
chore: update changelog
Mar 17, 2022
ec331a0
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 18, 2022
e21a6f8
Merge branch 'master' into sai/migration_for_adr40
gsk967 Mar 20, 2022
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
7 changes: 4 additions & 3 deletions store/rootmulti/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ func TestMultistoreSnapshotRestore(t *testing.T) {
require.Equal(t, *dummyExtensionItem.GetExtension(), *nextItem.GetExtension())

assert.Equal(t, source.LastCommitID(), target.LastCommitID())
for key, sourceStore := range source.GetStores() {
for _, key := range source.StoreKeysByName() {
sourceStore := source.GetStoreByName(key.Name()).(types.CommitKVStore)
targetStore := target.GetStoreByName(key.Name()).(types.CommitKVStore)
switch sourceStore.GetStoreType() {
case types.StoreTypeTransient:
Expand All @@ -234,7 +235,7 @@ func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) {

for i := 0; i < b.N; i++ {
target := rootmulti.NewStore(dbm.NewMemDB())
for key := range source.GetStores() {
for _, key := range source.StoreKeysByName() {
target.MountStoreWithDB(key, types.StoreTypeIAVL, nil)
}
err := target.LoadLatestVersion()
Expand Down Expand Up @@ -269,7 +270,7 @@ func benchmarkMultistoreSnapshotRestore(b *testing.B, stores uint8, storeKeys ui

for i := 0; i < b.N; i++ {
target := rootmulti.NewStore(dbm.NewMemDB())
for key := range source.GetStores() {
for _, key := range source.StoreKeysByName() {
target.MountStoreWithDB(key, types.StoreTypeIAVL, nil)
}
err := target.LoadLatestVersion()
Expand Down
6 changes: 3 additions & 3 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ func (rs *Store) GetCommitKVStore(key types.StoreKey) types.CommitKVStore {
return rs.stores[key]
}

// GetStores returns mounted stores
func (rs *Store) GetStores() map[types.StoreKey]types.CommitKVStore {
return rs.stores
// StoreKeysByName returns mapping storeNames -> StoreKeys
func (rs *Store) StoreKeysByName() map[string]types.StoreKey {
return rs.keysByName
}

// LoadLatestVersionAndUpgrade implements CommitMultiStore
Expand Down
68 changes: 68 additions & 0 deletions store/v2/multi/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package multi

import (
dbm "github.com/cosmos/cosmos-sdk/db"
"github.com/cosmos/cosmos-sdk/store/iavl"
"github.com/cosmos/cosmos-sdk/store/mem"
v1Store "github.com/cosmos/cosmos-sdk/store/rootmulti"
"github.com/cosmos/cosmos-sdk/store/transient"
"github.com/cosmos/cosmos-sdk/store/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// MigrateFromV1 will migrate the state from iavl to smt
func MigrateFromV1(rootMultiStore *v1Store.Store, store2db dbm.DBConnection, storeConfig StoreConfig) (*Store, error) {
type namedStore struct {
*iavl.Store
name string
}
var stores []namedStore
for _, storeKey := range rootMultiStore.StoreKeysByName() {
keyName := storeKey.Name()
switch store := rootMultiStore.GetStoreByName(keyName).(type) {
case *iavl.Store:
err := storeConfig.RegisterSubstore(keyName, types.StoreTypePersistent)
if err != nil {
return nil, err
}
stores = append(stores, namedStore{name: keyName, Store: store})
case *transient.Store, *mem.Store:
continue
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrLogic, "don't know how to migrate store %q of type %T", keyName, store)
}
}

// creating the new store of smt tree
rootStore, err := NewStore(store2db, storeConfig)
if err != nil {
return nil, err
}

// if version is 0 there is no state data to commit
if rootMultiStore.LastCommitID().Version == 0 {
return rootStore, nil
}

// iterate through the rootmulti stores and save the key/values into smt tree
for _, store := range stores {
subStore, err := rootStore.getSubstore(store.name)
Copy link
Collaborator

@robert-zaremba robert-zaremba Mar 11, 2022

Choose a reason for hiding this comment

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

shouldn't we make sure that we use the same store key when doing migration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if err != nil {
return nil, err
}
// iterate all iavl tree node key/values
iterator := store.Iterator(nil, nil)
for ; iterator.Valid(); iterator.Next() {
// set the iavl key,values into smt node
subStore.Set(iterator.Key(), iterator.Value())
}
}

// commit the all key/values from iavl to smt tree (SMT Store)
_, err = rootStore.commit(uint64(rootMultiStore.LastCommitID().Version))
if err != nil {
return nil, err
}

return rootStore, nil
}
106 changes: 106 additions & 0 deletions store/v2/multi/migration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package multi

import (
"encoding/binary"
"fmt"
"math/rand"
"testing"

"github.com/cosmos/cosmos-sdk/db/memdb"
"github.com/cosmos/cosmos-sdk/store/iavl"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
"github.com/cosmos/cosmos-sdk/store/types"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
)

func TestMigrationV2(t *testing.T) {
r := rand.New(rand.NewSource(49872768940))

// setup a rootmulti store
db := dbm.NewMemDB()
v1Store := rootmulti.NewStore(db)

// mount the kvStores
var keys []*types.KVStoreKey
for i := uint8(0); i < 10; i++ {
key := types.NewKVStoreKey(fmt.Sprintf("store%v", i))
v1Store.MountStoreWithDB(key, types.StoreTypeIAVL, nil)
keys = append(keys, key)
}

err := v1Store.LoadLatestVersion()
require.Nil(t, err)

// setup a random test data
for _, key := range keys {
store := v1Store.GetStore(key).(*iavl.Store)
store.Set([]byte("temp_data"), []byte("one"))

for i := 0; i < len(keys); i++ {
k := make([]byte, 8)
v := make([]byte, 1024)
binary.BigEndian.PutUint64(k, uint64(i))
_, err := r.Read(v)
if err != nil {
panic(err)
}
store.Set(k, v)
}
}

testCases := []struct {
testName string
emptyStore bool
}{
{
"Migration With Empty Store",
true,
},
{
"Migration From Root Multi Store (IAVL) to SMT ",
false,
},
}

for _, testCase := range testCases {
if !testCase.emptyStore {
v1Store.Commit()
}

// setup a new root store of smt
db2 := memdb.NewDB()
storeConfig := DefaultStoreConfig()
// migrating the iavl store (v1) to smt store (v2)
v2Store, err := MigrateFromV1(v1Store, db2, storeConfig)
require.NoError(t, err)

for _, key := range keys {
v2StoreKVStore := v2Store.GetKVStore(key)
if testCase.emptyStore {
// check the empty store
require.Nil(t, v2StoreKVStore.Get([]byte("temp_data")))
} else {
require.Equal(t, v2StoreKVStore.Get([]byte("temp_data")), []byte("one"))
}
require.Equal(t, v2Store.LastCommitID().Version, v1Store.LastCommitID().Version)
}
err = v2Store.Close()
require.NoError(t, err)
}
}

// TestMigrateV2ForEmptyStore checking empty store migration
func TestMigrateV2ForEmptyStore(t *testing.T) {
// setup a rootmulti store
db := dbm.NewMemDB()
v1Store := rootmulti.NewStore(db)
err := v1Store.LoadLatestVersion()
require.Nil(t, err)
db2 := memdb.NewDB()
storeConfig := DefaultStoreConfig()
// migrating the iavl store (v1) to smt store (v2)
v2Store, err := MigrateFromV1(v1Store, db2, storeConfig)
require.NoError(t, err)
require.Equal(t, v2Store.LastCommitID(), v1Store.LastCommitID())
}
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved