Merge PR #5561: v0.38 Migration Fixes

This commit is contained in:
Alexander Bezobchuk 2020-01-23 13:15:22 -05:00 committed by GitHub
parent 1feb22c4f0
commit a4b36b9dcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 316 additions and 21 deletions

View File

@ -13,7 +13,7 @@ func Migrate(authGenState v036auth.GenesisState, genAccountsGenState v036genacco
for i, acc := range genAccountsGenState { for i, acc := range genAccountsGenState {
var genAccount GenesisAccount 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 { switch {
case !acc.OriginalVesting.IsZero(): case !acc.OriginalVesting.IsZero():

View File

@ -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( 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..., acc2.ModuleName, acc2.ModulePermissions...,
) )
expectedAcc3 := NewContinuousVestingAccountRaw( expectedAcc3 := NewContinuousVestingAccountRaw(
NewBaseVestingAccount( 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.OriginalVesting, acc3.DelegatedFree, acc3.DelegatedVesting, acc3.EndTime,
), ),
acc3.StartTime, acc3.StartTime,
) )
expectedAcc4 := NewDelayedVestingAccountRaw( expectedAcc4 := NewDelayedVestingAccountRaw(
NewBaseVestingAccount( 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, acc4.OriginalVesting, acc4.DelegatedFree, acc4.DelegatedVesting, acc4.EndTime,
), ),
) )

View File

@ -5,6 +5,7 @@ package v038
import ( import (
"bytes" "bytes"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"sort" "sort"
@ -51,6 +52,14 @@ type (
Sequence uint64 `json:"sequence" yaml:"sequence"` 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 { BaseVestingAccount struct {
*BaseAccount *BaseAccount
@ -61,6 +70,21 @@ type (
EndTime int64 `json:"end_time"` 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 { ContinuousVestingAccount struct {
*BaseVestingAccount *BaseVestingAccount
@ -77,6 +101,16 @@ type (
Name string `json:"name" yaml:"name"` Name string `json:"name" yaml:"name"`
Permissions []string `json:"permissions" yaml:"permissions"` 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 { func NewGenesisState(params v034auth.Params, accounts GenesisAccounts) GenesisState {
@ -93,13 +127,13 @@ func NewBaseAccountWithAddress(addr sdk.AccAddress) BaseAccount {
} }
func NewBaseAccount( func NewBaseAccount(
address sdk.AccAddress, coins sdk.Coins, accountNumber, sequence uint64, address sdk.AccAddress, coins sdk.Coins, pk crypto.PubKey, accountNumber, sequence uint64,
) *BaseAccount { ) *BaseAccount {
return &BaseAccount{ return &BaseAccount{
Address: address, Address: address,
Coins: coins, Coins: coins,
PubKey: nil, PubKey: pk,
AccountNumber: accountNumber, AccountNumber: accountNumber,
Sequence: sequence, Sequence: sequence,
} }
@ -131,6 +165,50 @@ func (acc BaseAccount) Validate() error {
return nil 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( func NewBaseVestingAccount(
baseAccount *BaseAccount, originalVesting, delegatedFree, delegatedVesting sdk.Coins, endTime int64, baseAccount *BaseAccount, originalVesting, delegatedFree, delegatedVesting sdk.Coins, endTime int64,
) *BaseVestingAccount { ) *BaseVestingAccount {
@ -153,6 +231,59 @@ func (bva BaseVestingAccount) Validate() error {
return bva.BaseAccount.Validate() 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 { func NewContinuousVestingAccountRaw(bva *BaseVestingAccount, startTime int64) *ContinuousVestingAccount {
return &ContinuousVestingAccount{ return &ContinuousVestingAccount{
BaseVestingAccount: bva, BaseVestingAccount: bva,
@ -168,6 +299,63 @@ func (cva ContinuousVestingAccount) Validate() error {
return cva.BaseVestingAccount.Validate() 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 { func NewDelayedVestingAccountRaw(bva *BaseVestingAccount) *DelayedVestingAccount {
return &DelayedVestingAccount{ return &DelayedVestingAccount{
BaseVestingAccount: bva, BaseVestingAccount: bva,
@ -178,6 +366,61 @@ func (dva DelayedVestingAccount) Validate() error {
return dva.BaseVestingAccount.Validate() 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 { func NewModuleAddress(name string) sdk.AccAddress {
return sdk.AccAddress(crypto.AddressHash([]byte(name))) 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 { func (ma ModuleAccount) Validate() error {
if err := validatePermissions(ma.Permissions...); err != nil { if err := validatePermissions(ma.Permissions...); err != nil {
return err return err
@ -216,6 +449,43 @@ func (ma ModuleAccount) Validate() error {
return ma.BaseAccount.Validate() 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 { func sanitizeGenesisAccounts(genAccounts GenesisAccounts) GenesisAccounts {
sort.Slice(genAccounts, func(i, j int) bool { sort.Slice(genAccounts, func(i, j int) bool {
return genAccounts[i].GetAccountNumber() < genAccounts[j].GetAccountNumber() return genAccounts[i].GetAccountNumber() < genAccounts[j].GetAccountNumber()

View File

@ -146,4 +146,11 @@ func TestBaseAccountJSON(t *testing.T) {
var a BaseAccount var a BaseAccount
require.NoError(t, json.Unmarshal(bz, &a)) require.NoError(t, json.Unmarshal(bz, &a))
require.Equal(t, baseAcc.String(), a.String()) 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())
} }

View File

@ -6,6 +6,13 @@ import (
v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_36" v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_36"
) )
// DONTCOVER
// nolint
const (
ModuleName = "distribution"
)
type ( type (
GenesisState struct { GenesisState struct {
Params Params `json:"params" yaml:"params"` Params Params `json:"params" yaml:"params"`

View File

@ -4,13 +4,15 @@ import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_36" v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_36"
v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38" 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" v036genaccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_36"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36" v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36"
v038staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_38" 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 { func Migrate(appState genutil.AppMap) genutil.AppMap {
v036Codec := codec.New() v036Codec := codec.New()
codec.RegisterCrypto(v036Codec) codec.RegisterCrypto(v036Codec)
@ -27,14 +29,14 @@ func Migrate(appState genutil.AppMap) genutil.AppMap {
var genAccountsGenState v036genaccounts.GenesisState var genAccountsGenState v036genaccounts.GenesisState
v036Codec.MustUnmarshalJSON(appState[v036genaccounts.ModuleName], &genAccountsGenState) 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 // Migrate relative source genesis application state and marshal it into
// the respective key. // the respective key.
appState[v038auth.ModuleName] = v038Codec.MustMarshalJSON( appState[v038auth.ModuleName] = v038Codec.MustMarshalJSON(
v038auth.Migrate(authGenState, genAccountsGenState), v038auth.Migrate(authGenState, genAccountsGenState),
) )
// delete deprecated genaccounts genesis state
delete(appState, v036genaccounts.ModuleName)
} }
// migrate staking state // migrate staking state
@ -46,5 +48,14 @@ func Migrate(appState genutil.AppMap) genutil.AppMap {
appState[v038staking.ModuleName] = v038Codec.MustMarshalJSON(v038staking.Migrate(stakingGenState)) 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 return appState
} }