From 59592cf84440535066474af6248ea0d6b0a15f83 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 29 Jan 2020 23:20:30 -0500 Subject: [PATCH] Merge PR #5589: ADR 004 Geneis Migration --- x/auth/legacy/v0_38/migrate.go | 4 +- x/auth/legacy/v0_38/types.go | 12 ++-- x/auth/legacy/v0_39/migrate.go | 23 ++++++++ x/auth/legacy/v0_39/migrate_test.go | 87 +++++++++++++++++++++++++++++ x/auth/legacy/v0_39/types.go | 8 +++ x/bank/legacy/v0_38/types.go | 14 +++++ x/bank/legacy/v0_39/migrate.go | 22 ++++++++ x/bank/legacy/v0_39/migrate_test.go | 67 ++++++++++++++++++++++ x/bank/legacy/v0_39/types.go | 43 ++++++++++++++ x/genutil/client/cli/migrate.go | 2 + x/genutil/legacy/v0_39/migrate.go | 55 ++++++++++++++++++ 11 files changed, 329 insertions(+), 8 deletions(-) create mode 100644 x/auth/legacy/v0_39/migrate.go create mode 100644 x/auth/legacy/v0_39/migrate_test.go create mode 100644 x/auth/legacy/v0_39/types.go create mode 100644 x/bank/legacy/v0_38/types.go create mode 100644 x/bank/legacy/v0_39/migrate.go create mode 100644 x/bank/legacy/v0_39/migrate_test.go create mode 100644 x/bank/legacy/v0_39/types.go create mode 100644 x/genutil/legacy/v0_39/migrate.go diff --git a/x/auth/legacy/v0_38/migrate.go b/x/auth/legacy/v0_38/migrate.go index e76937777678..f4a32b4454c3 100644 --- a/x/auth/legacy/v0_38/migrate.go +++ b/x/auth/legacy/v0_38/migrate.go @@ -42,9 +42,9 @@ func Migrate(authGenState v036auth.GenesisState, genAccountsGenState v036genacco accounts[i] = genAccount } - accounts = sanitizeGenesisAccounts(accounts) + accounts = SanitizeGenesisAccounts(accounts) - if err := validateGenAccounts(accounts); err != nil { + if err := ValidateGenAccounts(accounts); err != nil { panic(err) } diff --git a/x/auth/legacy/v0_38/types.go b/x/auth/legacy/v0_38/types.go index 15896a39121f..1502fb27dbf0 100644 --- a/x/auth/legacy/v0_38/types.go +++ b/x/auth/legacy/v0_38/types.go @@ -46,7 +46,7 @@ type ( BaseAccount struct { Address sdk.AccAddress `json:"address" yaml:"address"` - Coins sdk.Coins `json:"coins" yaml:"coins"` + Coins sdk.Coins `json:"coins,omitempty" yaml:"coins,omitempty"` PubKey crypto.PubKey `json:"public_key" yaml:"public_key"` AccountNumber uint64 `json:"account_number" yaml:"account_number"` Sequence uint64 `json:"sequence" yaml:"sequence"` @@ -54,7 +54,7 @@ type ( baseAccountPretty struct { Address sdk.AccAddress `json:"address" yaml:"address"` - Coins sdk.Coins `json:"coins" yaml:"coins"` + Coins sdk.Coins `json:"coins,omitempty" yaml:"coins,omitempty"` PubKey string `json:"public_key" yaml:"public_key"` AccountNumber uint64 `json:"account_number" yaml:"account_number"` Sequence uint64 `json:"sequence" yaml:"sequence"` @@ -72,7 +72,7 @@ type ( vestingAccountPretty struct { Address sdk.AccAddress `json:"address" yaml:"address"` - Coins sdk.Coins `json:"coins" yaml:"coins"` + Coins sdk.Coins `json:"coins,omitempty" yaml:"coins,omitempty"` PubKey string `json:"public_key" yaml:"public_key"` AccountNumber uint64 `json:"account_number" yaml:"account_number"` Sequence uint64 `json:"sequence" yaml:"sequence"` @@ -104,7 +104,7 @@ type ( moduleAccountPretty struct { Address sdk.AccAddress `json:"address" yaml:"address"` - Coins sdk.Coins `json:"coins" yaml:"coins"` + Coins sdk.Coins `json:"coins,omitempty" yaml:"coins,omitempty"` PubKey string `json:"public_key" yaml:"public_key"` AccountNumber uint64 `json:"account_number" yaml:"account_number"` Sequence uint64 `json:"sequence" yaml:"sequence"` @@ -486,7 +486,7 @@ func validatePermissions(permissions ...string) error { return nil } -func sanitizeGenesisAccounts(genAccounts GenesisAccounts) GenesisAccounts { +func SanitizeGenesisAccounts(genAccounts GenesisAccounts) GenesisAccounts { sort.Slice(genAccounts, func(i, j int) bool { return genAccounts[i].GetAccountNumber() < genAccounts[j].GetAccountNumber() }) @@ -500,7 +500,7 @@ func sanitizeGenesisAccounts(genAccounts GenesisAccounts) GenesisAccounts { return genAccounts } -func validateGenAccounts(genAccounts GenesisAccounts) error { +func ValidateGenAccounts(genAccounts GenesisAccounts) error { addrMap := make(map[string]bool, len(genAccounts)) for _, acc := range genAccounts { diff --git a/x/auth/legacy/v0_39/migrate.go b/x/auth/legacy/v0_39/migrate.go new file mode 100644 index 000000000000..82b1390869f8 --- /dev/null +++ b/x/auth/legacy/v0_39/migrate.go @@ -0,0 +1,23 @@ +package v039 + +import ( + "fmt" + + v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" +) + +// Migrate accepts exported x/auth genesis state from v0.38 and migrates it to +// v0.39 x/auth genesis state. The migration includes: +// +// - Removing coins from account encoding. +func Migrate(authGenState v038auth.GenesisState) v038auth.GenesisState { + for _, account := range authGenState.Accounts { + // set coins to nil and allow the JSON encoding to omit coins + if err := account.SetCoins(nil); err != nil { + panic(fmt.Sprintf("failed to set account coins to nil: %s", err)) + } + } + + authGenState.Accounts = v038auth.SanitizeGenesisAccounts(authGenState.Accounts) + return authGenState +} diff --git a/x/auth/legacy/v0_39/migrate_test.go b/x/auth/legacy/v0_39/migrate_test.go new file mode 100644 index 000000000000..5f9cee0d257c --- /dev/null +++ b/x/auth/legacy/v0_39/migrate_test.go @@ -0,0 +1,87 @@ +package v039_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" + v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" + v039 "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_39" + + "github.com/stretchr/testify/require" +) + +func TestMigrate(t *testing.T) { + v039Codec := codec.New() + codec.RegisterCrypto(v039Codec) + v038auth.RegisterCodec(v039Codec) + + coins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50)) + addr1, _ := sdk.AccAddressFromBech32("cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u") + acc1 := v038auth.NewBaseAccount(addr1, coins, nil, 1, 0) + + addr2, _ := sdk.AccAddressFromBech32("cosmos15v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74") + vaac := v038auth.NewContinuousVestingAccountRaw( + v038auth.NewBaseVestingAccount( + v038auth.NewBaseAccount(addr2, coins, nil, 1, 0), coins, nil, nil, 3160620846, + ), + 1580309972, + ) + + gs := v038auth.GenesisState{ + Params: v0_34.Params{ + MaxMemoCharacters: 10, + TxSigLimit: 10, + TxSizeCostPerByte: 10, + SigVerifyCostED25519: 10, + SigVerifyCostSecp256k1: 10, + }, + Accounts: v038auth.GenesisAccounts{acc1, vaac}, + } + + migrated := v039.Migrate(gs) + expected := `{ + "params": { + "max_memo_characters": "10", + "tx_sig_limit": "10", + "tx_size_cost_per_byte": "10", + "sig_verify_cost_ed25519": "10", + "sig_verify_cost_secp256k1": "10" + }, + "accounts": [ + { + "type": "cosmos-sdk/Account", + "value": { + "address": "cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u", + "public_key": "", + "account_number": 1, + "sequence": 0 + } + }, + { + "type": "cosmos-sdk/ContinuousVestingAccount", + "value": { + "address": "cosmos15v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74", + "public_key": "", + "account_number": 1, + "sequence": 0, + "original_vesting": [ + { + "denom": "stake", + "amount": "50" + } + ], + "delegated_free": [], + "delegated_vesting": [], + "end_time": 3160620846, + "start_time": 1580309972 + } + } + ] +}` + + bz, err := v039Codec.MarshalJSONIndent(migrated, "", " ") + require.NoError(t, err) + require.Equal(t, expected, string(bz)) +} diff --git a/x/auth/legacy/v0_39/types.go b/x/auth/legacy/v0_39/types.go new file mode 100644 index 000000000000..419ffe39020d --- /dev/null +++ b/x/auth/legacy/v0_39/types.go @@ -0,0 +1,8 @@ +package v039 + +// DONTCOVER +// nolint + +const ( + ModuleName = "auth" +) diff --git a/x/bank/legacy/v0_38/types.go b/x/bank/legacy/v0_38/types.go new file mode 100644 index 000000000000..e67640bf2b12 --- /dev/null +++ b/x/bank/legacy/v0_38/types.go @@ -0,0 +1,14 @@ +package v038 + +// DONTCOVER +// nolint + +const ( + ModuleName = "bank" +) + +type ( + GenesisState struct { + SendEnabled bool `json:"send_enabled" yaml:"send_enabled"` + } +) diff --git a/x/bank/legacy/v0_39/migrate.go b/x/bank/legacy/v0_39/migrate.go new file mode 100644 index 000000000000..222992357d9f --- /dev/null +++ b/x/bank/legacy/v0_39/migrate.go @@ -0,0 +1,22 @@ +package v039 + +import ( + v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" + v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_38" +) + +// Migrate accepts exported x/auth and x/bank genesis state from v0.38 and migrates +// it to v0.39 x/bank genesis state. The migration includes: +// +// - Moving balances from x/auth to x/bank genesis state. +func Migrate(bankGenState v038bank.GenesisState, authGenState v038auth.GenesisState) GenesisState { + balances := make([]Balance, len(authGenState.Accounts)) + for i, acc := range authGenState.Accounts { + balances[i] = Balance{ + Address: acc.GetAddress(), + Coins: acc.GetCoins(), + } + } + + return NewGenesisState(bankGenState.SendEnabled, balances) +} diff --git a/x/bank/legacy/v0_39/migrate_test.go b/x/bank/legacy/v0_39/migrate_test.go new file mode 100644 index 000000000000..ae51134d47c1 --- /dev/null +++ b/x/bank/legacy/v0_39/migrate_test.go @@ -0,0 +1,67 @@ +package v039_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" + v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_38" + v039bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_39" + + "github.com/stretchr/testify/require" +) + +func TestMigrate(t *testing.T) { + v039Codec := codec.New() + codec.RegisterCrypto(v039Codec) + v038auth.RegisterCodec(v039Codec) + + coins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50)) + addr1, _ := sdk.AccAddressFromBech32("cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u") + acc1 := v038auth.NewBaseAccount(addr1, coins, nil, 1, 0) + + addr2, _ := sdk.AccAddressFromBech32("cosmos15v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74") + vaac := v038auth.NewContinuousVestingAccountRaw( + v038auth.NewBaseVestingAccount( + v038auth.NewBaseAccount(addr2, coins, nil, 1, 0), coins, nil, nil, 3160620846, + ), + 1580309972, + ) + + bankGenState := v038bank.GenesisState{ + SendEnabled: true, + } + authGenState := v038auth.GenesisState{ + Accounts: v038auth.GenesisAccounts{acc1, vaac}, + } + + migrated := v039bank.Migrate(bankGenState, authGenState) + expected := `{ + "send_enabled": true, + "balances": [ + { + "address": "cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u", + "coins": [ + { + "denom": "stake", + "amount": "50" + } + ] + }, + { + "address": "cosmos15v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74", + "coins": [ + { + "denom": "stake", + "amount": "50" + } + ] + } + ] +}` + + bz, err := v039Codec.MarshalJSONIndent(migrated, "", " ") + require.NoError(t, err) + require.Equal(t, expected, string(bz)) +} diff --git a/x/bank/legacy/v0_39/types.go b/x/bank/legacy/v0_39/types.go new file mode 100644 index 000000000000..d569ac4f7573 --- /dev/null +++ b/x/bank/legacy/v0_39/types.go @@ -0,0 +1,43 @@ +package v039 + +// DONTCOVER +// nolint + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ModuleName = "bank" +) + +var _ GenesisBalance = (*Balance)(nil) + +type ( + GenesisBalance interface { + GetAddress() sdk.AccAddress + GetCoins() sdk.Coins + } + + GenesisState struct { + SendEnabled bool `json:"send_enabled" yaml:"send_enabled"` + Balances []Balance `json:"balances" yaml:"balances"` + } + + Balance struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + Coins sdk.Coins `json:"coins" yaml:"coins"` + } +) + +func NewGenesisState(sendEnabled bool, balances []Balance) GenesisState { + return GenesisState{SendEnabled: sendEnabled, Balances: balances} +} + +func (b Balance) GetAddress() sdk.AccAddress { + return b.Address +} + +func (b Balance) GetCoins() sdk.Coins { + return b.Coins +} diff --git a/x/genutil/client/cli/migrate.go b/x/genutil/client/cli/migrate.go index 3ae77c506d61..eeba89356a95 100644 --- a/x/genutil/client/cli/migrate.go +++ b/x/genutil/client/cli/migrate.go @@ -16,6 +16,7 @@ import ( extypes "github.com/cosmos/cosmos-sdk/x/genutil" v036 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v0_36" v038 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v0_38" + v039 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v0_39" ) const ( @@ -29,6 +30,7 @@ const ( var migrationMap = extypes.MigrationMap{ "v0.36": v036.Migrate, "v0.38": v038.Migrate, // NOTE: v0.37 and v0.38 are genesis compatible + "v0.39": v039.Migrate, } // GetMigrationCallback returns a MigrationCallback for a given version. diff --git a/x/genutil/legacy/v0_39/migrate.go b/x/genutil/legacy/v0_39/migrate.go new file mode 100644 index 000000000000..aea5ccd3f91e --- /dev/null +++ b/x/genutil/legacy/v0_39/migrate.go @@ -0,0 +1,55 @@ +package v039 + +import ( + "github.com/cosmos/cosmos-sdk/codec" + v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" + v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_39" + v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_38" + v039bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_39" + "github.com/cosmos/cosmos-sdk/x/genutil" +) + +func Migrate(appState genutil.AppMap) genutil.AppMap { + v038Codec := codec.New() + codec.RegisterCrypto(v038Codec) + v038auth.RegisterCodec(v038Codec) + + v039Codec := codec.New() + codec.RegisterCrypto(v039Codec) + v038auth.RegisterCodec(v039Codec) + + // remove balances from existing accounts + if appState[v038auth.ModuleName] != nil { + // unmarshal relative source genesis application state + var authGenState v038auth.GenesisState + v038Codec.MustUnmarshalJSON(appState[v038auth.ModuleName], &authGenState) + + // delete deprecated x/auth genesis state + delete(appState, v038auth.ModuleName) + + // Migrate relative source genesis application state and marshal it into + // the respective key. + appState[v039auth.ModuleName] = v039Codec.MustMarshalJSON(v039auth.Migrate(authGenState)) + } + + if appState[v038bank.ModuleName] != nil { + // unmarshal relative source genesis application state + var bankGenState v038bank.GenesisState + v038Codec.MustUnmarshalJSON(appState[v038bank.ModuleName], &bankGenState) + + // unmarshal x/auth genesis state to retrieve all account balances + var authGenState v038auth.GenesisState + v038Codec.MustUnmarshalJSON(appState[v038auth.ModuleName], &authGenState) + + // delete deprecated x/bank genesis state + delete(appState, v038bank.ModuleName) + + // Migrate relative source genesis application state and marshal it into + // the respective key. + appState[v039bank.ModuleName] = v039Codec.MustMarshalJSON( + v039bank.Migrate(bankGenState, authGenState), + ) + } + + return appState +}