From 10d72d71f1a07bc8d158faa8a692f5ed552690ad Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 1 Feb 2021 16:18:22 +0100 Subject: [PATCH 01/46] Add 1st version of migrate --- simapp/app.go | 26 ++++++++++++ types/module/module.go | 14 +++++++ x/auth/legacy/v040/store.go | 4 ++ x/auth/module.go | 8 ++++ x/auth/vesting/module.go | 8 ++++ x/authz/module.go | 8 ++++ x/bank/legacy/v040/store.go | 25 ++++++++++++ x/bank/legacy/v042/store.go | 59 +++++++++++++++++++++++++++ x/bank/legacy/v042/store_test.go | 7 ++++ x/bank/legacy/v042/types.go | 5 +++ x/bank/module.go | 25 ++++++++++++ x/capability/module.go | 8 ++++ x/crisis/module.go | 8 ++++ x/distribution/module.go | 8 ++++ x/evidence/module.go | 8 ++++ x/feegrant/module.go | 8 ++++ x/genutil/module.go | 8 ++++ x/gov/module.go | 8 ++++ x/ibc/applications/transfer/module.go | 8 ++++ x/ibc/core/module.go | 8 ++++ x/mint/module.go | 8 ++++ x/params/module.go | 8 ++++ x/slashing/module.go | 8 ++++ x/staking/module.go | 8 ++++ x/upgrade/module.go | 8 ++++ 25 files changed, 301 insertions(+) create mode 100644 x/auth/legacy/v040/store.go create mode 100644 x/bank/legacy/v040/store.go create mode 100644 x/bank/legacy/v042/store.go create mode 100644 x/bank/legacy/v042/store_test.go create mode 100644 x/bank/legacy/v042/types.go diff --git a/simapp/app.go b/simapp/app.go index 23ced043d047..9fc5b32dc959 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -598,6 +598,32 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } +// MigrateStore performs in-place store migrations. This function is not called +// automatically, it is meant to be called from an x/upgrade UpgradeHandler. +// `migrationsMap` is a map of moduleName to fromVersion (unit64), where +// fromVersion denotes the version from which we should migrate the module. +// +// Example: +// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { +// err := app.MigrateStore(ctx, map[string]unint64{ +// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion +// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion +// }) +// if err != nil { +// panic(err) +// } +// }) +func (app *SimApp) MigrateStore(ctx sdk.Context, migrationsMap map[string]uint64) error { + for moduleName, module := range app.mm.Modules { + err := module.MigrateStore(ctx, app.keys[moduleName], migrationsMap[moduleName]) + if err != nil { + return err + } + } + + return nil +} + // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) { statikFS, err := fs.New() diff --git a/types/module/module.go b/types/module/module.go index 2379c93d5ebd..e02a85a66a9e 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -174,6 +174,12 @@ type AppModule interface { // RegisterServices allows a module to register services RegisterServices(Configurator) + // ConsensusVersion tracks state-breaking versions of the module + ConsensusVersion() uint64 + + // MigrateStore performs in-place store migrations. + MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error + // ABCI BeginBlock(sdk.Context, abci.RequestBeginBlock) EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate @@ -208,6 +214,14 @@ func (gam GenesisOnlyAppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Que // RegisterServices registers all services. func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {} +// ConsensusVersion tracks state-breaking versions of the module. +func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (gam GenesisOnlyAppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns an empty module begin-block func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} diff --git a/x/auth/legacy/v040/store.go b/x/auth/legacy/v040/store.go new file mode 100644 index 000000000000..9fb81b60a749 --- /dev/null +++ b/x/auth/legacy/v040/store.go @@ -0,0 +1,4 @@ +package v040 + +// AddrLen defines a valid address length +const AddrLen = 20 diff --git a/x/auth/module.go b/x/auth/module.go index 73aa9a1066a9..998af5809e97 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -147,6 +147,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the auth module. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go index 3cc579a40e37..0e20cc4d800c 100644 --- a/x/auth/vesting/module.go +++ b/x/auth/vesting/module.go @@ -127,3 +127,11 @@ func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Valid func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { return am.DefaultGenesis(cdc) } + +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} diff --git a/x/authz/module.go b/x/authz/module.go index 1bcd388e4df9..faf1c842604f 100644 --- a/x/authz/module.go +++ b/x/authz/module.go @@ -152,6 +152,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} // EndBlock does nothing diff --git a/x/bank/legacy/v040/store.go b/x/bank/legacy/v040/store.go new file mode 100644 index 000000000000..6ff84a34082c --- /dev/null +++ b/x/bank/legacy/v040/store.go @@ -0,0 +1,25 @@ +package v040 + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +// KVStore keys +var ( + BalancesPrefix = []byte("balances") +) + +// AddressFromBalancesStore returns an account address from a balances prefix +// store. The key must not contain the perfix BalancesPrefix as the prefix store +// iterator discards the actual prefix. +func AddressFromBalancesStore(key []byte) sdk.AccAddress { + addr := key[:v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic(fmt.Sprintf("unexpected account address key length; got: %d, expected: %d", len(addr), v040auth.AddrLen)) + } + + return sdk.AccAddress(addr) +} diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go new file mode 100644 index 000000000000..42665801ea2e --- /dev/null +++ b/x/bank/legacy/v042/store.go @@ -0,0 +1,59 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" + v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" +) + +// KVStore keys +var ( + // BalancesPrefix is the for the account balances store. We use a byte + // (instead of say `[]]byte("balances")` to save some disk space). + BalancesPrefix = []byte{0x02} +) + +// AddressFromBalancesStore returns an account address from a balances prefix +// store. The key must not contain the perfix BalancesPrefix as the prefix store +// iterator discards the actual prefix. +func AddressFromBalancesStore(key []byte) sdk.AccAddress { + addrLen := key[0] + addr := key[1 : addrLen+1] + + return sdk.AccAddress(addr) +} + +// CreateAccountBalancesPrefix creates the prefix for an account's balances. +func CreateAccountBalancesPrefix(addr []byte) []byte { + return append(BalancesPrefix, address.MustLengthPrefix(addr)...) +} + +// StoreMigration performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +// - Change balances prefix to 1 byte +func StoreMigration(store sdk.KVStore) error { + // old key is of format: + // prefix ("balances") || addrBytes (20 bytes) || denomBytes + // new key is of format + // prefix (0x02) || addrLen (1 byte) || addrBytes || denomBytes + oldStore := prefix.NewStore(store, v040bank.BalancesPrefix) + newStore := prefix.NewStore(store, BalancesPrefix) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key()) + denom := oldStoreIter.Key()[1+v040auth.AddrLen:] + newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...) + + newStore.Set(newStoreKey, oldStoreIter.Value()) // Values don't change. + oldStore.Delete(oldStoreIter.Key()) + } + + return nil +} diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go new file mode 100644 index 000000000000..61f87e8b97e6 --- /dev/null +++ b/x/bank/legacy/v042/store_test.go @@ -0,0 +1,7 @@ +package v042_test + +import "testing" + +func TestStoreMigration(t *testing.T) { + // TODO +} diff --git a/x/bank/legacy/v042/types.go b/x/bank/legacy/v042/types.go new file mode 100644 index 000000000000..22534d31f878 --- /dev/null +++ b/x/bank/legacy/v042/types.go @@ -0,0 +1,5 @@ +package v042 + +const ( + ModuleName = "bank" +) diff --git a/x/bank/module.go b/x/bank/module.go index f271fa21975c..547023bcae39 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -22,6 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/client/rest" "github.com/cosmos/cosmos-sdk/x/bank/keeper" + v042bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" "github.com/cosmos/cosmos-sdk/x/bank/simulation" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -151,6 +152,30 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + // Map of version n -> migrate function from version n to version n+1. + migrationsMap := map[uint64]func(store sdk.KVStore) error{ + 0: v042bank.StoreMigration, + } + + // Run in-place migrations sequentially until current ConsensusVersion. + for i := fromVersion; i < am.ConsensusVersion(); i++ { + migrateFn, found := migrationsMap[i] + if found { + err := migrateFn(ctx.KVStore(storeKey)) + if err != nil { + return err + } + } + } + + return nil +} + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/capability/module.go b/x/capability/module.go index 7957f57747d6..94809d2cbd99 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -136,6 +136,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(genState) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/crisis/module.go b/x/crisis/module.go index 5d34c1ce28f9..dbe1e2c28da4 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -158,6 +158,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/distribution/module.go b/x/distribution/module.go index 034be6d9651d..962345df8900 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -161,6 +161,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the distribution module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/evidence/module.go b/x/evidence/module.go index 4367fe8d58ce..ba6b80933b18 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -175,6 +175,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, am.keeper)) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock executes all ABCI BeginBlock logic respective to the evidence module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/feegrant/module.go b/x/feegrant/module.go index 5f4ba807d895..99fd5c6a12ab 100644 --- a/x/feegrant/module.go +++ b/x/feegrant/module.go @@ -167,6 +167,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the feegrant module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/genutil/module.go b/x/genutil/module.go index bfaeb0c59168..ce59f1f59b7a 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -110,3 +110,11 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data j func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { return am.DefaultGenesis(cdc) } + +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} diff --git a/x/gov/module.go b/x/gov/module.go index ad2191660c08..36d9a1b29dbb 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -177,6 +177,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 67c736555b8a..5762cc765e55 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -145,6 +145,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { } diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go index 3371dc88a446..67f1b276ab55 100644 --- a/x/ibc/core/module.go +++ b/x/ibc/core/module.go @@ -156,6 +156,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, *am.keeper)) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the ibc module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { ibcclient.BeginBlocker(ctx, am.keeper.ClientKeeper) diff --git a/x/mint/module.go b/x/mint/module.go index 44e96ce74bda..aa0ad4a794e7 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -146,6 +146,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the mint module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { BeginBlocker(ctx, am.keeper) diff --git a/x/params/module.go b/x/params/module.go index b0a4584129ef..3b1582a739b9 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -139,6 +139,14 @@ func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.Raw return nil } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/slashing/module.go b/x/slashing/module.go index 91ad472e90df..32ce7cffae97 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -159,6 +159,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the slashing module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/staking/module.go b/x/staking/module.go index f2e422117476..27ee2d4a0044 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -157,6 +157,14 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { BeginBlocker(ctx, am.keeper) diff --git a/x/upgrade/module.go b/x/upgrade/module.go index 4e4982a324cf..03cdaed2ebaa 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -120,6 +120,14 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } +// ConsensusVersion tracks state-breaking versions of the module. +func (AppModule) ConsensusVersion() uint64 { return 0 } + +// MigrateStore performs in-place store migrations. +func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { + return nil +} + // BeginBlock calls the upgrade module hooks // // CONTRACT: this is registered in BeginBlocker *before* all other modules' BeginBlock functions From a9a406ee9a3074f33073b1855ccfe978e86a6ce0 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Tue, 2 Feb 2021 14:53:11 +0100 Subject: [PATCH 02/46] Put migration logic into Configurator --- simapp/app.go | 28 +-------------- types/module/configurator.go | 51 +++++++++++++++++++++++++-- types/module/module.go | 35 +++++++++++++----- x/auth/module.go | 5 --- x/auth/vesting/module.go | 5 --- x/authz/module.go | 5 --- x/bank/module.go | 24 ++----------- x/capability/module.go | 5 --- x/crisis/module.go | 5 --- x/distribution/module.go | 5 --- x/evidence/module.go | 5 --- x/feegrant/module.go | 5 --- x/genutil/module.go | 5 --- x/gov/module.go | 5 --- x/ibc/applications/transfer/module.go | 5 --- x/ibc/core/module.go | 5 --- x/mint/module.go | 5 --- x/params/module.go | 5 --- x/slashing/module.go | 5 --- x/staking/module.go | 5 --- x/upgrade/module.go | 5 --- 21 files changed, 78 insertions(+), 145 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index 9fc5b32dc959..a56c67f32242 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -393,7 +393,7 @@ func NewSimApp( app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) - app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter())) + app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys)) // add test gRPC service for testing gRPC queries in isolation testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{}) @@ -598,32 +598,6 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } -// MigrateStore performs in-place store migrations. This function is not called -// automatically, it is meant to be called from an x/upgrade UpgradeHandler. -// `migrationsMap` is a map of moduleName to fromVersion (unit64), where -// fromVersion denotes the version from which we should migrate the module. -// -// Example: -// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { -// err := app.MigrateStore(ctx, map[string]unint64{ -// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion -// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion -// }) -// if err != nil { -// panic(err) -// } -// }) -func (app *SimApp) MigrateStore(ctx sdk.Context, migrationsMap map[string]uint64) error { - for moduleName, module := range app.mm.Modules { - err := module.MigrateStore(ctx, app.keys[moduleName], migrationsMap[moduleName]) - if err != nil { - return err - } - } - - return nil -} - // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) { statikFS, err := fs.New() diff --git a/types/module/configurator.go b/types/module/configurator.go index d561dd9eef0d..e40c064835ce 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -1,6 +1,10 @@ package module -import "github.com/gogo/protobuf/grpc" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/gogo/protobuf/grpc" +) // Configurator provides the hooks to allow modules to configure and register // their services in the RegisterServices method. It is designed to eventually @@ -15,16 +19,30 @@ type Configurator interface { // QueryServer returns a grpc.Server instance which allows registering services // that will be exposed as gRPC services as well as ABCI query handlers. QueryServer() grpc.Server + + // RegisterMigration registers an in-place store migration for a module. The + // handler is a migration script to perform in-place migrations from version + // `fromVersion` to version `fromVersion+1`. + RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) + + // RunMigration runs all in-place store migrations for a module from a + // given version to another version. + RunMigration(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error } type configurator struct { msgServer grpc.Server queryServer grpc.Server + + // storeKeys is used to access module stores inside in-place store migrations. + storeKeys map[string]*sdk.KVStoreKey + // migrations is a map of moduleName -> fromVersion -> migration script handler + migrations map[string]map[uint64]func(store sdk.KVStore) error } // NewConfigurator returns a new Configurator instance -func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server) Configurator { - return configurator{msgServer: msgServer, queryServer: queryServer} +func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server, storeKeys map[string]*sdk.KVStoreKey) Configurator { + return configurator{msgServer: msgServer, queryServer: queryServer, storeKeys: storeKeys} } var _ Configurator = configurator{} @@ -38,3 +56,30 @@ func (c configurator) MsgServer() grpc.Server { func (c configurator) QueryServer() grpc.Server { return c.queryServer } + +// RegisterMigration implements the Configurator.RegisterMigration method +func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) { + c.migrations[moduleName][fromVersion] = handler +} + +// RunMigration implements the Configurator.RunMigration method +func (c configurator) RunMigration(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { + storeKey, found := c.storeKeys[moduleName] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) + } + + // Run in-place migrations for the module sequentially until toVersion. + for i := fromVersion; i < toVersion; i++ { + migrateFn, found := c.migrations[moduleName][i] + // If no migrations has been registered for this module, we just skip. + if found { + err := migrateFn(ctx.KVStore(storeKey)) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/types/module/module.go b/types/module/module.go index e02a85a66a9e..2216b8c221bd 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -177,9 +177,6 @@ type AppModule interface { // ConsensusVersion tracks state-breaking versions of the module ConsensusVersion() uint64 - // MigrateStore performs in-place store migrations. - MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error - // ABCI BeginBlock(sdk.Context, abci.RequestBeginBlock) EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate @@ -217,11 +214,6 @@ func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {} // ConsensusVersion tracks state-breaking versions of the module. func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (gam GenesisOnlyAppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns an empty module begin-block func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} @@ -342,6 +334,33 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st return genesisData } +// MigrateStore performs in-place store migrations. This function is not called +// automatically, it is meant to be called from an x/upgrade UpgradeHandler. +// `migrationsMap` is a map of moduleName to fromVersion (unit64), where +// fromVersion denotes the version from which we should migrate the module. +// +// Example: +// cfg := module.NewConfigurator(...) +// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { +// err := app.mm.MigrateStore(ctx, cfg, map[string]unint64{ +// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion +// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion +// }) +// if err != nil { +// panic(err) +// } +// }) +func (m Manager) MigrateStore(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { + for moduleName, module := range m.Modules { + err := cfg.RunMigration(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) + if err != nil { + return err + } + } + + return nil +} + // BeginBlock performs begin block functionality for all modules. It creates a // child context with an event manager to aggregate events emitted from all // modules. diff --git a/x/auth/module.go b/x/auth/module.go index 998af5809e97..9ed1138c9ff1 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -150,11 +150,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the auth module. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go index 0e20cc4d800c..06a947721ba8 100644 --- a/x/auth/vesting/module.go +++ b/x/auth/vesting/module.go @@ -130,8 +130,3 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } - -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} diff --git a/x/authz/module.go b/x/authz/module.go index faf1c842604f..a8088656a7b7 100644 --- a/x/authz/module.go +++ b/x/authz/module.go @@ -155,11 +155,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} // EndBlock does nothing diff --git a/x/bank/module.go b/x/bank/module.go index 547023bcae39..0016a5d76438 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -22,7 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/client/rest" "github.com/cosmos/cosmos-sdk/x/bank/keeper" - v042bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" + v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" "github.com/cosmos/cosmos-sdk/x/bank/simulation" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -101,6 +101,7 @@ type AppModule struct { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + cfg.RegisterMigration(types.ModuleName, 0, v042.StoreMigration) } // NewAppModule creates a new AppModule object @@ -155,27 +156,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 1 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - // Map of version n -> migrate function from version n to version n+1. - migrationsMap := map[uint64]func(store sdk.KVStore) error{ - 0: v042bank.StoreMigration, - } - - // Run in-place migrations sequentially until current ConsensusVersion. - for i := fromVersion; i < am.ConsensusVersion(); i++ { - migrateFn, found := migrationsMap[i] - if found { - err := migrateFn(ctx.KVStore(storeKey)) - if err != nil { - return err - } - } - } - - return nil -} - // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/capability/module.go b/x/capability/module.go index 94809d2cbd99..8a1189400c7f 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -139,11 +139,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/crisis/module.go b/x/crisis/module.go index dbe1e2c28da4..4ef39afb4772 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -161,11 +161,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/distribution/module.go b/x/distribution/module.go index 962345df8900..1830d08c583a 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -164,11 +164,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the distribution module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/evidence/module.go b/x/evidence/module.go index ba6b80933b18..7de6a10c4604 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -178,11 +178,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock executes all ABCI BeginBlock logic respective to the evidence module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/feegrant/module.go b/x/feegrant/module.go index 99fd5c6a12ab..b61dd4855436 100644 --- a/x/feegrant/module.go +++ b/x/feegrant/module.go @@ -170,11 +170,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the feegrant module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/genutil/module.go b/x/genutil/module.go index ce59f1f59b7a..09b2f8e5c1b2 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -113,8 +113,3 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } - -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} diff --git a/x/gov/module.go b/x/gov/module.go index 36d9a1b29dbb..0a8ce0c24a7f 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -180,11 +180,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 5762cc765e55..987b73470b4f 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -148,11 +148,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { } diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go index 67f1b276ab55..53c39b508d27 100644 --- a/x/ibc/core/module.go +++ b/x/ibc/core/module.go @@ -159,11 +159,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the ibc module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { ibcclient.BeginBlocker(ctx, am.keeper.ClientKeeper) diff --git a/x/mint/module.go b/x/mint/module.go index aa0ad4a794e7..6f408e6763a7 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -149,11 +149,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the mint module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { BeginBlocker(ctx, am.keeper) diff --git a/x/params/module.go b/x/params/module.go index 3b1582a739b9..4a8f4ff5dcff 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -142,11 +142,6 @@ func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.Raw // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/slashing/module.go b/x/slashing/module.go index 32ce7cffae97..a1cac6ae864f 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -162,11 +162,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the slashing module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/staking/module.go b/x/staking/module.go index 27ee2d4a0044..5a1880055c3d 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -160,11 +160,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { BeginBlocker(ctx, am.keeper) diff --git a/x/upgrade/module.go b/x/upgrade/module.go index 03cdaed2ebaa..268ba817979f 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -123,11 +123,6 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R // ConsensusVersion tracks state-breaking versions of the module. func (AppModule) ConsensusVersion() uint64 { return 0 } -// MigrateStore performs in-place store migrations. -func (am AppModule) MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error { - return nil -} - // BeginBlock calls the upgrade module hooks // // CONTRACT: this is registered in BeginBlocker *before* all other modules' BeginBlock functions From 9ed398766574f0fb0ce87d36c2cf40828e7ce134 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Tue, 2 Feb 2021 16:33:18 +0100 Subject: [PATCH 03/46] add test to bank store migration --- testutil/context.go | 25 ++++++++++++++++++++++++ types/context_test.go | 17 +++------------- types/module/configurator.go | 6 +++--- types/module/module.go | 8 ++++---- x/bank/legacy/v042/store.go | 6 +++--- x/bank/legacy/v042/store_test.go | 33 ++++++++++++++++++++++++++++++-- x/params/keeper/common_test.go | 24 +++-------------------- 7 files changed, 72 insertions(+), 47 deletions(-) create mode 100644 testutil/context.go diff --git a/testutil/context.go b/testutil/context.go new file mode 100644 index 000000000000..b7fd34b686cb --- /dev/null +++ b/testutil/context.go @@ -0,0 +1,25 @@ +package testutil + +import ( + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// DefaultContext creates a sdk.Context that can be used in tests. +func DefaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context { + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db) + err := cms.LoadLatestVersion() + if err != nil { + panic(err) + } + ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) + + return ctx +} diff --git a/types/context_test.go b/types/context_test.go index 018bd6a25792..4af5d8390f2f 100644 --- a/types/context_test.go +++ b/types/context_test.go @@ -8,13 +8,11 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/tests/mocks" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/types" ) @@ -26,15 +24,6 @@ func TestContextTestSuite(t *testing.T) { suite.Run(t, new(contextTestSuite)) } -func (s *contextTestSuite) defaultContext(key types.StoreKey) types.Context { - db := dbm.NewMemDB() - cms := store.NewCommitMultiStore(db) - cms.MountStoreWithDB(key, types.StoreTypeIAVL, db) - s.Require().NoError(cms.LoadLatestVersion()) - ctx := types.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) - return ctx -} - func (s *contextTestSuite) TestCacheContext() { key := types.NewKVStoreKey(s.T().Name() + "_TestCacheContext") k1 := []byte("hello") @@ -42,7 +31,7 @@ func (s *contextTestSuite) TestCacheContext() { k2 := []byte("key") v2 := []byte("value") - ctx := s.defaultContext(key) + ctx := testutil.DefaultContext(key, types.NewTransientStoreKey("transient_"+s.T().Name())) store := ctx.KVStore(key) store.Set(k1, v1) s.Require().Equal(v1, store.Get(k1)) @@ -64,7 +53,7 @@ func (s *contextTestSuite) TestCacheContext() { func (s *contextTestSuite) TestLogContext() { key := types.NewKVStoreKey(s.T().Name()) - ctx := s.defaultContext(key) + ctx := testutil.DefaultContext(key, types.NewTransientStoreKey("transient_"+s.T().Name())) ctrl := gomock.NewController(s.T()) s.T().Cleanup(ctrl.Finish) diff --git a/types/module/configurator.go b/types/module/configurator.go index e40c064835ce..59f43cd8ae22 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -25,9 +25,9 @@ type Configurator interface { // `fromVersion` to version `fromVersion+1`. RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) - // RunMigration runs all in-place store migrations for a module from a + // RunMigrations runs all in-place store migrations for a module from a // given version to another version. - RunMigration(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error + RunMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error } type configurator struct { @@ -63,7 +63,7 @@ func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, h } // RunMigration implements the Configurator.RunMigration method -func (c configurator) RunMigration(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { +func (c configurator) RunMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { storeKey, found := c.storeKeys[moduleName] if !found { return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) diff --git a/types/module/module.go b/types/module/module.go index 2216b8c221bd..6af76d80fdf7 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -334,7 +334,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st return genesisData } -// MigrateStore performs in-place store migrations. This function is not called +// RunMigrations performs in-place store migrations. This function is not called // automatically, it is meant to be called from an x/upgrade UpgradeHandler. // `migrationsMap` is a map of moduleName to fromVersion (unit64), where // fromVersion denotes the version from which we should migrate the module. @@ -342,7 +342,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st // Example: // cfg := module.NewConfigurator(...) // app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { -// err := app.mm.MigrateStore(ctx, cfg, map[string]unint64{ +// err := app.mm.RunMigrations(ctx, cfg, map[string]unint64{ // "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion // "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion // }) @@ -350,9 +350,9 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st // panic(err) // } // }) -func (m Manager) MigrateStore(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { +func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { for moduleName, module := range m.Modules { - err := cfg.RunMigration(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) + err := cfg.RunMigrations(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) if err != nil { return err } diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go index 42665801ea2e..a4e51f28d65e 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -41,17 +41,17 @@ func StoreMigration(store sdk.KVStore) error { // new key is of format // prefix (0x02) || addrLen (1 byte) || addrBytes || denomBytes oldStore := prefix.NewStore(store, v040bank.BalancesPrefix) - newStore := prefix.NewStore(store, BalancesPrefix) oldStoreIter := oldStore.Iterator(nil, nil) defer oldStoreIter.Close() for ; oldStoreIter.Valid(); oldStoreIter.Next() { addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key()) - denom := oldStoreIter.Key()[1+v040auth.AddrLen:] + denom := oldStoreIter.Key()[v040auth.AddrLen:] newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...) - newStore.Set(newStoreKey, oldStoreIter.Value()) // Values don't change. + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) oldStore.Delete(oldStoreIter.Key()) } diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index 61f87e8b97e6..8690291b31a6 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -1,7 +1,36 @@ package v042_test -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" + v042bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" +) func TestStoreMigration(t *testing.T) { - // TODO + bankKey := sdk.NewKVStoreKey("bank") + ctx := testutil.DefaultContext(bankKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(bankKey) + + _, _, addr := testdata.KeyTestPubAddr() + denom := []byte("foo") + value := []byte("bar") + + oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) + store.Set(oldKey, value) + + err := v042bank.StoreMigration(store) + require.NoError(t, err) + + newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) + // -7 because we replaced "balances" with 0x02, + // +1 because we added length-prefix to address. + require.Equal(t, len(oldKey)-7+1, len(newKey)) + require.Nil(t, store.Get(oldKey)) + require.Equal(t, value, store.Get(newKey)) } diff --git a/x/params/keeper/common_test.go b/x/params/keeper/common_test.go index f6d567db11f7..3ba444173588 100644 --- a/x/params/keeper/common_test.go +++ b/x/params/keeper/common_test.go @@ -1,14 +1,9 @@ package keeper_test import ( - "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" ) @@ -18,7 +13,7 @@ func testComponents() (*codec.LegacyAmino, sdk.Context, sdk.StoreKey, sdk.StoreK legacyAmino := createTestCodec() mkey := sdk.NewKVStoreKey("test") tkey := sdk.NewTransientStoreKey("transient_test") - ctx := defaultContext(mkey, tkey) + ctx := testutil.DefaultContext(mkey, tkey) keeper := paramskeeper.NewKeeper(marshaler, legacyAmino, mkey, tkey) return legacyAmino, ctx, mkey, tkey, keeper @@ -37,16 +32,3 @@ func createTestCodec() *codec.LegacyAmino { cdc.RegisterConcrete(invalid{}, "test/invalid", nil) return cdc } - -func defaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context { - db := dbm.NewMemDB() - cms := store.NewCommitMultiStore(db) - cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) - cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db) - err := cms.LoadLatestVersion() - if err != nil { - panic(err) - } - ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) - return ctx -} From a095d3acb11555544e9d4c8c1398c86bb3f819ec Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Tue, 2 Feb 2021 18:21:40 +0100 Subject: [PATCH 04/46] add test for configurator --- simapp/app.go | 29 +++++++++++- simapp/app_test.go | 71 +++++++++++++++++++++++++++++- tests/mocks/types_module_module.go | 3 ++ types/module/configurator.go | 34 ++++++++++++-- types/module/module.go | 17 +------ types/module/module_test.go | 2 +- 6 files changed, 133 insertions(+), 23 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index a56c67f32242..d2b59cf3581c 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -198,6 +198,9 @@ type SimApp struct { // simulation manager sm *module.SimulationManager + + // the configurator + configurator module.Configurator } func init() { @@ -393,7 +396,8 @@ func NewSimApp( app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) - app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys)) + app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) + app.mm.RegisterServices(app.configurator) // add test gRPC service for testing gRPC queries in isolation testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{}) @@ -598,6 +602,29 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } +// RunMigrations performs in-place store migrations for all modules. This +// function is not called automatically, it is meant to be called from an +// x/upgrade UpgradeHandler. +// +// `migrationsMap` is a map of moduleName to fromVersion (unit64), where +// fromVersion denotes the version from which we should migrate the module, the +// target version being the module's latest ConsensusVersion. +// +// Example: +// cfg := module.NewConfigurator(...) +// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { +// err := app.RunMigrations(ctx, map[string]unint64{ +// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion +// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion +// }) +// if err != nil { +// panic(err) +// } +// }) +func (app *SimApp) RunMigrations(ctx sdk.Context, migrationsMap map[string]uint64) error { + return app.mm.RunMigrations(ctx, app.configurator, migrationsMap) +} + // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) { statikFS, err := fs.New() diff --git a/simapp/app_test.go b/simapp/app_test.go index 6543f94fd437..bbd76ba6edcb 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -2,14 +2,18 @@ package simapp import ( "encoding/json" + "fmt" "os" "testing" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - abci "github.com/tendermint/tendermint/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" ) func TestSimAppExportAndBlockedAddrs(t *testing.T) { @@ -45,3 +49,68 @@ func TestGetMaccPerms(t *testing.T) { dup := GetMaccPerms() require.Equal(t, maccPerms, dup, "duplicated module account permissions differed from actual module account permissions") } + +func TestRunMigrations(t *testing.T) { + db := dbm.NewMemDB() + app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, MakeTestEncodingConfig(), EmptyAppOptions{}) + + // Create a new configurator for the purpose of this test. + app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) + + testCases := []struct { + name string + moduleName string + expRegErr bool + expRegErrMsg string + expCalled int + }{ + { + "cannot register migration for non-existant module", + "foo", + true, "store key for module foo not found: not found", 0, + }, + { + "can register and run migration handler for x/bank", + "bank", + false, "", 1, + }, + { + "cannot register migration handler for same module & fromVersion", + "bank", + true, "another migration for module bank and version 0 already exists: internal logic error", 0, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + // Since it's very hard to test in-place store migrations in tests (due + // to the difficulty of maintaing multiple versions of a module), we're + // just testing here that the migration logic is called or not for our + // custom module. + called := 0 + + err := app.configurator.RegisterMigration(tc.moduleName, 0, func(sdk.KVStore) error { + fmt.Println("HELLO") + called++ + + return nil + }) + + if tc.expRegErr { + require.Error(t, err) + require.Equal(t, tc.expRegErrMsg, err.Error()) + + return + } + require.NoError(t, err) + + err = app.RunMigrations( + app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), + map[string]uint64{"bank": 0}, + ) + require.NoError(t, err) + require.Equal(t, tc.expCalled, called) + }) + } +} diff --git a/tests/mocks/types_module_module.go b/tests/mocks/types_module_module.go index 41ded4d7a2c0..e465e115423b 100644 --- a/tests/mocks/types_module_module.go +++ b/tests/mocks/types_module_module.go @@ -492,6 +492,9 @@ func (m *MockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONMarsha return ret0 } +// ConsensusVersion mocks base method +func (m *MockAppModule) ConsensusVersion() uint64 { return 0 } + // ExportGenesis indicates an expected call of ExportGenesis func (mr *MockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() diff --git a/types/module/configurator.go b/types/module/configurator.go index 59f43cd8ae22..eacf8ded7c2b 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -23,7 +23,7 @@ type Configurator interface { // RegisterMigration registers an in-place store migration for a module. The // handler is a migration script to perform in-place migrations from version // `fromVersion` to version `fromVersion+1`. - RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) + RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) error // RunMigrations runs all in-place store migrations for a module from a // given version to another version. @@ -42,7 +42,12 @@ type configurator struct { // NewConfigurator returns a new Configurator instance func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server, storeKeys map[string]*sdk.KVStoreKey) Configurator { - return configurator{msgServer: msgServer, queryServer: queryServer, storeKeys: storeKeys} + return configurator{ + msgServer: msgServer, + queryServer: queryServer, + storeKeys: storeKeys, + migrations: map[string]map[uint64]func(store sdk.KVStore) error{}, + } } var _ Configurator = configurator{} @@ -58,12 +63,33 @@ func (c configurator) QueryServer() grpc.Server { } // RegisterMigration implements the Configurator.RegisterMigration method -func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) { +func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) error { + if c.migrations[moduleName][fromVersion] != nil { + return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, fromVersion) + } + + _, found := c.storeKeys[moduleName] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) + } + + if c.migrations[moduleName] == nil { + c.migrations[moduleName] = map[uint64]func(store sdk.KVStore) error{} + } + c.migrations[moduleName][fromVersion] = handler + + return nil } // RunMigration implements the Configurator.RunMigration method func (c configurator) RunMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { + _, found := c.migrations[moduleName] + if !found { + // If no migrations has been registered for this module, we just skip. + return nil + } + storeKey, found := c.storeKeys[moduleName] if !found { return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) @@ -72,7 +98,7 @@ func (c configurator) RunMigrations(ctx sdk.Context, moduleName string, fromVers // Run in-place migrations for the module sequentially until toVersion. for i := fromVersion; i < toVersion; i++ { migrateFn, found := c.migrations[moduleName][i] - // If no migrations has been registered for this module, we just skip. + // If no migrations has been registered for this version, we just skip. if found { err := migrateFn(ctx.KVStore(storeKey)) if err != nil { diff --git a/types/module/module.go b/types/module/module.go index 6af76d80fdf7..b3172728dbb8 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -334,22 +334,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st return genesisData } -// RunMigrations performs in-place store migrations. This function is not called -// automatically, it is meant to be called from an x/upgrade UpgradeHandler. -// `migrationsMap` is a map of moduleName to fromVersion (unit64), where -// fromVersion denotes the version from which we should migrate the module. -// -// Example: -// cfg := module.NewConfigurator(...) -// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { -// err := app.mm.RunMigrations(ctx, cfg, map[string]unint64{ -// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion -// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion -// }) -// if err != nil { -// panic(err) -// } -// }) +// RunMigrations performs in-place store migrations for all modules. func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { for moduleName, module := range m.Modules { err := cfg.RunMigrations(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) diff --git a/types/module/module_test.go b/types/module/module_test.go index 630c57619245..fa11d7a49603 100644 --- a/types/module/module_test.go +++ b/types/module/module_test.go @@ -179,7 +179,7 @@ func TestManager_RegisterQueryServices(t *testing.T) { msgRouter := mocks.NewMockServer(mockCtrl) queryRouter := mocks.NewMockServer(mockCtrl) - cfg := module.NewConfigurator(msgRouter, queryRouter) + cfg := module.NewConfigurator(msgRouter, queryRouter, nil) mockAppModule1.EXPECT().RegisterServices(cfg).Times(1) mockAppModule2.EXPECT().RegisterServices(cfg).Times(1) From b7141f990988ea994788c1e350e6b334004bd868 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 11:31:23 +0100 Subject: [PATCH 05/46] Error if no migration found --- simapp/app_test.go | 45 +++++++++++++++++++++++------------- types/module/configurator.go | 21 +++++++++-------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index bbd76ba6edcb..88455a272304 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -2,7 +2,6 @@ package simapp import ( "encoding/json" - "fmt" "os" "testing" @@ -60,42 +59,51 @@ func TestRunMigrations(t *testing.T) { testCases := []struct { name string moduleName string - expRegErr bool + expRegErr bool // errors while registering migration expRegErrMsg string + expRunErr bool // errors while running migration + expRunErrMsg string expCalled int }{ { "cannot register migration for non-existant module", "foo", - true, "store key for module foo not found: not found", 0, + true, "store key for module foo not found: not found", false, "", 0, + }, + { + "throws error on RunMigrations if no migration registered for bank", + "", + false, "", true, "no migration found for module bank from version 0 to version 1: not found", 0, }, { "can register and run migration handler for x/bank", "bank", - false, "", 1, + false, "", false, "", 1, }, { "cannot register migration handler for same module & fromVersion", "bank", - true, "another migration for module bank and version 0 already exists: internal logic error", 0, + true, "another migration for module bank and version 0 already exists: internal logic error", false, "", 0, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + var err error - // Since it's very hard to test in-place store migrations in tests (due - // to the difficulty of maintaing multiple versions of a module), we're - // just testing here that the migration logic is called or not for our - // custom module. + // Since it's very hard to test actual in-place store migrations in + // tests (due to the difficulty of maintaing multiple versions of a + // module), we're just testing here that the migration logic is + // called. called := 0 - err := app.configurator.RegisterMigration(tc.moduleName, 0, func(sdk.KVStore) error { - fmt.Println("HELLO") - called++ + if tc.moduleName != "" { + err = app.configurator.RegisterMigration(tc.moduleName, 0, func(sdk.KVStore) error { + called++ - return nil - }) + return nil + }) + } if tc.expRegErr { require.Error(t, err) @@ -109,8 +117,13 @@ func TestRunMigrations(t *testing.T) { app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), map[string]uint64{"bank": 0}, ) - require.NoError(t, err) - require.Equal(t, tc.expCalled, called) + if tc.expRunErr { + require.Error(t, err) + require.Equal(t, tc.expRunErrMsg, err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tc.expCalled, called) + } }) } } diff --git a/types/module/configurator.go b/types/module/configurator.go index eacf8ded7c2b..d53180ccea50 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -84,9 +84,11 @@ func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, h // RunMigration implements the Configurator.RunMigration method func (c configurator) RunMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { - _, found := c.migrations[moduleName] - if !found { - // If no migrations has been registered for this module, we just skip. + // No-op if toVersion is the initial version. + // Some modules don't have a store key (e.g. vesting), in this case, their + // ConsensusVersion will always stay at 0, and running migrations on + // those modules will be skipped on this line. + if toVersion == 0 { return nil } @@ -98,12 +100,13 @@ func (c configurator) RunMigrations(ctx sdk.Context, moduleName string, fromVers // Run in-place migrations for the module sequentially until toVersion. for i := fromVersion; i < toVersion; i++ { migrateFn, found := c.migrations[moduleName][i] - // If no migrations has been registered for this version, we just skip. - if found { - err := migrateFn(ctx.KVStore(storeKey)) - if err != nil { - return err - } + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) + } + + err := migrateFn(ctx.KVStore(storeKey)) + if err != nil { + return err } } From 2d554cefef3be4964a1a15c788075f8ee711d31d Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 11:41:48 +0100 Subject: [PATCH 06/46] Remove RunMigrations from Configurator interface --- types/module/configurator.go | 35 ------------------------------- types/module/module.go | 40 +++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/types/module/configurator.go b/types/module/configurator.go index d53180ccea50..1a18880e3255 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -24,10 +24,6 @@ type Configurator interface { // handler is a migration script to perform in-place migrations from version // `fromVersion` to version `fromVersion+1`. RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) error - - // RunMigrations runs all in-place store migrations for a module from a - // given version to another version. - RunMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error } type configurator struct { @@ -81,34 +77,3 @@ func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, h return nil } - -// RunMigration implements the Configurator.RunMigration method -func (c configurator) RunMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { - // No-op if toVersion is the initial version. - // Some modules don't have a store key (e.g. vesting), in this case, their - // ConsensusVersion will always stay at 0, and running migrations on - // those modules will be skipped on this line. - if toVersion == 0 { - return nil - } - - storeKey, found := c.storeKeys[moduleName] - if !found { - return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) - } - - // Run in-place migrations for the module sequentially until toVersion. - for i := fromVersion; i < toVersion; i++ { - migrateFn, found := c.migrations[moduleName][i] - if !found { - return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) - } - - err := migrateFn(ctx.KVStore(storeKey)) - if err != nil { - return err - } - } - - return nil -} diff --git a/types/module/module.go b/types/module/module.go index b3172728dbb8..8018bb751c42 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -40,6 +40,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) //__________________________________________________________________________________________ @@ -336,8 +337,13 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st // RunMigrations performs in-place store migrations for all modules. func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { + c, ok := cfg.(configurator) + if !ok { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg) + } + for moduleName, module := range m.Modules { - err := cfg.RunMigrations(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) + err := runMigrations(c, ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) if err != nil { return err } @@ -387,3 +393,35 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo Events: ctx.EventManager().ABCIEvents(), } } + +// runMigrations runs all in-place store migrations for one given module from a +// version to another version. +func runMigrations(cfg configurator, ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { + // No-op if toVersion is the initial version. + // Some modules don't have a store key (e.g. vesting), in this case, their + // ConsensusVersion will always stay at 0, and running migrations on + // those modules will be skipped on this line. + if toVersion == 0 { + return nil + } + + storeKey, found := cfg.storeKeys[moduleName] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) + } + + // Run in-place migrations for the module sequentially until toVersion. + for i := fromVersion; i < toVersion; i++ { + migrateFn, found := cfg.migrations[moduleName][i] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) + } + + err := migrateFn(ctx.KVStore(storeKey)) + if err != nil { + return err + } + } + + return nil +} From 3df3f44734ad9b6e115242ff328565e7b1543275 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 11:55:23 +0100 Subject: [PATCH 07/46] Update spec --- x/bank/spec/01_state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/bank/spec/01_state.md b/x/bank/spec/01_state.md index f744e2e779a1..6ca6b97e8fc1 100644 --- a/x/bank/spec/01_state.md +++ b/x/bank/spec/01_state.md @@ -7,5 +7,5 @@ order: 1 The `x/bank` module keeps state of two primary objects, account balances and the total supply of all balances. -- Balances: `[]byte("balances") | []byte(address) / []byte(balance.Denom) -> ProtocolBuffer(balance)` - Supply: `0x0 -> ProtocolBuffer(Supply)` +- Balances: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)` From ba6bd446b8da68cae18d324c07a19f666ac229bd Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 12:04:59 +0100 Subject: [PATCH 08/46] Rename folders --- x/bank/legacy/v040/{store.go => keys.go} | 0 x/bank/legacy/v042/keys.go | 28 ++++++++++++++++++++++++ x/bank/legacy/v042/store.go | 27 ++--------------------- x/bank/legacy/v042/store_test.go | 2 +- x/bank/module.go | 2 +- 5 files changed, 32 insertions(+), 27 deletions(-) rename x/bank/legacy/v040/{store.go => keys.go} (100%) create mode 100644 x/bank/legacy/v042/keys.go diff --git a/x/bank/legacy/v040/store.go b/x/bank/legacy/v040/keys.go similarity index 100% rename from x/bank/legacy/v040/store.go rename to x/bank/legacy/v040/keys.go diff --git a/x/bank/legacy/v042/keys.go b/x/bank/legacy/v042/keys.go new file mode 100644 index 000000000000..1f526f7faffe --- /dev/null +++ b/x/bank/legacy/v042/keys.go @@ -0,0 +1,28 @@ +package v042 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +// KVStore keys +var ( + // BalancesPrefix is the for the account balances store. We use a byte + // (instead of say `[]]byte("balances")` to save some disk space). + BalancesPrefix = []byte{0x02} +) + +// AddressFromBalancesStore returns an account address from a balances prefix +// store. The key must not contain the perfix BalancesPrefix as the prefix store +// iterator discards the actual prefix. +func AddressFromBalancesStore(key []byte) sdk.AccAddress { + addrLen := key[0] + addr := key[1 : addrLen+1] + + return sdk.AccAddress(addr) +} + +// CreateAccountBalancesPrefix creates the prefix for an account's balances. +func CreateAccountBalancesPrefix(addr []byte) []byte { + return append(BalancesPrefix, address.MustLengthPrefix(addr)...) +} diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go index a4e51f28d65e..a83521182088 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -3,39 +3,16 @@ package v042 import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" ) -// KVStore keys -var ( - // BalancesPrefix is the for the account balances store. We use a byte - // (instead of say `[]]byte("balances")` to save some disk space). - BalancesPrefix = []byte{0x02} -) - -// AddressFromBalancesStore returns an account address from a balances prefix -// store. The key must not contain the perfix BalancesPrefix as the prefix store -// iterator discards the actual prefix. -func AddressFromBalancesStore(key []byte) sdk.AccAddress { - addrLen := key[0] - addr := key[1 : addrLen+1] - - return sdk.AccAddress(addr) -} - -// CreateAccountBalancesPrefix creates the prefix for an account's balances. -func CreateAccountBalancesPrefix(addr []byte) []byte { - return append(BalancesPrefix, address.MustLengthPrefix(addr)...) -} - -// StoreMigration performs in-place store migrations from v0.40 to v0.42. The +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The // migration includes: // // - Change addresses to be length-prefixed. // - Change balances prefix to 1 byte -func StoreMigration(store sdk.KVStore) error { +func MigrateStore(store sdk.KVStore) error { // old key is of format: // prefix ("balances") || addrBytes (20 bytes) || denomBytes // new key is of format diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index 8690291b31a6..aeb02485f7f4 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -24,7 +24,7 @@ func TestStoreMigration(t *testing.T) { oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) store.Set(oldKey, value) - err := v042bank.StoreMigration(store) + err := v042bank.MigrateStore(store) require.NoError(t, err) newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) diff --git a/x/bank/module.go b/x/bank/module.go index 0016a5d76438..e68c908ec8a8 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -101,7 +101,7 @@ type AppModule struct { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - cfg.RegisterMigration(types.ModuleName, 0, v042.StoreMigration) + cfg.RegisterMigration(types.ModuleName, 0, v042.MigrateStore) } // NewAppModule creates a new AppModule object From 424932cbf103e926c307696f8b8b49519d09befd Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 15:45:46 +0100 Subject: [PATCH 09/46] copy-paste from keys.go --- x/bank/legacy/v040/keys.go | 24 +++++++++++++++++++++++- x/bank/legacy/v040/types.go | 5 ----- x/bank/legacy/v042/keys.go | 24 +++++++++++++++++++++++- x/bank/legacy/v042/types.go | 5 ----- 4 files changed, 46 insertions(+), 12 deletions(-) delete mode 100644 x/bank/legacy/v040/types.go delete mode 100644 x/bank/legacy/v042/types.go diff --git a/x/bank/legacy/v040/keys.go b/x/bank/legacy/v040/keys.go index 6ff84a34082c..bd1035599164 100644 --- a/x/bank/legacy/v040/keys.go +++ b/x/bank/legacy/v040/keys.go @@ -7,11 +7,33 @@ import ( v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" ) +const ( + // ModuleName defines the module name + ModuleName = "bank" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName +) + // KVStore keys var ( - BalancesPrefix = []byte("balances") + BalancesPrefix = []byte("balances") + SupplyKey = []byte{0x00} + DenomMetadataPrefix = []byte{0x1} ) +// DenomMetadataKey returns the denomination metadata key. +func DenomMetadataKey(denom string) []byte { + d := []byte(denom) + return append(DenomMetadataPrefix, d...) +} + // AddressFromBalancesStore returns an account address from a balances prefix // store. The key must not contain the perfix BalancesPrefix as the prefix store // iterator discards the actual prefix. diff --git a/x/bank/legacy/v040/types.go b/x/bank/legacy/v040/types.go deleted file mode 100644 index 04ac05f9fcd3..000000000000 --- a/x/bank/legacy/v040/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v040 - -const ( - ModuleName = "bank" -) diff --git a/x/bank/legacy/v042/keys.go b/x/bank/legacy/v042/keys.go index 1f526f7faffe..8d718b1c5d3c 100644 --- a/x/bank/legacy/v042/keys.go +++ b/x/bank/legacy/v042/keys.go @@ -5,13 +5,35 @@ import ( "github.com/cosmos/cosmos-sdk/types/address" ) +const ( + // ModuleName defines the module name + ModuleName = "bank" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName +) + // KVStore keys var ( // BalancesPrefix is the for the account balances store. We use a byte // (instead of say `[]]byte("balances")` to save some disk space). - BalancesPrefix = []byte{0x02} + BalancesPrefix = []byte{0x02} + SupplyKey = []byte{0x00} + DenomMetadataPrefix = []byte{0x1} ) +// DenomMetadataKey returns the denomination metadata key. +func DenomMetadataKey(denom string) []byte { + d := []byte(denom) + return append(DenomMetadataPrefix, d...) +} + // AddressFromBalancesStore returns an account address from a balances prefix // store. The key must not contain the perfix BalancesPrefix as the prefix store // iterator discards the actual prefix. diff --git a/x/bank/legacy/v042/types.go b/x/bank/legacy/v042/types.go deleted file mode 100644 index 22534d31f878..000000000000 --- a/x/bank/legacy/v042/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v042 - -const ( - ModuleName = "bank" -) From b6c0714320eddfa625a42e05767e90bf860e5c3e Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 16:00:38 +0100 Subject: [PATCH 10/46] Fix nil map --- types/module/configurator.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/types/module/configurator.go b/types/module/configurator.go index 1a18880e3255..d2dde870026f 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -60,6 +60,10 @@ func (c configurator) QueryServer() grpc.Server { // RegisterMigration implements the Configurator.RegisterMigration method func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) error { + if c.migrations[moduleName] == nil { + c.migrations[moduleName] = map[uint64]func(store sdk.KVStore) error{} + } + if c.migrations[moduleName][fromVersion] != nil { return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, fromVersion) } @@ -69,10 +73,6 @@ func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, h return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) } - if c.migrations[moduleName] == nil { - c.migrations[moduleName] = map[uint64]func(store sdk.KVStore) error{} - } - c.migrations[moduleName][fromVersion] = handler return nil From 9ab7f138c6c8fafad6ee0b9f6da14ea64f63ea9c Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 16:04:11 +0100 Subject: [PATCH 11/46] rename function --- types/module/module.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/module/module.go b/types/module/module.go index 8018bb751c42..e1cf7c56fbca 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -343,7 +343,7 @@ func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap } for moduleName, module := range m.Modules { - err := runMigrations(c, ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) + err := runModuleMigrations(c, ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) if err != nil { return err } @@ -396,7 +396,7 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo // runMigrations runs all in-place store migrations for one given module from a // version to another version. -func runMigrations(cfg configurator, ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { +func runModuleMigrations(cfg configurator, ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { // No-op if toVersion is the initial version. // Some modules don't have a store key (e.g. vesting), in this case, their // ConsensusVersion will always stay at 0, and running migrations on From fc076f5906a7803f9903ef4068e3ca1a3234ae6c Mon Sep 17 00:00:00 2001 From: Amaury Date: Fri, 5 Feb 2021 16:11:13 +0100 Subject: [PATCH 12/46] Update simapp/app.go Co-authored-by: Robert Zaremba --- simapp/app.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index d2b59cf3581c..eec692e982e0 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -603,8 +603,7 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { } // RunMigrations performs in-place store migrations for all modules. This -// function is not called automatically, it is meant to be called from an -// x/upgrade UpgradeHandler. +// function MUST be only called by x/upgrade UpgradeHandler. // // `migrationsMap` is a map of moduleName to fromVersion (unit64), where // fromVersion denotes the version from which we should migrate the module, the From ae7b7dcf3b87eb683182b27cc05485d12d3e8187 Mon Sep 17 00:00:00 2001 From: Amaury Date: Fri, 5 Feb 2021 16:11:23 +0100 Subject: [PATCH 13/46] Update simapp/app_test.go Co-authored-by: Robert Zaremba --- simapp/app_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 88455a272304..371bfce7cdf6 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -103,13 +103,9 @@ func TestRunMigrations(t *testing.T) { return nil }) - } - if tc.expRegErr { - require.Error(t, err) - require.Equal(t, tc.expRegErrMsg, err.Error()) - - return + assert.ErrorEqual(t, err, tc.expRegErrMsg) + } } require.NoError(t, err) From 2c26734678b9dbee5ca57b71a1a864eaca26ebbb Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 14:38:55 +0100 Subject: [PATCH 14/46] Adderss reviews --- simapp/app.go | 2 +- simapp/app_test.go | 8 +++-- types/module/configurator.go | 50 +++++++++++++++++++++++++++----- types/module/module.go | 41 +++++--------------------- x/bank/legacy/v042/store.go | 5 +++- x/bank/legacy/v042/store_test.go | 2 +- 6 files changed, 62 insertions(+), 46 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index d2b59cf3581c..eefbe0496f21 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -396,7 +396,7 @@ func NewSimApp( app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) - app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) + app.configurator = module.NewConfigurator(app.AppCodec(), app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) app.mm.RegisterServices(app.configurator) // add test gRPC service for testing gRPC queries in isolation diff --git a/simapp/app_test.go b/simapp/app_test.go index 88455a272304..9fd00f339e02 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -11,6 +11,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" ) @@ -51,10 +52,11 @@ func TestGetMaccPerms(t *testing.T) { func TestRunMigrations(t *testing.T) { db := dbm.NewMemDB() - app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, MakeTestEncodingConfig(), EmptyAppOptions{}) + encCfg := MakeTestEncodingConfig() + app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) // Create a new configurator for the purpose of this test. - app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) + app.configurator = module.NewConfigurator(encCfg.Marshaler, app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) testCases := []struct { name string @@ -98,7 +100,7 @@ func TestRunMigrations(t *testing.T) { called := 0 if tc.moduleName != "" { - err = app.configurator.RegisterMigration(tc.moduleName, 0, func(sdk.KVStore) error { + err = app.configurator.RegisterMigration(tc.moduleName, 0, func(sdk.Context, sdk.StoreKey, codec.Marshaler) error { called++ return nil diff --git a/types/module/configurator.go b/types/module/configurator.go index d2dde870026f..15c50c1465e7 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -1,9 +1,11 @@ package module import ( + "github.com/gogo/protobuf/grpc" + + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/gogo/protobuf/grpc" ) // Configurator provides the hooks to allow modules to configure and register @@ -23,26 +25,28 @@ type Configurator interface { // RegisterMigration registers an in-place store migration for a module. The // handler is a migration script to perform in-place migrations from version // `fromVersion` to version `fromVersion+1`. - RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) error + RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error } type configurator struct { + cdc codec.Marshaler msgServer grpc.Server queryServer grpc.Server // storeKeys is used to access module stores inside in-place store migrations. storeKeys map[string]*sdk.KVStoreKey // migrations is a map of moduleName -> fromVersion -> migration script handler - migrations map[string]map[uint64]func(store sdk.KVStore) error + migrations map[string]map[uint64]MigrationHandler } // NewConfigurator returns a new Configurator instance -func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server, storeKeys map[string]*sdk.KVStoreKey) Configurator { +func NewConfigurator(cdc codec.Marshaler, msgServer grpc.Server, queryServer grpc.Server, storeKeys map[string]*sdk.KVStoreKey) Configurator { return configurator{ + cdc: cdc, msgServer: msgServer, queryServer: queryServer, storeKeys: storeKeys, - migrations: map[string]map[uint64]func(store sdk.KVStore) error{}, + migrations: map[string]map[uint64]MigrationHandler{}, } } @@ -59,9 +63,9 @@ func (c configurator) QueryServer() grpc.Server { } // RegisterMigration implements the Configurator.RegisterMigration method -func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler func(store sdk.KVStore) error) error { +func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error { if c.migrations[moduleName] == nil { - c.migrations[moduleName] = map[uint64]func(store sdk.KVStore) error{} + c.migrations[moduleName] = map[uint64]MigrationHandler{} } if c.migrations[moduleName][fromVersion] != nil { @@ -77,3 +81,35 @@ func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, h return nil } + +// runModuleMigrations runs all in-place store migrations for one given module from a +// version to another version. +func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { + // No-op if toVersion is the initial version. + // Some modules don't have a store key (e.g. vesting), in this case, their + // ConsensusVersion will always stay at 0, and running migrations on + // those modules will be skipped on this line. + if toVersion == 0 { + return nil + } + + storeKey, found := c.storeKeys[moduleName] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) + } + + // Run in-place migrations for the module sequentially until toVersion. + for i := fromVersion; i < toVersion; i++ { + migrateFn, found := c.migrations[moduleName][i] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) + } + + err := migrateFn(ctx, storeKey, c.cdc) + if err != nil { + return err + } + } + + return nil +} diff --git a/types/module/module.go b/types/module/module.go index e1cf7c56fbca..4e3308204b47 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -335,6 +335,13 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st return genesisData } +// MigrationHandler is the migration function that each module registers. +type MigrationHandler func(store sdk.Context, storeKey sdk.StoreKey, cdc codec.Marshaler) error + +// MigrationMap is a map of moduleName -> version, where version denotes the +// version from which we should perform the migration for each module. +type MigrationMap map[string]uint64 + // RunMigrations performs in-place store migrations for all modules. func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { c, ok := cfg.(configurator) @@ -343,7 +350,7 @@ func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap } for moduleName, module := range m.Modules { - err := runModuleMigrations(c, ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) + err := c.runModuleMigrations(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) if err != nil { return err } @@ -393,35 +400,3 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo Events: ctx.EventManager().ABCIEvents(), } } - -// runMigrations runs all in-place store migrations for one given module from a -// version to another version. -func runModuleMigrations(cfg configurator, ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { - // No-op if toVersion is the initial version. - // Some modules don't have a store key (e.g. vesting), in this case, their - // ConsensusVersion will always stay at 0, and running migrations on - // those modules will be skipped on this line. - if toVersion == 0 { - return nil - } - - storeKey, found := cfg.storeKeys[moduleName] - if !found { - return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) - } - - // Run in-place migrations for the module sequentially until toVersion. - for i := fromVersion; i < toVersion; i++ { - migrateFn, found := cfg.migrations[moduleName][i] - if !found { - return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) - } - - err := migrateFn(ctx.KVStore(storeKey)) - if err != nil { - return err - } - } - - return nil -} diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go index a83521182088..4511ba6159fc 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -1,6 +1,7 @@ package v042 import ( + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" @@ -12,7 +13,9 @@ import ( // // - Change addresses to be length-prefixed. // - Change balances prefix to 1 byte -func MigrateStore(store sdk.KVStore) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { + store := ctx.KVStore(storeKey) + // old key is of format: // prefix ("balances") || addrBytes (20 bytes) || denomBytes // new key is of format diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index aeb02485f7f4..19067497b2be 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -24,7 +24,7 @@ func TestStoreMigration(t *testing.T) { oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) store.Set(oldKey, value) - err := v042bank.MigrateStore(store) + err := v042bank.MigrateStore(ctx, bankKey, nil) require.NoError(t, err) newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) From 291a9e6bd45d49ed21d6f9299bf46fc3dfc016ee Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 14:40:54 +0100 Subject: [PATCH 15/46] Fix tests --- simapp/app_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 4445abf6f9c1..3d81bc691469 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -105,9 +105,9 @@ func TestRunMigrations(t *testing.T) { return nil }) - if tc.expRegErr { - assert.ErrorEqual(t, err, tc.expRegErrMsg) - } + if tc.expRegErr { + require.EqualError(t, err, tc.expRegErrMsg) + } } require.NoError(t, err) @@ -116,8 +116,7 @@ func TestRunMigrations(t *testing.T) { map[string]uint64{"bank": 0}, ) if tc.expRunErr { - require.Error(t, err) - require.Equal(t, tc.expRunErrMsg, err.Error()) + require.EqualError(t, err, tc.expRunErrMsg) } else { require.NoError(t, err) require.Equal(t, tc.expCalled, called) From 41d29ed7a4231597603ce4b9d4236418a7c7d071 Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 8 Feb 2021 14:41:31 +0100 Subject: [PATCH 16/46] Update testutil/context.go Co-authored-by: Robert Zaremba --- testutil/context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testutil/context.go b/testutil/context.go index b7fd34b686cb..2fb9865a2696 100644 --- a/testutil/context.go +++ b/testutil/context.go @@ -9,7 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// DefaultContext creates a sdk.Context that can be used in tests. +// DefaultContext creates a sdk.Context with a fresh MemDB that can be used in tests. func DefaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context { db := dbm.NewMemDB() cms := store.NewCommitMultiStore(db) From 33494dcdb89f970def4979b2a98d5e44b6e68bf6 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 14:47:10 +0100 Subject: [PATCH 17/46] Update docs for ConsensusVersion --- types/module/module.go | 10 ++++++++-- types/module/module_test.go | 4 +++- x/auth/module.go | 7 +++++-- x/auth/vesting/module.go | 7 +++++-- x/authz/module.go | 7 +++++-- x/bank/module.go | 7 +++++-- x/capability/module.go | 7 +++++-- x/crisis/module.go | 7 +++++-- x/distribution/module.go | 7 +++++-- x/evidence/module.go | 7 +++++-- x/feegrant/module.go | 7 +++++-- x/genutil/module.go | 7 +++++-- x/gov/module.go | 7 +++++-- x/ibc/applications/transfer/module.go | 7 +++++-- x/ibc/core/module.go | 7 +++++-- x/mint/module.go | 7 +++++-- x/params/module.go | 7 +++++-- x/slashing/module.go | 7 +++++-- x/staking/module.go | 7 +++++-- x/upgrade/module.go | 7 +++++-- 20 files changed, 101 insertions(+), 39 deletions(-) diff --git a/types/module/module.go b/types/module/module.go index 4e3308204b47..26a2972c93c3 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -175,7 +175,10 @@ type AppModule interface { // RegisterServices allows a module to register services RegisterServices(Configurator) - // ConsensusVersion tracks state-breaking versions of the module + // ConsensusVersion is a sequence number for state-breaking change of the + // module. It should be incremented on each consensus-breaking change + // introduced by the module. To avoid wrong/empty versions, the initial version + // is set to 1. ConsensusVersion() uint64 // ABCI @@ -212,7 +215,10 @@ func (gam GenesisOnlyAppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Que // RegisterServices registers all services. func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {} -// ConsensusVersion tracks state-breaking versions of the module. +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 0 } // BeginBlock returns an empty module begin-block diff --git a/types/module/module_test.go b/types/module/module_test.go index fa11d7a49603..9dafb37566c2 100644 --- a/types/module/module_test.go +++ b/types/module/module_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/golang/mock/gomock" "github.com/gorilla/mux" @@ -168,6 +169,7 @@ func TestManager_RegisterRoutes(t *testing.T) { func TestManager_RegisterQueryServices(t *testing.T) { mockCtrl := gomock.NewController(t) t.Cleanup(mockCtrl.Finish) + encCfg := simapp.MakeTestEncodingConfig() mockAppModule1 := mocks.NewMockAppModule(mockCtrl) mockAppModule2 := mocks.NewMockAppModule(mockCtrl) @@ -179,7 +181,7 @@ func TestManager_RegisterQueryServices(t *testing.T) { msgRouter := mocks.NewMockServer(mockCtrl) queryRouter := mocks.NewMockServer(mockCtrl) - cfg := module.NewConfigurator(msgRouter, queryRouter, nil) + cfg := module.NewConfigurator(encCfg.Marshaler, msgRouter, queryRouter, nil) mockAppModule1.EXPECT().RegisterServices(cfg).Times(1) mockAppModule2.EXPECT().RegisterServices(cfg).Times(1) diff --git a/x/auth/module.go b/x/auth/module.go index 9ed1138c9ff1..338ee70e7ccb 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -147,8 +147,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the auth module. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go index 06a947721ba8..ecc5a77baf5a 100644 --- a/x/auth/vesting/module.go +++ b/x/auth/vesting/module.go @@ -128,5 +128,8 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/authz/module.go b/x/authz/module.go index a8088656a7b7..c94aaa871f4a 100644 --- a/x/authz/module.go +++ b/x/authz/module.go @@ -152,8 +152,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} diff --git a/x/bank/module.go b/x/bank/module.go index e68c908ec8a8..8e7b11070da5 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -153,8 +153,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 1 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/capability/module.go b/x/capability/module.go index 8a1189400c7f..e9a17d9b2dbf 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -136,8 +136,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(genState) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/crisis/module.go b/x/crisis/module.go index 4ef39afb4772..ca41e9bc08de 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -158,8 +158,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/distribution/module.go b/x/distribution/module.go index 1830d08c583a..658781b103cf 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -161,8 +161,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the distribution module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/evidence/module.go b/x/evidence/module.go index 7de6a10c4604..d72a693a1277 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -175,8 +175,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, am.keeper)) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock executes all ABCI BeginBlock logic respective to the evidence module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/feegrant/module.go b/x/feegrant/module.go index b61dd4855436..4a222b3cee09 100644 --- a/x/feegrant/module.go +++ b/x/feegrant/module.go @@ -167,8 +167,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the feegrant module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/genutil/module.go b/x/genutil/module.go index 09b2f8e5c1b2..becca6a950c4 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -111,5 +111,8 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/gov/module.go b/x/gov/module.go index 0a8ce0c24a7f..f47fe91ff3ed 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -177,8 +177,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 987b73470b4f..74ff5e57b339 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -145,8 +145,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go index 53c39b508d27..f2b2318771c8 100644 --- a/x/ibc/core/module.go +++ b/x/ibc/core/module.go @@ -156,8 +156,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, *am.keeper)) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the ibc module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/mint/module.go b/x/mint/module.go index 6f408e6763a7..cf9e5e8999ff 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -146,8 +146,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the mint module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/params/module.go b/x/params/module.go index 4a8f4ff5dcff..88205c65f4af 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -139,8 +139,11 @@ func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.Raw return nil } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/slashing/module.go b/x/slashing/module.go index a1cac6ae864f..52c78a626231 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -159,8 +159,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the slashing module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/staking/module.go b/x/staking/module.go index 5a1880055c3d..0ec94958a299 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -157,8 +157,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/upgrade/module.go b/x/upgrade/module.go index 268ba817979f..ccf7b077e65e 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -120,8 +120,11 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } -// ConsensusVersion tracks state-breaking versions of the module. -func (AppModule) ConsensusVersion() uint64 { return 0 } +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// is set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock calls the upgrade module hooks // From e3a241226a79d64a5cdfd4776e3bec72e0e2c312 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 14:50:34 +0100 Subject: [PATCH 18/46] Rename to forVersion --- simapp/app_test.go | 18 ++++++++++++------ types/module/configurator.go | 22 +++++++++++++--------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 3d81bc691469..3be13a14f8f2 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -61,6 +61,7 @@ func TestRunMigrations(t *testing.T) { testCases := []struct { name string moduleName string + forVersion uint64 expRegErr bool // errors while registering migration expRegErrMsg string expRunErr bool // errors while running migration @@ -69,22 +70,27 @@ func TestRunMigrations(t *testing.T) { }{ { "cannot register migration for non-existant module", - "foo", + "foo", 0, + true, "store key for module foo not found: not found", false, "", 0, + }, + { + "cannot register migration for version 0", + "foo", 1, true, "store key for module foo not found: not found", false, "", 0, }, { "throws error on RunMigrations if no migration registered for bank", - "", + "", 1, false, "", true, "no migration found for module bank from version 0 to version 1: not found", 0, }, { "can register and run migration handler for x/bank", - "bank", + "bank", 1, false, "", false, "", 1, }, { - "cannot register migration handler for same module & fromVersion", - "bank", + "cannot register migration handler for same module & forVersion", + "bank", 1, true, "another migration for module bank and version 0 already exists: internal logic error", false, "", 0, }, } @@ -100,7 +106,7 @@ func TestRunMigrations(t *testing.T) { called := 0 if tc.moduleName != "" { - err = app.configurator.RegisterMigration(tc.moduleName, 0, func(sdk.Context, sdk.StoreKey, codec.Marshaler) error { + err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context, sdk.StoreKey, codec.Marshaler) error { called++ return nil diff --git a/types/module/configurator.go b/types/module/configurator.go index 15c50c1465e7..a096cacf9564 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -24,8 +24,8 @@ type Configurator interface { // RegisterMigration registers an in-place store migration for a module. The // handler is a migration script to perform in-place migrations from version - // `fromVersion` to version `fromVersion+1`. - RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error + // `forVersion` to version `forVersion+1`. + RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error } type configurator struct { @@ -35,7 +35,7 @@ type configurator struct { // storeKeys is used to access module stores inside in-place store migrations. storeKeys map[string]*sdk.KVStoreKey - // migrations is a map of moduleName -> fromVersion -> migration script handler + // migrations is a map of moduleName -> forVersion -> migration script handler migrations map[string]map[uint64]MigrationHandler } @@ -63,13 +63,17 @@ func (c configurator) QueryServer() grpc.Server { } // RegisterMigration implements the Configurator.RegisterMigration method -func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error { +func (c configurator) RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error { + if forVersion == 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "module migration versions should start at 1") + } + if c.migrations[moduleName] == nil { c.migrations[moduleName] = map[uint64]MigrationHandler{} } - if c.migrations[moduleName][fromVersion] != nil { - return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, fromVersion) + if c.migrations[moduleName][forVersion] != nil { + return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, forVersion) } _, found := c.storeKeys[moduleName] @@ -77,14 +81,14 @@ func (c configurator) RegisterMigration(moduleName string, fromVersion uint64, h return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) } - c.migrations[moduleName][fromVersion] = handler + c.migrations[moduleName][forVersion] = handler return nil } // runModuleMigrations runs all in-place store migrations for one given module from a // version to another version. -func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { +func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, forVersion, toVersion uint64) error { // No-op if toVersion is the initial version. // Some modules don't have a store key (e.g. vesting), in this case, their // ConsensusVersion will always stay at 0, and running migrations on @@ -99,7 +103,7 @@ func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fr } // Run in-place migrations for the module sequentially until toVersion. - for i := fromVersion; i < toVersion; i++ { + for i := forVersion; i < toVersion; i++ { migrateFn, found := c.migrations[moduleName][i] if !found { return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) From 55f547e9f3658b49b02855119ce16bae8d089eeb Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 15:15:29 +0100 Subject: [PATCH 19/46] Fix tests --- simapp/app.go | 4 ++-- simapp/app_test.go | 20 ++++++++++++++------ types/module/configurator.go | 6 +++--- types/module/module.go | 4 ++-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index 511d93a4036e..444e2007a95b 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -612,7 +612,7 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { // Example: // cfg := module.NewConfigurator(...) // app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { -// err := app.RunMigrations(ctx, map[string]unint64{ +// err := app.RunMigrations(ctx, module.MigrationMap{ // "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion // "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion // }) @@ -620,7 +620,7 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { // panic(err) // } // }) -func (app *SimApp) RunMigrations(ctx sdk.Context, migrationsMap map[string]uint64) error { +func (app *SimApp) RunMigrations(ctx sdk.Context, migrationsMap module.MigrationMap) error { return app.mm.RunMigrations(ctx, app.configurator, migrationsMap) } diff --git a/simapp/app_test.go b/simapp/app_test.go index 3be13a14f8f2..55799ddc62f5 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -70,18 +70,18 @@ func TestRunMigrations(t *testing.T) { }{ { "cannot register migration for non-existant module", - "foo", 0, + "foo", 1, true, "store key for module foo not found: not found", false, "", 0, }, { "cannot register migration for version 0", - "foo", 1, - true, "store key for module foo not found: not found", false, "", 0, + "bank", 0, + true, "module migration versions should start at 1: invalid version", false, "", 0, }, { "throws error on RunMigrations if no migration registered for bank", "", 1, - false, "", true, "no migration found for module bank from version 0 to version 1: not found", 0, + false, "", true, "no migration found for module bank from version 1 to version 2: not found", 0, }, { "can register and run migration handler for x/bank", @@ -91,7 +91,7 @@ func TestRunMigrations(t *testing.T) { { "cannot register migration handler for same module & forVersion", "bank", 1, - true, "another migration for module bank and version 0 already exists: internal logic error", false, "", 0, + true, "another migration for module bank and version 1 already exists: internal logic error", false, "", 0, }, } @@ -106,20 +106,28 @@ func TestRunMigrations(t *testing.T) { called := 0 if tc.moduleName != "" { + // Register migration for module from version `forVersion` to `forVersion+1`. err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context, sdk.StoreKey, codec.Marshaler) error { called++ return nil }) + if tc.expRegErr { require.EqualError(t, err, tc.expRegErrMsg) + + return } } require.NoError(t, err) err = app.RunMigrations( app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), - map[string]uint64{"bank": 0}, + module.MigrationMap{ + "auth": 1, "authz": 1, "bank": 1, "staking": 1, "mint": 1, "distribution": 1, + "slashing": 1, "gov": 1, "params": 1, "ibc": 1, "upgrade": 1, "vesting": 1, + "feegrant": 1, "transfer": 1, "evidence": 1, "crisis": 1, "genutil": 1, "capability": 1, + }, ) if tc.expRunErr { require.EqualError(t, err, tc.expRunErrMsg) diff --git a/types/module/configurator.go b/types/module/configurator.go index a096cacf9564..f6fba83a6115 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -88,12 +88,12 @@ func (c configurator) RegisterMigration(moduleName string, forVersion uint64, ha // runModuleMigrations runs all in-place store migrations for one given module from a // version to another version. -func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, forVersion, toVersion uint64) error { +func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { // No-op if toVersion is the initial version. // Some modules don't have a store key (e.g. vesting), in this case, their // ConsensusVersion will always stay at 0, and running migrations on // those modules will be skipped on this line. - if toVersion == 0 { + if toVersion <= 1 { return nil } @@ -103,7 +103,7 @@ func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fo } // Run in-place migrations for the module sequentially until toVersion. - for i := forVersion; i < toVersion; i++ { + for i := fromVersion; i < toVersion; i++ { migrateFn, found := c.migrations[moduleName][i] if !found { return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) diff --git a/types/module/module.go b/types/module/module.go index 26a2972c93c3..91ecec90741e 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -349,14 +349,14 @@ type MigrationHandler func(store sdk.Context, storeKey sdk.StoreKey, cdc codec.M type MigrationMap map[string]uint64 // RunMigrations performs in-place store migrations for all modules. -func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationsMap map[string]uint64) error { +func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationMap MigrationMap) error { c, ok := cfg.(configurator) if !ok { return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg) } for moduleName, module := range m.Modules { - err := c.runModuleMigrations(ctx, moduleName, migrationsMap[moduleName], module.ConsensusVersion()) + err := c.runModuleMigrations(ctx, moduleName, migrationMap[moduleName], module.ConsensusVersion()) if err != nil { return err } From 8f3b9d4e10b0c17ea1bbdd8346d2fb98377c9b00 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 15:19:15 +0100 Subject: [PATCH 20/46] Check error early --- simapp/app_test.go | 2 +- types/module/configurator.go | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 55799ddc62f5..768c00a7394a 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -81,7 +81,7 @@ func TestRunMigrations(t *testing.T) { { "throws error on RunMigrations if no migration registered for bank", "", 1, - false, "", true, "no migration found for module bank from version 1 to version 2: not found", 0, + false, "", true, "no migrations found for module bank: not found", 0, }, { "can register and run migration handler for x/bank", diff --git a/types/module/configurator.go b/types/module/configurator.go index f6fba83a6115..e1e856c6d337 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -91,7 +91,7 @@ func (c configurator) RegisterMigration(moduleName string, forVersion uint64, ha func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { // No-op if toVersion is the initial version. // Some modules don't have a store key (e.g. vesting), in this case, their - // ConsensusVersion will always stay at 0, and running migrations on + // ConsensusVersion will always stay at 1, and running migrations on // those modules will be skipped on this line. if toVersion <= 1 { return nil @@ -102,9 +102,14 @@ func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fr return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) } + moduleMigrationsMap, found := c.migrations[moduleName] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migrations found for module %s", moduleName) + } + // Run in-place migrations for the module sequentially until toVersion. for i := fromVersion; i < toVersion; i++ { - migrateFn, found := c.migrations[moduleName][i] + migrateFn, found := moduleMigrationsMap[i] if !found { return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) } From 29b85b7a63b02a0fea2d5a40d7b283d9f43aa854 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 15:20:08 +0100 Subject: [PATCH 21/46] Return 1 for intiial version --- tests/mocks/types_module_module.go | 2 +- types/module/module.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/mocks/types_module_module.go b/tests/mocks/types_module_module.go index e465e115423b..0d00584ab9a8 100644 --- a/tests/mocks/types_module_module.go +++ b/tests/mocks/types_module_module.go @@ -493,7 +493,7 @@ func (m *MockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONMarsha } // ConsensusVersion mocks base method -func (m *MockAppModule) ConsensusVersion() uint64 { return 0 } +func (m *MockAppModule) ConsensusVersion() uint64 { return 1 } // ExportGenesis indicates an expected call of ExportGenesis func (mr *MockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call { diff --git a/types/module/module.go b/types/module/module.go index 91ecec90741e..3733892a247a 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -219,7 +219,7 @@ func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {} // module. It should be incremented on each consensus-breaking change // introduced by the module. To avoid wrong/empty versions, the initial version // is set to 1. -func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 0 } +func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns an empty module begin-block func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} From 41e0339b8256ac99f348ea7825b000b0895f1c67 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 10 Feb 2021 16:21:37 +0100 Subject: [PATCH 22/46] Use MigrationKeeper --- simapp/app_test.go | 8 +------- types/module/configurator.go | 15 +-------------- types/module/module.go | 2 +- x/bank/keeper/migrations.go | 20 ++++++++++++++++++++ x/bank/legacy/v042/store.go | 3 +-- x/bank/module.go | 5 +++-- 6 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 x/bank/keeper/migrations.go diff --git a/simapp/app_test.go b/simapp/app_test.go index 768c00a7394a..aeabe3132f44 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -11,7 +11,6 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" ) @@ -68,11 +67,6 @@ func TestRunMigrations(t *testing.T) { expRunErrMsg string expCalled int }{ - { - "cannot register migration for non-existant module", - "foo", 1, - true, "store key for module foo not found: not found", false, "", 0, - }, { "cannot register migration for version 0", "bank", 0, @@ -107,7 +101,7 @@ func TestRunMigrations(t *testing.T) { if tc.moduleName != "" { // Register migration for module from version `forVersion` to `forVersion+1`. - err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context, sdk.StoreKey, codec.Marshaler) error { + err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context) error { called++ return nil diff --git a/types/module/configurator.go b/types/module/configurator.go index e1e856c6d337..a2de025836e3 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -33,8 +33,6 @@ type configurator struct { msgServer grpc.Server queryServer grpc.Server - // storeKeys is used to access module stores inside in-place store migrations. - storeKeys map[string]*sdk.KVStoreKey // migrations is a map of moduleName -> forVersion -> migration script handler migrations map[string]map[uint64]MigrationHandler } @@ -45,7 +43,6 @@ func NewConfigurator(cdc codec.Marshaler, msgServer grpc.Server, queryServer grp cdc: cdc, msgServer: msgServer, queryServer: queryServer, - storeKeys: storeKeys, migrations: map[string]map[uint64]MigrationHandler{}, } } @@ -76,11 +73,6 @@ func (c configurator) RegisterMigration(moduleName string, forVersion uint64, ha return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, forVersion) } - _, found := c.storeKeys[moduleName] - if !found { - return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) - } - c.migrations[moduleName][forVersion] = handler return nil @@ -97,11 +89,6 @@ func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fr return nil } - storeKey, found := c.storeKeys[moduleName] - if !found { - return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "store key for module %s not found", moduleName) - } - moduleMigrationsMap, found := c.migrations[moduleName] if !found { return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migrations found for module %s", moduleName) @@ -114,7 +101,7 @@ func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fr return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) } - err := migrateFn(ctx, storeKey, c.cdc) + err := migrateFn(ctx) if err != nil { return err } diff --git a/types/module/module.go b/types/module/module.go index 3733892a247a..64e7a68d8406 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -342,7 +342,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st } // MigrationHandler is the migration function that each module registers. -type MigrationHandler func(store sdk.Context, storeKey sdk.StoreKey, cdc codec.Marshaler) error +type MigrationHandler func(store sdk.Context) error // MigrationMap is a map of moduleName -> version, where version denotes the // version from which we should perform the migration for each module. diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go new file mode 100644 index 000000000000..de6b61a9c2b6 --- /dev/null +++ b/x/bank/keeper/migrations.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" +) + +// MigrationKeeper is an interface that the keeper implements for handling +// in-place store migrations. +type MigrationKeeper interface { + // Migrate1 migrates the store from version 1 to 2. + Migrate1(ctx sdk.Context) error +} + +var _ MigrationKeeper = (*BaseKeeper)(nil) + +// Migrate1 implements MigrationKeeper.Migrate1 method. +func (keeper BaseKeeper) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, keeper.storeKey) +} diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go index 4511ba6159fc..9295d8d2ff77 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -1,7 +1,6 @@ package v042 import ( - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" @@ -13,7 +12,7 @@ import ( // // - Change addresses to be length-prefixed. // - Change balances prefix to 1 byte -func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) // old key is of format: diff --git a/x/bank/module.go b/x/bank/module.go index 8e7b11070da5..e1a1a3adbf0b 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -22,7 +22,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/client/rest" "github.com/cosmos/cosmos-sdk/x/bank/keeper" - v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" "github.com/cosmos/cosmos-sdk/x/bank/simulation" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -101,7 +100,9 @@ type AppModule struct { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - cfg.RegisterMigration(types.ModuleName, 0, v042.MigrateStore) + cfg.RegisterMigration(types.ModuleName, 0, func(ctx sdk.Context) error { + return am.keeper.(keeper.MigrationKeeper).Migrate1(ctx) + }) } // NewAppModule creates a new AppModule object From d9220031d8953ad01178108cf4d796705093ce74 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 10 Feb 2021 16:23:15 +0100 Subject: [PATCH 23/46] Fix test --- x/bank/legacy/v042/store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index 19067497b2be..e1b6a7987a04 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -24,7 +24,7 @@ func TestStoreMigration(t *testing.T) { oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) store.Set(oldKey, value) - err := v042bank.MigrateStore(ctx, bankKey, nil) + err := v042bank.MigrateStore(ctx, bankKey) require.NoError(t, err) newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) From f422b93afc40bdb055af3b628f78b72bbe86f3e6 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 10 Feb 2021 16:27:44 +0100 Subject: [PATCH 24/46] Revert adding marshaler to Configurator --- simapp/app.go | 2 +- simapp/app_test.go | 2 +- types/module/configurator.go | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index 444e2007a95b..688aa429fd7b 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -396,7 +396,7 @@ func NewSimApp( app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) - app.configurator = module.NewConfigurator(app.AppCodec(), app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) + app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) app.mm.RegisterServices(app.configurator) // add test gRPC service for testing gRPC queries in isolation diff --git a/simapp/app_test.go b/simapp/app_test.go index aeabe3132f44..2adcf2e7e8d2 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -55,7 +55,7 @@ func TestRunMigrations(t *testing.T) { app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) // Create a new configurator for the purpose of this test. - app.configurator = module.NewConfigurator(encCfg.Marshaler, app.MsgServiceRouter(), app.GRPCQueryRouter(), app.keys) + app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) testCases := []struct { name string diff --git a/types/module/configurator.go b/types/module/configurator.go index a2de025836e3..36092d7b5a98 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -3,7 +3,6 @@ package module import ( "github.com/gogo/protobuf/grpc" - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -29,7 +28,6 @@ type Configurator interface { } type configurator struct { - cdc codec.Marshaler msgServer grpc.Server queryServer grpc.Server @@ -38,9 +36,8 @@ type configurator struct { } // NewConfigurator returns a new Configurator instance -func NewConfigurator(cdc codec.Marshaler, msgServer grpc.Server, queryServer grpc.Server, storeKeys map[string]*sdk.KVStoreKey) Configurator { +func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server) Configurator { return configurator{ - cdc: cdc, msgServer: msgServer, queryServer: queryServer, migrations: map[string]map[uint64]MigrationHandler{}, From 8cf88fe48acb241a128d523b5f36af62217e35db Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 10 Feb 2021 16:58:30 +0100 Subject: [PATCH 25/46] Godoc updates --- simapp/app.go | 6 +++--- types/module/module.go | 11 ++++------- x/auth/module.go | 5 +---- x/auth/vesting/module.go | 5 +---- x/authz/module.go | 5 +---- x/bank/module.go | 5 +---- x/capability/module.go | 5 +---- x/crisis/module.go | 5 +---- x/distribution/module.go | 5 +---- x/evidence/module.go | 5 +---- x/feegrant/module.go | 5 +---- x/genutil/module.go | 5 +---- x/gov/module.go | 5 +---- x/ibc/applications/transfer/module.go | 5 +---- x/ibc/core/module.go | 5 +---- x/mint/module.go | 5 +---- x/params/module.go | 5 +---- x/slashing/module.go | 5 +---- x/staking/module.go | 5 +---- x/upgrade/module.go | 5 +---- 20 files changed, 25 insertions(+), 82 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index 688aa429fd7b..4db7d53d7755 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -605,7 +605,7 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { // RunMigrations performs in-place store migrations for all modules. This // function MUST be only called by x/upgrade UpgradeHandler. // -// `migrationsMap` is a map of moduleName to fromVersion (unit64), where +// `migrateFromVersions` is a map of moduleName to fromVersion (unit64), where // fromVersion denotes the version from which we should migrate the module, the // target version being the module's latest ConsensusVersion. // @@ -620,8 +620,8 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { // panic(err) // } // }) -func (app *SimApp) RunMigrations(ctx sdk.Context, migrationsMap module.MigrationMap) error { - return app.mm.RunMigrations(ctx, app.configurator, migrationsMap) +func (app *SimApp) RunMigrations(ctx sdk.Context, migrateFromVersions module.MigrationMap) error { + return app.mm.RunMigrations(ctx, app.configurator, migrateFromVersions) } // RegisterSwaggerAPI registers swagger route with API Server diff --git a/types/module/module.go b/types/module/module.go index 64e7a68d8406..58bb4927b29a 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -178,7 +178,7 @@ type AppModule interface { // ConsensusVersion is a sequence number for state-breaking change of the // module. It should be incremented on each consensus-breaking change // introduced by the module. To avoid wrong/empty versions, the initial version - // is set to 1. + // should be set to 1. ConsensusVersion() uint64 // ABCI @@ -215,10 +215,7 @@ func (gam GenesisOnlyAppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Que // RegisterServices registers all services. func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {} -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns an empty module begin-block @@ -349,14 +346,14 @@ type MigrationHandler func(store sdk.Context) error type MigrationMap map[string]uint64 // RunMigrations performs in-place store migrations for all modules. -func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrationMap MigrationMap) error { +func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrateFromVersions MigrationMap) error { c, ok := cfg.(configurator) if !ok { return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg) } for moduleName, module := range m.Modules { - err := c.runModuleMigrations(ctx, moduleName, migrationMap[moduleName], module.ConsensusVersion()) + err := c.runModuleMigrations(ctx, moduleName, migrateFromVersions[moduleName], module.ConsensusVersion()) if err != nil { return err } diff --git a/x/auth/module.go b/x/auth/module.go index 338ee70e7ccb..9e4af71ff037 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -147,10 +147,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the auth module. diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go index ecc5a77baf5a..259143469388 100644 --- a/x/auth/vesting/module.go +++ b/x/auth/vesting/module.go @@ -128,8 +128,5 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/authz/module.go b/x/authz/module.go index c94aaa871f4a..b39c02487fe0 100644 --- a/x/authz/module.go +++ b/x/authz/module.go @@ -152,10 +152,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} diff --git a/x/bank/module.go b/x/bank/module.go index e1a1a3adbf0b..77bff6b73b61 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -154,10 +154,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock performs a no-op. diff --git a/x/capability/module.go b/x/capability/module.go index e9a17d9b2dbf..06bee1e2d029 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -136,10 +136,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(genState) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. diff --git a/x/crisis/module.go b/x/crisis/module.go index ca41e9bc08de..66d829be810e 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -158,10 +158,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock performs a no-op. diff --git a/x/distribution/module.go b/x/distribution/module.go index 658781b103cf..0f0c0d358a91 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -161,10 +161,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the distribution module. diff --git a/x/evidence/module.go b/x/evidence/module.go index d72a693a1277..9143e208e716 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -175,10 +175,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, am.keeper)) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock executes all ABCI BeginBlock logic respective to the evidence module. diff --git a/x/feegrant/module.go b/x/feegrant/module.go index 4a222b3cee09..31b08e6baab1 100644 --- a/x/feegrant/module.go +++ b/x/feegrant/module.go @@ -167,10 +167,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the feegrant module. diff --git a/x/genutil/module.go b/x/genutil/module.go index becca6a950c4..7a65531e453f 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -111,8 +111,5 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/gov/module.go b/x/gov/module.go index f47fe91ff3ed..b72a4bfe5f5c 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -177,10 +177,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock performs a no-op. diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 74ff5e57b339..25290d69a64c 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -145,10 +145,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock implements the AppModule interface diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go index f2b2318771c8..6527ab71eb2f 100644 --- a/x/ibc/core/module.go +++ b/x/ibc/core/module.go @@ -156,10 +156,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, *am.keeper)) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the ibc module. diff --git a/x/mint/module.go b/x/mint/module.go index cf9e5e8999ff..d33043b36a2e 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -146,10 +146,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the mint module. diff --git a/x/params/module.go b/x/params/module.go index 88205c65f4af..c1a115b210c1 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -139,10 +139,7 @@ func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.Raw return nil } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock performs a no-op. diff --git a/x/slashing/module.go b/x/slashing/module.go index 52c78a626231..ba5cfb60adb9 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -159,10 +159,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the slashing module. diff --git a/x/staking/module.go b/x/staking/module.go index 0ec94958a299..48c67e6f5cd1 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -157,10 +157,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock returns the begin blocker for the staking module. diff --git a/x/upgrade/module.go b/x/upgrade/module.go index ccf7b077e65e..23311c22d5f3 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -120,10 +120,7 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// is set to 1. +// ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock calls the upgrade module hooks From 5add13a2fa1c38bbff91c03a5477edec872bc8af Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 10 Feb 2021 17:56:55 +0100 Subject: [PATCH 26/46] Update docs --- types/module/configurator.go | 9 ++++++--- types/module/module_test.go | 4 +--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/types/module/configurator.go b/types/module/configurator.go index 36092d7b5a98..0e766df2a13d 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -24,6 +24,12 @@ type Configurator interface { // RegisterMigration registers an in-place store migration for a module. The // handler is a migration script to perform in-place migrations from version // `forVersion` to version `forVersion+1`. + // + // EACH TIME a module's ConsensusVersion increments, a new migration MUST + // be registered using this function. If a migration handler is missing for + // a particular function, the upgrade logic (see RunMigrations function) + // will panic. If the ConsensusVersion bump does not introduce any store + // changes, then a no-op function must be registered here. RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error } @@ -79,9 +85,6 @@ func (c configurator) RegisterMigration(moduleName string, forVersion uint64, ha // version to another version. func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { // No-op if toVersion is the initial version. - // Some modules don't have a store key (e.g. vesting), in this case, their - // ConsensusVersion will always stay at 1, and running migrations on - // those modules will be skipped on this line. if toVersion <= 1 { return nil } diff --git a/types/module/module_test.go b/types/module/module_test.go index 9dafb37566c2..630c57619245 100644 --- a/types/module/module_test.go +++ b/types/module/module_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/simapp" "github.com/golang/mock/gomock" "github.com/gorilla/mux" @@ -169,7 +168,6 @@ func TestManager_RegisterRoutes(t *testing.T) { func TestManager_RegisterQueryServices(t *testing.T) { mockCtrl := gomock.NewController(t) t.Cleanup(mockCtrl.Finish) - encCfg := simapp.MakeTestEncodingConfig() mockAppModule1 := mocks.NewMockAppModule(mockCtrl) mockAppModule2 := mocks.NewMockAppModule(mockCtrl) @@ -181,7 +179,7 @@ func TestManager_RegisterQueryServices(t *testing.T) { msgRouter := mocks.NewMockServer(mockCtrl) queryRouter := mocks.NewMockServer(mockCtrl) - cfg := module.NewConfigurator(encCfg.Marshaler, msgRouter, queryRouter, nil) + cfg := module.NewConfigurator(msgRouter, queryRouter) mockAppModule1.EXPECT().RegisterServices(cfg).Times(1) mockAppModule2.EXPECT().RegisterServices(cfg).Times(1) From 74b761a963eec6dec51a993fb04af7aca4d00c35 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 12:02:39 +0100 Subject: [PATCH 27/46] Add distrib legacy folder --- x/distribution/legacy/v040/keys.go | 180 ++++++++++++++++++++ x/distribution/legacy/v042/keys.go | 200 +++++++++++++++++++++++ x/distribution/legacy/v042/store_test.go | 36 ++++ x/distribution/legacy/v042/types.go | 5 + 4 files changed, 421 insertions(+) create mode 100644 x/distribution/legacy/v040/keys.go create mode 100644 x/distribution/legacy/v042/keys.go create mode 100644 x/distribution/legacy/v042/store_test.go create mode 100644 x/distribution/legacy/v042/types.go diff --git a/x/distribution/legacy/v040/keys.go b/x/distribution/legacy/v040/keys.go new file mode 100644 index 000000000000..ac9524a9ffef --- /dev/null +++ b/x/distribution/legacy/v040/keys.go @@ -0,0 +1,180 @@ +package v040 + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +// Keys for distribution store +// Items are stored with the following key: values +// +// - 0x00: FeePol +// +// - 0x01: sdk.ConsAddress +// +// - 0x02: ValidatorOutstandingRewards +// +// - 0x03: sdk.AccAddress +// +// - 0x04: DelegatorStartingInfo +// +// - 0x05: ValidatorHistoricalRewards +// +// - 0x06: ValidatorCurrentRewards +// +// - 0x07: ValidatorCurrentRewards +// +// - 0x08: ValidatorSlashEvent +var ( + FeePoolKey = []byte{0x00} // key for global distribution state + ProposerKey = []byte{0x01} // key for the proposer operator address + ValidatorOutstandingRewardsPrefix = []byte{0x02} // key for outstanding rewards + + DelegatorWithdrawAddrPrefix = []byte{0x03} // key for delegator withdraw address + DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info + ValidatorHistoricalRewardsPrefix = []byte{0x05} // key for historical validators rewards / stake + ValidatorCurrentRewardsPrefix = []byte{0x06} // key for current validator rewards + ValidatorAccumulatedCommissionPrefix = []byte{0x07} // key for accumulated validator commission + ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction +) + +// gets an address from a validator's outstanding rewards key +func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ValAddress(addr) +} + +// gets an address from a delegator's withdraw info key +func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.AccAddress(addr) +} + +// gets the addresses from a delegator starting info key +func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) { + addr := key[1 : 1+v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + valAddr = sdk.ValAddress(addr) + addr = key[1+v040auth.AddrLen:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + delAddr = sdk.AccAddress(addr) + return +} + +// gets the address & period from a validator's historical rewards key +func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) { + addr := key[1 : 1+v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + valAddr = sdk.ValAddress(addr) + b := key[1+v040auth.AddrLen:] + if len(b) != 8 { + panic("unexpected key length") + } + period = binary.LittleEndian.Uint64(b) + return +} + +// gets the address from a validator's current rewards key +func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ValAddress(addr) +} + +// gets the address from a validator's accumulated commission key +func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ValAddress(addr) +} + +// gets the height from a validator's slash event key +func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) { + addr := key[1 : 1+v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + valAddr = sdk.ValAddress(addr) + startB := 1 + v040auth.AddrLen + b := key[startB : startB+8] // the next 8 bytes represent the height + height = binary.BigEndian.Uint64(b) + return +} + +// gets the outstanding rewards key for a validator +func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte { + return append(ValidatorOutstandingRewardsPrefix, valAddr.Bytes()...) +} + +// gets the key for a delegator's withdraw addr +func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { + return append(DelegatorWithdrawAddrPrefix, delAddr.Bytes()...) +} + +// gets the key for a delegator's starting info +func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte { + return append(append(DelegatorStartingInfoPrefix, v.Bytes()...), d.Bytes()...) +} + +// gets the prefix key for a validator's historical rewards +func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte { + return append(ValidatorHistoricalRewardsPrefix, v.Bytes()...) +} + +// gets the key for a validator's historical rewards +func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, k) + return append(append(ValidatorHistoricalRewardsPrefix, v.Bytes()...), b...) +} + +// gets the key for a validator's current rewards +func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte { + return append(ValidatorCurrentRewardsPrefix, v.Bytes()...) +} + +// gets the key for a validator's current commission +func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte { + return append(ValidatorAccumulatedCommissionPrefix, v.Bytes()...) +} + +// gets the prefix key for a validator's slash fractions +func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte { + return append(ValidatorSlashEventPrefix, v.Bytes()...) +} + +// gets the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height) +func GetValidatorSlashEventKeyPrefix(v sdk.ValAddress, height uint64) []byte { + heightBz := make([]byte, 8) + binary.BigEndian.PutUint64(heightBz, height) + return append( + ValidatorSlashEventPrefix, + append(v.Bytes(), heightBz...)..., + ) +} + +// gets the key for a validator's slash fraction +func GetValidatorSlashEventKey(v sdk.ValAddress, height, period uint64) []byte { + periodBz := make([]byte, 8) + binary.BigEndian.PutUint64(periodBz, period) + prefix := GetValidatorSlashEventKeyPrefix(v, height) + return append(prefix, periodBz...) +} diff --git a/x/distribution/legacy/v042/keys.go b/x/distribution/legacy/v042/keys.go new file mode 100644 index 000000000000..1991f9064a37 --- /dev/null +++ b/x/distribution/legacy/v042/keys.go @@ -0,0 +1,200 @@ +package v042 + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +// Keys for distribution store +// Items are stored with the following key: values +// +// - 0x00: FeePol +// +// - 0x01: sdk.ConsAddress +// +// - 0x02: ValidatorOutstandingRewards +// +// - 0x03: sdk.AccAddress +// +// - 0x04: DelegatorStartingInfo +// +// - 0x05: ValidatorHistoricalRewards +// +// - 0x06: ValidatorCurrentRewards +// +// - 0x07: ValidatorCurrentRewards +// +// - 0x08: ValidatorSlashEvent +var ( + FeePoolKey = []byte{0x00} // key for global distribution state + ProposerKey = []byte{0x01} // key for the proposer operator address + ValidatorOutstandingRewardsPrefix = []byte{0x02} // key for outstanding rewards + + DelegatorWithdrawAddrPrefix = []byte{0x03} // key for delegator withdraw address + DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info + ValidatorHistoricalRewardsPrefix = []byte{0x05} // key for historical validators rewards / stake + ValidatorCurrentRewardsPrefix = []byte{0x06} // key for current validator rewards + ValidatorAccumulatedCommissionPrefix = []byte{0x07} // key for accumulated validator commission + ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction +) + +// GetValidatorOutstandingRewardsAddress creates an address from a validator's outstanding rewards key. +func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) { + // key is in the format: + // 0x02 + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { + panic("unexpected key length") + } + + return sdk.ValAddress(addr) +} + +// GetDelegatorWithdrawInfoAddress creates an address from a delegator's withdraw info key. +func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) { + // key is in the format: + // 0x03 + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { + panic("unexpected key length") + } + + return sdk.AccAddress(addr) +} + +// GetDelegatorStartingInfoAddresses creates the addresses from a delegator starting info key. +func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) { + // key is in the format: + // 0x04 + valAddrLen := int(key[1]) + valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) + delAddrLen := int(key[2+valAddrLen]) + delAddr = sdk.AccAddress(key[3+valAddrLen:]) + if len(delAddr.Bytes()) != delAddrLen { + panic("unexpected key length") + } + + return +} + +// GetValidatorHistoricalRewardsAddressPeriod creates the address & period from a validator's historical rewards key. +func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) { + // key is in the format: + // 0x05 + valAddrLen := int(key[1]) + valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) + b := key[2+valAddrLen:] + if len(b) != 8 { + panic("unexpected key length") + } + period = binary.LittleEndian.Uint64(b) + return +} + +// GetValidatorCurrentRewardsAddress creates the address from a validator's current rewards key. +func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) { + // key is in the format: + // 0x06: ValidatorCurrentRewards + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { + panic("unexpected key length") + } + + return sdk.ValAddress(addr) +} + +// GetValidatorAccumulatedCommissionAddress creates the address from a validator's accumulated commission key. +func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) { + // key is in the format: + // 0x07: ValidatorCurrentRewards + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { + panic("unexpected key length") + } + + return sdk.ValAddress(addr) +} + +// GetValidatorSlashEventAddressHeight creates the height from a validator's slash event key. +func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) { + // key is in the format: + // 0x08: ValidatorSlashEvent + valAddrLen := int(key[1]) + valAddr = key[2 : 2+valAddrLen] + startB := 2 + valAddrLen + b := key[startB : startB+8] // the next 8 bytes represent the height + height = binary.BigEndian.Uint64(b) + return +} + +// GetValidatorOutstandingRewardsKey creates the outstanding rewards key for a validator. +func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte { + return append(ValidatorOutstandingRewardsPrefix, address.MustLengthPrefix(valAddr.Bytes())...) +} + +// GetDelegatorWithdrawAddrKey creates the key for a delegator's withdraw addr. +func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { + return append(DelegatorWithdrawAddrPrefix, address.MustLengthPrefix(delAddr.Bytes())...) +} + +// GetDelegatorStartingInfoKey creates the key for a delegator's starting info. +func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte { + return append(append(DelegatorStartingInfoPrefix, address.MustLengthPrefix(v.Bytes())...), address.MustLengthPrefix(d.Bytes())...) +} + +// GetValidatorHistoricalRewardsPrefix creates the prefix key for a validator's historical rewards. +func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte { + return append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) +} + +// GetValidatorHistoricalRewardsKey creates the key for a validator's historical rewards. +func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, k) + return append(append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...), b...) +} + +// GetValidatorCurrentRewardsKey creates the key for a validator's current rewards. +func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte { + return append(ValidatorCurrentRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) +} + +// GetValidatorAccumulatedCommissionKey creates the key for a validator's current commission. +func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte { + return append(ValidatorAccumulatedCommissionPrefix, address.MustLengthPrefix(v.Bytes())...) +} + +// GetValidatorSlashEventPrefix creates the prefix key for a validator's slash fractions. +func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte { + return append(ValidatorSlashEventPrefix, address.MustLengthPrefix(v.Bytes())...) +} + +// GetValidatorSlashEventKeyPrefix creates the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height). +func GetValidatorSlashEventKeyPrefix(v sdk.ValAddress, height uint64) []byte { + heightBz := make([]byte, 8) + binary.BigEndian.PutUint64(heightBz, height) + + return append( + ValidatorSlashEventPrefix, + append(address.MustLengthPrefix(v.Bytes()), heightBz...)..., + ) +} + +// GetValidatorSlashEventKey creates the key for a validator's slash fraction. +func GetValidatorSlashEventKey(v sdk.ValAddress, height, period uint64) []byte { + periodBz := make([]byte, 8) + binary.BigEndian.PutUint64(periodBz, period) + prefix := GetValidatorSlashEventKeyPrefix(v, height) + + return append(prefix, periodBz...) +} diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go new file mode 100644 index 000000000000..2ba0143db1eb --- /dev/null +++ b/x/distribution/legacy/v042/store_test.go @@ -0,0 +1,36 @@ +package v042_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" +) + +func TestStoreMigration(t *testing.T) { + distributionKey := sdk.NewKVStoreKey("distribution") + ctx := testutil.DefaultContext(distributionKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(distributionKey) + + _, _, addr := testdata.KeyTestPubAddr() + denom := []byte("foo") + value := []byte("bar") + + oldKey := append(append(v040distribution.BalancesPrefix, addr...), denom...) + store.Set(oldKey, value) + + err := v042distribution.StoreMigration(store) + require.NoError(t, err) + + newKey := append(v042distribution.CreateAccountBalancesPrefix(addr), denom...) + // -7 because we replaced "balances" with 0x02, + // +1 because we added length-prefix to address. + require.Equal(t, len(oldKey)-7+1, len(newKey)) + require.Nil(t, store.Get(oldKey)) + require.Equal(t, value, store.Get(newKey)) +} diff --git a/x/distribution/legacy/v042/types.go b/x/distribution/legacy/v042/types.go new file mode 100644 index 000000000000..0cee671b5f1b --- /dev/null +++ b/x/distribution/legacy/v042/types.go @@ -0,0 +1,5 @@ +package v042 + +const ( + ModuleName = "distribution" +) From 2816a20fd79cd1f9b8f872b9b8ffd95658d3c57c Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 12:47:56 +0100 Subject: [PATCH 28/46] Add tests for distrib migration --- x/distribution/legacy/v042/helpers.go | 70 +++++++++++++++++++++++ x/distribution/legacy/v042/store.go | 22 +++++++ x/distribution/legacy/v042/store_test.go | 73 ++++++++++++++++++++---- 3 files changed, 153 insertions(+), 12 deletions(-) create mode 100644 x/distribution/legacy/v042/helpers.go create mode 100644 x/distribution/legacy/v042/store.go diff --git a/x/distribution/legacy/v042/helpers.go b/x/distribution/legacy/v042/helpers.go new file mode 100644 index 000000000000..fa7d817abc18 --- /dev/null +++ b/x/distribution/legacy/v042/helpers.go @@ -0,0 +1,70 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +// MigratePrefixAddress is a helper function that migrates all keys of format: +// +// into format: +// +func MigratePrefixAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr := oldStoreIter.Key() + newStoreKey := append(prefixBz, address.MustLengthPrefix(addr)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigratePrefixAddressBytes is a helper function that migrates all keys of format: +// +// into format: +// +func MigratePrefixAddressBytes(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr := oldStoreIter.Key()[:v040auth.AddrLen] + endBz := oldStoreIter.Key()[v040auth.AddrLen:] + newStoreKey := append(append(prefixBz, address.MustLengthPrefix(addr)...), endBz...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigratePrefixAddressAddress is a helper function that migrates all keys of format: +// +// into format: +// +func MigratePrefixAddressAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr1 := oldStoreIter.Key()[:v040auth.AddrLen] + addr2 := oldStoreIter.Key()[v040auth.AddrLen:] + newStoreKey := append(append(prefixBz, address.MustLengthPrefix(addr1)...), address.MustLengthPrefix(addr2)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} diff --git a/x/distribution/legacy/v042/store.go b/x/distribution/legacy/v042/store.go new file mode 100644 index 000000000000..16b25c65ee74 --- /dev/null +++ b/x/distribution/legacy/v042/store.go @@ -0,0 +1,22 @@ +package v042 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" +) + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(store sdk.KVStore) error { + MigratePrefixAddress(store, v040distribution.ValidatorOutstandingRewardsPrefix) + MigratePrefixAddress(store, v040distribution.DelegatorWithdrawAddrPrefix) + MigratePrefixAddressAddress(store, v040distribution.DelegatorStartingInfoPrefix) + MigratePrefixAddressBytes(store, v040distribution.ValidatorHistoricalRewardsPrefix) + MigratePrefixAddress(store, v040distribution.ValidatorCurrentRewardsPrefix) + MigratePrefixAddress(store, v040distribution.ValidatorAccumulatedCommissionPrefix) + MigratePrefixAddressBytes(store, v040distribution.ValidatorSlashEventPrefix) + + return nil +} diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go index 2ba0143db1eb..88b835d4624a 100644 --- a/x/distribution/legacy/v042/store_test.go +++ b/x/distribution/legacy/v042/store_test.go @@ -17,20 +17,69 @@ func TestStoreMigration(t *testing.T) { ctx := testutil.DefaultContext(distributionKey, sdk.NewTransientStoreKey("transient_test")) store := ctx.KVStore(distributionKey) - _, _, addr := testdata.KeyTestPubAddr() - denom := []byte("foo") - value := []byte("bar") + _, _, addr1 := testdata.KeyTestPubAddr() + valAddr := sdk.ValAddress(addr1) + _, _, addr2 := testdata.KeyTestPubAddr() + // Use dummy value for all keys. + value := []byte("foo") - oldKey := append(append(v040distribution.BalancesPrefix, addr...), denom...) - store.Set(oldKey, value) + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "ValidatorOutstandingRewards", + v040distribution.GetValidatorOutstandingRewardsKey(valAddr), + v042distribution.GetValidatorOutstandingRewardsKey(valAddr), + }, + { + "DelegatorWithdrawAddr", + v040distribution.GetDelegatorWithdrawAddrKey(addr2), + v042distribution.GetDelegatorWithdrawAddrKey(addr2), + }, + { + "DelegatorStartingInfo", + v040distribution.GetDelegatorStartingInfoKey(valAddr, addr2), + v042distribution.GetDelegatorStartingInfoKey(valAddr, addr2), + }, + { + "ValidatorHistoricalRewards", + v040distribution.GetValidatorHistoricalRewardsKey(valAddr, 6), + v042distribution.GetValidatorHistoricalRewardsKey(valAddr, 6), + }, + { + "ValidatorCurrentRewards", + v040distribution.GetValidatorCurrentRewardsKey(valAddr), + v042distribution.GetValidatorCurrentRewardsKey(valAddr), + }, + { + "ValidatorAccumulatedCommission", + v040distribution.GetValidatorAccumulatedCommissionKey(valAddr), + v042distribution.GetValidatorAccumulatedCommissionKey(valAddr), + }, + { + "ValidatorSlashEvent", + v040distribution.GetValidatorSlashEventKey(valAddr, 6, 8), + v042distribution.GetValidatorSlashEventKey(valAddr, 6, 8), + }, + } - err := v042distribution.StoreMigration(store) + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042distribution.MigrateStore(store) require.NoError(t, err) - newKey := append(v042distribution.CreateAccountBalancesPrefix(addr), denom...) - // -7 because we replaced "balances" with 0x02, - // +1 because we added length-prefix to address. - require.Equal(t, len(oldKey)-7+1, len(newKey)) - require.Nil(t, store.Get(oldKey)) - require.Equal(t, value, store.Get(newKey)) + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + require.Nil(t, store.Get(tc.oldKey)) + require.Equal(t, value, store.Get(tc.newKey)) + }) + } } From f18f253fca7ee5de6bae7c18fd5dbdd4eff86e93 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 13:07:39 +0100 Subject: [PATCH 29/46] Add gov migrations --- x/distribution/legacy/v040/keys.go | 14 ++ x/distribution/legacy/v040/types.go | 6 - x/distribution/legacy/v042/store_test.go | 15 ++- x/gov/legacy/v040/keys.go | 165 +++++++++++++++++++++++ x/gov/legacy/v040/types.go | 6 - x/gov/legacy/v042/keys.go | 163 ++++++++++++++++++++++ x/gov/legacy/v042/store.go | 42 ++++++ x/gov/legacy/v042/store_test.go | 84 ++++++++++++ 8 files changed, 482 insertions(+), 13 deletions(-) delete mode 100644 x/distribution/legacy/v040/types.go create mode 100644 x/gov/legacy/v040/keys.go delete mode 100644 x/gov/legacy/v040/types.go create mode 100644 x/gov/legacy/v042/keys.go create mode 100644 x/gov/legacy/v042/store.go create mode 100644 x/gov/legacy/v042/store_test.go diff --git a/x/distribution/legacy/v040/keys.go b/x/distribution/legacy/v040/keys.go index ac9524a9ffef..c83ab09f5582 100644 --- a/x/distribution/legacy/v040/keys.go +++ b/x/distribution/legacy/v040/keys.go @@ -7,6 +7,20 @@ import ( v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" ) +const ( + // ModuleName is the module name constant used in many places + ModuleName = "distribution" + + // StoreKey is the store key string for distribution + StoreKey = ModuleName + + // RouterKey is the message route for distribution + RouterKey = ModuleName + + // QuerierRoute is the querier route for distribution + QuerierRoute = ModuleName +) + // Keys for distribution store // Items are stored with the following key: values // diff --git a/x/distribution/legacy/v040/types.go b/x/distribution/legacy/v040/types.go deleted file mode 100644 index aa502303803e..000000000000 --- a/x/distribution/legacy/v040/types.go +++ /dev/null @@ -1,6 +0,0 @@ -package v040 - -// Default parameter values -const ( - ModuleName = "distribution" -) diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go index 88b835d4624a..a2855eabbf04 100644 --- a/x/distribution/legacy/v042/store_test.go +++ b/x/distribution/legacy/v042/store_test.go @@ -1,6 +1,7 @@ package v042_test import ( + "bytes" "testing" "github.com/stretchr/testify/require" @@ -28,6 +29,16 @@ func TestStoreMigration(t *testing.T) { oldKey []byte newKey []byte }{ + { + "FeePoolKey", + v040distribution.FeePoolKey, + v042distribution.FeePoolKey, + }, + { + "ProposerKey", + v040distribution.ProposerKey, + v042distribution.ProposerKey, + }, { "ValidatorOutstandingRewards", v040distribution.GetValidatorOutstandingRewardsKey(valAddr), @@ -78,7 +89,9 @@ func TestStoreMigration(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - require.Nil(t, store.Get(tc.oldKey)) + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } require.Equal(t, value, store.Get(tc.newKey)) }) } diff --git a/x/gov/legacy/v040/keys.go b/x/gov/legacy/v040/keys.go new file mode 100644 index 000000000000..273dbcff10e7 --- /dev/null +++ b/x/gov/legacy/v040/keys.go @@ -0,0 +1,165 @@ +package v040 + +import ( + "encoding/binary" + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +const ( + // ModuleName is the name of the module + ModuleName = "gov" + + // StoreKey is the store key string for gov + StoreKey = ModuleName + + // RouterKey is the message route for gov + RouterKey = ModuleName + + // QuerierRoute is the querier route for gov + QuerierRoute = ModuleName +) + +// Keys for governance store +// Items are stored with the following key: values +// +// - 0x00: Proposal +// +// - 0x01: activeProposalID +// +// - 0x02: inactiveProposalID +// +// - 0x03: nextProposalID +// +// - 0x10: Deposit +// +// - 0x20: Voter +var ( + ProposalsKeyPrefix = []byte{0x00} + ActiveProposalQueuePrefix = []byte{0x01} + InactiveProposalQueuePrefix = []byte{0x02} + ProposalIDKey = []byte{0x03} + + DepositsKeyPrefix = []byte{0x10} + + VotesKeyPrefix = []byte{0x20} +) + +var lenTime = len(sdk.FormatTimeBytes(time.Now())) + +// GetProposalIDBytes returns the byte representation of the proposalID +func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) { + proposalIDBz = make([]byte, 8) + binary.BigEndian.PutUint64(proposalIDBz, proposalID) + return +} + +// GetProposalIDFromBytes returns proposalID in uint64 format from a byte array +func GetProposalIDFromBytes(bz []byte) (proposalID uint64) { + return binary.BigEndian.Uint64(bz) +} + +// ProposalKey gets a specific proposal from the store +func ProposalKey(proposalID uint64) []byte { + return append(ProposalsKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// ActiveProposalByTimeKey gets the active proposal queue key by endTime +func ActiveProposalByTimeKey(endTime time.Time) []byte { + return append(ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) +} + +// ActiveProposalQueueKey returns the key for a proposalID in the activeProposalQueue +func ActiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { + return append(ActiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) +} + +// InactiveProposalByTimeKey gets the inactive proposal queue key by endTime +func InactiveProposalByTimeKey(endTime time.Time) []byte { + return append(InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) +} + +// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue +func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { + return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) +} + +// DepositsKey gets the first part of the deposits key based on the proposalID +func DepositsKey(proposalID uint64) []byte { + return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// DepositKey key of a specific deposit from the store +func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte { + return append(DepositsKey(proposalID), depositorAddr.Bytes()...) +} + +// VotesKey gets the first part of the votes key based on the proposalID +func VotesKey(proposalID uint64) []byte { + return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// VoteKey key of a specific vote from the store +func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte { + return append(VotesKey(proposalID), voterAddr.Bytes()...) +} + +// Split keys function; used for iterators + +// SplitProposalKey split the proposal key and returns the proposal id +func SplitProposalKey(key []byte) (proposalID uint64) { + if len(key[1:]) != 8 { + panic(fmt.Sprintf("unexpected key length (%d ≠ 8)", len(key[1:]))) + } + + return GetProposalIDFromBytes(key[1:]) +} + +// SplitActiveProposalQueueKey split the active proposal key and returns the proposal id and endTime +func SplitActiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { + return splitKeyWithTime(key) +} + +// SplitInactiveProposalQueueKey split the inactive proposal key and returns the proposal id and endTime +func SplitInactiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { + return splitKeyWithTime(key) +} + +// SplitKeyDeposit split the deposits key and returns the proposal id and depositor address +func SplitKeyDeposit(key []byte) (proposalID uint64, depositorAddr sdk.AccAddress) { + return splitKeyWithAddress(key) +} + +// SplitKeyVote split the votes key and returns the proposal id and voter address +func SplitKeyVote(key []byte) (proposalID uint64, voterAddr sdk.AccAddress) { + return splitKeyWithAddress(key) +} + +// private functions + +func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) { + if len(key[1:]) != 8+lenTime { + panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key[1:]), lenTime+8)) + } + + endTime, err := sdk.ParseTimeBytes(key[1 : 1+lenTime]) + if err != nil { + panic(err) + } + + proposalID = GetProposalIDFromBytes(key[1+lenTime:]) + return +} + +func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) { + if len(key[1:]) != 8+v040auth.AddrLen { + panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key), 8+v040auth.AddrLen)) + } + + proposalID = GetProposalIDFromBytes(key[1:9]) + addr = sdk.AccAddress(key[9:]) + return +} diff --git a/x/gov/legacy/v040/types.go b/x/gov/legacy/v040/types.go deleted file mode 100644 index 27f668b2e1aa..000000000000 --- a/x/gov/legacy/v040/types.go +++ /dev/null @@ -1,6 +0,0 @@ -package v040 - -// Default parameter values -const ( - ModuleName = "gov" -) diff --git a/x/gov/legacy/v042/keys.go b/x/gov/legacy/v042/keys.go new file mode 100644 index 000000000000..bfd380e6d344 --- /dev/null +++ b/x/gov/legacy/v042/keys.go @@ -0,0 +1,163 @@ +package v042 + +import ( + "encoding/binary" + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +const ( + // ModuleName is the name of the module + ModuleName = "gov" + + // StoreKey is the store key string for gov + StoreKey = ModuleName + + // RouterKey is the message route for gov + RouterKey = ModuleName + + // QuerierRoute is the querier route for gov + QuerierRoute = ModuleName +) + +// Keys for governance store +// Items are stored with the following key: values +// +// - 0x00: Proposal +// +// - 0x01: activeProposalID +// +// - 0x02: inactiveProposalID +// +// - 0x03: nextProposalID +// +// - 0x10: Deposit +// +// - 0x20: Voter +var ( + ProposalsKeyPrefix = []byte{0x00} + ActiveProposalQueuePrefix = []byte{0x01} + InactiveProposalQueuePrefix = []byte{0x02} + ProposalIDKey = []byte{0x03} + + DepositsKeyPrefix = []byte{0x10} + + VotesKeyPrefix = []byte{0x20} +) + +var lenTime = len(sdk.FormatTimeBytes(time.Now())) + +// GetProposalIDBytes returns the byte representation of the proposalID +func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) { + proposalIDBz = make([]byte, 8) + binary.BigEndian.PutUint64(proposalIDBz, proposalID) + return +} + +// GetProposalIDFromBytes returns proposalID in uint64 format from a byte array +func GetProposalIDFromBytes(bz []byte) (proposalID uint64) { + return binary.BigEndian.Uint64(bz) +} + +// ProposalKey gets a specific proposal from the store +func ProposalKey(proposalID uint64) []byte { + return append(ProposalsKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// ActiveProposalByTimeKey gets the active proposal queue key by endTime +func ActiveProposalByTimeKey(endTime time.Time) []byte { + return append(ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) +} + +// ActiveProposalQueueKey returns the key for a proposalID in the activeProposalQueue +func ActiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { + return append(ActiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) +} + +// InactiveProposalByTimeKey gets the inactive proposal queue key by endTime +func InactiveProposalByTimeKey(endTime time.Time) []byte { + return append(InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) +} + +// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue +func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { + return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) +} + +// DepositsKey gets the first part of the deposits key based on the proposalID +func DepositsKey(proposalID uint64) []byte { + return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// DepositKey key of a specific deposit from the store +func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte { + return append(DepositsKey(proposalID), address.MustLengthPrefix(depositorAddr.Bytes())...) +} + +// VotesKey gets the first part of the votes key based on the proposalID +func VotesKey(proposalID uint64) []byte { + return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// VoteKey key of a specific vote from the store +func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte { + return append(VotesKey(proposalID), address.MustLengthPrefix(voterAddr.Bytes())...) +} + +// Split keys function; used for iterators + +// SplitProposalKey split the proposal key and returns the proposal id +func SplitProposalKey(key []byte) (proposalID uint64) { + if len(key[1:]) != 8 { + panic(fmt.Sprintf("unexpected key length (%d ≠ 8)", len(key[1:]))) + } + + return GetProposalIDFromBytes(key[1:]) +} + +// SplitActiveProposalQueueKey split the active proposal key and returns the proposal id and endTime +func SplitActiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { + return splitKeyWithTime(key) +} + +// SplitInactiveProposalQueueKey split the inactive proposal key and returns the proposal id and endTime +func SplitInactiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { + return splitKeyWithTime(key) +} + +// SplitKeyDeposit split the deposits key and returns the proposal id and depositor address +func SplitKeyDeposit(key []byte) (proposalID uint64, depositorAddr sdk.AccAddress) { + return splitKeyWithAddress(key) +} + +// SplitKeyVote split the votes key and returns the proposal id and voter address +func SplitKeyVote(key []byte) (proposalID uint64, voterAddr sdk.AccAddress) { + return splitKeyWithAddress(key) +} + +// private functions + +func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) { + if len(key[1:]) != 8+lenTime { + panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key[1:]), lenTime+8)) + } + + endTime, err := sdk.ParseTimeBytes(key[1 : 1+lenTime]) + if err != nil { + panic(err) + } + + proposalID = GetProposalIDFromBytes(key[1+lenTime:]) + return +} + +func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) { + // Both Vote and Deposit store keys are of format: + // + proposalID = GetProposalIDFromBytes(key[1:9]) + addr = sdk.AccAddress(key[10:]) + return +} diff --git a/x/gov/legacy/v042/store.go b/x/gov/legacy/v042/store.go new file mode 100644 index 000000000000..599fd2edff30 --- /dev/null +++ b/x/gov/legacy/v042/store.go @@ -0,0 +1,42 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" +) + +const proposalIDLen = 8 + +// migratePrefixProposalAddress is a helper function that migrates all keys of format: +// +// into format: +// +func migratePrefixProposalAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + proposalID := oldStoreIter.Key()[:proposalIDLen] + addr := oldStoreIter.Key()[proposalIDLen:] + newStoreKey := append(append(prefixBz, proposalID...), address.MustLengthPrefix(addr)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(store sdk.KVStore) error { + migratePrefixProposalAddress(store, v040gov.DepositsKeyPrefix) + migratePrefixProposalAddress(store, v040gov.VotesKeyPrefix) + + return nil +} diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v042/store_test.go new file mode 100644 index 000000000000..4fe218885cec --- /dev/null +++ b/x/gov/legacy/v042/store_test.go @@ -0,0 +1,84 @@ +package v042_test + +import ( + "bytes" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" + v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" +) + +func TestStoreMigration(t *testing.T) { + govKey := sdk.NewKVStoreKey("gov") + ctx := testutil.DefaultContext(govKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(govKey) + + _, _, addr1 := testdata.KeyTestPubAddr() + proposalID := uint64(6) + now := time.Now() + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "ProposalKey", + v040gov.ProposalKey(proposalID), + v042gov.ProposalKey(proposalID), + }, + { + "ActiveProposalQueue", + v040gov.ActiveProposalQueueKey(proposalID, now), + v042gov.ActiveProposalQueueKey(proposalID, now), + }, + { + "InactiveProposalQueue", + v040gov.InactiveProposalQueueKey(proposalID, now), + v042gov.InactiveProposalQueueKey(proposalID, now), + }, + { + "ProposalIDKey", + v040gov.ProposalIDKey, + v042gov.ProposalIDKey, + }, + { + "DepositKey", + v040gov.DepositKey(proposalID, addr1), + v042gov.DepositKey(proposalID, addr1), + }, + { + "VotesKeyPrefix", + v040gov.VoteKey(proposalID, addr1), + v042gov.VoteKey(proposalID, addr1), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042gov.MigrateStore(store) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} From 9e5999edd92514a984f0f2ac4450b0be0f5f3cf4 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 13:09:17 +0100 Subject: [PATCH 30/46] Copy paste whole keys file --- x/distribution/legacy/v042/keys.go | 14 ++++++++++++++ x/distribution/legacy/v042/types.go | 5 ----- 2 files changed, 14 insertions(+), 5 deletions(-) delete mode 100644 x/distribution/legacy/v042/types.go diff --git a/x/distribution/legacy/v042/keys.go b/x/distribution/legacy/v042/keys.go index 1991f9064a37..8f8ce391ef76 100644 --- a/x/distribution/legacy/v042/keys.go +++ b/x/distribution/legacy/v042/keys.go @@ -7,6 +7,20 @@ import ( "github.com/cosmos/cosmos-sdk/types/address" ) +const ( + // ModuleName is the module name constant used in many places + ModuleName = "distribution" + + // StoreKey is the store key string for distribution + StoreKey = ModuleName + + // RouterKey is the message route for distribution + RouterKey = ModuleName + + // QuerierRoute is the querier route for distribution + QuerierRoute = ModuleName +) + // Keys for distribution store // Items are stored with the following key: values // diff --git a/x/distribution/legacy/v042/types.go b/x/distribution/legacy/v042/types.go deleted file mode 100644 index 0cee671b5f1b..000000000000 --- a/x/distribution/legacy/v042/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v042 - -const ( - ModuleName = "distribution" -) From b15f03d108923cdbfd24d37cc4cd4b33d77dd92c Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 13:18:07 +0100 Subject: [PATCH 31/46] Add gov migrations --- x/slashing/legacy/v040/keys.go | 67 ++++++++++++++++++++++++++++ x/slashing/legacy/v040/types.go | 5 --- x/slashing/legacy/v042/keys.go | 67 ++++++++++++++++++++++++++++ x/slashing/legacy/v042/store.go | 19 ++++++++ x/slashing/legacy/v042/store_test.go | 67 ++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 x/slashing/legacy/v040/keys.go delete mode 100644 x/slashing/legacy/v040/types.go create mode 100644 x/slashing/legacy/v042/keys.go create mode 100644 x/slashing/legacy/v042/store.go create mode 100644 x/slashing/legacy/v042/store_test.go diff --git a/x/slashing/legacy/v040/keys.go b/x/slashing/legacy/v040/keys.go new file mode 100644 index 000000000000..0bcd5012e970 --- /dev/null +++ b/x/slashing/legacy/v040/keys.go @@ -0,0 +1,67 @@ +package v040 + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +const ( + // ModuleName is the name of the module + ModuleName = "slashing" + + // StoreKey is the store key string for slashing + StoreKey = ModuleName + + // RouterKey is the message route for slashing + RouterKey = ModuleName + + // QuerierRoute is the querier route for slashing + QuerierRoute = ModuleName +) + +// Keys for slashing store +// Items are stored with the following key: values +// +// - 0x01: ValidatorSigningInfo +// +// - 0x02: bool +// +// - 0x03: crypto.PubKey +var ( + ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info + ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array + AddrPubkeyRelationKeyPrefix = []byte{0x03} // Prefix for address-pubkey relation +) + +// ValidatorSigningInfoKey - stored by *Consensus* address (not operator address) +func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte { + return append(ValidatorSigningInfoKeyPrefix, v.Bytes()...) +} + +// ValidatorSigningInfoAddress - extract the address from a validator signing info key +func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ConsAddress(addr) +} + +// ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address) +func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte { + return append(ValidatorMissedBlockBitArrayKeyPrefix, v.Bytes()...) +} + +// ValidatorMissedBlockBitArrayKey - stored by *Consensus* address (not operator address) +func ValidatorMissedBlockBitArrayKey(v sdk.ConsAddress, i int64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(i)) + return append(ValidatorMissedBlockBitArrayPrefixKey(v), b...) +} + +// AddrPubkeyRelationKey gets pubkey relation key used to get the pubkey from the address +func AddrPubkeyRelationKey(address []byte) []byte { + return append(AddrPubkeyRelationKeyPrefix, address...) +} diff --git a/x/slashing/legacy/v040/types.go b/x/slashing/legacy/v040/types.go deleted file mode 100644 index b95fa6fe2445..000000000000 --- a/x/slashing/legacy/v040/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v040 - -const ( - ModuleName = "slashing" -) diff --git a/x/slashing/legacy/v042/keys.go b/x/slashing/legacy/v042/keys.go new file mode 100644 index 000000000000..63862c039349 --- /dev/null +++ b/x/slashing/legacy/v042/keys.go @@ -0,0 +1,67 @@ +package v042 + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +const ( + // ModuleName is the name of the module + ModuleName = "slashing" + + // StoreKey is the store key string for slashing + StoreKey = ModuleName + + // RouterKey is the message route for slashing + RouterKey = ModuleName + + // QuerierRoute is the querier route for slashing + QuerierRoute = ModuleName +) + +// Keys for slashing store +// Items are stored with the following key: values +// +// - 0x01: ValidatorSigningInfo +// +// - 0x02: bool +// +// - 0x03: cryptotypes.PubKey +var ( + ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info + ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array + AddrPubkeyRelationKeyPrefix = []byte{0x03} // Prefix for address-pubkey relation +) + +// ValidatorSigningInfoKey - stored by *Consensus* address (not operator address) +func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte { + return append(ValidatorSigningInfoKeyPrefix, address.MustLengthPrefix(v.Bytes())...) +} + +// ValidatorSigningInfoAddress - extract the address from a validator signing info key +func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) { + // Remove prefix and address length. + addr := key[2:] + + return sdk.ConsAddress(addr) +} + +// ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address) +func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte { + return append(ValidatorMissedBlockBitArrayKeyPrefix, address.MustLengthPrefix(v.Bytes())...) +} + +// ValidatorMissedBlockBitArrayKey - stored by *Consensus* address (not operator address) +func ValidatorMissedBlockBitArrayKey(v sdk.ConsAddress, i int64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(i)) + + return append(ValidatorMissedBlockBitArrayPrefixKey(v), b...) +} + +// AddrPubkeyRelationKey gets pubkey relation key used to get the pubkey from the address +func AddrPubkeyRelationKey(addr []byte) []byte { + return append(AddrPubkeyRelationKeyPrefix, address.MustLengthPrefix(addr)...) +} diff --git a/x/slashing/legacy/v042/store.go b/x/slashing/legacy/v042/store.go new file mode 100644 index 000000000000..d94c4a267296 --- /dev/null +++ b/x/slashing/legacy/v042/store.go @@ -0,0 +1,19 @@ +package v042 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" +) + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(store sdk.KVStore) error { + v042distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix) + v042distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix) + v042distribution.MigratePrefixAddress(store, v040slashing.AddrPubkeyRelationKeyPrefix) + + return nil +} diff --git a/x/slashing/legacy/v042/store_test.go b/x/slashing/legacy/v042/store_test.go new file mode 100644 index 000000000000..ba7e77f15f69 --- /dev/null +++ b/x/slashing/legacy/v042/store_test.go @@ -0,0 +1,67 @@ +package v042_test + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" + v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" +) + +func TestStoreMigration(t *testing.T) { + slashingKey := sdk.NewKVStoreKey("slashing") + ctx := testutil.DefaultContext(slashingKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(slashingKey) + + _, _, addr1 := testdata.KeyTestPubAddr() + consAddr := sdk.ConsAddress(addr1) + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "ValidatorSigningInfoKey", + v040slashing.ValidatorSigningInfoKey(consAddr), + v042slashing.ValidatorSigningInfoKey(consAddr), + }, + { + "ValidatorMissedBlockBitArrayKey", + v040slashing.ValidatorMissedBlockBitArrayKey(consAddr, 2), + v042slashing.ValidatorMissedBlockBitArrayKey(consAddr, 2), + }, + { + "AddrPubkeyRelationKey", + v040slashing.AddrPubkeyRelationKey(consAddr), + v042slashing.AddrPubkeyRelationKey(consAddr), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042slashing.MigrateStore(store) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} From 236e46cbbe2d4bce328c3788a7225fc0478da011 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 15:11:18 +0100 Subject: [PATCH 32/46] Add staking --- x/distribution/legacy/v042/helpers.go | 12 +- x/staking/legacy/v040/keys.go | 328 +++++++++++++++++++++++++ x/staking/legacy/v040/types.go | 5 - x/staking/legacy/v042/keys.go | 336 ++++++++++++++++++++++++++ x/staking/legacy/v042/store.go | 70 ++++++ x/staking/legacy/v042/store_test.go | 136 +++++++++++ 6 files changed, 876 insertions(+), 11 deletions(-) create mode 100644 x/staking/legacy/v040/keys.go delete mode 100644 x/staking/legacy/v040/types.go create mode 100644 x/staking/legacy/v042/keys.go create mode 100644 x/staking/legacy/v042/store.go create mode 100644 x/staking/legacy/v042/store_test.go diff --git a/x/distribution/legacy/v042/helpers.go b/x/distribution/legacy/v042/helpers.go index fa7d817abc18..afc99cf70888 100644 --- a/x/distribution/legacy/v042/helpers.go +++ b/x/distribution/legacy/v042/helpers.go @@ -8,9 +8,9 @@ import ( ) // MigratePrefixAddress is a helper function that migrates all keys of format: -// +// prefix_bytes | address_bytes // into format: -// +// prefix_bytes | address_len (1 byte) | address_bytes func MigratePrefixAddress(store sdk.KVStore, prefixBz []byte) { oldStore := prefix.NewStore(store, prefixBz) @@ -28,9 +28,9 @@ func MigratePrefixAddress(store sdk.KVStore, prefixBz []byte) { } // MigratePrefixAddressBytes is a helper function that migrates all keys of format: -// +// prefix_bytes | address_bytes | arbitrary_bytes // into format: -// +// prefix_bytes | address_len (1 byte) | address_bytes | arbitrary_bytes func MigratePrefixAddressBytes(store sdk.KVStore, prefixBz []byte) { oldStore := prefix.NewStore(store, prefixBz) @@ -49,9 +49,9 @@ func MigratePrefixAddressBytes(store sdk.KVStore, prefixBz []byte) { } // MigratePrefixAddressAddress is a helper function that migrates all keys of format: -// +// prefix_bytes | address_1_bytes | address_2_bytes // into format: -// +// prefix_bytes | address_1_len (1 byte) | address_1_bytes | address_2_len (1 byte) | address_2_bytes func MigratePrefixAddressAddress(store sdk.KVStore, prefixBz []byte) { oldStore := prefix.NewStore(store, prefixBz) diff --git a/x/staking/legacy/v040/keys.go b/x/staking/legacy/v040/keys.go new file mode 100644 index 000000000000..108e262f1b37 --- /dev/null +++ b/x/staking/legacy/v040/keys.go @@ -0,0 +1,328 @@ +package v040 + +import ( + "bytes" + "encoding/binary" + "fmt" + "strconv" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +const ( + // ModuleName is the name of the staking module + ModuleName = "staking" + + // StoreKey is the string store representation + StoreKey = ModuleName + + // QuerierRoute is the querier route for the staking module + QuerierRoute = ModuleName + + // RouterKey is the msg router key for the staking module + RouterKey = ModuleName +) + +var ( + // Keys for store prefixes + // Last* values are constant during a block. + LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators + LastTotalPowerKey = []byte{0x12} // prefix for the total power + + ValidatorsKey = []byte{0x21} // prefix for each key to a validator + ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey + ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power + + DelegationKey = []byte{0x31} // key for a delegation + UnbondingDelegationKey = []byte{0x32} // key for an unbonding-delegation + UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator + RedelegationKey = []byte{0x34} // key for a redelegation + RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator + RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator + + UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue + RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue + ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue + + HistoricalInfoKey = []byte{0x50} // prefix for the historical info +) + +// gets the key for the validator with address +// VALUE: staking/Validator +func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { + return append(ValidatorsKey, operatorAddr.Bytes()...) +} + +// gets the key for the validator with pubkey +// VALUE: validator operator address ([]byte) +func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { + return append(ValidatorsByConsAddrKey, addr.Bytes()...) +} + +// Get the validator operator address from LastValidatorPowerKey +func AddressFromLastValidatorPowerKey(key []byte) []byte { + return key[1:] // remove prefix bytes +} + +// get the validator by power index. +// Power index is the key used in the power-store, and represents the relative +// power ranking of the validator. +// VALUE: validator operator address ([]byte) +func GetValidatorsByPowerIndexKey(validator types.Validator) []byte { + // NOTE the address doesn't need to be stored because counter bytes must always be different + // NOTE the larger values are of higher value + + consensusPower := sdk.TokensToConsensusPower(validator.Tokens) + consensusPowerBytes := make([]byte, 8) + binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower)) + + powerBytes := consensusPowerBytes + powerBytesLen := len(powerBytes) // 8 + + // key is of format prefix || powerbytes || addrBytes + key := make([]byte, 1+powerBytesLen+v040auth.AddrLen) + + key[0] = ValidatorsByPowerIndexKey[0] + copy(key[1:powerBytesLen+1], powerBytes) + addr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) + if err != nil { + panic(err) + } + operAddrInvr := sdk.CopyBytes(addr) + + for i, b := range operAddrInvr { + operAddrInvr[i] = ^b + } + + copy(key[powerBytesLen+1:], operAddrInvr) + + return key +} + +// get the bonded validator index key for an operator address +func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { + return append(LastValidatorPowerKey, operator...) +} + +// parse the validators operator address from power rank key +func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) { + powerBytesLen := 8 + if len(key) != 1+powerBytesLen+v040auth.AddrLen { + panic("Invalid validator power rank key length") + } + + operAddr = sdk.CopyBytes(key[powerBytesLen+1:]) + + for i, b := range operAddr { + operAddr[i] = ^b + } + + return operAddr +} + +// GetValidatorQueueKey returns the prefix key used for getting a set of unbonding +// validators whose unbonding completion occurs at the given time and height. +func GetValidatorQueueKey(timestamp time.Time, height int64) []byte { + heightBz := sdk.Uint64ToBigEndian(uint64(height)) + timeBz := sdk.FormatTimeBytes(timestamp) + timeBzL := len(timeBz) + prefixL := len(ValidatorQueueKey) + + bz := make([]byte, prefixL+8+timeBzL+8) + + // copy the prefix + copy(bz[:prefixL], ValidatorQueueKey) + + // copy the encoded time bytes length + copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL))) + + // copy the encoded time bytes + copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz) + + // copy the encoded height + copy(bz[prefixL+8+timeBzL:], heightBz) + + return bz +} + +// ParseValidatorQueueKey returns the encoded time and height from a key created +// from GetValidatorQueueKey. +func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) { + prefixL := len(ValidatorQueueKey) + if prefix := bz[:prefixL]; !bytes.Equal(prefix, ValidatorQueueKey) { + return time.Time{}, 0, fmt.Errorf("invalid prefix; expected: %X, got: %X", ValidatorQueueKey, prefix) + } + + timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) + ts, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) + if err != nil { + return time.Time{}, 0, err + } + + height := sdk.BigEndianToUint64(bz[prefixL+8+int(timeBzL):]) + + return ts, int64(height), nil +} + +// gets the key for delegator bond with validator +// VALUE: staking/Delegation +func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetDelegationsKey(delAddr), valAddr.Bytes()...) +} + +// gets the prefix for a delegator for all validators +func GetDelegationsKey(delAddr sdk.AccAddress) []byte { + return append(DelegationKey, delAddr.Bytes()...) +} + +// gets the key for an unbonding delegation by delegator and validator addr +// VALUE: staking/UnbondingDelegation +func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append( + GetUBDsKey(delAddr.Bytes()), + valAddr.Bytes()...) +} + +// gets the index-key for an unbonding delegation, stored by validator-index +// VALUE: none (key rearrangement used) +func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetUBDsByValIndexKey(valAddr), delAddr.Bytes()...) +} + +// rearranges the ValIndexKey to get the UBDKey +func GetUBDKeyFromValIndexKey(indexKey []byte) []byte { + addrs := indexKey[1:] // remove prefix bytes + if len(addrs) != 2*v040auth.AddrLen { + panic("unexpected key length") + } + + valAddr := addrs[:v040auth.AddrLen] + delAddr := addrs[v040auth.AddrLen:] + + return GetUBDKey(delAddr, valAddr) +} + +// gets the prefix for all unbonding delegations from a delegator +func GetUBDsKey(delAddr sdk.AccAddress) []byte { + return append(UnbondingDelegationKey, delAddr.Bytes()...) +} + +// gets the prefix keyspace for the indexes of unbonding delegations for a validator +func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { + return append(UnbondingDelegationByValIndexKey, valAddr.Bytes()...) +} + +// gets the prefix for all unbonding delegations from a delegator +func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { + bz := sdk.FormatTimeBytes(timestamp) + return append(UnbondingQueueKey, bz...) +} + +// GetREDKey returns a key prefix for indexing a redelegation from a delegator +// and source validator to a destination validator. +func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { + key := make([]byte, 1+v040auth.AddrLen*3) + + copy(key[0:v040auth.AddrLen+1], GetREDsKey(delAddr.Bytes())) + copy(key[v040auth.AddrLen+1:2*v040auth.AddrLen+1], valSrcAddr.Bytes()) + copy(key[2*v040auth.AddrLen+1:3*v040auth.AddrLen+1], valDstAddr.Bytes()) + + return key +} + +// gets the index-key for a redelegation, stored by source-validator-index +// VALUE: none (key rearrangement used) +func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { + REDSFromValsSrcKey := GetREDsFromValSrcIndexKey(valSrcAddr) + offset := len(REDSFromValsSrcKey) + + // key is of the form REDSFromValsSrcKey || delAddr || valDstAddr + key := make([]byte, len(REDSFromValsSrcKey)+2*v040auth.AddrLen) + copy(key[0:offset], REDSFromValsSrcKey) + copy(key[offset:offset+v040auth.AddrLen], delAddr.Bytes()) + copy(key[offset+v040auth.AddrLen:offset+2*v040auth.AddrLen], valDstAddr.Bytes()) + + return key +} + +// gets the index-key for a redelegation, stored by destination-validator-index +// VALUE: none (key rearrangement used) +func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { + REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr) + offset := len(REDSToValsDstKey) + + // key is of the form REDSToValsDstKey || delAddr || valSrcAddr + key := make([]byte, len(REDSToValsDstKey)+2*v040auth.AddrLen) + copy(key[0:offset], REDSToValsDstKey) + copy(key[offset:offset+v040auth.AddrLen], delAddr.Bytes()) + copy(key[offset+v040auth.AddrLen:offset+2*v040auth.AddrLen], valSrcAddr.Bytes()) + + return key +} + +// GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey +func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte { + // note that first byte is prefix byte + if len(indexKey) != 3*v040auth.AddrLen+1 { + panic("unexpected key length") + } + + valSrcAddr := indexKey[1 : v040auth.AddrLen+1] + delAddr := indexKey[v040auth.AddrLen+1 : 2*v040auth.AddrLen+1] + valDstAddr := indexKey[2*v040auth.AddrLen+1 : 3*v040auth.AddrLen+1] + + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey +func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte { + // note that first byte is prefix byte + if len(indexKey) != 3*v040auth.AddrLen+1 { + panic("unexpected key length") + } + + valDstAddr := indexKey[1 : v040auth.AddrLen+1] + delAddr := indexKey[v040auth.AddrLen+1 : 2*v040auth.AddrLen+1] + valSrcAddr := indexKey[2*v040auth.AddrLen+1 : 3*v040auth.AddrLen+1] + + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// GetRedelegationTimeKey returns a key prefix for indexing an unbonding +// redelegation based on a completion time. +func GetRedelegationTimeKey(timestamp time.Time) []byte { + bz := sdk.FormatTimeBytes(timestamp) + return append(RedelegationQueueKey, bz...) +} + +// GetREDsKey returns a key prefix for indexing a redelegation from a delegator +// address. +func GetREDsKey(delAddr sdk.AccAddress) []byte { + return append(RedelegationKey, delAddr.Bytes()...) +} + +// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to +// a source validator. +func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { + return append(RedelegationByValSrcIndexKey, valSrcAddr.Bytes()...) +} + +// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a +// destination (target) validator. +func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte { + return append(RedelegationByValDstIndexKey, valDstAddr.Bytes()...) +} + +// GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation +// from an address to a source validator. +func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte { + return append(GetREDsToValDstIndexKey(valDstAddr), delAddr.Bytes()...) +} + +// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects. +func GetHistoricalInfoKey(height int64) []byte { + return append(HistoricalInfoKey, []byte(strconv.FormatInt(height, 10))...) +} diff --git a/x/staking/legacy/v040/types.go b/x/staking/legacy/v040/types.go deleted file mode 100644 index 6ad280e277e5..000000000000 --- a/x/staking/legacy/v040/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v040 - -const ( - ModuleName = "staking" -) diff --git a/x/staking/legacy/v042/keys.go b/x/staking/legacy/v042/keys.go new file mode 100644 index 000000000000..a43f3f9880ed --- /dev/null +++ b/x/staking/legacy/v042/keys.go @@ -0,0 +1,336 @@ +package v042 + +import ( + "bytes" + "encoding/binary" + "fmt" + "strconv" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +const ( + // ModuleName is the name of the staking module + ModuleName = "staking" + + // StoreKey is the string store representation + StoreKey = ModuleName + + // QuerierRoute is the querier route for the staking module + QuerierRoute = ModuleName + + // RouterKey is the msg router key for the staking module + RouterKey = ModuleName +) + +var ( + // Keys for store prefixes + // Last* values are constant during a block. + LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators + LastTotalPowerKey = []byte{0x12} // prefix for the total power + + ValidatorsKey = []byte{0x21} // prefix for each key to a validator + ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey + ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power + + DelegationKey = []byte{0x31} // key for a delegation + UnbondingDelegationKey = []byte{0x32} // key for an unbonding-delegation + UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator + RedelegationKey = []byte{0x34} // key for a redelegation + RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator + RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator + + UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue + RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue + ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue + + HistoricalInfoKey = []byte{0x50} // prefix for the historical info +) + +// GetValidatorKey creates the key for the validator with address +// VALUE: staking/Validator +func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { + return append(ValidatorsKey, address.MustLengthPrefix(operatorAddr)...) +} + +// GetValidatorByConsAddrKey creates the key for the validator with pubkey +// VALUE: validator operator address ([]byte) +func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { + return append(ValidatorsByConsAddrKey, address.MustLengthPrefix(addr)...) +} + +// AddressFromValidatorsKey creates the validator operator address from ValidatorsKey +func AddressFromValidatorsKey(key []byte) []byte { + return key[2:] // remove prefix bytes and address length +} + +// AddressFromLastValidatorPowerKey creates the validator operator address from LastValidatorPowerKey +func AddressFromLastValidatorPowerKey(key []byte) []byte { + return key[2:] // remove prefix bytes and address length +} + +// GetValidatorsByPowerIndexKey creates the validator by power index. +// Power index is the key used in the power-store, and represents the relative +// power ranking of the validator. +// VALUE: validator operator address ([]byte) +func GetValidatorsByPowerIndexKey(validator types.Validator) []byte { + // NOTE the address doesn't need to be stored because counter bytes must always be different + // NOTE the larger values are of higher value + + consensusPower := sdk.TokensToConsensusPower(validator.Tokens) + consensusPowerBytes := make([]byte, 8) + binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower)) + + powerBytes := consensusPowerBytes + powerBytesLen := len(powerBytes) // 8 + + addr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) + if err != nil { + panic(err) + } + operAddrInvr := sdk.CopyBytes(addr) + addrLen := len(operAddrInvr) + + for i, b := range operAddrInvr { + operAddrInvr[i] = ^b + } + + // key is of format prefix || powerbytes || addrLen (1byte) || addrBytes + key := make([]byte, 1+powerBytesLen+1+addrLen) + + key[0] = ValidatorsByPowerIndexKey[0] + copy(key[1:powerBytesLen+1], powerBytes) + key[powerBytesLen+1] = byte(addrLen) + copy(key[powerBytesLen+2:], operAddrInvr) + + return key +} + +// GetLastValidatorPowerKey creates the bonded validator index key for an operator address +func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { + return append(LastValidatorPowerKey, address.MustLengthPrefix(operator)...) +} + +// ParseValidatorPowerRankKey parses the validators operator address from power rank key +func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) { + powerBytesLen := 8 + + // key is of format prefix (1 byte) || powerbytes || addrLen (1byte) || addrBytes + operAddr = sdk.CopyBytes(key[powerBytesLen+2:]) + + for i, b := range operAddr { + operAddr[i] = ^b + } + + return operAddr +} + +// GetValidatorQueueKey returns the prefix key used for getting a set of unbonding +// validators whose unbonding completion occurs at the given time and height. +func GetValidatorQueueKey(timestamp time.Time, height int64) []byte { + heightBz := sdk.Uint64ToBigEndian(uint64(height)) + timeBz := sdk.FormatTimeBytes(timestamp) + timeBzL := len(timeBz) + prefixL := len(ValidatorQueueKey) + + bz := make([]byte, prefixL+8+timeBzL+8) + + // copy the prefix + copy(bz[:prefixL], ValidatorQueueKey) + + // copy the encoded time bytes length + copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL))) + + // copy the encoded time bytes + copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz) + + // copy the encoded height + copy(bz[prefixL+8+timeBzL:], heightBz) + + return bz +} + +// ParseValidatorQueueKey returns the encoded time and height from a key created +// from GetValidatorQueueKey. +func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) { + prefixL := len(ValidatorQueueKey) + if prefix := bz[:prefixL]; !bytes.Equal(prefix, ValidatorQueueKey) { + return time.Time{}, 0, fmt.Errorf("invalid prefix; expected: %X, got: %X", ValidatorQueueKey, prefix) + } + + timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) + ts, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) + if err != nil { + return time.Time{}, 0, err + } + + height := sdk.BigEndianToUint64(bz[prefixL+8+int(timeBzL):]) + + return ts, int64(height), nil +} + +// GetDelegationKey creates the key for delegator bond with validator +// VALUE: staking/Delegation +func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetDelegationsKey(delAddr), address.MustLengthPrefix(valAddr)...) +} + +// GetDelegationsKey creates the prefix for a delegator for all validators +func GetDelegationsKey(delAddr sdk.AccAddress) []byte { + return append(DelegationKey, address.MustLengthPrefix(delAddr)...) +} + +// GetUBDKey creates the key for an unbonding delegation by delegator and validator addr +// VALUE: staking/UnbondingDelegation +func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetUBDsKey(delAddr.Bytes()), address.MustLengthPrefix(valAddr)...) +} + +// GetUBDByValIndexKey creates the index-key for an unbonding delegation, stored by validator-index +// VALUE: none (key rearrangement used) +func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetUBDsByValIndexKey(valAddr), address.MustLengthPrefix(delAddr)...) +} + +// GetUBDKeyFromValIndexKey rearranges the ValIndexKey to get the UBDKey +func GetUBDKeyFromValIndexKey(indexKey []byte) []byte { + addrs := indexKey[1:] // remove prefix bytes + + valAddrLen := addrs[0] + valAddr := addrs[1 : 1+valAddrLen] + delAddr := addrs[valAddrLen+2:] + + return GetUBDKey(delAddr, valAddr) +} + +// GetUBDsKey creates the prefix for all unbonding delegations from a delegator +func GetUBDsKey(delAddr sdk.AccAddress) []byte { + return append(UnbondingDelegationKey, address.MustLengthPrefix(delAddr)...) +} + +// GetUBDsByValIndexKey creates the prefix keyspace for the indexes of unbonding delegations for a validator +func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { + return append(UnbondingDelegationByValIndexKey, address.MustLengthPrefix(valAddr)...) +} + +// GetUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator +func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { + bz := sdk.FormatTimeBytes(timestamp) + return append(UnbondingQueueKey, bz...) +} + +// GetREDKey returns a key prefix for indexing a redelegation from a delegator +// and source validator to a destination validator. +func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { + // key is of the form GetREDsKey || valSrcAddrLen (1 byte) || valSrcAddr || valDstAddrLen (1 byte) || valDstAddr + key := make([]byte, 1+3+len(delAddr)+len(valSrcAddr)+len(valDstAddr)) + + copy(key[0:2+len(delAddr)], GetREDsKey(delAddr.Bytes())) + key[2+len(delAddr)] = byte(len(valSrcAddr)) + copy(key[3+len(delAddr):3+len(delAddr)+len(valSrcAddr)], valSrcAddr.Bytes()) + key[3+len(delAddr)+len(valSrcAddr)] = byte(len(valDstAddr)) + copy(key[4+len(delAddr)+len(valSrcAddr):], valDstAddr.Bytes()) + + return key +} + +// GetREDByValSrcIndexKey creates the index-key for a redelegation, stored by source-validator-index +// VALUE: none (key rearrangement used) +func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { + REDSFromValsSrcKey := GetREDsFromValSrcIndexKey(valSrcAddr) + offset := len(REDSFromValsSrcKey) + + // key is of the form REDSFromValsSrcKey || delAddrLen (1 byte) || delAddr || valDstAddrLen (1 byte) || valDstAddr + key := make([]byte, offset+2+len(delAddr)+len(valDstAddr)) + copy(key[0:offset], REDSFromValsSrcKey) + key[offset] = byte(len(delAddr)) + copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) + key[offset+1+len(delAddr)] = byte(len(valDstAddr)) + copy(key[offset+2+len(delAddr):], valDstAddr.Bytes()) + + return key +} + +// GetREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index +// VALUE: none (key rearrangement used) +func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { + REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr) + offset := len(REDSToValsDstKey) + + // key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr + key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr)) + copy(key[0:offset], REDSToValsDstKey) + key[offset] = byte(len(delAddr)) + copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) + key[offset+1+len(delAddr)] = byte(len(valSrcAddr)) + copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes()) + + return key +} + +// GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey +func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte { + // note that first byte is prefix byte, which we remove + addrs := indexKey[1:] + + valSrcAddrLen := addrs[0] + valSrcAddr := addrs[1 : valSrcAddrLen+1] + delAddrLen := addrs[valSrcAddrLen+1] + delAddr := addrs[valSrcAddrLen+2 : valSrcAddrLen+2+delAddrLen] + valDstAddr := addrs[valSrcAddrLen+delAddrLen+3:] + + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey +func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte { + // note that first byte is prefix byte, which we remove + addrs := indexKey[1:] + + valDstAddrLen := addrs[0] + valDstAddr := addrs[1 : valDstAddrLen+1] + delAddrLen := addrs[valDstAddrLen+1] + delAddr := addrs[valDstAddrLen+2 : valDstAddrLen+2+delAddrLen] + valSrcAddr := addrs[valDstAddrLen+delAddrLen+3:] + + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// GetRedelegationTimeKey returns a key prefix for indexing an unbonding +// redelegation based on a completion time. +func GetRedelegationTimeKey(timestamp time.Time) []byte { + bz := sdk.FormatTimeBytes(timestamp) + return append(RedelegationQueueKey, bz...) +} + +// GetREDsKey returns a key prefix for indexing a redelegation from a delegator +// address. +func GetREDsKey(delAddr sdk.AccAddress) []byte { + return append(RedelegationKey, address.MustLengthPrefix(delAddr)...) +} + +// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to +// a source validator. +func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { + return append(RedelegationByValSrcIndexKey, address.MustLengthPrefix(valSrcAddr)...) +} + +// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a +// destination (target) validator. +func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte { + return append(RedelegationByValDstIndexKey, address.MustLengthPrefix(valDstAddr)...) +} + +// GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation +// from an address to a source validator. +func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte { + return append(GetREDsToValDstIndexKey(valDstAddr), address.MustLengthPrefix(delAddr)...) +} + +// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects. +func GetHistoricalInfoKey(height int64) []byte { + return append(HistoricalInfoKey, []byte(strconv.FormatInt(height, 10))...) +} diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go new file mode 100644 index 000000000000..bb351284706e --- /dev/null +++ b/x/staking/legacy/v042/store.go @@ -0,0 +1,70 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" +) + +// migratePrefixAddressAddressAddress is a helper function that migrates all keys of format: +// prefix_bytes | address_1_bytes | address_2_bytes | address_3_bytes +// into format: +// prefix_bytes | address_1_len (1 byte) | address_1_bytes | address_2_len (1 byte) | address_2_bytes | address_3_len (1 byte) | address_3_bytes +func migratePrefixAddressAddressAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr1 := oldStoreIter.Key()[:v040auth.AddrLen] + addr2 := oldStoreIter.Key()[v040auth.AddrLen : 2*v040auth.AddrLen] + addr3 := oldStoreIter.Key()[2*v040auth.AddrLen:] + newStoreKey := append(append(append( + prefixBz, + address.MustLengthPrefix(addr1)...), address.MustLengthPrefix(addr2)...), address.MustLengthPrefix(addr3)..., + ) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { + oldStore := prefix.NewStore(store, v040staking.ValidatorsByPowerIndexKey) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(store sdk.KVStore) error { + v042distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey) + + v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey) + v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsByConsAddrKey) + // todo ValidatorsByPowerIndexKey + + v042distribution.MigratePrefixAddressAddress(store, v040staking.DelegationKey) + v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationKey) + v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationByValIndexKey) + migratePrefixAddressAddressAddress(store, v040staking.RedelegationKey) + migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValSrcIndexKey) + migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValDstIndexKey) + + return nil +} diff --git a/x/staking/legacy/v042/store_test.go b/x/staking/legacy/v042/store_test.go new file mode 100644 index 000000000000..9086a3fd42c2 --- /dev/null +++ b/x/staking/legacy/v042/store_test.go @@ -0,0 +1,136 @@ +package v042_test + +import ( + "bytes" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" + v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/staking/teststaking" +) + +func TestStoreMigration(t *testing.T) { + stakingKey := sdk.NewKVStoreKey("staking") + ctx := testutil.DefaultContext(stakingKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(stakingKey) + + _, pk1, addr1 := testdata.KeyTestPubAddr() + valAddr1 := sdk.ValAddress(addr1) + val := teststaking.NewValidator(t, valAddr1, pk1) + _, pk1, addr2 := testdata.KeyTestPubAddr() + valAddr2 := sdk.ValAddress(addr2) + _, _, addr3 := testdata.KeyTestPubAddr() + consAddr := sdk.ConsAddress(addr3.String()) + _, _, addr4 := testdata.KeyTestPubAddr() + now := time.Now() + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "LastValidatorPowerKey", + v040staking.GetLastValidatorPowerKey(valAddr1), + v042staking.GetLastValidatorPowerKey(valAddr1), + }, + { + "LastTotalPowerKey", + v040staking.LastTotalPowerKey, + v042staking.LastTotalPowerKey, + }, + { + "ValidatorsKey", + v040staking.GetValidatorKey(valAddr1), + v042staking.GetValidatorKey(valAddr1), + }, + { + "ValidatorsByConsAddrKey", + v040staking.GetValidatorByConsAddrKey(consAddr), + v042staking.GetValidatorByConsAddrKey(consAddr), + }, + { + "ValidatorsByPowerIndexKey", + v040staking.GetValidatorsByPowerIndexKey(val), + v042staking.GetValidatorsByPowerIndexKey(val), + }, + { + "DelegationKey", + v040staking.GetDelegationKey(addr4, valAddr1), + v042staking.GetDelegationKey(addr4, valAddr1), + }, + { + "UnbondingDelegationKey", + v040staking.GetUBDKey(addr4, valAddr1), + v042staking.GetUBDKey(addr4, valAddr1), + }, + { + "UnbondingDelegationByValIndexKey", + v040staking.GetUBDByValIndexKey(addr4, valAddr1), + v042staking.GetUBDByValIndexKey(addr4, valAddr1), + }, + { + "RedelegationKey", + v040staking.GetREDKey(addr4, valAddr1, valAddr2), + v042staking.GetREDKey(addr4, valAddr1, valAddr2), + }, + { + "RedelegationByValSrcIndexKey", + v040staking.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), + v042staking.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), + }, + { + "RedelegationByValDstIndexKey", + v040staking.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), + v042staking.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), + }, + { + "UnbondingQueueKey", + v040staking.GetUnbondingDelegationTimeKey(now), + v042staking.GetUnbondingDelegationTimeKey(now), + }, + { + "RedelegationQueueKey", + v040staking.GetRedelegationTimeKey(now), + v042staking.GetRedelegationTimeKey(now), + }, + { + "ValidatorQueueKey", + v040staking.GetValidatorQueueKey(now, 4), + v042staking.GetValidatorQueueKey(now, 4), + }, + { + "HistoricalInfoKey", + v040staking.GetHistoricalInfoKey(4), + v042staking.GetHistoricalInfoKey(4), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042staking.MigrateStore(store) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} From a52441e6b183f2e28f40e568c855363ef64927ba Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 15:17:36 +0100 Subject: [PATCH 33/46] Fix staking tests --- x/staking/legacy/v042/store.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go index bb351284706e..449a7f83b63c 100644 --- a/x/staking/legacy/v042/store.go +++ b/x/staking/legacy/v042/store.go @@ -34,6 +34,8 @@ func migratePrefixAddressAddressAddress(store sdk.KVStore, prefixBz []byte) { } } +const powerBytesLen = 8 + func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { oldStore := prefix.NewStore(store, v040staking.ValidatorsByPowerIndexKey) @@ -41,6 +43,9 @@ func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { defer oldStoreIter.Close() for ; oldStoreIter.Valid(); oldStoreIter.Next() { + powerBytes := oldStoreIter.Key()[:8] + valAddr := oldStoreIter.Key()[8:] + newStoreKey := append(append(ValidatorsByPowerIndexKey, powerBytes...), address.MustLengthPrefix(valAddr)...) // Set new key on store. Values don't change. store.Set(newStoreKey, oldStoreIter.Value()) @@ -57,7 +62,7 @@ func MigrateStore(store sdk.KVStore) error { v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey) v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsByConsAddrKey) - // todo ValidatorsByPowerIndexKey + migrateValidatorsByPowerIndexKey(store) v042distribution.MigratePrefixAddressAddress(store, v040staking.DelegationKey) v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationKey) From b4037707d0393990537fbc3456dee67fc85bc295 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 3 Feb 2021 15:39:13 +0100 Subject: [PATCH 34/46] Update spec and module.go --- x/distribution/module.go | 2 ++ x/distribution/spec/02_state.md | 14 +++++++------- x/gov/module.go | 2 ++ x/slashing/module.go | 2 ++ x/slashing/spec/02_state.md | 4 ++-- x/staking/legacy/v042/store.go | 4 ++-- x/staking/module.go | 2 ++ x/staking/spec/01_state.md | 20 ++++++++++---------- 8 files changed, 29 insertions(+), 21 deletions(-) diff --git a/x/distribution/module.go b/x/distribution/module.go index 0f0c0d358a91..2b80338c803c 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -21,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" "github.com/cosmos/cosmos-sdk/x/distribution/client/rest" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" "github.com/cosmos/cosmos-sdk/x/distribution/simulation" "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -143,6 +144,7 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + cfg.RegisterMigration(types.ModuleName, 0, v042distribution.MigrateStore) } // InitGenesis performs genesis initialization for the distribution module. It returns diff --git a/x/distribution/spec/02_state.md b/x/distribution/spec/02_state.md index b8dbde4a9ae4..07dea459a00e 100644 --- a/x/distribution/spec/02_state.md +++ b/x/distribution/spec/02_state.md @@ -15,7 +15,7 @@ for fractions of coins to be received from operations like inflation. When coins are distributed from the pool they are truncated back to `sdk.Coins` which are non-decimal. -- FeePool: `0x00 -> ProtocolBuffer(FeePool)` +- FeePool: `0x00 -> ProtocolBuffer(FeePool)` ```go // coins with decimal @@ -33,12 +33,12 @@ type DecCoin struct { Validator distribution information for the relevant validator is updated each time: - 1. delegation amount to a validator is updated, - 2. a validator successfully proposes a block and receives a reward, - 3. any delegator withdraws from a validator, or - 4. the validator withdraws it's commission. +1. delegation amount to a validator is updated, +2. a validator successfully proposes a block and receives a reward, +3. any delegator withdraws from a validator, or +4. the validator withdraws it's commission. -- ValidatorDistInfo: `0x02 | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` +- ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` ```go type ValidatorDistInfo struct { @@ -56,7 +56,7 @@ properties change (aka bonded tokens etc.) its properties will remain constant and the delegator's _accumulation_ factor can be calculated passively knowing only the height of the last withdrawal and its current properties. -- DelegationDistInfo: `0x02 | DelegatorAddr | ValOperatorAddr -> ProtocolBuffer(delegatorDist)` +- DelegationDistInfo: `0x02 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(delegatorDist)` ```go type DelegationDistInfo struct { diff --git a/x/gov/module.go b/x/gov/module.go index b72a4bfe5f5c..487f24cb20da 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -25,6 +25,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov/client/cli" "github.com/cosmos/cosmos-sdk/x/gov/client/rest" "github.com/cosmos/cosmos-sdk/x/gov/keeper" + v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -159,6 +160,7 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + cfg.RegisterMigration(types.ModuleName, 0, v042gov.MigrateStore) } // InitGenesis performs genesis initialization for the gov module. It returns diff --git a/x/slashing/module.go b/x/slashing/module.go index ba5cfb60adb9..0ed370c01f65 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -22,6 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/slashing/client/cli" "github.com/cosmos/cosmos-sdk/x/slashing/client/rest" "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" "github.com/cosmos/cosmos-sdk/x/slashing/simulation" "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -141,6 +142,7 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + cfg.RegisterMigration(types.ModuleName, 0, v042slashing.MigrateStore) } // InitGenesis performs genesis initialization for the slashing module. It returns diff --git a/x/slashing/spec/02_state.md b/x/slashing/spec/02_state.md index 3644ff9651e9..8b2755a180b5 100644 --- a/x/slashing/spec/02_state.md +++ b/x/slashing/spec/02_state.md @@ -27,8 +27,8 @@ number of blocks by being automatically jailed, potentially slashed, and unbonde Information about validator's liveness activity is tracked through `ValidatorSigningInfo`. It is indexed in the store as follows: -- ValidatorSigningInfo: ` 0x01 | ConsAddress -> ProtocolBuffer(ValSigningInfo)` -- MissedBlocksBitArray: ` 0x02 | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format) +- ValidatorSigningInfo: ` 0x01 | ConsAddrLen (1 byte) | ConsAddress -> ProtocolBuffer(ValSigningInfo)` +- MissedBlocksBitArray: ` 0x02 | ConsAddrLen (1 byte) | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format) The first mapping allows us to easily lookup the recent signing info for a validator based on the validator's consensus address. diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go index 449a7f83b63c..02be5f38def8 100644 --- a/x/staking/legacy/v042/store.go +++ b/x/staking/legacy/v042/store.go @@ -43,8 +43,8 @@ func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { defer oldStoreIter.Close() for ; oldStoreIter.Valid(); oldStoreIter.Next() { - powerBytes := oldStoreIter.Key()[:8] - valAddr := oldStoreIter.Key()[8:] + powerBytes := oldStoreIter.Key()[:powerBytesLen] + valAddr := oldStoreIter.Key()[powerBytesLen:] newStoreKey := append(append(ValidatorsByPowerIndexKey, powerBytes...), address.MustLengthPrefix(valAddr)...) // Set new key on store. Values don't change. diff --git a/x/staking/module.go b/x/staking/module.go index 48c67e6f5cd1..b2e4bbce03c7 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -21,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/client/cli" "github.com/cosmos/cosmos-sdk/x/staking/client/rest" "github.com/cosmos/cosmos-sdk/x/staking/keeper" + v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" "github.com/cosmos/cosmos-sdk/x/staking/simulation" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -138,6 +139,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) querier := keeper.Querier{Keeper: am.keeper} types.RegisterQueryServer(cfg.QueryServer(), querier) + cfg.RegisterMigration(types.ModuleName, 0, v042staking.MigrateStore) } // InitGenesis performs genesis initialization for the staking module. It returns diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index e090acb01541..045bc5f35d44 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -44,10 +44,10 @@ required lookups for slashing and validator-set updates. A third special index throughout each block, unlike the first two indices which mirror the validator records within a block. -- Validators: `0x21 | OperatorAddr -> ProtocolBuffer(validator)` -- ValidatorsByConsAddr: `0x22 | ConsAddr -> OperatorAddr` -- ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddr -> OperatorAddr` -- LastValidatorsPower: `0x11 OperatorAddr -> ProtocolBuffer(ConsensusPower)` +- Validators: `0x21 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(validator)` +- ValidatorsByConsAddr: `0x22 | ConsAddrLen (1 byte) | ConsAddr -> OperatorAddr` +- ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddrLen (1 byte) | OperatorAddr -> OperatorAddr` +- LastValidatorsPower: `0x11 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(ConsensusPower)` `Validators` is the primary index - it ensures that each operator can have only one associated validator, where the public key of that validator can change in the @@ -79,7 +79,7 @@ Each validator's state is stored in a `Validator` struct: Delegations are identified by combining `DelegatorAddr` (the address of the delegator) with the `ValidatorAddr` Delegators are indexed in the store as follows: -- Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(delegation)` +- Delegation: `0x31 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(delegation)` Stake holders may delegate coins to validators; under this circumstance their funds are held in a `Delegation` data structure. It is owned by one @@ -115,8 +115,8 @@ detected. `UnbondingDelegation` are indexed in the store as: -- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` -- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> nil` +- UnbondingDelegation: `0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` +- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddrLen (1 byte) | ValidatorAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` The first map here is used in queries, to lookup all unbonding delegations for a given delegator, while the second map is used in slashing, to lookup all @@ -137,9 +137,9 @@ committed by the source validator. `Redelegation` are indexed in the store as: -- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` -- RedelegationsBySrc: `0x35 | ValidatorSrcAddr | ValidatorDstAddr | DelegatorAddr -> nil` -- RedelegationsByDst: `0x36 | ValidatorDstAddr | ValidatorSrcAddr | DelegatorAddr -> nil` +- Redelegations: `0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` +- RedelegationsBySrc: `0x35 | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` +- RedelegationsByDst: `0x36 | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` The first map here is used for queries, to lookup all redelegations for a given delegator. The second map is used for slashing based on the `ValidatorSrcAddr`, From 9546583c2dcb6642cee9b6ac2773fe32dbc2ec7d Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 8 Feb 2021 15:42:15 +0100 Subject: [PATCH 35/46] Update to latest changes --- x/capability/module.go | 2 +- x/distribution/legacy/v042/store.go | 4 +++- x/distribution/legacy/v042/store_test.go | 2 +- x/distribution/module.go | 2 +- x/gov/legacy/v042/store.go | 4 +++- x/gov/legacy/v042/store_test.go | 2 +- x/gov/module.go | 2 +- x/slashing/legacy/v042/store.go | 4 +++- x/slashing/legacy/v042/store_test.go | 2 +- x/staking/legacy/v042/store.go | 5 ++++- x/staking/legacy/v042/store_test.go | 2 +- x/staking/module.go | 2 +- 12 files changed, 21 insertions(+), 12 deletions(-) diff --git a/x/capability/module.go b/x/capability/module.go index 06bee1e2d029..1b285d14a865 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -137,7 +137,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/distribution/legacy/v042/store.go b/x/distribution/legacy/v042/store.go index 16b25c65ee74..723553a88466 100644 --- a/x/distribution/legacy/v042/store.go +++ b/x/distribution/legacy/v042/store.go @@ -1,6 +1,7 @@ package v042 import ( + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" ) @@ -9,7 +10,8 @@ import ( // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(store sdk.KVStore) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { + store := ctx.KVStore(storeKey) MigratePrefixAddress(store, v040distribution.ValidatorOutstandingRewardsPrefix) MigratePrefixAddress(store, v040distribution.DelegatorWithdrawAddrPrefix) MigratePrefixAddressAddress(store, v040distribution.DelegatorStartingInfoPrefix) diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go index a2855eabbf04..152b18838d66 100644 --- a/x/distribution/legacy/v042/store_test.go +++ b/x/distribution/legacy/v042/store_test.go @@ -82,7 +82,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042distribution.MigrateStore(store) + err := v042distribution.MigrateStore(ctx, distributionKey, nil) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/distribution/module.go b/x/distribution/module.go index 2b80338c803c..62f8595f31b3 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -164,7 +164,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock returns the begin blocker for the distribution module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/gov/legacy/v042/store.go b/x/gov/legacy/v042/store.go index 599fd2edff30..cfbafee5b998 100644 --- a/x/gov/legacy/v042/store.go +++ b/x/gov/legacy/v042/store.go @@ -1,6 +1,7 @@ package v042 import ( + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" @@ -34,7 +35,8 @@ func migratePrefixProposalAddress(store sdk.KVStore, prefixBz []byte) { // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(store sdk.KVStore) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { + store := ctx.KVStore(storeKey) migratePrefixProposalAddress(store, v040gov.DepositsKeyPrefix) migratePrefixProposalAddress(store, v040gov.VotesKeyPrefix) diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v042/store_test.go index 4fe218885cec..e5e80b527bb6 100644 --- a/x/gov/legacy/v042/store_test.go +++ b/x/gov/legacy/v042/store_test.go @@ -68,7 +68,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042gov.MigrateStore(store) + err := v042gov.MigrateStore(ctx, govKey, nil) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/gov/module.go b/x/gov/module.go index 487f24cb20da..96c19263b36f 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -180,7 +180,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/slashing/legacy/v042/store.go b/x/slashing/legacy/v042/store.go index d94c4a267296..8a472d887f4c 100644 --- a/x/slashing/legacy/v042/store.go +++ b/x/slashing/legacy/v042/store.go @@ -1,6 +1,7 @@ package v042 import ( + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" @@ -10,7 +11,8 @@ import ( // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(store sdk.KVStore) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { + store := ctx.KVStore(storeKey) v042distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix) v042distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix) v042distribution.MigratePrefixAddress(store, v040slashing.AddrPubkeyRelationKeyPrefix) diff --git a/x/slashing/legacy/v042/store_test.go b/x/slashing/legacy/v042/store_test.go index ba7e77f15f69..d04f7ec5176e 100644 --- a/x/slashing/legacy/v042/store_test.go +++ b/x/slashing/legacy/v042/store_test.go @@ -51,7 +51,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042slashing.MigrateStore(store) + err := v042slashing.MigrateStore(ctx, slashingKey, nil) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go index 02be5f38def8..0f782ea2ef1d 100644 --- a/x/staking/legacy/v042/store.go +++ b/x/staking/legacy/v042/store.go @@ -1,6 +1,7 @@ package v042 import ( + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" @@ -57,7 +58,9 @@ func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(store sdk.KVStore) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { + store := ctx.KVStore(storeKey) + v042distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey) v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey) diff --git a/x/staking/legacy/v042/store_test.go b/x/staking/legacy/v042/store_test.go index 9086a3fd42c2..affed1901345 100644 --- a/x/staking/legacy/v042/store_test.go +++ b/x/staking/legacy/v042/store_test.go @@ -120,7 +120,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042staking.MigrateStore(store) + err := v042staking.MigrateStore(ctx, stakingKey, nil) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/staking/module.go b/x/staking/module.go index b2e4bbce03c7..c9b4188cb51d 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -160,7 +160,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { From 9e5d6116462bb357a0d4c0a35175914511516326 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 10 Feb 2021 19:08:10 +0100 Subject: [PATCH 36/46] Update migration scripts --- types/module/module.go | 2 +- x/bank/module.go | 2 +- x/distribution/keeper/migrations.go | 20 ++++++++++++++++++++ x/distribution/legacy/v042/store.go | 3 +-- x/distribution/legacy/v042/store_test.go | 2 +- x/distribution/module.go | 5 +++-- x/gov/keeper/migrations.go | 20 ++++++++++++++++++++ x/gov/legacy/v042/store.go | 3 +-- x/gov/legacy/v042/store_test.go | 2 +- x/gov/module.go | 5 +++-- x/slashing/keeper/migrations.go | 20 ++++++++++++++++++++ x/slashing/legacy/v042/store.go | 3 +-- x/slashing/legacy/v042/store_test.go | 2 +- x/slashing/module.go | 5 +++-- x/staking/keeper/migrations.go | 20 ++++++++++++++++++++ x/staking/legacy/v042/store.go | 3 +-- x/staking/legacy/v042/store_test.go | 2 +- x/staking/module.go | 5 +++-- 18 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 x/distribution/keeper/migrations.go create mode 100644 x/gov/keeper/migrations.go create mode 100644 x/slashing/keeper/migrations.go create mode 100644 x/staking/keeper/migrations.go diff --git a/types/module/module.go b/types/module/module.go index 58bb4927b29a..b2234b99d0bd 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -339,7 +339,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st } // MigrationHandler is the migration function that each module registers. -type MigrationHandler func(store sdk.Context) error +type MigrationHandler func(sdk.Context) error // MigrationMap is a map of moduleName -> version, where version denotes the // version from which we should perform the migration for each module. diff --git a/x/bank/module.go b/x/bank/module.go index 77bff6b73b61..c0ce819fd2dc 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -100,7 +100,7 @@ type AppModule struct { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - cfg.RegisterMigration(types.ModuleName, 0, func(ctx sdk.Context) error { + cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { return am.keeper.(keeper.MigrationKeeper).Migrate1(ctx) }) } diff --git a/x/distribution/keeper/migrations.go b/x/distribution/keeper/migrations.go new file mode 100644 index 000000000000..e8ceafb63ab5 --- /dev/null +++ b/x/distribution/keeper/migrations.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" +) + +// MigrationKeeper is an interface that the keeper implements for handling +// in-place store migrations. +type MigrationKeeper interface { + // Migrate1 migrates the store from version 1 to 2. + Migrate1(ctx sdk.Context) error +} + +var _ MigrationKeeper = (*Keeper)(nil) + +// Migrate1 implements MigrationKeeper.Migrate1 method. +func (keeper Keeper) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, keeper.storeKey) +} diff --git a/x/distribution/legacy/v042/store.go b/x/distribution/legacy/v042/store.go index 723553a88466..31c575b4adc3 100644 --- a/x/distribution/legacy/v042/store.go +++ b/x/distribution/legacy/v042/store.go @@ -1,7 +1,6 @@ package v042 import ( - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" ) @@ -10,7 +9,7 @@ import ( // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) MigratePrefixAddress(store, v040distribution.ValidatorOutstandingRewardsPrefix) MigratePrefixAddress(store, v040distribution.DelegatorWithdrawAddrPrefix) diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go index 152b18838d66..992294e3aaf6 100644 --- a/x/distribution/legacy/v042/store_test.go +++ b/x/distribution/legacy/v042/store_test.go @@ -82,7 +82,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042distribution.MigrateStore(ctx, distributionKey, nil) + err := v042distribution.MigrateStore(ctx, distributionKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/distribution/module.go b/x/distribution/module.go index 62f8595f31b3..0b95845d260b 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -21,7 +21,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" "github.com/cosmos/cosmos-sdk/x/distribution/client/rest" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" "github.com/cosmos/cosmos-sdk/x/distribution/simulation" "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -144,7 +143,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - cfg.RegisterMigration(types.ModuleName, 0, v042distribution.MigrateStore) + cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { + return am.keeper.Migrate1(ctx) + }) } // InitGenesis performs genesis initialization for the distribution module. It returns diff --git a/x/gov/keeper/migrations.go b/x/gov/keeper/migrations.go new file mode 100644 index 000000000000..9f9f3107608f --- /dev/null +++ b/x/gov/keeper/migrations.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" +) + +// MigrationKeeper is an interface that the keeper implements for handling +// in-place store migrations. +type MigrationKeeper interface { + // Migrate1 migrates the store from version 1 to 2. + Migrate1(ctx sdk.Context) error +} + +var _ MigrationKeeper = (*Keeper)(nil) + +// Migrate1 implements MigrationKeeper.Migrate1 method. +func (keeper Keeper) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, keeper.storeKey) +} diff --git a/x/gov/legacy/v042/store.go b/x/gov/legacy/v042/store.go index cfbafee5b998..acf824a16139 100644 --- a/x/gov/legacy/v042/store.go +++ b/x/gov/legacy/v042/store.go @@ -1,7 +1,6 @@ package v042 import ( - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" @@ -35,7 +34,7 @@ func migratePrefixProposalAddress(store sdk.KVStore, prefixBz []byte) { // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) migratePrefixProposalAddress(store, v040gov.DepositsKeyPrefix) migratePrefixProposalAddress(store, v040gov.VotesKeyPrefix) diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v042/store_test.go index e5e80b527bb6..89edef75e0fa 100644 --- a/x/gov/legacy/v042/store_test.go +++ b/x/gov/legacy/v042/store_test.go @@ -68,7 +68,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042gov.MigrateStore(ctx, govKey, nil) + err := v042gov.MigrateStore(ctx, govKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/gov/module.go b/x/gov/module.go index 96c19263b36f..45bb4f331a83 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -25,7 +25,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov/client/cli" "github.com/cosmos/cosmos-sdk/x/gov/client/rest" "github.com/cosmos/cosmos-sdk/x/gov/keeper" - v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -160,7 +159,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - cfg.RegisterMigration(types.ModuleName, 0, v042gov.MigrateStore) + cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { + return am.keeper.Migrate1(ctx) + }) } // InitGenesis performs genesis initialization for the gov module. It returns diff --git a/x/slashing/keeper/migrations.go b/x/slashing/keeper/migrations.go new file mode 100644 index 000000000000..dd9e0f8c3c02 --- /dev/null +++ b/x/slashing/keeper/migrations.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" +) + +// MigrationKeeper is an interface that the keeper implements for handling +// in-place store migrations. +type MigrationKeeper interface { + // Migrate1 migrates the store from version 1 to 2. + Migrate1(ctx sdk.Context) error +} + +var _ MigrationKeeper = (*Keeper)(nil) + +// Migrate1 implements MigrationKeeper.Migrate1 method. +func (keeper Keeper) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, keeper.storeKey) +} diff --git a/x/slashing/legacy/v042/store.go b/x/slashing/legacy/v042/store.go index 8a472d887f4c..7864087b10ff 100644 --- a/x/slashing/legacy/v042/store.go +++ b/x/slashing/legacy/v042/store.go @@ -1,7 +1,6 @@ package v042 import ( - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" @@ -11,7 +10,7 @@ import ( // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) v042distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix) v042distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix) diff --git a/x/slashing/legacy/v042/store_test.go b/x/slashing/legacy/v042/store_test.go index d04f7ec5176e..be08c864c0a6 100644 --- a/x/slashing/legacy/v042/store_test.go +++ b/x/slashing/legacy/v042/store_test.go @@ -51,7 +51,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042slashing.MigrateStore(ctx, slashingKey, nil) + err := v042slashing.MigrateStore(ctx, slashingKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/slashing/module.go b/x/slashing/module.go index 0ed370c01f65..a9d36e2c0b90 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -22,7 +22,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/slashing/client/cli" "github.com/cosmos/cosmos-sdk/x/slashing/client/rest" "github.com/cosmos/cosmos-sdk/x/slashing/keeper" - v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" "github.com/cosmos/cosmos-sdk/x/slashing/simulation" "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -142,7 +141,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - cfg.RegisterMigration(types.ModuleName, 0, v042slashing.MigrateStore) + cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { + return am.keeper.Migrate1(ctx) + }) } // InitGenesis performs genesis initialization for the slashing module. It returns diff --git a/x/staking/keeper/migrations.go b/x/staking/keeper/migrations.go new file mode 100644 index 000000000000..e3ddaeef37d9 --- /dev/null +++ b/x/staking/keeper/migrations.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" +) + +// MigrationKeeper is an interface that the keeper implements for handling +// in-place store migrations. +type MigrationKeeper interface { + // Migrate1 migrates the store from version 1 to 2. + Migrate1(ctx sdk.Context) error +} + +var _ MigrationKeeper = (*Keeper)(nil) + +// Migrate1 implements MigrationKeeper.Migrate1 method. +func (keeper Keeper) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, keeper.storeKey) +} diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go index 0f782ea2ef1d..6e090e0076a9 100644 --- a/x/staking/legacy/v042/store.go +++ b/x/staking/legacy/v042/store.go @@ -1,7 +1,6 @@ package v042 import ( - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" @@ -58,7 +57,7 @@ func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, _ codec.Marshaler) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) v042distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey) diff --git a/x/staking/legacy/v042/store_test.go b/x/staking/legacy/v042/store_test.go index affed1901345..be082306aed0 100644 --- a/x/staking/legacy/v042/store_test.go +++ b/x/staking/legacy/v042/store_test.go @@ -120,7 +120,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042staking.MigrateStore(ctx, stakingKey, nil) + err := v042staking.MigrateStore(ctx, stakingKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/staking/module.go b/x/staking/module.go index c9b4188cb51d..1d22cbb22a51 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -21,7 +21,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/client/cli" "github.com/cosmos/cosmos-sdk/x/staking/client/rest" "github.com/cosmos/cosmos-sdk/x/staking/keeper" - v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" "github.com/cosmos/cosmos-sdk/x/staking/simulation" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -139,7 +138,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) querier := keeper.Querier{Keeper: am.keeper} types.RegisterQueryServer(cfg.QueryServer(), querier) - cfg.RegisterMigration(types.ModuleName, 0, v042staking.MigrateStore) + cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { + return am.keeper.Migrate1(ctx) + }) } // InitGenesis performs genesis initialization for the staking module. It returns From 518b8780e2ac530d26491c1bcd8302aa92ce8f52 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Thu, 11 Feb 2021 11:28:19 +0100 Subject: [PATCH 37/46] capability to 1 --- x/capability/module.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/capability/module.go b/x/capability/module.go index 1b285d14a865..06bee1e2d029 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -137,7 +137,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 2 } +func (AppModule) ConsensusVersion() uint64 { return 1 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} From 9b625b0eab4f0f95b9d720db14ba4fffd1b64937 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Thu, 11 Feb 2021 12:33:02 +0100 Subject: [PATCH 38/46] Fix tests --- simapp/app_test.go | 73 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 2adcf2e7e8d2..3d19a19f2624 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -11,8 +11,28 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/capability" + "github.com/cosmos/cosmos-sdk/x/crisis" + "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/evidence" + feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/gov" + transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" + "github.com/cosmos/cosmos-sdk/x/mint" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/upgrade" ) func TestSimAppExportAndBlockedAddrs(t *testing.T) { @@ -52,11 +72,34 @@ func TestGetMaccPerms(t *testing.T) { func TestRunMigrations(t *testing.T) { db := dbm.NewMemDB() encCfg := MakeTestEncodingConfig() - app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) - - // Create a new configurator for the purpose of this test. + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) + + // Create a new baseapp and configurator for the purpose of this test. + bApp := baseapp.NewBaseApp(appName, logger, db, encCfg.TxConfig.TxDecoder()) + bApp.SetCommitMultiStoreTracer(nil) + bApp.SetAppVersion(version.Version) + bApp.SetInterfaceRegistry(encCfg.InterfaceRegistry) + app.BaseApp = bApp app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) + // We register all modules on the Configurator, except x/bank. x/bank will + // serve as the test subject on which we run the migration tests. + // + // The loop below is the same as calling `RegisterServices` on + // ModuleManager, except that we skip x/bank. + for _, module := range app.mm.Modules { + if module.Name() == banktypes.ModuleName { + continue + } + + module.RegisterServices(app.configurator) + } + + // Initialize the chain + app.InitChain(abci.RequestInitChain{}) + app.Commit() + testCases := []struct { name string moduleName string @@ -115,12 +158,30 @@ func TestRunMigrations(t *testing.T) { } require.NoError(t, err) + // Run migrations for all modules from their current + // Consensusversion, except x/bank, which we start from the initial + // version 1, as we are specifically testing x/bank. err = app.RunMigrations( app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), module.MigrationMap{ - "auth": 1, "authz": 1, "bank": 1, "staking": 1, "mint": 1, "distribution": 1, - "slashing": 1, "gov": 1, "params": 1, "ibc": 1, "upgrade": 1, "vesting": 1, - "feegrant": 1, "transfer": 1, "evidence": 1, "crisis": 1, "genutil": 1, "capability": 1, + "bank": 1, + "auth": auth.AppModule{}.ConsensusVersion(), + "authz": authz.AppModule{}.ConsensusVersion(), + "staking": staking.AppModule{}.ConsensusVersion(), + "mint": mint.AppModule{}.ConsensusVersion(), + "distribution": distribution.AppModule{}.ConsensusVersion(), + "slashing": slashing.AppModule{}.ConsensusVersion(), + "gov": gov.AppModule{}.ConsensusVersion(), + "params": params.AppModule{}.ConsensusVersion(), + "ibc": ibc.AppModule{}.ConsensusVersion(), + "upgrade": upgrade.AppModule{}.ConsensusVersion(), + "vesting": vesting.AppModule{}.ConsensusVersion(), + "feegrant": feegrant.AppModule{}.ConsensusVersion(), + "transfer": transfer.AppModule{}.ConsensusVersion(), + "evidence": evidence.AppModule{}.ConsensusVersion(), + "crisis": crisis.AppModule{}.ConsensusVersion(), + "genutil": genutil.AppModule{}.ConsensusVersion(), + "capability": capability.AppModule{}.ConsensusVersion(), }, ) if tc.expRunErr { From c734484d1b9c74993fa6fef6f310d8d18d8135e4 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Thu, 11 Feb 2021 12:44:38 +0100 Subject: [PATCH 39/46] Add package godoc --- x/bank/legacy/v040/keys.go | 2 ++ x/bank/legacy/v042/keys.go | 2 ++ x/distribution/legacy/v040/keys.go | 2 ++ x/distribution/legacy/v042/keys.go | 2 ++ x/gov/legacy/v040/keys.go | 2 ++ x/gov/legacy/v042/keys.go | 2 ++ x/slashing/legacy/v040/keys.go | 2 ++ x/slashing/legacy/v042/keys.go | 2 ++ x/staking/legacy/v040/keys.go | 2 ++ x/staking/legacy/v042/keys.go | 2 ++ 10 files changed, 20 insertions(+) diff --git a/x/bank/legacy/v040/keys.go b/x/bank/legacy/v040/keys.go index bd1035599164..043c208b627c 100644 --- a/x/bank/legacy/v040/keys.go +++ b/x/bank/legacy/v040/keys.go @@ -1,3 +1,5 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/bank/types/key.go package v040 import ( diff --git a/x/bank/legacy/v042/keys.go b/x/bank/legacy/v042/keys.go index 8d718b1c5d3c..fc9aae8c0de4 100644 --- a/x/bank/legacy/v042/keys.go +++ b/x/bank/legacy/v042/keys.go @@ -1,3 +1,5 @@ +// Package v042 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/bank/types/key.go package v042 import ( diff --git a/x/distribution/legacy/v040/keys.go b/x/distribution/legacy/v040/keys.go index c83ab09f5582..88a3c78079bb 100644 --- a/x/distribution/legacy/v040/keys.go +++ b/x/distribution/legacy/v040/keys.go @@ -1,3 +1,5 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/distribution/types/keys.go package v040 import ( diff --git a/x/distribution/legacy/v042/keys.go b/x/distribution/legacy/v042/keys.go index 8f8ce391ef76..5d11677abc51 100644 --- a/x/distribution/legacy/v042/keys.go +++ b/x/distribution/legacy/v042/keys.go @@ -1,3 +1,5 @@ +// Package v042 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/distribution/types/keys.go package v042 import ( diff --git a/x/gov/legacy/v040/keys.go b/x/gov/legacy/v040/keys.go index 273dbcff10e7..b1559875bb1f 100644 --- a/x/gov/legacy/v040/keys.go +++ b/x/gov/legacy/v040/keys.go @@ -1,3 +1,5 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/gov/types/keys.go package v040 import ( diff --git a/x/gov/legacy/v042/keys.go b/x/gov/legacy/v042/keys.go index bfd380e6d344..1075d90d63e9 100644 --- a/x/gov/legacy/v042/keys.go +++ b/x/gov/legacy/v042/keys.go @@ -1,3 +1,5 @@ +// Package v042 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/gov/types/keys.go package v042 import ( diff --git a/x/slashing/legacy/v040/keys.go b/x/slashing/legacy/v040/keys.go index 0bcd5012e970..02cefbc4525e 100644 --- a/x/slashing/legacy/v040/keys.go +++ b/x/slashing/legacy/v040/keys.go @@ -1,3 +1,5 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/slashing/types/keys.go package v040 import ( diff --git a/x/slashing/legacy/v042/keys.go b/x/slashing/legacy/v042/keys.go index 63862c039349..992f9aad1dc4 100644 --- a/x/slashing/legacy/v042/keys.go +++ b/x/slashing/legacy/v042/keys.go @@ -1,3 +1,5 @@ +// Package v042 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/slashing/types/keys.go package v042 import ( diff --git a/x/staking/legacy/v040/keys.go b/x/staking/legacy/v040/keys.go index 108e262f1b37..8c074a1ed097 100644 --- a/x/staking/legacy/v040/keys.go +++ b/x/staking/legacy/v040/keys.go @@ -1,3 +1,5 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/staking/types/keys.go package v040 import ( diff --git a/x/staking/legacy/v042/keys.go b/x/staking/legacy/v042/keys.go index a43f3f9880ed..d8eb838e8320 100644 --- a/x/staking/legacy/v042/keys.go +++ b/x/staking/legacy/v042/keys.go @@ -1,3 +1,5 @@ +// Package v042 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/staking/types/keys.go package v042 import ( From 4942857c2d1161e2a4c22fb1bd0b86d6e0ad11d8 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:17:55 +0100 Subject: [PATCH 40/46] Remove whitespace --- x/distribution/spec/02_state.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/distribution/spec/02_state.md b/x/distribution/spec/02_state.md index 07dea459a00e..4111089cc7fd 100644 --- a/x/distribution/spec/02_state.md +++ b/x/distribution/spec/02_state.md @@ -33,10 +33,10 @@ type DecCoin struct { Validator distribution information for the relevant validator is updated each time: -1. delegation amount to a validator is updated, -2. a validator successfully proposes a block and receives a reward, -3. any delegator withdraws from a validator, or -4. the validator withdraws it's commission. +1. delegation amount to a validator is updated, +2. a validator successfully proposes a block and receives a reward, +3. any delegator withdraws from a validator, or +4. the validator withdraws it's commission. - ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` From 30d9045ecaa919afea25d20f1b59b0550cec0df8 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:18:01 +0100 Subject: [PATCH 41/46] Remove global --- simapp/app_test.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 3d19a19f2624..aa881407313a 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -14,7 +14,6 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/vesting" "github.com/cosmos/cosmos-sdk/x/authz" @@ -78,7 +77,6 @@ func TestRunMigrations(t *testing.T) { // Create a new baseapp and configurator for the purpose of this test. bApp := baseapp.NewBaseApp(appName, logger, db, encCfg.TxConfig.TxDecoder()) bApp.SetCommitMultiStoreTracer(nil) - bApp.SetAppVersion(version.Version) bApp.SetInterfaceRegistry(encCfg.InterfaceRegistry) app.BaseApp = bApp app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) @@ -158,9 +156,9 @@ func TestRunMigrations(t *testing.T) { } require.NoError(t, err) - // Run migrations for all modules from their current - // Consensusversion, except x/bank, which we start from the initial - // version 1, as we are specifically testing x/bank. + // Run migrations only for bank. That's why we put the initial + // version for bank as 1, and for all other modules, we put as + // their latest ConsensusVersion. err = app.RunMigrations( app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), module.MigrationMap{ From 828a41bb07222826111308de9792438437b26111 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:22:11 +0100 Subject: [PATCH 42/46] Use Migrator --- x/bank/keeper/migrations.go | 19 ++++++++++--------- x/bank/module.go | 4 +++- x/distribution/keeper/migrations.go | 19 ++++++++++--------- x/distribution/module.go | 4 +++- x/gov/keeper/migrations.go | 19 ++++++++++--------- x/gov/module.go | 4 +++- x/slashing/keeper/migrations.go | 19 ++++++++++--------- x/slashing/module.go | 4 +++- x/staking/keeper/migrations.go | 19 ++++++++++--------- x/staking/module.go | 4 +++- 10 files changed, 65 insertions(+), 50 deletions(-) diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go index de6b61a9c2b6..4141ecbcac72 100644 --- a/x/bank/keeper/migrations.go +++ b/x/bank/keeper/migrations.go @@ -5,16 +5,17 @@ import ( v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" ) -// MigrationKeeper is an interface that the keeper implements for handling -// in-place store migrations. -type MigrationKeeper interface { - // Migrate1 migrates the store from version 1 to 2. - Migrate1(ctx sdk.Context) error +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper BaseKeeper } -var _ MigrationKeeper = (*BaseKeeper)(nil) +// NewMigrator returns a new Migrator. +func NewMigrator(keeper BaseKeeper) Migrator { + return Migrator{keeper: keeper} +} -// Migrate1 implements MigrationKeeper.Migrate1 method. -func (keeper BaseKeeper) Migrate1(ctx sdk.Context) error { - return v042.MigrateStore(ctx, keeper.storeKey) +// Migrate1 migrates from version 1 to 2. +func (m Migrator) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/bank/module.go b/x/bank/module.go index c0ce819fd2dc..0fc9ad7a8ae7 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -100,8 +100,10 @@ type AppModule struct { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper)) cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return am.keeper.(keeper.MigrationKeeper).Migrate1(ctx) + return m.Migrate1(ctx) }) } diff --git a/x/distribution/keeper/migrations.go b/x/distribution/keeper/migrations.go index e8ceafb63ab5..34599c2622a7 100644 --- a/x/distribution/keeper/migrations.go +++ b/x/distribution/keeper/migrations.go @@ -5,16 +5,17 @@ import ( v042 "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" ) -// MigrationKeeper is an interface that the keeper implements for handling -// in-place store migrations. -type MigrationKeeper interface { - // Migrate1 migrates the store from version 1 to 2. - Migrate1(ctx sdk.Context) error +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper } -var _ MigrationKeeper = (*Keeper)(nil) +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} -// Migrate1 implements MigrationKeeper.Migrate1 method. -func (keeper Keeper) Migrate1(ctx sdk.Context) error { - return v042.MigrateStore(ctx, keeper.storeKey) +// Migrate1 migrates from version 1 to 2. +func (m Migrator) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/distribution/module.go b/x/distribution/module.go index 0b95845d260b..fab9a26bd308 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -143,8 +143,10 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.NewMigrator(am.keeper) cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return am.keeper.Migrate1(ctx) + return m.Migrate1(ctx) }) } diff --git a/x/gov/keeper/migrations.go b/x/gov/keeper/migrations.go index 9f9f3107608f..1c31489caeea 100644 --- a/x/gov/keeper/migrations.go +++ b/x/gov/keeper/migrations.go @@ -5,16 +5,17 @@ import ( v042 "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" ) -// MigrationKeeper is an interface that the keeper implements for handling -// in-place store migrations. -type MigrationKeeper interface { - // Migrate1 migrates the store from version 1 to 2. - Migrate1(ctx sdk.Context) error +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper } -var _ MigrationKeeper = (*Keeper)(nil) +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} -// Migrate1 implements MigrationKeeper.Migrate1 method. -func (keeper Keeper) Migrate1(ctx sdk.Context) error { - return v042.MigrateStore(ctx, keeper.storeKey) +// Migrate1 migrates from version 1 to 2. +func (m Migrator) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/gov/module.go b/x/gov/module.go index 45bb4f331a83..364d21efd11e 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -159,8 +159,10 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.Migrator{keeper: am.keeper} cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return am.keeper.Migrate1(ctx) + return m.Migrate1(ctx) }) } diff --git a/x/slashing/keeper/migrations.go b/x/slashing/keeper/migrations.go index dd9e0f8c3c02..7a5d5a4ea5aa 100644 --- a/x/slashing/keeper/migrations.go +++ b/x/slashing/keeper/migrations.go @@ -5,16 +5,17 @@ import ( v042 "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" ) -// MigrationKeeper is an interface that the keeper implements for handling -// in-place store migrations. -type MigrationKeeper interface { - // Migrate1 migrates the store from version 1 to 2. - Migrate1(ctx sdk.Context) error +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper } -var _ MigrationKeeper = (*Keeper)(nil) +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} -// Migrate1 implements MigrationKeeper.Migrate1 method. -func (keeper Keeper) Migrate1(ctx sdk.Context) error { - return v042.MigrateStore(ctx, keeper.storeKey) +// Migrate1 migrates from version 1 to 2. +func (m Migrator) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/slashing/module.go b/x/slashing/module.go index a9d36e2c0b90..86cb97f1eac8 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -141,8 +141,10 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.NewMigrator(am.keeper) cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return am.keeper.Migrate1(ctx) + return m.Migrate1(ctx) }) } diff --git a/x/staking/keeper/migrations.go b/x/staking/keeper/migrations.go index e3ddaeef37d9..70e738482e17 100644 --- a/x/staking/keeper/migrations.go +++ b/x/staking/keeper/migrations.go @@ -5,16 +5,17 @@ import ( v042 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" ) -// MigrationKeeper is an interface that the keeper implements for handling -// in-place store migrations. -type MigrationKeeper interface { - // Migrate1 migrates the store from version 1 to 2. - Migrate1(ctx sdk.Context) error +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper } -var _ MigrationKeeper = (*Keeper)(nil) +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} -// Migrate1 implements MigrationKeeper.Migrate1 method. -func (keeper Keeper) Migrate1(ctx sdk.Context) error { - return v042.MigrateStore(ctx, keeper.storeKey) +// Migrate1 migrates from version 1 to 2. +func (m Migrator) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/staking/module.go b/x/staking/module.go index 1d22cbb22a51..a8e7048ef4fa 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -138,8 +138,10 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) querier := keeper.Querier{Keeper: am.keeper} types.RegisterQueryServer(cfg.QueryServer(), querier) + + m := keeper.NewMigrator(am.keeper) cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return am.keeper.Migrate1(ctx) + return m.Migrate1(ctx) }) } From f3ca3e5e2afcd5850cf7c39c0c4643ebb29460f6 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:28:46 +0100 Subject: [PATCH 43/46] Remove 042 keys files --- x/bank/legacy/v042/keys.go | 52 ---- x/bank/legacy/v042/store.go | 3 +- x/bank/legacy/v042/store_test.go | 3 +- x/distribution/legacy/v042/keys.go | 216 --------------- x/distribution/legacy/v042/store_test.go | 19 +- x/gov/legacy/v042/keys.go | 165 ----------- x/gov/legacy/v042/store_test.go | 13 +- x/slashing/legacy/v042/keys.go | 69 ----- x/slashing/legacy/v042/store_test.go | 7 +- x/staking/legacy/v042/keys.go | 338 ----------------------- x/staking/legacy/v042/store_test.go | 31 ++- 11 files changed, 41 insertions(+), 875 deletions(-) delete mode 100644 x/bank/legacy/v042/keys.go delete mode 100644 x/distribution/legacy/v042/keys.go delete mode 100644 x/gov/legacy/v042/keys.go delete mode 100644 x/slashing/legacy/v042/keys.go delete mode 100644 x/staking/legacy/v042/keys.go diff --git a/x/bank/legacy/v042/keys.go b/x/bank/legacy/v042/keys.go deleted file mode 100644 index fc9aae8c0de4..000000000000 --- a/x/bank/legacy/v042/keys.go +++ /dev/null @@ -1,52 +0,0 @@ -// Package v042 is copy-pasted from: -// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/bank/types/key.go -package v042 - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" -) - -const ( - // ModuleName defines the module name - ModuleName = "bank" - - // StoreKey defines the primary module store key - StoreKey = ModuleName - - // RouterKey defines the module's message routing key - RouterKey = ModuleName - - // QuerierRoute defines the module's query routing key - QuerierRoute = ModuleName -) - -// KVStore keys -var ( - // BalancesPrefix is the for the account balances store. We use a byte - // (instead of say `[]]byte("balances")` to save some disk space). - BalancesPrefix = []byte{0x02} - SupplyKey = []byte{0x00} - DenomMetadataPrefix = []byte{0x1} -) - -// DenomMetadataKey returns the denomination metadata key. -func DenomMetadataKey(denom string) []byte { - d := []byte(denom) - return append(DenomMetadataPrefix, d...) -} - -// AddressFromBalancesStore returns an account address from a balances prefix -// store. The key must not contain the perfix BalancesPrefix as the prefix store -// iterator discards the actual prefix. -func AddressFromBalancesStore(key []byte) sdk.AccAddress { - addrLen := key[0] - addr := key[1 : addrLen+1] - - return sdk.AccAddress(addr) -} - -// CreateAccountBalancesPrefix creates the prefix for an account's balances. -func CreateAccountBalancesPrefix(addr []byte) []byte { - return append(BalancesPrefix, address.MustLengthPrefix(addr)...) -} diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go index 9295d8d2ff77..894305b6c8f7 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" + "github.com/cosmos/cosmos-sdk/x/bank/types" ) // MigrateStore performs in-place store migrations from v0.40 to v0.42. The @@ -27,7 +28,7 @@ func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { for ; oldStoreIter.Valid(); oldStoreIter.Next() { addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key()) denom := oldStoreIter.Key()[v040auth.AddrLen:] - newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...) + newStoreKey := append(types.CreateAccountBalancesPrefix(addr), denom...) // Set new key on store. Values don't change. store.Set(newStoreKey, oldStoreIter.Value()) diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index e1b6a7987a04..7481232f5c59 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -10,6 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" v042bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/bank/types" ) func TestStoreMigration(t *testing.T) { @@ -27,7 +28,7 @@ func TestStoreMigration(t *testing.T) { err := v042bank.MigrateStore(ctx, bankKey) require.NoError(t, err) - newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) + newKey := append(types.CreateAccountBalancesPrefix(addr), denom...) // -7 because we replaced "balances" with 0x02, // +1 because we added length-prefix to address. require.Equal(t, len(oldKey)-7+1, len(newKey)) diff --git a/x/distribution/legacy/v042/keys.go b/x/distribution/legacy/v042/keys.go deleted file mode 100644 index 5d11677abc51..000000000000 --- a/x/distribution/legacy/v042/keys.go +++ /dev/null @@ -1,216 +0,0 @@ -// Package v042 is copy-pasted from: -// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/distribution/types/keys.go -package v042 - -import ( - "encoding/binary" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" -) - -const ( - // ModuleName is the module name constant used in many places - ModuleName = "distribution" - - // StoreKey is the store key string for distribution - StoreKey = ModuleName - - // RouterKey is the message route for distribution - RouterKey = ModuleName - - // QuerierRoute is the querier route for distribution - QuerierRoute = ModuleName -) - -// Keys for distribution store -// Items are stored with the following key: values -// -// - 0x00: FeePol -// -// - 0x01: sdk.ConsAddress -// -// - 0x02: ValidatorOutstandingRewards -// -// - 0x03: sdk.AccAddress -// -// - 0x04: DelegatorStartingInfo -// -// - 0x05: ValidatorHistoricalRewards -// -// - 0x06: ValidatorCurrentRewards -// -// - 0x07: ValidatorCurrentRewards -// -// - 0x08: ValidatorSlashEvent -var ( - FeePoolKey = []byte{0x00} // key for global distribution state - ProposerKey = []byte{0x01} // key for the proposer operator address - ValidatorOutstandingRewardsPrefix = []byte{0x02} // key for outstanding rewards - - DelegatorWithdrawAddrPrefix = []byte{0x03} // key for delegator withdraw address - DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info - ValidatorHistoricalRewardsPrefix = []byte{0x05} // key for historical validators rewards / stake - ValidatorCurrentRewardsPrefix = []byte{0x06} // key for current validator rewards - ValidatorAccumulatedCommissionPrefix = []byte{0x07} // key for accumulated validator commission - ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction -) - -// GetValidatorOutstandingRewardsAddress creates an address from a validator's outstanding rewards key. -func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) { - // key is in the format: - // 0x02 - - // Remove prefix and address length. - addr := key[2:] - if len(addr) != int(key[1]) { - panic("unexpected key length") - } - - return sdk.ValAddress(addr) -} - -// GetDelegatorWithdrawInfoAddress creates an address from a delegator's withdraw info key. -func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) { - // key is in the format: - // 0x03 - - // Remove prefix and address length. - addr := key[2:] - if len(addr) != int(key[1]) { - panic("unexpected key length") - } - - return sdk.AccAddress(addr) -} - -// GetDelegatorStartingInfoAddresses creates the addresses from a delegator starting info key. -func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) { - // key is in the format: - // 0x04 - valAddrLen := int(key[1]) - valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) - delAddrLen := int(key[2+valAddrLen]) - delAddr = sdk.AccAddress(key[3+valAddrLen:]) - if len(delAddr.Bytes()) != delAddrLen { - panic("unexpected key length") - } - - return -} - -// GetValidatorHistoricalRewardsAddressPeriod creates the address & period from a validator's historical rewards key. -func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) { - // key is in the format: - // 0x05 - valAddrLen := int(key[1]) - valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) - b := key[2+valAddrLen:] - if len(b) != 8 { - panic("unexpected key length") - } - period = binary.LittleEndian.Uint64(b) - return -} - -// GetValidatorCurrentRewardsAddress creates the address from a validator's current rewards key. -func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) { - // key is in the format: - // 0x06: ValidatorCurrentRewards - - // Remove prefix and address length. - addr := key[2:] - if len(addr) != int(key[1]) { - panic("unexpected key length") - } - - return sdk.ValAddress(addr) -} - -// GetValidatorAccumulatedCommissionAddress creates the address from a validator's accumulated commission key. -func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) { - // key is in the format: - // 0x07: ValidatorCurrentRewards - - // Remove prefix and address length. - addr := key[2:] - if len(addr) != int(key[1]) { - panic("unexpected key length") - } - - return sdk.ValAddress(addr) -} - -// GetValidatorSlashEventAddressHeight creates the height from a validator's slash event key. -func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) { - // key is in the format: - // 0x08: ValidatorSlashEvent - valAddrLen := int(key[1]) - valAddr = key[2 : 2+valAddrLen] - startB := 2 + valAddrLen - b := key[startB : startB+8] // the next 8 bytes represent the height - height = binary.BigEndian.Uint64(b) - return -} - -// GetValidatorOutstandingRewardsKey creates the outstanding rewards key for a validator. -func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte { - return append(ValidatorOutstandingRewardsPrefix, address.MustLengthPrefix(valAddr.Bytes())...) -} - -// GetDelegatorWithdrawAddrKey creates the key for a delegator's withdraw addr. -func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { - return append(DelegatorWithdrawAddrPrefix, address.MustLengthPrefix(delAddr.Bytes())...) -} - -// GetDelegatorStartingInfoKey creates the key for a delegator's starting info. -func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte { - return append(append(DelegatorStartingInfoPrefix, address.MustLengthPrefix(v.Bytes())...), address.MustLengthPrefix(d.Bytes())...) -} - -// GetValidatorHistoricalRewardsPrefix creates the prefix key for a validator's historical rewards. -func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte { - return append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) -} - -// GetValidatorHistoricalRewardsKey creates the key for a validator's historical rewards. -func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte { - b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, k) - return append(append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...), b...) -} - -// GetValidatorCurrentRewardsKey creates the key for a validator's current rewards. -func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte { - return append(ValidatorCurrentRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) -} - -// GetValidatorAccumulatedCommissionKey creates the key for a validator's current commission. -func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte { - return append(ValidatorAccumulatedCommissionPrefix, address.MustLengthPrefix(v.Bytes())...) -} - -// GetValidatorSlashEventPrefix creates the prefix key for a validator's slash fractions. -func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte { - return append(ValidatorSlashEventPrefix, address.MustLengthPrefix(v.Bytes())...) -} - -// GetValidatorSlashEventKeyPrefix creates the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height). -func GetValidatorSlashEventKeyPrefix(v sdk.ValAddress, height uint64) []byte { - heightBz := make([]byte, 8) - binary.BigEndian.PutUint64(heightBz, height) - - return append( - ValidatorSlashEventPrefix, - append(address.MustLengthPrefix(v.Bytes()), heightBz...)..., - ) -} - -// GetValidatorSlashEventKey creates the key for a validator's slash fraction. -func GetValidatorSlashEventKey(v sdk.ValAddress, height, period uint64) []byte { - periodBz := make([]byte, 8) - binary.BigEndian.PutUint64(periodBz, period) - prefix := GetValidatorSlashEventKeyPrefix(v, height) - - return append(prefix, periodBz...) -} diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go index 992294e3aaf6..2a4a5df75bb1 100644 --- a/x/distribution/legacy/v042/store_test.go +++ b/x/distribution/legacy/v042/store_test.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/distribution/types" ) func TestStoreMigration(t *testing.T) { @@ -32,47 +33,47 @@ func TestStoreMigration(t *testing.T) { { "FeePoolKey", v040distribution.FeePoolKey, - v042distribution.FeePoolKey, + types.FeePoolKey, }, { "ProposerKey", v040distribution.ProposerKey, - v042distribution.ProposerKey, + types.ProposerKey, }, { "ValidatorOutstandingRewards", v040distribution.GetValidatorOutstandingRewardsKey(valAddr), - v042distribution.GetValidatorOutstandingRewardsKey(valAddr), + types.GetValidatorOutstandingRewardsKey(valAddr), }, { "DelegatorWithdrawAddr", v040distribution.GetDelegatorWithdrawAddrKey(addr2), - v042distribution.GetDelegatorWithdrawAddrKey(addr2), + types.GetDelegatorWithdrawAddrKey(addr2), }, { "DelegatorStartingInfo", v040distribution.GetDelegatorStartingInfoKey(valAddr, addr2), - v042distribution.GetDelegatorStartingInfoKey(valAddr, addr2), + types.GetDelegatorStartingInfoKey(valAddr, addr2), }, { "ValidatorHistoricalRewards", v040distribution.GetValidatorHistoricalRewardsKey(valAddr, 6), - v042distribution.GetValidatorHistoricalRewardsKey(valAddr, 6), + types.GetValidatorHistoricalRewardsKey(valAddr, 6), }, { "ValidatorCurrentRewards", v040distribution.GetValidatorCurrentRewardsKey(valAddr), - v042distribution.GetValidatorCurrentRewardsKey(valAddr), + types.GetValidatorCurrentRewardsKey(valAddr), }, { "ValidatorAccumulatedCommission", v040distribution.GetValidatorAccumulatedCommissionKey(valAddr), - v042distribution.GetValidatorAccumulatedCommissionKey(valAddr), + types.GetValidatorAccumulatedCommissionKey(valAddr), }, { "ValidatorSlashEvent", v040distribution.GetValidatorSlashEventKey(valAddr, 6, 8), - v042distribution.GetValidatorSlashEventKey(valAddr, 6, 8), + types.GetValidatorSlashEventKey(valAddr, 6, 8), }, } diff --git a/x/gov/legacy/v042/keys.go b/x/gov/legacy/v042/keys.go deleted file mode 100644 index 1075d90d63e9..000000000000 --- a/x/gov/legacy/v042/keys.go +++ /dev/null @@ -1,165 +0,0 @@ -// Package v042 is copy-pasted from: -// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/gov/types/keys.go -package v042 - -import ( - "encoding/binary" - "fmt" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" -) - -const ( - // ModuleName is the name of the module - ModuleName = "gov" - - // StoreKey is the store key string for gov - StoreKey = ModuleName - - // RouterKey is the message route for gov - RouterKey = ModuleName - - // QuerierRoute is the querier route for gov - QuerierRoute = ModuleName -) - -// Keys for governance store -// Items are stored with the following key: values -// -// - 0x00: Proposal -// -// - 0x01: activeProposalID -// -// - 0x02: inactiveProposalID -// -// - 0x03: nextProposalID -// -// - 0x10: Deposit -// -// - 0x20: Voter -var ( - ProposalsKeyPrefix = []byte{0x00} - ActiveProposalQueuePrefix = []byte{0x01} - InactiveProposalQueuePrefix = []byte{0x02} - ProposalIDKey = []byte{0x03} - - DepositsKeyPrefix = []byte{0x10} - - VotesKeyPrefix = []byte{0x20} -) - -var lenTime = len(sdk.FormatTimeBytes(time.Now())) - -// GetProposalIDBytes returns the byte representation of the proposalID -func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) { - proposalIDBz = make([]byte, 8) - binary.BigEndian.PutUint64(proposalIDBz, proposalID) - return -} - -// GetProposalIDFromBytes returns proposalID in uint64 format from a byte array -func GetProposalIDFromBytes(bz []byte) (proposalID uint64) { - return binary.BigEndian.Uint64(bz) -} - -// ProposalKey gets a specific proposal from the store -func ProposalKey(proposalID uint64) []byte { - return append(ProposalsKeyPrefix, GetProposalIDBytes(proposalID)...) -} - -// ActiveProposalByTimeKey gets the active proposal queue key by endTime -func ActiveProposalByTimeKey(endTime time.Time) []byte { - return append(ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) -} - -// ActiveProposalQueueKey returns the key for a proposalID in the activeProposalQueue -func ActiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { - return append(ActiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) -} - -// InactiveProposalByTimeKey gets the inactive proposal queue key by endTime -func InactiveProposalByTimeKey(endTime time.Time) []byte { - return append(InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) -} - -// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue -func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { - return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) -} - -// DepositsKey gets the first part of the deposits key based on the proposalID -func DepositsKey(proposalID uint64) []byte { - return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...) -} - -// DepositKey key of a specific deposit from the store -func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte { - return append(DepositsKey(proposalID), address.MustLengthPrefix(depositorAddr.Bytes())...) -} - -// VotesKey gets the first part of the votes key based on the proposalID -func VotesKey(proposalID uint64) []byte { - return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...) -} - -// VoteKey key of a specific vote from the store -func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte { - return append(VotesKey(proposalID), address.MustLengthPrefix(voterAddr.Bytes())...) -} - -// Split keys function; used for iterators - -// SplitProposalKey split the proposal key and returns the proposal id -func SplitProposalKey(key []byte) (proposalID uint64) { - if len(key[1:]) != 8 { - panic(fmt.Sprintf("unexpected key length (%d ≠ 8)", len(key[1:]))) - } - - return GetProposalIDFromBytes(key[1:]) -} - -// SplitActiveProposalQueueKey split the active proposal key and returns the proposal id and endTime -func SplitActiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { - return splitKeyWithTime(key) -} - -// SplitInactiveProposalQueueKey split the inactive proposal key and returns the proposal id and endTime -func SplitInactiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { - return splitKeyWithTime(key) -} - -// SplitKeyDeposit split the deposits key and returns the proposal id and depositor address -func SplitKeyDeposit(key []byte) (proposalID uint64, depositorAddr sdk.AccAddress) { - return splitKeyWithAddress(key) -} - -// SplitKeyVote split the votes key and returns the proposal id and voter address -func SplitKeyVote(key []byte) (proposalID uint64, voterAddr sdk.AccAddress) { - return splitKeyWithAddress(key) -} - -// private functions - -func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) { - if len(key[1:]) != 8+lenTime { - panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key[1:]), lenTime+8)) - } - - endTime, err := sdk.ParseTimeBytes(key[1 : 1+lenTime]) - if err != nil { - panic(err) - } - - proposalID = GetProposalIDFromBytes(key[1+lenTime:]) - return -} - -func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) { - // Both Vote and Deposit store keys are of format: - // - proposalID = GetProposalIDFromBytes(key[1:9]) - addr = sdk.AccAddress(key[10:]) - return -} diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v042/store_test.go index 89edef75e0fa..6bcb056a9c99 100644 --- a/x/gov/legacy/v042/store_test.go +++ b/x/gov/legacy/v042/store_test.go @@ -12,6 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/gov/types" ) func TestStoreMigration(t *testing.T) { @@ -33,32 +34,32 @@ func TestStoreMigration(t *testing.T) { { "ProposalKey", v040gov.ProposalKey(proposalID), - v042gov.ProposalKey(proposalID), + types.ProposalKey(proposalID), }, { "ActiveProposalQueue", v040gov.ActiveProposalQueueKey(proposalID, now), - v042gov.ActiveProposalQueueKey(proposalID, now), + types.ActiveProposalQueueKey(proposalID, now), }, { "InactiveProposalQueue", v040gov.InactiveProposalQueueKey(proposalID, now), - v042gov.InactiveProposalQueueKey(proposalID, now), + types.InactiveProposalQueueKey(proposalID, now), }, { "ProposalIDKey", v040gov.ProposalIDKey, - v042gov.ProposalIDKey, + types.ProposalIDKey, }, { "DepositKey", v040gov.DepositKey(proposalID, addr1), - v042gov.DepositKey(proposalID, addr1), + types.DepositKey(proposalID, addr1), }, { "VotesKeyPrefix", v040gov.VoteKey(proposalID, addr1), - v042gov.VoteKey(proposalID, addr1), + types.VoteKey(proposalID, addr1), }, } diff --git a/x/slashing/legacy/v042/keys.go b/x/slashing/legacy/v042/keys.go deleted file mode 100644 index 992f9aad1dc4..000000000000 --- a/x/slashing/legacy/v042/keys.go +++ /dev/null @@ -1,69 +0,0 @@ -// Package v042 is copy-pasted from: -// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/slashing/types/keys.go -package v042 - -import ( - "encoding/binary" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" -) - -const ( - // ModuleName is the name of the module - ModuleName = "slashing" - - // StoreKey is the store key string for slashing - StoreKey = ModuleName - - // RouterKey is the message route for slashing - RouterKey = ModuleName - - // QuerierRoute is the querier route for slashing - QuerierRoute = ModuleName -) - -// Keys for slashing store -// Items are stored with the following key: values -// -// - 0x01: ValidatorSigningInfo -// -// - 0x02: bool -// -// - 0x03: cryptotypes.PubKey -var ( - ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info - ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array - AddrPubkeyRelationKeyPrefix = []byte{0x03} // Prefix for address-pubkey relation -) - -// ValidatorSigningInfoKey - stored by *Consensus* address (not operator address) -func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte { - return append(ValidatorSigningInfoKeyPrefix, address.MustLengthPrefix(v.Bytes())...) -} - -// ValidatorSigningInfoAddress - extract the address from a validator signing info key -func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) { - // Remove prefix and address length. - addr := key[2:] - - return sdk.ConsAddress(addr) -} - -// ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address) -func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte { - return append(ValidatorMissedBlockBitArrayKeyPrefix, address.MustLengthPrefix(v.Bytes())...) -} - -// ValidatorMissedBlockBitArrayKey - stored by *Consensus* address (not operator address) -func ValidatorMissedBlockBitArrayKey(v sdk.ConsAddress, i int64) []byte { - b := make([]byte, 8) - binary.LittleEndian.PutUint64(b, uint64(i)) - - return append(ValidatorMissedBlockBitArrayPrefixKey(v), b...) -} - -// AddrPubkeyRelationKey gets pubkey relation key used to get the pubkey from the address -func AddrPubkeyRelationKey(addr []byte) []byte { - return append(AddrPubkeyRelationKeyPrefix, address.MustLengthPrefix(addr)...) -} diff --git a/x/slashing/legacy/v042/store_test.go b/x/slashing/legacy/v042/store_test.go index be08c864c0a6..60bf43a27b84 100644 --- a/x/slashing/legacy/v042/store_test.go +++ b/x/slashing/legacy/v042/store_test.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/slashing/types" ) func TestStoreMigration(t *testing.T) { @@ -31,17 +32,17 @@ func TestStoreMigration(t *testing.T) { { "ValidatorSigningInfoKey", v040slashing.ValidatorSigningInfoKey(consAddr), - v042slashing.ValidatorSigningInfoKey(consAddr), + types.ValidatorSigningInfoKey(consAddr), }, { "ValidatorMissedBlockBitArrayKey", v040slashing.ValidatorMissedBlockBitArrayKey(consAddr, 2), - v042slashing.ValidatorMissedBlockBitArrayKey(consAddr, 2), + types.ValidatorMissedBlockBitArrayKey(consAddr, 2), }, { "AddrPubkeyRelationKey", v040slashing.AddrPubkeyRelationKey(consAddr), - v042slashing.AddrPubkeyRelationKey(consAddr), + types.AddrPubkeyRelationKey(consAddr), }, } diff --git a/x/staking/legacy/v042/keys.go b/x/staking/legacy/v042/keys.go deleted file mode 100644 index d8eb838e8320..000000000000 --- a/x/staking/legacy/v042/keys.go +++ /dev/null @@ -1,338 +0,0 @@ -// Package v042 is copy-pasted from: -// https://github.com/cosmos/cosmos-sdk/blob/bddbc131fd232a0c4c3acf402eb5880109c96281/x/staking/types/keys.go -package v042 - -import ( - "bytes" - "encoding/binary" - "fmt" - "strconv" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -const ( - // ModuleName is the name of the staking module - ModuleName = "staking" - - // StoreKey is the string store representation - StoreKey = ModuleName - - // QuerierRoute is the querier route for the staking module - QuerierRoute = ModuleName - - // RouterKey is the msg router key for the staking module - RouterKey = ModuleName -) - -var ( - // Keys for store prefixes - // Last* values are constant during a block. - LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators - LastTotalPowerKey = []byte{0x12} // prefix for the total power - - ValidatorsKey = []byte{0x21} // prefix for each key to a validator - ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey - ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power - - DelegationKey = []byte{0x31} // key for a delegation - UnbondingDelegationKey = []byte{0x32} // key for an unbonding-delegation - UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator - RedelegationKey = []byte{0x34} // key for a redelegation - RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator - RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator - - UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue - RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue - ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue - - HistoricalInfoKey = []byte{0x50} // prefix for the historical info -) - -// GetValidatorKey creates the key for the validator with address -// VALUE: staking/Validator -func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { - return append(ValidatorsKey, address.MustLengthPrefix(operatorAddr)...) -} - -// GetValidatorByConsAddrKey creates the key for the validator with pubkey -// VALUE: validator operator address ([]byte) -func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { - return append(ValidatorsByConsAddrKey, address.MustLengthPrefix(addr)...) -} - -// AddressFromValidatorsKey creates the validator operator address from ValidatorsKey -func AddressFromValidatorsKey(key []byte) []byte { - return key[2:] // remove prefix bytes and address length -} - -// AddressFromLastValidatorPowerKey creates the validator operator address from LastValidatorPowerKey -func AddressFromLastValidatorPowerKey(key []byte) []byte { - return key[2:] // remove prefix bytes and address length -} - -// GetValidatorsByPowerIndexKey creates the validator by power index. -// Power index is the key used in the power-store, and represents the relative -// power ranking of the validator. -// VALUE: validator operator address ([]byte) -func GetValidatorsByPowerIndexKey(validator types.Validator) []byte { - // NOTE the address doesn't need to be stored because counter bytes must always be different - // NOTE the larger values are of higher value - - consensusPower := sdk.TokensToConsensusPower(validator.Tokens) - consensusPowerBytes := make([]byte, 8) - binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower)) - - powerBytes := consensusPowerBytes - powerBytesLen := len(powerBytes) // 8 - - addr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) - if err != nil { - panic(err) - } - operAddrInvr := sdk.CopyBytes(addr) - addrLen := len(operAddrInvr) - - for i, b := range operAddrInvr { - operAddrInvr[i] = ^b - } - - // key is of format prefix || powerbytes || addrLen (1byte) || addrBytes - key := make([]byte, 1+powerBytesLen+1+addrLen) - - key[0] = ValidatorsByPowerIndexKey[0] - copy(key[1:powerBytesLen+1], powerBytes) - key[powerBytesLen+1] = byte(addrLen) - copy(key[powerBytesLen+2:], operAddrInvr) - - return key -} - -// GetLastValidatorPowerKey creates the bonded validator index key for an operator address -func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { - return append(LastValidatorPowerKey, address.MustLengthPrefix(operator)...) -} - -// ParseValidatorPowerRankKey parses the validators operator address from power rank key -func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) { - powerBytesLen := 8 - - // key is of format prefix (1 byte) || powerbytes || addrLen (1byte) || addrBytes - operAddr = sdk.CopyBytes(key[powerBytesLen+2:]) - - for i, b := range operAddr { - operAddr[i] = ^b - } - - return operAddr -} - -// GetValidatorQueueKey returns the prefix key used for getting a set of unbonding -// validators whose unbonding completion occurs at the given time and height. -func GetValidatorQueueKey(timestamp time.Time, height int64) []byte { - heightBz := sdk.Uint64ToBigEndian(uint64(height)) - timeBz := sdk.FormatTimeBytes(timestamp) - timeBzL := len(timeBz) - prefixL := len(ValidatorQueueKey) - - bz := make([]byte, prefixL+8+timeBzL+8) - - // copy the prefix - copy(bz[:prefixL], ValidatorQueueKey) - - // copy the encoded time bytes length - copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL))) - - // copy the encoded time bytes - copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz) - - // copy the encoded height - copy(bz[prefixL+8+timeBzL:], heightBz) - - return bz -} - -// ParseValidatorQueueKey returns the encoded time and height from a key created -// from GetValidatorQueueKey. -func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) { - prefixL := len(ValidatorQueueKey) - if prefix := bz[:prefixL]; !bytes.Equal(prefix, ValidatorQueueKey) { - return time.Time{}, 0, fmt.Errorf("invalid prefix; expected: %X, got: %X", ValidatorQueueKey, prefix) - } - - timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) - ts, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) - if err != nil { - return time.Time{}, 0, err - } - - height := sdk.BigEndianToUint64(bz[prefixL+8+int(timeBzL):]) - - return ts, int64(height), nil -} - -// GetDelegationKey creates the key for delegator bond with validator -// VALUE: staking/Delegation -func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetDelegationsKey(delAddr), address.MustLengthPrefix(valAddr)...) -} - -// GetDelegationsKey creates the prefix for a delegator for all validators -func GetDelegationsKey(delAddr sdk.AccAddress) []byte { - return append(DelegationKey, address.MustLengthPrefix(delAddr)...) -} - -// GetUBDKey creates the key for an unbonding delegation by delegator and validator addr -// VALUE: staking/UnbondingDelegation -func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetUBDsKey(delAddr.Bytes()), address.MustLengthPrefix(valAddr)...) -} - -// GetUBDByValIndexKey creates the index-key for an unbonding delegation, stored by validator-index -// VALUE: none (key rearrangement used) -func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetUBDsByValIndexKey(valAddr), address.MustLengthPrefix(delAddr)...) -} - -// GetUBDKeyFromValIndexKey rearranges the ValIndexKey to get the UBDKey -func GetUBDKeyFromValIndexKey(indexKey []byte) []byte { - addrs := indexKey[1:] // remove prefix bytes - - valAddrLen := addrs[0] - valAddr := addrs[1 : 1+valAddrLen] - delAddr := addrs[valAddrLen+2:] - - return GetUBDKey(delAddr, valAddr) -} - -// GetUBDsKey creates the prefix for all unbonding delegations from a delegator -func GetUBDsKey(delAddr sdk.AccAddress) []byte { - return append(UnbondingDelegationKey, address.MustLengthPrefix(delAddr)...) -} - -// GetUBDsByValIndexKey creates the prefix keyspace for the indexes of unbonding delegations for a validator -func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { - return append(UnbondingDelegationByValIndexKey, address.MustLengthPrefix(valAddr)...) -} - -// GetUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator -func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { - bz := sdk.FormatTimeBytes(timestamp) - return append(UnbondingQueueKey, bz...) -} - -// GetREDKey returns a key prefix for indexing a redelegation from a delegator -// and source validator to a destination validator. -func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { - // key is of the form GetREDsKey || valSrcAddrLen (1 byte) || valSrcAddr || valDstAddrLen (1 byte) || valDstAddr - key := make([]byte, 1+3+len(delAddr)+len(valSrcAddr)+len(valDstAddr)) - - copy(key[0:2+len(delAddr)], GetREDsKey(delAddr.Bytes())) - key[2+len(delAddr)] = byte(len(valSrcAddr)) - copy(key[3+len(delAddr):3+len(delAddr)+len(valSrcAddr)], valSrcAddr.Bytes()) - key[3+len(delAddr)+len(valSrcAddr)] = byte(len(valDstAddr)) - copy(key[4+len(delAddr)+len(valSrcAddr):], valDstAddr.Bytes()) - - return key -} - -// GetREDByValSrcIndexKey creates the index-key for a redelegation, stored by source-validator-index -// VALUE: none (key rearrangement used) -func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { - REDSFromValsSrcKey := GetREDsFromValSrcIndexKey(valSrcAddr) - offset := len(REDSFromValsSrcKey) - - // key is of the form REDSFromValsSrcKey || delAddrLen (1 byte) || delAddr || valDstAddrLen (1 byte) || valDstAddr - key := make([]byte, offset+2+len(delAddr)+len(valDstAddr)) - copy(key[0:offset], REDSFromValsSrcKey) - key[offset] = byte(len(delAddr)) - copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) - key[offset+1+len(delAddr)] = byte(len(valDstAddr)) - copy(key[offset+2+len(delAddr):], valDstAddr.Bytes()) - - return key -} - -// GetREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index -// VALUE: none (key rearrangement used) -func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { - REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr) - offset := len(REDSToValsDstKey) - - // key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr - key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr)) - copy(key[0:offset], REDSToValsDstKey) - key[offset] = byte(len(delAddr)) - copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) - key[offset+1+len(delAddr)] = byte(len(valSrcAddr)) - copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes()) - - return key -} - -// GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey -func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte { - // note that first byte is prefix byte, which we remove - addrs := indexKey[1:] - - valSrcAddrLen := addrs[0] - valSrcAddr := addrs[1 : valSrcAddrLen+1] - delAddrLen := addrs[valSrcAddrLen+1] - delAddr := addrs[valSrcAddrLen+2 : valSrcAddrLen+2+delAddrLen] - valDstAddr := addrs[valSrcAddrLen+delAddrLen+3:] - - return GetREDKey(delAddr, valSrcAddr, valDstAddr) -} - -// GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey -func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte { - // note that first byte is prefix byte, which we remove - addrs := indexKey[1:] - - valDstAddrLen := addrs[0] - valDstAddr := addrs[1 : valDstAddrLen+1] - delAddrLen := addrs[valDstAddrLen+1] - delAddr := addrs[valDstAddrLen+2 : valDstAddrLen+2+delAddrLen] - valSrcAddr := addrs[valDstAddrLen+delAddrLen+3:] - - return GetREDKey(delAddr, valSrcAddr, valDstAddr) -} - -// GetRedelegationTimeKey returns a key prefix for indexing an unbonding -// redelegation based on a completion time. -func GetRedelegationTimeKey(timestamp time.Time) []byte { - bz := sdk.FormatTimeBytes(timestamp) - return append(RedelegationQueueKey, bz...) -} - -// GetREDsKey returns a key prefix for indexing a redelegation from a delegator -// address. -func GetREDsKey(delAddr sdk.AccAddress) []byte { - return append(RedelegationKey, address.MustLengthPrefix(delAddr)...) -} - -// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to -// a source validator. -func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { - return append(RedelegationByValSrcIndexKey, address.MustLengthPrefix(valSrcAddr)...) -} - -// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a -// destination (target) validator. -func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte { - return append(RedelegationByValDstIndexKey, address.MustLengthPrefix(valDstAddr)...) -} - -// GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation -// from an address to a source validator. -func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte { - return append(GetREDsToValDstIndexKey(valDstAddr), address.MustLengthPrefix(delAddr)...) -} - -// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects. -func GetHistoricalInfoKey(height int64) []byte { - return append(HistoricalInfoKey, []byte(strconv.FormatInt(height, 10))...) -} diff --git a/x/staking/legacy/v042/store_test.go b/x/staking/legacy/v042/store_test.go index be082306aed0..963ef02ed9c9 100644 --- a/x/staking/legacy/v042/store_test.go +++ b/x/staking/legacy/v042/store_test.go @@ -13,6 +13,7 @@ import ( v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" + "github.com/cosmos/cosmos-sdk/x/staking/types" ) func TestStoreMigration(t *testing.T) { @@ -40,77 +41,77 @@ func TestStoreMigration(t *testing.T) { { "LastValidatorPowerKey", v040staking.GetLastValidatorPowerKey(valAddr1), - v042staking.GetLastValidatorPowerKey(valAddr1), + types.GetLastValidatorPowerKey(valAddr1), }, { "LastTotalPowerKey", v040staking.LastTotalPowerKey, - v042staking.LastTotalPowerKey, + types.LastTotalPowerKey, }, { "ValidatorsKey", v040staking.GetValidatorKey(valAddr1), - v042staking.GetValidatorKey(valAddr1), + types.GetValidatorKey(valAddr1), }, { "ValidatorsByConsAddrKey", v040staking.GetValidatorByConsAddrKey(consAddr), - v042staking.GetValidatorByConsAddrKey(consAddr), + types.GetValidatorByConsAddrKey(consAddr), }, { "ValidatorsByPowerIndexKey", v040staking.GetValidatorsByPowerIndexKey(val), - v042staking.GetValidatorsByPowerIndexKey(val), + types.GetValidatorsByPowerIndexKey(val), }, { "DelegationKey", v040staking.GetDelegationKey(addr4, valAddr1), - v042staking.GetDelegationKey(addr4, valAddr1), + types.GetDelegationKey(addr4, valAddr1), }, { "UnbondingDelegationKey", v040staking.GetUBDKey(addr4, valAddr1), - v042staking.GetUBDKey(addr4, valAddr1), + types.GetUBDKey(addr4, valAddr1), }, { "UnbondingDelegationByValIndexKey", v040staking.GetUBDByValIndexKey(addr4, valAddr1), - v042staking.GetUBDByValIndexKey(addr4, valAddr1), + types.GetUBDByValIndexKey(addr4, valAddr1), }, { "RedelegationKey", v040staking.GetREDKey(addr4, valAddr1, valAddr2), - v042staking.GetREDKey(addr4, valAddr1, valAddr2), + types.GetREDKey(addr4, valAddr1, valAddr2), }, { "RedelegationByValSrcIndexKey", v040staking.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), - v042staking.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), + types.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), }, { "RedelegationByValDstIndexKey", v040staking.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), - v042staking.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), + types.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), }, { "UnbondingQueueKey", v040staking.GetUnbondingDelegationTimeKey(now), - v042staking.GetUnbondingDelegationTimeKey(now), + types.GetUnbondingDelegationTimeKey(now), }, { "RedelegationQueueKey", v040staking.GetRedelegationTimeKey(now), - v042staking.GetRedelegationTimeKey(now), + types.GetRedelegationTimeKey(now), }, { "ValidatorQueueKey", v040staking.GetValidatorQueueKey(now, 4), - v042staking.GetValidatorQueueKey(now, 4), + types.GetValidatorQueueKey(now, 4), }, { "HistoricalInfoKey", v040staking.GetHistoricalInfoKey(4), - v042staking.GetHistoricalInfoKey(4), + types.GetHistoricalInfoKey(4), }, } From 0e178480aa1cf77cd16694ea19fdfc37986142d9 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:30:25 +0100 Subject: [PATCH 44/46] Fix build --- x/gov/module.go | 2 +- x/staking/legacy/v042/store.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/gov/module.go b/x/gov/module.go index 364d21efd11e..37eb240e1116 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -160,7 +160,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) - m := keeper.Migrator{keeper: am.keeper} + m := keeper.NewMigrator(am.keeper) cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { return m.Migrate1(ctx) }) diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go index 6e090e0076a9..2be604e66099 100644 --- a/x/staking/legacy/v042/store.go +++ b/x/staking/legacy/v042/store.go @@ -7,6 +7,7 @@ import ( v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" + "github.com/cosmos/cosmos-sdk/x/staking/types" ) // migratePrefixAddressAddressAddress is a helper function that migrates all keys of format: @@ -45,7 +46,7 @@ func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { for ; oldStoreIter.Valid(); oldStoreIter.Next() { powerBytes := oldStoreIter.Key()[:powerBytesLen] valAddr := oldStoreIter.Key()[powerBytesLen:] - newStoreKey := append(append(ValidatorsByPowerIndexKey, powerBytes...), address.MustLengthPrefix(valAddr)...) + newStoreKey := append(append(types.ValidatorsByPowerIndexKey, powerBytes...), address.MustLengthPrefix(valAddr)...) // Set new key on store. Values don't change. store.Set(newStoreKey, oldStoreIter.Value()) From 5456591f7143ad70a6050b41b6f8c742c8d16fd0 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:38:26 +0100 Subject: [PATCH 45/46] Unlambda --- x/bank/module.go | 4 +--- x/distribution/module.go | 4 +--- x/gov/module.go | 4 +--- x/slashing/module.go | 4 +--- x/staking/module.go | 4 +--- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/x/bank/module.go b/x/bank/module.go index 0fc9ad7a8ae7..36cf5920f685 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -102,9 +102,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper)) - cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return m.Migrate1(ctx) - }) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) } // NewAppModule creates a new AppModule object diff --git a/x/distribution/module.go b/x/distribution/module.go index fab9a26bd308..0d98af219e69 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -145,9 +145,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return m.Migrate1(ctx) - }) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) } // InitGenesis performs genesis initialization for the distribution module. It returns diff --git a/x/gov/module.go b/x/gov/module.go index 37eb240e1116..91e4ce08b836 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -161,9 +161,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return m.Migrate1(ctx) - }) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) } // InitGenesis performs genesis initialization for the gov module. It returns diff --git a/x/slashing/module.go b/x/slashing/module.go index 86cb97f1eac8..dbd208179fb6 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -143,9 +143,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return m.Migrate1(ctx) - }) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) } // InitGenesis performs genesis initialization for the slashing module. It returns diff --git a/x/staking/module.go b/x/staking/module.go index a8e7048ef4fa..38d88fc7808a 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -140,9 +140,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), querier) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { - return m.Migrate1(ctx) - }) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) } // InitGenesis performs genesis initialization for the staking module. It returns From 036bd3023936a90639ee5de35ed0c0ff6ce2628d Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Thu, 25 Feb 2021 11:31:29 +0100 Subject: [PATCH 46/46] Rename to Migrate1to2 --- x/bank/keeper/migrations.go | 4 ++-- x/bank/module.go | 2 +- x/distribution/keeper/migrations.go | 4 ++-- x/distribution/module.go | 2 +- x/gov/keeper/migrations.go | 4 ++-- x/gov/module.go | 2 +- x/slashing/keeper/migrations.go | 4 ++-- x/slashing/module.go | 2 +- x/staking/keeper/migrations.go | 4 ++-- x/staking/module.go | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go index 4141ecbcac72..3a200fc2730d 100644 --- a/x/bank/keeper/migrations.go +++ b/x/bank/keeper/migrations.go @@ -15,7 +15,7 @@ func NewMigrator(keeper BaseKeeper) Migrator { return Migrator{keeper: keeper} } -// Migrate1 migrates from version 1 to 2. -func (m Migrator) Migrate1(ctx sdk.Context) error { +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/bank/module.go b/x/bank/module.go index eb0fc185dc09..3e728e6039fe 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -100,7 +100,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper)) - cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // NewAppModule creates a new AppModule object diff --git a/x/distribution/keeper/migrations.go b/x/distribution/keeper/migrations.go index 34599c2622a7..7c5d40dba4db 100644 --- a/x/distribution/keeper/migrations.go +++ b/x/distribution/keeper/migrations.go @@ -15,7 +15,7 @@ func NewMigrator(keeper Keeper) Migrator { return Migrator{keeper: keeper} } -// Migrate1 migrates from version 1 to 2. -func (m Migrator) Migrate1(ctx sdk.Context) error { +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/distribution/module.go b/x/distribution/module.go index f8a0d3a4a500..d6261d3cd573 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -143,7 +143,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the distribution module. It returns diff --git a/x/gov/keeper/migrations.go b/x/gov/keeper/migrations.go index 1c31489caeea..c643c6dd7b99 100644 --- a/x/gov/keeper/migrations.go +++ b/x/gov/keeper/migrations.go @@ -15,7 +15,7 @@ func NewMigrator(keeper Keeper) Migrator { return Migrator{keeper: keeper} } -// Migrate1 migrates from version 1 to 2. -func (m Migrator) Migrate1(ctx sdk.Context) error { +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/gov/module.go b/x/gov/module.go index 910bcd1f1c13..5e24cda3ab13 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -159,7 +159,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the gov module. It returns diff --git a/x/slashing/keeper/migrations.go b/x/slashing/keeper/migrations.go index 7a5d5a4ea5aa..b1bda4ab648e 100644 --- a/x/slashing/keeper/migrations.go +++ b/x/slashing/keeper/migrations.go @@ -15,7 +15,7 @@ func NewMigrator(keeper Keeper) Migrator { return Migrator{keeper: keeper} } -// Migrate1 migrates from version 1 to 2. -func (m Migrator) Migrate1(ctx sdk.Context) error { +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/slashing/module.go b/x/slashing/module.go index f6043f02091b..69e96b49d68d 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -141,7 +141,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), am.keeper) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the slashing module. It returns diff --git a/x/staking/keeper/migrations.go b/x/staking/keeper/migrations.go index 70e738482e17..948f93ed67af 100644 --- a/x/staking/keeper/migrations.go +++ b/x/staking/keeper/migrations.go @@ -15,7 +15,7 @@ func NewMigrator(keeper Keeper) Migrator { return Migrator{keeper: keeper} } -// Migrate1 migrates from version 1 to 2. -func (m Migrator) Migrate1(ctx sdk.Context) error { +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/staking/module.go b/x/staking/module.go index e12fe5790f44..067620cc6f38 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -140,7 +140,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), querier) m := keeper.NewMigrator(am.keeper) - cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the staking module. It returns