From a4b36b9dcd4c320204ffd12e1cb7b53a44246d2e Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Thu, 23 Jan 2020 13:15:22 -0500 Subject: [PATCH] Merge PR #5561: v0.38 Migration Fixes --- x/auth/legacy/v0_38/migrate.go | 2 +- x/auth/legacy/v0_38/migrate_test.go | 8 +- x/auth/legacy/v0_38/types.go | 294 +++++++++++++++++++++++++-- x/auth/types/account_test.go | 7 + x/distribution/legacy/v0_38/types.go | 7 + x/genutil/legacy/v0_38/migrate.go | 19 +- 6 files changed, 316 insertions(+), 21 deletions(-) diff --git a/x/auth/legacy/v0_38/migrate.go b/x/auth/legacy/v0_38/migrate.go index 32a5b8346..e76937777 100644 --- a/x/auth/legacy/v0_38/migrate.go +++ b/x/auth/legacy/v0_38/migrate.go @@ -13,7 +13,7 @@ func Migrate(authGenState v036auth.GenesisState, genAccountsGenState v036genacco for i, acc := range genAccountsGenState { var genAccount GenesisAccount - baseAccount := NewBaseAccount(acc.Address, acc.Coins.Sort(), acc.AccountNumber, acc.Sequence) + baseAccount := NewBaseAccount(acc.Address, acc.Coins.Sort(), nil, acc.AccountNumber, acc.Sequence) switch { case !acc.OriginalVesting.IsZero(): diff --git a/x/auth/legacy/v0_38/migrate_test.go b/x/auth/legacy/v0_38/migrate_test.go index 107545403..3afea8c87 100644 --- a/x/auth/legacy/v0_38/migrate_test.go +++ b/x/auth/legacy/v0_38/migrate_test.go @@ -70,21 +70,21 @@ func TestMigrate(t *testing.T) { ) }) - expectedAcc1 := NewBaseAccount(acc1.Address, acc1.Coins, acc1.AccountNumber, acc1.Sequence) + expectedAcc1 := NewBaseAccount(acc1.Address, acc1.Coins, nil, acc1.AccountNumber, acc1.Sequence) expectedAcc2 := NewModuleAccount( - NewBaseAccount(acc2.Address, acc2.Coins, acc2.AccountNumber, acc2.Sequence), + NewBaseAccount(acc2.Address, acc2.Coins, nil, acc2.AccountNumber, acc2.Sequence), acc2.ModuleName, acc2.ModulePermissions..., ) expectedAcc3 := NewContinuousVestingAccountRaw( NewBaseVestingAccount( - NewBaseAccount(acc3.Address, acc3.Coins, acc3.AccountNumber, acc3.Sequence), + NewBaseAccount(acc3.Address, acc3.Coins, nil, acc3.AccountNumber, acc3.Sequence), acc3.OriginalVesting, acc3.DelegatedFree, acc3.DelegatedVesting, acc3.EndTime, ), acc3.StartTime, ) expectedAcc4 := NewDelayedVestingAccountRaw( NewBaseVestingAccount( - NewBaseAccount(acc4.Address, acc4.Coins, acc4.AccountNumber, acc4.Sequence), + NewBaseAccount(acc4.Address, acc4.Coins, nil, acc4.AccountNumber, acc4.Sequence), acc4.OriginalVesting, acc4.DelegatedFree, acc4.DelegatedVesting, acc4.EndTime, ), ) diff --git a/x/auth/legacy/v0_38/types.go b/x/auth/legacy/v0_38/types.go index 90d42133b..15896a391 100644 --- a/x/auth/legacy/v0_38/types.go +++ b/x/auth/legacy/v0_38/types.go @@ -5,6 +5,7 @@ package v038 import ( "bytes" + "encoding/json" "errors" "fmt" "sort" @@ -51,6 +52,14 @@ type ( Sequence uint64 `json:"sequence" yaml:"sequence"` } + baseAccountPretty struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + Coins sdk.Coins `json:"coins" yaml:"coins"` + PubKey string `json:"public_key" yaml:"public_key"` + AccountNumber uint64 `json:"account_number" yaml:"account_number"` + Sequence uint64 `json:"sequence" yaml:"sequence"` + } + BaseVestingAccount struct { *BaseAccount @@ -61,6 +70,21 @@ type ( EndTime int64 `json:"end_time"` } + vestingAccountPretty struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + Coins sdk.Coins `json:"coins" yaml:"coins"` + PubKey string `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"` + } + ContinuousVestingAccount struct { *BaseVestingAccount @@ -77,6 +101,16 @@ type ( 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" 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 { @@ -93,13 +127,13 @@ func NewBaseAccountWithAddress(addr sdk.AccAddress) BaseAccount { } func NewBaseAccount( - address sdk.AccAddress, coins sdk.Coins, accountNumber, sequence uint64, + address sdk.AccAddress, coins sdk.Coins, pk crypto.PubKey, accountNumber, sequence uint64, ) *BaseAccount { return &BaseAccount{ Address: address, Coins: coins, - PubKey: nil, + PubKey: pk, AccountNumber: accountNumber, Sequence: sequence, } @@ -131,6 +165,50 @@ func (acc BaseAccount) Validate() error { return nil } +func (acc BaseAccount) MarshalJSON() ([]byte, error) { + alias := baseAccountPretty{ + Address: acc.Address, + Coins: acc.Coins, + AccountNumber: acc.AccountNumber, + Sequence: acc.Sequence, + } + + if acc.PubKey != nil { + pks, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) + if err != nil { + return nil, err + } + + alias.PubKey = pks + } + + return json.Marshal(alias) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a BaseAccount. +func (acc *BaseAccount) UnmarshalJSON(bz []byte) error { + var alias baseAccountPretty + if err := json.Unmarshal(bz, &alias); err != nil { + return err + } + + if alias.PubKey != "" { + pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) + if err != nil { + return err + } + + acc.PubKey = pk + } + + acc.Address = alias.Address + acc.Coins = alias.Coins + acc.AccountNumber = alias.AccountNumber + acc.Sequence = alias.Sequence + + return nil +} + func NewBaseVestingAccount( baseAccount *BaseAccount, originalVesting, delegatedFree, delegatedVesting sdk.Coins, endTime int64, ) *BaseVestingAccount { @@ -153,6 +231,59 @@ func (bva BaseVestingAccount) Validate() error { return bva.BaseAccount.Validate() } +// MarshalJSON returns the JSON representation of a BaseVestingAccount. +func (bva BaseVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountPretty{ + Address: bva.Address, + Coins: bva.Coins, + AccountNumber: bva.AccountNumber, + Sequence: bva.Sequence, + OriginalVesting: bva.OriginalVesting, + DelegatedFree: bva.DelegatedFree, + DelegatedVesting: bva.DelegatedVesting, + EndTime: bva.EndTime, + } + + if bva.PubKey != nil { + pks, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, bva.PubKey) + if err != nil { + return nil, err + } + + alias.PubKey = pks + } + + return json.Marshal(alias) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a BaseVestingAccount. +func (bva *BaseVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountPretty + if err := json.Unmarshal(bz, &alias); err != nil { + return err + } + + var ( + pk crypto.PubKey + err error + ) + + if alias.PubKey != "" { + pk, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) + if err != nil { + return err + } + } + + bva.BaseAccount = NewBaseAccount(alias.Address, alias.Coins, pk, alias.AccountNumber, alias.Sequence) + bva.OriginalVesting = alias.OriginalVesting + bva.DelegatedFree = alias.DelegatedFree + bva.DelegatedVesting = alias.DelegatedVesting + bva.EndTime = alias.EndTime + + return nil +} + func NewContinuousVestingAccountRaw(bva *BaseVestingAccount, startTime int64) *ContinuousVestingAccount { return &ContinuousVestingAccount{ BaseVestingAccount: bva, @@ -168,6 +299,63 @@ func (cva ContinuousVestingAccount) Validate() error { return cva.BaseVestingAccount.Validate() } +// MarshalJSON returns the JSON representation of a ContinuousVestingAccount. +func (cva ContinuousVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountPretty{ + Address: cva.Address, + Coins: cva.Coins, + AccountNumber: cva.AccountNumber, + Sequence: cva.Sequence, + OriginalVesting: cva.OriginalVesting, + DelegatedFree: cva.DelegatedFree, + DelegatedVesting: cva.DelegatedVesting, + EndTime: cva.EndTime, + StartTime: cva.StartTime, + } + + if cva.PubKey != nil { + pks, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, cva.PubKey) + if err != nil { + return nil, err + } + + alias.PubKey = pks + } + + return json.Marshal(alias) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a ContinuousVestingAccount. +func (cva *ContinuousVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountPretty + if err := json.Unmarshal(bz, &alias); err != nil { + return err + } + + var ( + pk crypto.PubKey + err error + ) + + if alias.PubKey != "" { + pk, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) + if err != nil { + return err + } + } + + cva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: NewBaseAccount(alias.Address, alias.Coins, pk, alias.AccountNumber, alias.Sequence), + OriginalVesting: alias.OriginalVesting, + DelegatedFree: alias.DelegatedFree, + DelegatedVesting: alias.DelegatedVesting, + EndTime: alias.EndTime, + } + cva.StartTime = alias.StartTime + + return nil +} + func NewDelayedVestingAccountRaw(bva *BaseVestingAccount) *DelayedVestingAccount { return &DelayedVestingAccount{ BaseVestingAccount: bva, @@ -178,6 +366,61 @@ func (dva DelayedVestingAccount) Validate() error { return dva.BaseVestingAccount.Validate() } +// MarshalJSON returns the JSON representation of a DelayedVestingAccount. +func (dva DelayedVestingAccount) MarshalJSON() ([]byte, error) { + alias := vestingAccountPretty{ + Address: dva.Address, + Coins: dva.Coins, + AccountNumber: dva.AccountNumber, + Sequence: dva.Sequence, + OriginalVesting: dva.OriginalVesting, + DelegatedFree: dva.DelegatedFree, + DelegatedVesting: dva.DelegatedVesting, + EndTime: dva.EndTime, + } + + if dva.PubKey != nil { + pks, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, dva.PubKey) + if err != nil { + return nil, err + } + + alias.PubKey = pks + } + + return json.Marshal(alias) +} + +// UnmarshalJSON unmarshals raw JSON bytes into a DelayedVestingAccount. +func (dva *DelayedVestingAccount) UnmarshalJSON(bz []byte) error { + var alias vestingAccountPretty + if err := json.Unmarshal(bz, &alias); err != nil { + return err + } + + var ( + pk crypto.PubKey + err error + ) + + if alias.PubKey != "" { + pk, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) + if err != nil { + return err + } + } + + dva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: NewBaseAccount(alias.Address, alias.Coins, pk, alias.AccountNumber, alias.Sequence), + OriginalVesting: alias.OriginalVesting, + DelegatedFree: alias.DelegatedFree, + DelegatedVesting: alias.DelegatedVesting, + EndTime: alias.EndTime, + } + + return nil +} + func NewModuleAddress(name string) sdk.AccAddress { return sdk.AccAddress(crypto.AddressHash([]byte(name))) } @@ -190,16 +433,6 @@ func NewModuleAccount(baseAccount *BaseAccount, name string, permissions ...stri } } -func validatePermissions(permissions ...string) error { - for _, perm := range permissions { - if strings.TrimSpace(perm) == "" { - return fmt.Errorf("module permission is empty") - } - } - - return nil -} - func (ma ModuleAccount) Validate() error { if err := validatePermissions(ma.Permissions...); err != nil { return err @@ -216,6 +449,43 @@ func (ma ModuleAccount) Validate() error { return ma.BaseAccount.Validate() } +// MarshalJSON returns the JSON representation of a ModuleAccount. +func (ma ModuleAccount) MarshalJSON() ([]byte, error) { + return json.Marshal(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 := json.Unmarshal(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 validatePermissions(permissions ...string) error { + for _, perm := range permissions { + if strings.TrimSpace(perm) == "" { + return fmt.Errorf("module permission is empty") + } + } + + return nil +} + func sanitizeGenesisAccounts(genAccounts GenesisAccounts) GenesisAccounts { sort.Slice(genAccounts, func(i, j int) bool { return genAccounts[i].GetAccountNumber() < genAccounts[j].GetAccountNumber() diff --git a/x/auth/types/account_test.go b/x/auth/types/account_test.go index 171c15d72..7be6a25e5 100644 --- a/x/auth/types/account_test.go +++ b/x/auth/types/account_test.go @@ -146,4 +146,11 @@ func TestBaseAccountJSON(t *testing.T) { var a BaseAccount require.NoError(t, json.Unmarshal(bz, &a)) require.Equal(t, baseAcc.String(), a.String()) + + bz, err = ModuleCdc.MarshalJSON(baseAcc) + require.NoError(t, err) + + var b BaseAccount + require.NoError(t, ModuleCdc.UnmarshalJSON(bz, &b)) + require.Equal(t, baseAcc.String(), b.String()) } diff --git a/x/distribution/legacy/v0_38/types.go b/x/distribution/legacy/v0_38/types.go index 4457e2738..0b904372e 100644 --- a/x/distribution/legacy/v0_38/types.go +++ b/x/distribution/legacy/v0_38/types.go @@ -6,6 +6,13 @@ import ( v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_36" ) +// DONTCOVER +// nolint + +const ( + ModuleName = "distribution" +) + type ( GenesisState struct { Params Params `json:"params" yaml:"params"` diff --git a/x/genutil/legacy/v0_38/migrate.go b/x/genutil/legacy/v0_38/migrate.go index ec7f495fa..59ba47727 100644 --- a/x/genutil/legacy/v0_38/migrate.go +++ b/x/genutil/legacy/v0_38/migrate.go @@ -4,13 +4,15 @@ import ( "github.com/cosmos/cosmos-sdk/codec" v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_36" v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" + v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_36" + v038distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_38" v036genaccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_36" "github.com/cosmos/cosmos-sdk/x/genutil" v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36" v038staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_38" ) -// Migrate migrates exported state from v0.34 to a v0.36 genesis state. +// Migrate migrates exported state from v0.36/v0.37 to a v0.38 genesis state. func Migrate(appState genutil.AppMap) genutil.AppMap { v036Codec := codec.New() codec.RegisterCrypto(v036Codec) @@ -27,14 +29,14 @@ func Migrate(appState genutil.AppMap) genutil.AppMap { var genAccountsGenState v036genaccounts.GenesisState v036Codec.MustUnmarshalJSON(appState[v036genaccounts.ModuleName], &genAccountsGenState) + // delete deprecated genaccounts genesis state + delete(appState, v036genaccounts.ModuleName) + // Migrate relative source genesis application state and marshal it into // the respective key. appState[v038auth.ModuleName] = v038Codec.MustMarshalJSON( v038auth.Migrate(authGenState, genAccountsGenState), ) - - // delete deprecated genaccounts genesis state - delete(appState, v036genaccounts.ModuleName) } // migrate staking state @@ -46,5 +48,14 @@ func Migrate(appState genutil.AppMap) genutil.AppMap { appState[v038staking.ModuleName] = v038Codec.MustMarshalJSON(v038staking.Migrate(stakingGenState)) } + // migrate distribution state + if appState[v036distr.ModuleName] != nil { + var distrGenState v036distr.GenesisState + v036Codec.MustUnmarshalJSON(appState[v036distr.ModuleName], &distrGenState) + + delete(appState, v036distr.ModuleName) // delete old key in case the name changed + appState[v038distr.ModuleName] = v038Codec.MustMarshalJSON(v038distr.Migrate(distrGenState)) + } + return appState }