Skip to content

Commit

Permalink
Fix 0.39 x/auth Migration Types (#6870)
Browse files Browse the repository at this point in the history
* types: add coins to JSON

* add migrate test

* finish test

* Add panic

* fix test
  • Loading branch information
alexanderbez authored Jul 28, 2020
1 parent 3ff3e58 commit 72f6bf0
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 78 deletions.
4 changes: 2 additions & 2 deletions x/auth/legacy/v0_38/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ func NewModuleAccount(baseAccount *BaseAccount, name string, permissions ...stri
}

func (ma ModuleAccount) Validate() error {
if err := validatePermissions(ma.Permissions...); err != nil {
if err := ValidatePermissions(ma.Permissions...); err != nil {
return err
}

Expand Down Expand Up @@ -476,7 +476,7 @@ func (ma *ModuleAccount) UnmarshalJSON(bz []byte) error {
return nil
}

func validatePermissions(permissions ...string) error {
func ValidatePermissions(permissions ...string) error {
for _, perm := range permissions {
if strings.TrimSpace(perm) == "" {
return fmt.Errorf("module permission is empty")
Expand Down
60 changes: 60 additions & 0 deletions x/auth/legacy/v0_39/migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package v039

import (
"fmt"

v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38"
)

// Migrate accepts exported genesis state from v0.38 and migrates it to v0.39
// genesis state.
func Migrate(oldAuthGenState v038auth.GenesisState) GenesisState {
accounts := make(v038auth.GenesisAccounts, len(oldAuthGenState.Accounts))

for i, acc := range oldAuthGenState.Accounts {
switch t := acc.(type) {
case *v038auth.BaseAccount:
accounts[i] = NewBaseAccount(t.Address, t.Coins, t.PubKey, t.AccountNumber, t.Sequence)

case *v038auth.BaseVestingAccount:
accounts[i] = NewBaseVestingAccount(
NewBaseAccount(t.Address, t.Coins, t.PubKey, t.AccountNumber, t.Sequence),
t.OriginalVesting, t.DelegatedFree, t.DelegatedVesting, t.EndTime,
)

case *v038auth.ContinuousVestingAccount:
accounts[i] = NewContinuousVestingAccountRaw(
NewBaseVestingAccount(
NewBaseAccount(t.Address, t.Coins, t.PubKey, t.AccountNumber, t.Sequence),
t.OriginalVesting, t.DelegatedFree, t.DelegatedVesting, t.EndTime,
),
t.StartTime,
)

case *v038auth.DelayedVestingAccount:
accounts[i] = NewDelayedVestingAccountRaw(
NewBaseVestingAccount(
NewBaseAccount(t.Address, t.Coins, t.PubKey, t.AccountNumber, t.Sequence),
t.OriginalVesting, t.DelegatedFree, t.DelegatedVesting, t.EndTime,
),
)

case *v038auth.ModuleAccount:
accounts[i] = NewModuleAccount(
NewBaseAccount(t.Address, t.Coins, t.PubKey, t.AccountNumber, t.Sequence),
t.Name, t.Permissions...,
)

default:
panic(fmt.Sprintf("unexpected account type: %T", acc))
}
}

accounts = v038auth.SanitizeGenesisAccounts(accounts)

if err := v038auth.ValidateGenAccounts(accounts); err != nil {
panic(err)
}

return NewGenesisState(oldAuthGenState.Params, accounts)
}
97 changes: 27 additions & 70 deletions x/auth/legacy/v0_39/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"bytes"
"errors"
"fmt"
"sort"
"strings"

"github.com/tendermint/tendermint/crypto"
Expand All @@ -16,32 +15,17 @@ import (
"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"
v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38"
)

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"`
Params v034auth.Params `json:"params" yaml:"params"`
Accounts v038auth.GenesisAccounts `json:"accounts" yaml:"accounts"`
}

BaseAccount struct {
Expand Down Expand Up @@ -119,7 +103,7 @@ type (
}
)

func NewGenesisState(params v034auth.Params, accounts GenesisAccounts) GenesisState {
func NewGenesisState(params v034auth.Params, accounts v038auth.GenesisAccounts) GenesisState {
return GenesisState{
Params: params,
Accounts: accounts,
Expand Down Expand Up @@ -187,6 +171,7 @@ func NewBaseVestingAccount(
func (bva BaseVestingAccount) MarshalJSON() ([]byte, error) {
alias := vestingAccountJSON{
Address: bva.Address,
Coins: bva.Coins,
PubKey: bva.PubKey,
AccountNumber: bva.AccountNumber,
Sequence: bva.Sequence,
Expand Down Expand Up @@ -245,6 +230,7 @@ func (cva ContinuousVestingAccount) Validate() error {
func (cva ContinuousVestingAccount) MarshalJSON() ([]byte, error) {
alias := vestingAccountJSON{
Address: cva.Address,
Coins: cva.Coins,
PubKey: cva.PubKey,
AccountNumber: cva.AccountNumber,
Sequence: cva.Sequence,
Expand Down Expand Up @@ -276,13 +262,20 @@ func (cva *ContinuousVestingAccount) UnmarshalJSON(bz []byte) error {
return nil
}

func NewDelayedVestingAccountRaw(bva *BaseVestingAccount) *DelayedVestingAccount {
return &DelayedVestingAccount{
BaseVestingAccount: bva,
}
}

func (dva DelayedVestingAccount) Validate() error {
return dva.BaseVestingAccount.Validate()
}

func (dva DelayedVestingAccount) MarshalJSON() ([]byte, error) {
alias := vestingAccountJSON{
Address: dva.Address,
Coins: dva.Coins,
PubKey: dva.PubKey,
AccountNumber: dva.AccountNumber,
Sequence: dva.Sequence,
Expand Down Expand Up @@ -340,6 +333,7 @@ func (pva PeriodicVestingAccount) Validate() error {
func (pva PeriodicVestingAccount) MarshalJSON() ([]byte, error) {
alias := vestingAccountJSON{
Address: pva.Address,
Coins: pva.Coins,
PubKey: pva.PubKey,
AccountNumber: pva.AccountNumber,
Sequence: pva.Sequence,
Expand Down Expand Up @@ -374,17 +368,25 @@ func (pva *PeriodicVestingAccount) UnmarshalJSON(bz []byte) error {
return nil
}

func NewModuleAccount(baseAccount *BaseAccount, name string, permissions ...string) *ModuleAccount {
return &ModuleAccount{
BaseAccount: baseAccount,
Name: name,
Permissions: permissions,
}
}

func (ma ModuleAccount) Validate() error {
if err := validatePermissions(ma.Permissions...); err != nil {
if err := v038auth.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)
if x := sdk.AccAddress(crypto.AddressHash([]byte(ma.Name))); !ma.Address.Equals(x) {
return fmt.Errorf("address %s cannot be derived from the module name '%s'; expected: %s", ma.Address, ma.Name, x)
}

return ma.BaseAccount.Validate()
Expand Down Expand Up @@ -417,54 +419,9 @@ func (ma *ModuleAccount) UnmarshalJSON(bz []byte) error {
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.RegisterInterface((*v038auth.GenesisAccount)(nil), nil)
cdc.RegisterInterface((*v038auth.Account)(nil), nil)
cdc.RegisterConcrete(&BaseAccount{}, "cosmos-sdk/BaseAccount", nil)
cdc.RegisterConcrete(&BaseVestingAccount{}, "cosmos-sdk/BaseVestingAccount", nil)
cdc.RegisterConcrete(&ContinuousVestingAccount{}, "cosmos-sdk/ContinuousVestingAccount", nil)
Expand Down
3 changes: 2 additions & 1 deletion x/auth/legacy/v0_40/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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"
)

Expand All @@ -18,6 +19,6 @@ func Migrate(authGenState v039auth.GenesisState) v039auth.GenesisState {
}
}

authGenState.Accounts = v039auth.SanitizeGenesisAccounts(authGenState.Accounts)
authGenState.Accounts = v038auth.SanitizeGenesisAccounts(authGenState.Accounts)
return authGenState
}
7 changes: 4 additions & 3 deletions x/auth/legacy/v0_40/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package v040_test
import (
"testing"

"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/codec"
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"
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"
)

func TestMigrate(t *testing.T) {
Expand All @@ -36,7 +37,7 @@ func TestMigrate(t *testing.T) {
SigVerifyCostED25519: 10,
SigVerifyCostSecp256k1: 10,
},
Accounts: v039auth.GenesisAccounts{acc1, vaac},
Accounts: v038auth.GenesisAccounts{acc1, vaac},
}

migrated := v040.Migrate(gs)
Expand Down
2 changes: 1 addition & 1 deletion x/bank/legacy/v0_40/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestMigrate(t *testing.T) {
SendEnabled: true,
}
authGenState := v039auth.GenesisState{
Accounts: v039auth.GenesisAccounts{acc1, vaac},
Accounts: v038auth.GenesisAccounts{acc1, vaac},
}

migrated := v040bank.Migrate(bankGenState, authGenState)
Expand Down
2 changes: 1 addition & 1 deletion x/genutil/legacy/v0_39/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Migrate(appState types.AppMap) types.AppMap {
v038Codec.MustUnmarshalJSON(appState[v038auth.ModuleName], &authGenState)

delete(appState, v038auth.ModuleName) // delete old key in case the name changed
appState[v039auth.ModuleName] = v039Codec.MustMarshalJSON(authGenState)
appState[v039auth.ModuleName] = v039Codec.MustMarshalJSON(v039auth.Migrate(authGenState))
}

return appState
Expand Down
Loading

0 comments on commit 72f6bf0

Please sign in to comment.