diff --git a/x/auth/legacy/v0_39/types.go b/x/auth/legacy/v0_39/types.go index 419ffe39020d..55ecec23332c 100644 --- a/x/auth/legacy/v0_39/types.go +++ b/x/auth/legacy/v0_39/types.go @@ -3,6 +3,472 @@ package v039 // DONTCOVER // nolint +import ( + "bytes" + "errors" + "fmt" + "sort" + "strings" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + sdk "github.com/cosmos/cosmos-sdk/types" + v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" +) + const ( ModuleName = "auth" ) + +type ( + // partial interface needed only for amino encoding and sanitization + Account interface { + GetAddress() sdk.AccAddress + GetAccountNumber() uint64 + GetCoins() sdk.Coins + SetCoins(sdk.Coins) error + } + + GenesisAccount interface { + Account + + Validate() error + } + + GenesisAccounts []GenesisAccount + + GenesisState struct { + Params v034auth.Params `json:"params" yaml:"params"` + Accounts GenesisAccounts `json:"accounts" yaml:"accounts"` + } + + BaseAccount struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + 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"` + } + + BaseVestingAccount struct { + *BaseAccount + + OriginalVesting sdk.Coins `json:"original_vesting"` + DelegatedFree sdk.Coins `json:"delegated_free"` + DelegatedVesting sdk.Coins `json:"delegated_vesting"` + + EndTime int64 `json:"end_time"` + } + + vestingAccountJSON struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + Coins sdk.Coins `json:"coins,omitempty" yaml:"coins"` + PubKey crypto.PubKey `json:"public_key" yaml:"public_key"` + AccountNumber uint64 `json:"account_number" yaml:"account_number"` + Sequence uint64 `json:"sequence" yaml:"sequence"` + OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"` + DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"` + DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"` + EndTime int64 `json:"end_time" yaml:"end_time"` + + // custom fields based on concrete vesting type which can be omitted + StartTime int64 `json:"start_time,omitempty" yaml:"start_time,omitempty"` + VestingPeriods Periods `json:"vesting_periods,omitempty" yaml:"vesting_periods,omitempty"` + } + + ContinuousVestingAccount struct { + *BaseVestingAccount + + StartTime int64 `json:"start_time"` + } + + DelayedVestingAccount struct { + *BaseVestingAccount + } + + Period struct { + Length int64 `json:"length" yaml:"length"` // length of the period, in seconds + Amount sdk.Coins `json:"amount" yaml:"amount"` // amount of coins vesting during this period + } + + Periods []Period + + PeriodicVestingAccount struct { + *BaseVestingAccount + StartTime int64 `json:"start_time" yaml:"start_time"` // when the coins start to vest + VestingPeriods Periods `json:"vesting_periods" yaml:"vesting_periods"` // the vesting schedule + } + + ModuleAccount struct { + *BaseAccount + + Name string `json:"name" yaml:"name"` + Permissions []string `json:"permissions" yaml:"permissions"` + } + + moduleAccountPretty struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + Coins sdk.Coins `json:"coins,omitempty" yaml:"coins"` + PubKey string `json:"public_key" yaml:"public_key"` + AccountNumber uint64 `json:"account_number" yaml:"account_number"` + Sequence uint64 `json:"sequence" yaml:"sequence"` + Name string `json:"name" yaml:"name"` + Permissions []string `json:"permissions" yaml:"permissions"` + } +) + +func NewGenesisState(params v034auth.Params, accounts GenesisAccounts) GenesisState { + return GenesisState{ + Params: params, + Accounts: accounts, + } +} + +func NewBaseAccountWithAddress(addr sdk.AccAddress) BaseAccount { + return BaseAccount{ + Address: addr, + } +} + +func NewBaseAccount( + address sdk.AccAddress, coins sdk.Coins, pk crypto.PubKey, accountNumber, sequence uint64, +) *BaseAccount { + + return &BaseAccount{ + Address: address, + Coins: coins, + PubKey: pk, + AccountNumber: accountNumber, + Sequence: sequence, + } +} + +func (acc BaseAccount) GetAddress() sdk.AccAddress { + return acc.Address +} + +func (acc *BaseAccount) GetAccountNumber() uint64 { + return acc.AccountNumber +} + +func (acc *BaseAccount) GetCoins() sdk.Coins { + return acc.Coins +} + +func (acc *BaseAccount) SetCoins(coins sdk.Coins) error { + acc.Coins = coins + return nil +} + +func (acc BaseAccount) Validate() error { + if acc.PubKey != nil && acc.Address != nil && + !bytes.Equal(acc.PubKey.Address().Bytes(), acc.Address.Bytes()) { + return errors.New("pubkey and address pair is invalid") + } + + return nil +} + +func NewBaseVestingAccount( + baseAccount *BaseAccount, originalVesting, delegatedFree, delegatedVesting sdk.Coins, endTime int64, +) *BaseVestingAccount { + + return &BaseVestingAccount{ + BaseAccount: baseAccount, + OriginalVesting: originalVesting, + DelegatedFree: delegatedFree, + DelegatedVesting: delegatedVesting, + EndTime: endTime, + } +} + +func (bva BaseVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountJSON{ + Address: bva.Address, + PubKey: bva.PubKey, + AccountNumber: bva.AccountNumber, + Sequence: bva.Sequence, + OriginalVesting: bva.OriginalVesting, + DelegatedFree: bva.DelegatedFree, + DelegatedVesting: bva.DelegatedVesting, + EndTime: bva.EndTime, + } + + return legacy.Cdc.MarshalJSON(alias) +} + +func (bva *BaseVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountJSON + if err := legacy.Cdc.UnmarshalJSON(bz, &alias); err != nil { + return err + } + + bva.BaseAccount = NewBaseAccount(alias.Address, alias.Coins, alias.PubKey, alias.AccountNumber, alias.Sequence) + bva.OriginalVesting = alias.OriginalVesting + bva.DelegatedFree = alias.DelegatedFree + bva.DelegatedVesting = alias.DelegatedVesting + bva.EndTime = alias.EndTime + + return nil +} + +func (bva BaseVestingAccount) GetEndTime() int64 { + return bva.EndTime +} + +func (bva BaseVestingAccount) Validate() error { + if (bva.Coins.IsZero() && !bva.OriginalVesting.IsZero()) || + bva.OriginalVesting.IsAnyGT(bva.Coins) { + return errors.New("vesting amount cannot be greater than total amount") + } + + return bva.BaseAccount.Validate() +} + +func NewContinuousVestingAccountRaw(bva *BaseVestingAccount, startTime int64) *ContinuousVestingAccount { + return &ContinuousVestingAccount{ + BaseVestingAccount: bva, + StartTime: startTime, + } +} + +func (cva ContinuousVestingAccount) Validate() error { + if cva.StartTime >= cva.EndTime { + return errors.New("vesting start-time cannot be before end-time") + } + + return cva.BaseVestingAccount.Validate() +} + +func (cva ContinuousVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountJSON{ + Address: cva.Address, + PubKey: cva.PubKey, + AccountNumber: cva.AccountNumber, + Sequence: cva.Sequence, + OriginalVesting: cva.OriginalVesting, + DelegatedFree: cva.DelegatedFree, + DelegatedVesting: cva.DelegatedVesting, + EndTime: cva.EndTime, + StartTime: cva.StartTime, + } + + return legacy.Cdc.MarshalJSON(alias) +} + +func (cva *ContinuousVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountJSON + if err := legacy.Cdc.UnmarshalJSON(bz, &alias); err != nil { + return err + } + + cva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: NewBaseAccount(alias.Address, alias.Coins, alias.PubKey, alias.AccountNumber, alias.Sequence), + OriginalVesting: alias.OriginalVesting, + DelegatedFree: alias.DelegatedFree, + DelegatedVesting: alias.DelegatedVesting, + EndTime: alias.EndTime, + } + cva.StartTime = alias.StartTime + + return nil +} + +func (dva DelayedVestingAccount) Validate() error { + return dva.BaseVestingAccount.Validate() +} + +func (dva DelayedVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountJSON{ + Address: dva.Address, + PubKey: dva.PubKey, + AccountNumber: dva.AccountNumber, + Sequence: dva.Sequence, + OriginalVesting: dva.OriginalVesting, + DelegatedFree: dva.DelegatedFree, + DelegatedVesting: dva.DelegatedVesting, + EndTime: dva.EndTime, + } + + return legacy.Cdc.MarshalJSON(alias) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a DelayedVestingAccount. +func (dva *DelayedVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountJSON + if err := legacy.Cdc.UnmarshalJSON(bz, &alias); err != nil { + return err + } + + dva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: NewBaseAccount(alias.Address, alias.Coins, alias.PubKey, alias.AccountNumber, alias.Sequence), + OriginalVesting: alias.OriginalVesting, + DelegatedFree: alias.DelegatedFree, + DelegatedVesting: alias.DelegatedVesting, + EndTime: alias.EndTime, + } + + return nil +} + +func (pva PeriodicVestingAccount) GetStartTime() int64 { + return pva.StartTime +} + +func (pva PeriodicVestingAccount) Validate() error { + if pva.GetStartTime() >= pva.GetEndTime() { + return errors.New("vesting start-time cannot be before end-time") + } + endTime := pva.StartTime + originalVesting := sdk.NewCoins() + for _, p := range pva.VestingPeriods { + endTime += p.Length + originalVesting = originalVesting.Add(p.Amount...) + } + if endTime != pva.EndTime { + return errors.New("vesting end time does not match length of all vesting periods") + } + if !originalVesting.IsEqual(pva.OriginalVesting) { + return errors.New("original vesting coins does not match the sum of all coins in vesting periods") + } + + return pva.BaseVestingAccount.Validate() +} + +func (pva PeriodicVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountJSON{ + Address: pva.Address, + PubKey: pva.PubKey, + AccountNumber: pva.AccountNumber, + Sequence: pva.Sequence, + OriginalVesting: pva.OriginalVesting, + DelegatedFree: pva.DelegatedFree, + DelegatedVesting: pva.DelegatedVesting, + EndTime: pva.EndTime, + StartTime: pva.StartTime, + VestingPeriods: pva.VestingPeriods, + } + + return legacy.Cdc.MarshalJSON(alias) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a PeriodicVestingAccount. +func (pva *PeriodicVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountJSON + if err := legacy.Cdc.UnmarshalJSON(bz, &alias); err != nil { + return err + } + + pva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: NewBaseAccount(alias.Address, alias.Coins, alias.PubKey, alias.AccountNumber, alias.Sequence), + OriginalVesting: alias.OriginalVesting, + DelegatedFree: alias.DelegatedFree, + DelegatedVesting: alias.DelegatedVesting, + EndTime: alias.EndTime, + } + pva.StartTime = alias.StartTime + pva.VestingPeriods = alias.VestingPeriods + + return nil +} + +func (ma ModuleAccount) Validate() error { + if err := validatePermissions(ma.Permissions...); err != nil { + return err + } + + if strings.TrimSpace(ma.Name) == "" { + return errors.New("module account name cannot be blank") + } + + if !ma.Address.Equals(sdk.AccAddress(crypto.AddressHash([]byte(ma.Name)))) { + return fmt.Errorf("address %s cannot be derived from the module name '%s'", ma.Address, ma.Name) + } + + return ma.BaseAccount.Validate() +} + +// MarshalJSON returns the JSON representation of a ModuleAccount. +func (ma ModuleAccount) MarshalJSON() ([]byte, error) { + return legacy.Cdc.MarshalJSON(moduleAccountPretty{ + Address: ma.Address, + Coins: ma.Coins, + PubKey: "", + AccountNumber: ma.AccountNumber, + Sequence: ma.Sequence, + Name: ma.Name, + Permissions: ma.Permissions, + }) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a ModuleAccount. +func (ma *ModuleAccount) UnmarshalJSON(bz []byte) error { + var alias moduleAccountPretty + if err := legacy.Cdc.UnmarshalJSON(bz, &alias); err != nil { + return err + } + + ma.BaseAccount = NewBaseAccount(alias.Address, alias.Coins, nil, alias.AccountNumber, alias.Sequence) + ma.Name = alias.Name + ma.Permissions = alias.Permissions + + return nil +} + +func SanitizeGenesisAccounts(genAccounts GenesisAccounts) GenesisAccounts { + sort.Slice(genAccounts, func(i, j int) bool { + return genAccounts[i].GetAccountNumber() < genAccounts[j].GetAccountNumber() + }) + + for _, acc := range genAccounts { + if err := acc.SetCoins(acc.GetCoins().Sort()); err != nil { + panic(err) + } + } + + return genAccounts +} + +func ValidateGenAccounts(genAccounts GenesisAccounts) error { + addrMap := make(map[string]bool, len(genAccounts)) + for _, acc := range genAccounts { + + // check for duplicated accounts + addrStr := acc.GetAddress().String() + if _, ok := addrMap[addrStr]; ok { + return fmt.Errorf("duplicate account found in genesis state; address: %s", addrStr) + } + + addrMap[addrStr] = true + + // check account specific validation + if err := acc.Validate(); err != nil { + return fmt.Errorf("invalid account found in genesis state; address: %s, error: %s", addrStr, err.Error()) + } + } + + return nil +} + +func validatePermissions(permissions ...string) error { + for _, perm := range permissions { + if strings.TrimSpace(perm) == "" { + return fmt.Errorf("module permission is empty") + } + } + + return nil +} + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*GenesisAccount)(nil), nil) + cdc.RegisterInterface((*Account)(nil), nil) + cdc.RegisterConcrete(&BaseAccount{}, "cosmos-sdk/BaseAccount", nil) + cdc.RegisterConcrete(&BaseVestingAccount{}, "cosmos-sdk/BaseVestingAccount", nil) + cdc.RegisterConcrete(&ContinuousVestingAccount{}, "cosmos-sdk/ContinuousVestingAccount", nil) + cdc.RegisterConcrete(&DelayedVestingAccount{}, "cosmos-sdk/DelayedVestingAccount", nil) + cdc.RegisterConcrete(&PeriodicVestingAccount{}, "cosmos-sdk/PeriodicVestingAccount", nil) + cdc.RegisterConcrete(&ModuleAccount{}, "cosmos-sdk/ModuleAccount", nil) +} diff --git a/x/auth/legacy/v0_39/migrate.go b/x/auth/legacy/v0_40/migrate.go similarity index 50% rename from x/auth/legacy/v0_39/migrate.go rename to x/auth/legacy/v0_40/migrate.go index 82b1390869f8..cf25525d15e1 100644 --- a/x/auth/legacy/v0_39/migrate.go +++ b/x/auth/legacy/v0_40/migrate.go @@ -1,16 +1,16 @@ -package v039 +package v040 import ( "fmt" - v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" + v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_39" ) -// Migrate accepts exported x/auth genesis state from v0.38 and migrates it to -// v0.39 x/auth genesis state. The migration includes: +// Migrate accepts exported x/auth genesis state from v0.38/v0.39 and migrates +// it to v0.40 x/auth genesis state. The migration includes: // // - Removing coins from account encoding. -func Migrate(authGenState v038auth.GenesisState) v038auth.GenesisState { +func Migrate(authGenState v039auth.GenesisState) v039auth.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 { @@ -18,6 +18,6 @@ func Migrate(authGenState v038auth.GenesisState) v038auth.GenesisState { } } - authGenState.Accounts = v038auth.SanitizeGenesisAccounts(authGenState.Accounts) + authGenState.Accounts = v039auth.SanitizeGenesisAccounts(authGenState.Accounts) return authGenState } diff --git a/x/auth/legacy/v0_39/migrate_test.go b/x/auth/legacy/v0_40/migrate_test.go similarity index 68% rename from x/auth/legacy/v0_39/migrate_test.go rename to x/auth/legacy/v0_40/migrate_test.go index 76eb51e21e61..879805c3edee 100644 --- a/x/auth/legacy/v0_39/migrate_test.go +++ b/x/auth/legacy/v0_40/migrate_test.go @@ -1,4 +1,4 @@ -package v039_test +package v040_test import ( "testing" @@ -7,8 +7,8 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/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" + v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_39" + v040 "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_40" "github.com/stretchr/testify/require" ) @@ -16,21 +16,19 @@ import ( func TestMigrate(t *testing.T) { v039Codec := codec.New() cryptocodec.RegisterCrypto(v039Codec) - v038auth.RegisterCodec(v039Codec) + v039auth.RegisterCodec(v039Codec) coins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50)) addr1, _ := sdk.AccAddressFromBech32("cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u") - acc1 := v038auth.NewBaseAccount(addr1, coins, nil, 1, 0) + acc1 := v039auth.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, - ), + vaac := v039auth.NewContinuousVestingAccountRaw( + v039auth.NewBaseVestingAccount(v039auth.NewBaseAccount(addr2, coins, nil, 1, 0), coins, nil, nil, 3160620846), 1580309972, ) - gs := v038auth.GenesisState{ + gs := v039auth.GenesisState{ Params: v0_34.Params{ MaxMemoCharacters: 10, TxSigLimit: 10, @@ -38,10 +36,10 @@ func TestMigrate(t *testing.T) { SigVerifyCostED25519: 10, SigVerifyCostSecp256k1: 10, }, - Accounts: v038auth.GenesisAccounts{acc1, vaac}, + Accounts: v039auth.GenesisAccounts{acc1, vaac}, } - migrated := v039.Migrate(gs) + migrated := v040.Migrate(gs) expected := `{ "params": { "max_memo_characters": "10", @@ -55,18 +53,18 @@ func TestMigrate(t *testing.T) { "type": "cosmos-sdk/BaseAccount", "value": { "address": "cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u", - "public_key": "", - "account_number": 1, - "sequence": 0 + "public_key": null, + "account_number": "1", + "sequence": "0" } }, { "type": "cosmos-sdk/ContinuousVestingAccount", "value": { "address": "cosmos15v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74", - "public_key": "", - "account_number": 1, - "sequence": 0, + "public_key": null, + "account_number": "1", + "sequence": "0", "original_vesting": [ { "denom": "stake", @@ -75,8 +73,8 @@ func TestMigrate(t *testing.T) { ], "delegated_free": [], "delegated_vesting": [], - "end_time": 3160620846, - "start_time": 1580309972 + "end_time": "3160620846", + "start_time": "1580309972" } } ] diff --git a/x/auth/legacy/v0_40/types.go b/x/auth/legacy/v0_40/types.go new file mode 100644 index 000000000000..9313a178b2d4 --- /dev/null +++ b/x/auth/legacy/v0_40/types.go @@ -0,0 +1,8 @@ +package v040 + +// DONTCOVER +// nolint + +const ( + ModuleName = "auth" +) diff --git a/x/bank/legacy/v0_39/migrate.go b/x/bank/legacy/v0_40/migrate.go similarity index 63% rename from x/bank/legacy/v0_39/migrate.go rename to x/bank/legacy/v0_40/migrate.go index 222992357d9f..66702d3c1e5a 100644 --- a/x/bank/legacy/v0_39/migrate.go +++ b/x/bank/legacy/v0_40/migrate.go @@ -1,15 +1,15 @@ -package v039 +package v040 import ( - 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" ) -// 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: +// Migrate accepts exported v0.39 x/auth and v0.38 x/bank genesis state and +// migrates it to v0.40 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 { +func Migrate(bankGenState v038bank.GenesisState, authGenState v039auth.GenesisState) GenesisState { balances := make([]Balance, len(authGenState.Accounts)) for i, acc := range authGenState.Accounts { balances[i] = Balance{ diff --git a/x/bank/legacy/v0_39/migrate_test.go b/x/bank/legacy/v0_40/migrate_test.go similarity index 75% rename from x/bank/legacy/v0_39/migrate_test.go rename to x/bank/legacy/v0_40/migrate_test.go index 1b61ccdcb89e..e51909702492 100644 --- a/x/bank/legacy/v0_39/migrate_test.go +++ b/x/bank/legacy/v0_40/migrate_test.go @@ -1,4 +1,4 @@ -package v039_test +package v040_test import ( "testing" @@ -7,16 +7,17 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" 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" + v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_40" "github.com/stretchr/testify/require" ) func TestMigrate(t *testing.T) { - v039Codec := codec.New() - cryptocodec.RegisterCrypto(v039Codec) - v038auth.RegisterCodec(v039Codec) + v040Codec := codec.New() + cryptocodec.RegisterCrypto(v040Codec) + v039auth.RegisterCodec(v040Codec) coins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50)) addr1, _ := sdk.AccAddressFromBech32("cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u") @@ -33,11 +34,11 @@ func TestMigrate(t *testing.T) { bankGenState := v038bank.GenesisState{ SendEnabled: true, } - authGenState := v038auth.GenesisState{ - Accounts: v038auth.GenesisAccounts{acc1, vaac}, + authGenState := v039auth.GenesisState{ + Accounts: v039auth.GenesisAccounts{acc1, vaac}, } - migrated := v039bank.Migrate(bankGenState, authGenState) + migrated := v040bank.Migrate(bankGenState, authGenState) expected := `{ "send_enabled": true, "balances": [ @@ -62,7 +63,7 @@ func TestMigrate(t *testing.T) { ] }` - bz, err := v039Codec.MarshalJSONIndent(migrated, "", " ") + bz, err := v040Codec.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_40/types.go similarity index 98% rename from x/bank/legacy/v0_39/types.go rename to x/bank/legacy/v0_40/types.go index d569ac4f7573..d40c4ed16399 100644 --- a/x/bank/legacy/v0_39/types.go +++ b/x/bank/legacy/v0_40/types.go @@ -1,4 +1,4 @@ -package v039 +package v040 // DONTCOVER // nolint diff --git a/x/genutil/client/cli/migrate.go b/x/genutil/client/cli/migrate.go index 2ac83338394f..c0453e8344cd 100644 --- a/x/genutil/client/cli/migrate.go +++ b/x/genutil/client/cli/migrate.go @@ -16,6 +16,7 @@ import ( 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" + v040 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v0_40" "github.com/cosmos/cosmos-sdk/x/genutil/types" ) @@ -31,6 +32,7 @@ var migrationMap = types.MigrationMap{ "v0.36": v036.Migrate, "v0.38": v038.Migrate, // NOTE: v0.37 and v0.38 are genesis compatible "v0.39": v039.Migrate, + "v0.40": v040.Migrate, } // GetMigrationCallback returns a MigrationCallback for a given version. diff --git a/x/genutil/legacy/v0_38/migrate.go b/x/genutil/legacy/v0_38/migrate.go index 2bbbae64db1f..6c9e8c003676 100644 --- a/x/genutil/legacy/v0_38/migrate.go +++ b/x/genutil/legacy/v0_38/migrate.go @@ -35,9 +35,7 @@ func Migrate(appState types.AppMap) types.AppMap { // Migrate relative source genesis application state and marshal it into // the respective key. - appState[v038auth.ModuleName] = v038Codec.MustMarshalJSON( - v038auth.Migrate(authGenState, genAccountsGenState), - ) + appState[v038auth.ModuleName] = v038Codec.MustMarshalJSON(v038auth.Migrate(authGenState, genAccountsGenState)) } // migrate staking state diff --git a/x/genutil/legacy/v0_39/migrate.go b/x/genutil/legacy/v0_39/migrate.go index 6c285bdd8efc..0452b6dead01 100644 --- a/x/genutil/legacy/v0_39/migrate.go +++ b/x/genutil/legacy/v0_39/migrate.go @@ -5,11 +5,13 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/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/types" ) +// Migrate migrates exported state from v0.38 to a v0.39 genesis state. +// +// NOTE: No actual migration occurs since the types do not change, but JSON +// serialization of accounts do change. func Migrate(appState types.AppMap) types.AppMap { v038Codec := codec.New() cryptocodec.RegisterCrypto(v038Codec) @@ -17,39 +19,15 @@ func Migrate(appState types.AppMap) types.AppMap { v039Codec := codec.New() cryptocodec.RegisterCrypto(v039Codec) - v038auth.RegisterCodec(v039Codec) + v039auth.RegisterCodec(v039Codec) - // remove balances from existing accounts + // migrate x/auth state (JSON serialization only) 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), - ) + delete(appState, v038auth.ModuleName) // delete old key in case the name changed + appState[v039auth.ModuleName] = v039Codec.MustMarshalJSON(authGenState) } return appState diff --git a/x/genutil/legacy/v0_40/migrate.go b/x/genutil/legacy/v0_40/migrate.go new file mode 100644 index 000000000000..9b04a9222d06 --- /dev/null +++ b/x/genutil/legacy/v0_40/migrate.go @@ -0,0 +1,55 @@ +package v040 + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_39" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_40" + v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_38" + v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v0_40" + "github.com/cosmos/cosmos-sdk/x/genutil/types" +) + +// Migrate migrates exported state from v0.39 to a v0.40 genesis state. +func Migrate(appState types.AppMap) types.AppMap { + v039Codec := codec.New() + cryptocodec.RegisterCrypto(v039Codec) + v039auth.RegisterCodec(v039Codec) + + v040Codec := codec.New() + cryptocodec.RegisterCrypto(v040Codec) + v039auth.RegisterCodec(v040Codec) + + // remove balances from existing accounts + if appState[v039auth.ModuleName] != nil { + // unmarshal relative source genesis application state + var authGenState v039auth.GenesisState + v039Codec.MustUnmarshalJSON(appState[v039auth.ModuleName], &authGenState) + + // delete deprecated x/auth genesis state + delete(appState, v039auth.ModuleName) + + // Migrate relative source genesis application state and marshal it into + // the respective key. + appState[v040auth.ModuleName] = v040Codec.MustMarshalJSON(v040auth.Migrate(authGenState)) + } + + if appState[v038bank.ModuleName] != nil { + // unmarshal relative source genesis application state + var bankGenState v038bank.GenesisState + v039Codec.MustUnmarshalJSON(appState[v038bank.ModuleName], &bankGenState) + + // unmarshal x/auth genesis state to retrieve all account balances + var authGenState v039auth.GenesisState + v039Codec.MustUnmarshalJSON(appState[v039auth.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[v040bank.ModuleName] = v040Codec.MustMarshalJSON(v040bank.Migrate(bankGenState, authGenState)) + } + + return appState +}