Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add in-place store migrations #8485

Merged
merged 33 commits into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
10d72d7
Add 1st version of migrate
amaury1093 Feb 1, 2021
8036fca
Merge branch 'master' of ssh://github.com/cosmos/cosmos-sdk into am-8…
amaury1093 Feb 2, 2021
a9a406e
Put migration logic into Configurator
amaury1093 Feb 2, 2021
9ed3987
add test to bank store migration
amaury1093 Feb 2, 2021
a095d3a
add test for configurator
amaury1093 Feb 2, 2021
d550bff
Merge branch 'master' into am-8345-migration
amaury1093 Feb 2, 2021
b7141f9
Error if no migration found
amaury1093 Feb 3, 2021
2d554ce
Remove RunMigrations from Configurator interface
amaury1093 Feb 3, 2021
3df3f44
Update spec
amaury1093 Feb 3, 2021
ba6bd44
Rename folders
amaury1093 Feb 3, 2021
197b7ce
Merge branch 'master' into am-8345-migration
amaury1093 Feb 3, 2021
424932c
copy-paste from keys.go
amaury1093 Feb 3, 2021
254a71f
Merge branch 'am-8345-migration' of ssh://github.com/cosmos/cosmos-sd…
amaury1093 Feb 3, 2021
b6c0714
Fix nil map
amaury1093 Feb 3, 2021
9ab7f13
rename function
amaury1093 Feb 3, 2021
fc076f5
Update simapp/app.go
amaury1093 Feb 5, 2021
ae7b7dc
Update simapp/app_test.go
amaury1093 Feb 5, 2021
2c26734
Adderss reviews
amaury1093 Feb 8, 2021
eb15047
Merge branch 'am-8345-migration' of ssh://github.com/cosmos/cosmos-sd…
amaury1093 Feb 8, 2021
291a9e6
Fix tests
amaury1093 Feb 8, 2021
41d29ed
Update testutil/context.go
amaury1093 Feb 8, 2021
33494dc
Update docs for ConsensusVersion
amaury1093 Feb 8, 2021
e3a2412
Rename to forVersion
amaury1093 Feb 8, 2021
6db31d4
Merge branch 'am-8345-migration' of ssh://github.com/cosmos/cosmos-sd…
amaury1093 Feb 8, 2021
55f547e
Fix tests
amaury1093 Feb 8, 2021
8f3b9d4
Check error early
amaury1093 Feb 8, 2021
29b85b7
Return 1 for intiial version
amaury1093 Feb 8, 2021
41e0339
Use MigrationKeeper
amaury1093 Feb 10, 2021
d922003
Fix test
amaury1093 Feb 10, 2021
f422b93
Revert adding marshaler to Configurator
amaury1093 Feb 10, 2021
8cf88fe
Godoc updates
amaury1093 Feb 10, 2021
5add13a
Update docs
amaury1093 Feb 10, 2021
2cef291
Merge branch 'master' into am-8345-migration
aaronc Feb 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
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()
Expand Down
14 changes: 14 additions & 0 deletions types/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ type AppModule interface {
// RegisterServices allows a module to register services
RegisterServices(Configurator)

// ConsensusVersion tracks state-breaking versions of the module
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
ConsensusVersion() uint64

// MigrateStore performs in-place store migrations.
MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, fromVersion uint64) error
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved

// ABCI
BeginBlock(sdk.Context, abci.RequestBeginBlock)
EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
Expand Down Expand Up @@ -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.
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 0 }
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved

// 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) {}

Expand Down
4 changes: 4 additions & 0 deletions x/auth/legacy/v040/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package v040

// AddrLen defines a valid address length
const AddrLen = 20
8 changes: 8 additions & 0 deletions x/auth/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down
8 changes: 8 additions & 0 deletions x/auth/vesting/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
8 changes: 8 additions & 0 deletions x/authz/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions x/bank/legacy/v040/store.go
Original file line number Diff line number Diff line change
@@ -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)
}
59 changes: 59 additions & 0 deletions x/bank/legacy/v042/store.go
Original file line number Diff line number Diff line change
@@ -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
}
7 changes: 7 additions & 0 deletions x/bank/legacy/v042/store_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package v042_test

import "testing"

func TestStoreMigration(t *testing.T) {
// TODO
}
5 changes: 5 additions & 0 deletions x/bank/legacy/v042/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package v042

const (
ModuleName = "bank"
)
25 changes: 25 additions & 0 deletions x/bank/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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) {}

Expand Down
8 changes: 8 additions & 0 deletions x/capability/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down
8 changes: 8 additions & 0 deletions x/crisis/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down
8 changes: 8 additions & 0 deletions x/distribution/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions x/evidence/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions x/feegrant/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down
8 changes: 8 additions & 0 deletions x/genutil/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
8 changes: 8 additions & 0 deletions x/gov/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down
8 changes: 8 additions & 0 deletions x/ibc/applications/transfer/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
}
Expand Down
8 changes: 8 additions & 0 deletions x/ibc/core/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions x/mint/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading