Fix 0.39 x/auth Migration Types (#6870)
* types: add coins to JSON * add migrate test * finish test * Add panic * fix test
This commit is contained in:
parent
3ff3e58240
commit
72f6bf0893
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -7,7 +7,6 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
@ -16,6 +15,7 @@ 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 (
|
||||
|
@ -23,25 +23,9 @@ const (
|
|||
)
|
||||
|
||||
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 {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -276,6 +262,12 @@ 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()
|
||||
}
|
||||
|
@ -283,6 +275,7 @@ func (dva DelayedVestingAccount) Validate() error {
|
|||
func (dva DelayedVestingAccount) MarshalJSON() ([]byte, error) {
|
||||
alias := vestingAccountJSON{
|
||||
Address: dva.Address,
|
||||
Coins: dva.Coins,
|
||||
PubKey: dva.PubKey,
|
||||
AccountNumber: dva.AccountNumber,
|
||||
Sequence: dva.Sequence,
|
||||
|
@ -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,
|
||||
|
@ -374,8 +368,16 @@ 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
|
||||
}
|
||||
|
||||
|
@ -383,8 +385,8 @@ func (ma ModuleAccount) Validate() error {
|
|||
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()
|
||||
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
package v039_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38"
|
||||
v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_39"
|
||||
v039 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v0_39"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
var genAuthState = []byte(`{
|
||||
"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/BaseAccount",
|
||||
"value": {
|
||||
"address": "cosmos19hz3ee9e3lj9mne4jggj3v8hxjrpre22jukj9y",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "stake",
|
||||
"amount": "400000"
|
||||
}
|
||||
],
|
||||
"public_key": "cosmospub1addwnpepqtezq4ajkevh724ls45zp72x70rj8mhszqf5pxcaahazm8trv490swlf404",
|
||||
"account_number": 1,
|
||||
"sequence": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cosmos-sdk/ModuleAccount",
|
||||
"value": {
|
||||
"address": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "stake",
|
||||
"amount": "400000000"
|
||||
}
|
||||
],
|
||||
"public_key": "",
|
||||
"account_number": 2,
|
||||
"sequence": 4,
|
||||
"name": "bonded_tokens_pool",
|
||||
"permissions": [
|
||||
"burner",
|
||||
"staking"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cosmos-sdk/ContinuousVestingAccount",
|
||||
"value": {
|
||||
"address": "cosmos1vtzxzyjv506dvhl9pa527xsugf5gez4fnqxq0n",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "stake",
|
||||
"amount": "10000205"
|
||||
}
|
||||
],
|
||||
"public_key": "cosmospub1addwnpepqdxrk48q89xlmnzrr5nkssle05tkp73uknevzaavm53c02v26vlyzz6vcdh",
|
||||
"account_number": 3,
|
||||
"sequence": 5,
|
||||
"original_vesting": [
|
||||
{
|
||||
"denom": "stake",
|
||||
"amount": "10000205"
|
||||
}
|
||||
],
|
||||
"delegated_free": [],
|
||||
"delegated_vesting": [],
|
||||
"end_time": 1596125048,
|
||||
"start_time": 1595952248
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cosmos-sdk/DelayedVestingAccount",
|
||||
"value": {
|
||||
"address": "cosmos1prxkcqclweqa0g28p7vmf6z78ghyeckm4qak30",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "stake",
|
||||
"amount": "10000205"
|
||||
}
|
||||
],
|
||||
"public_key": "cosmospub1addwnpepqwewcad349e2yw3weatf8lzfyv5cd6am9jkk4ajach3f568k6gg47nls3p8",
|
||||
"account_number": 4,
|
||||
"sequence": 15,
|
||||
"original_vesting": [
|
||||
{
|
||||
"denom": "stake",
|
||||
"amount": "10000205"
|
||||
}
|
||||
],
|
||||
"delegated_free": [],
|
||||
"delegated_vesting": [],
|
||||
"end_time": 1596125048
|
||||
}
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
||||
var expectedGenAuthState = []byte(`{"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/BaseAccount","value":{"address":"cosmos19hz3ee9e3lj9mne4jggj3v8hxjrpre22jukj9y","coins":[{"denom":"stake","amount":"400000"}],"public_key":{"type":"tendermint/PubKeySecp256k1","value":"AvIgV7K2WX8qv4VoIPlG88cj7vAQE0CbHe36LZ1jZUr4"},"account_number":"1","sequence":"1"}},{"type":"cosmos-sdk/ModuleAccount","value":{"address":"cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh","coins":[{"denom":"stake","amount":"400000000"}],"public_key":"","account_number":"2","sequence":"4","name":"bonded_tokens_pool","permissions":["burner","staking"]}},{"type":"cosmos-sdk/ContinuousVestingAccount","value":{"address":"cosmos1vtzxzyjv506dvhl9pa527xsugf5gez4fnqxq0n","coins":[{"denom":"stake","amount":"10000205"}],"public_key":{"type":"tendermint/PubKeySecp256k1","value":"A0w7VOA5Tf3MQx0naEP5fRdg+jy08sF3rN0jh6mK0z5B"},"account_number":"3","sequence":"5","original_vesting":[{"denom":"stake","amount":"10000205"}],"delegated_free":[],"delegated_vesting":[],"end_time":"1596125048","start_time":"1595952248"}},{"type":"cosmos-sdk/DelayedVestingAccount","value":{"address":"cosmos1prxkcqclweqa0g28p7vmf6z78ghyeckm4qak30","coins":[{"denom":"stake","amount":"10000205"}],"public_key":{"type":"tendermint/PubKeySecp256k1","value":"A7LsdbGpcqI6Ls9Wk/xJIymG67ssrWr2XcXimmj20hFf"},"account_number":"4","sequence":"15","original_vesting":[{"denom":"stake","amount":"10000205"}],"delegated_free":[],"delegated_vesting":[],"end_time":"1596125048"}}]}`)
|
||||
|
||||
func TestMigrate(t *testing.T) {
|
||||
genesis := types.AppMap{
|
||||
v038auth.ModuleName: genAuthState,
|
||||
}
|
||||
|
||||
var migrated types.AppMap
|
||||
require.NotPanics(t, func() { migrated = v039.Migrate(genesis) })
|
||||
require.Equal(t, string(expectedGenAuthState), string(migrated[v039auth.ModuleName]))
|
||||
}
|
Loading…
Reference in New Issue