Merge PR #5042: Auxiliary Functionality for Genesis Accounts

This commit is contained in:
Alexander Bezobchuk 2019-09-13 18:26:29 -04:00 committed by GitHub
parent ed6366679c
commit 1028283e6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 118 additions and 15 deletions

View File

@ -55,7 +55,7 @@ var (
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
Sanitize = types.Sanitize
SanitizeGenesisAccounts = types.SanitizeGenesisAccounts
AddressStoreKey = types.AddressStoreKey
NewParams = types.NewParams
ParamKeyTable = types.ParamKeyTable
@ -70,6 +70,7 @@ var (
NewTxBuilder = types.NewTxBuilder
NewTxBuilderFromCLI = types.NewTxBuilderFromCLI
MakeSignature = types.MakeSignature
GetGenesisStateFromAppState = types.GetGenesisStateFromAppState
// variable aliases
ModuleCdc = types.ModuleCdc
@ -102,4 +103,5 @@ type (
StdSignDoc = types.StdSignDoc
StdSignature = types.StdSignature
TxBuilder = types.TxBuilder
GenesisAccountIterator = types.GenesisAccountIterator
)

View File

@ -58,6 +58,21 @@ type VestingAccount interface {
GetDelegatedVesting() sdk.Coins
}
// GenesisAccounts defines a slice of GenesisAccount objects
type GenesisAccounts []GenesisAccount
// Contains returns true if the given address exists in a slice of GenesisAccount
// objects.
func (ga GenesisAccounts) Contains(addr sdk.AccAddress) bool {
for _, acc := range ga {
if acc.GetAddress().Equals(addr) {
return true
}
}
return false
}
// GenesisAccount defines a genesis account that embeds an Account with validation capabilities.
type GenesisAccount interface {
Account

View File

@ -0,0 +1,24 @@
package exported_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)
func TestGenesisAccountsContains(t *testing.T) {
pubkey := secp256k1.GenPrivKey().PubKey()
addr := sdk.AccAddress(pubkey.Address())
acc := authtypes.NewBaseAccount(addr, nil, secp256k1.GenPrivKey().PubKey(), 0, 0)
genAccounts := exported.GenesisAccounts{}
require.False(t, genAccounts.Contains(acc.GetAddress()))
genAccounts = append(genAccounts, acc)
require.True(t, genAccounts.Contains(acc.GetAddress()))
}

View File

@ -11,7 +11,7 @@ import (
// a genesis port script to the new fee collector account
func InitGenesis(ctx sdk.Context, ak AccountKeeper, data GenesisState) {
ak.SetParams(ctx, data.Params)
data.Accounts = Sanitize(data.Accounts)
data.Accounts = SanitizeGenesisAccounts(data.Accounts)
for _, a := range data.Accounts {
acc := ak.NewAccount(ctx, a)
@ -23,7 +23,7 @@ func InitGenesis(ctx sdk.Context, ak AccountKeeper, data GenesisState) {
func ExportGenesis(ctx sdk.Context, ak AccountKeeper) GenesisState {
params := ak.GetParams(ctx)
var genAccounts []exported.GenesisAccount
var genAccounts exported.GenesisAccounts
ak.IterateAccounts(ctx, func(account exported.Account) bool {
genAccount := account.(exported.GenesisAccount)
genAccounts = append(genAccounts, genAccount)

View File

@ -91,7 +91,7 @@ func RandomizedGenState(simState *module.SimulationState) {
}
// RandomGenesisAccounts returns randomly generated genesis accounts
func RandomGenesisAccounts(simState *module.SimulationState) (genesisAccs []exported.GenesisAccount) {
func RandomGenesisAccounts(simState *module.SimulationState) (genesisAccs exported.GenesisAccounts) {
for i, acc := range simState.Accounts {
coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(simState.InitialStake))}
bacc := types.NewBaseAccountWithAddress(acc.Address)

View File

@ -1,20 +1,22 @@
package types
import (
"encoding/json"
"fmt"
"sort"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
)
// GenesisState - all auth state that must be provided at genesis
type GenesisState struct {
Params Params `json:"params" yaml:"params"`
Accounts []exported.GenesisAccount `json:"accounts" yaml:"accounts"`
Accounts exported.GenesisAccounts `json:"accounts" yaml:"accounts"`
}
// NewGenesisState - Create a new genesis state
func NewGenesisState(params Params, accounts []exported.GenesisAccount) GenesisState {
func NewGenesisState(params Params, accounts exported.GenesisAccounts) GenesisState {
return GenesisState{
Params: params,
Accounts: accounts,
@ -23,7 +25,18 @@ func NewGenesisState(params Params, accounts []exported.GenesisAccount) GenesisS
// DefaultGenesisState - Return a default genesis state
func DefaultGenesisState() GenesisState {
return NewGenesisState(DefaultParams(), []exported.GenesisAccount{})
return NewGenesisState(DefaultParams(), exported.GenesisAccounts{})
}
// GetGenesisStateFromAppState returns x/auth GenesisState given raw application
// genesis state.
func GetGenesisStateFromAppState(cdc *codec.Codec, appState map[string]json.RawMessage) GenesisState {
var genesisState GenesisState
if appState[ModuleName] != nil {
cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState)
}
return genesisState
}
// ValidateGenesis performs basic validation of auth genesis data returning an
@ -36,8 +49,8 @@ func ValidateGenesis(data GenesisState) error {
return validateGenAccounts(data.Accounts)
}
// Sanitize sorts accounts and coin sets.
func Sanitize(genAccs []exported.GenesisAccount) []exported.GenesisAccount {
// SanitizeGenesisAccounts sorts accounts and coin sets.
func SanitizeGenesisAccounts(genAccs exported.GenesisAccounts) exported.GenesisAccounts {
sort.Slice(genAccs, func(i, j int) bool {
return genAccs[i].GetAccountNumber() < genAccs[j].GetAccountNumber()
})
@ -51,7 +64,7 @@ func Sanitize(genAccs []exported.GenesisAccount) []exported.GenesisAccount {
return genAccs
}
func validateGenAccounts(accounts []exported.GenesisAccount) error {
func validateGenAccounts(accounts exported.GenesisAccounts) error {
addrMap := make(map[string]bool, len(accounts))
for _, acc := range accounts {
@ -70,3 +83,20 @@ func validateGenAccounts(accounts []exported.GenesisAccount) error {
}
return nil
}
// GenesisAccountIterator implements genesis account iteration.
type GenesisAccountIterator struct{}
// IterateGenesisAccounts iterates over all the genesis accounts found in
// appGenesis and invokes a callback on each genesis account. If any call
// returns true, iteration stops.
func (GenesisAccountIterator) IterateGenesisAccounts(
cdc *codec.Codec, appGenesis map[string]json.RawMessage, cb func(exported.Account) (stop bool),
) {
for _, genAcc := range GetGenesisStateFromAppState(cdc, appGenesis).Accounts {
if cb(genAcc) {
break
}
}
}

View File

@ -1,6 +1,7 @@
package types
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
@ -26,13 +27,13 @@ func TestSanitize(t *testing.T) {
sdk.NewInt64Coin("bcoin", 150),
})
genAccs := []exported.GenesisAccount{&authAcc1, &authAcc2}
genAccs := exported.GenesisAccounts{&authAcc1, &authAcc2}
require.True(t, genAccs[0].GetAccountNumber() > genAccs[1].GetAccountNumber())
require.Equal(t, genAccs[0].GetCoins()[0].Denom, "bcoin")
require.Equal(t, genAccs[0].GetCoins()[1].Denom, "acoin")
require.Equal(t, genAccs[1].GetAddress(), addr2)
genAccs = Sanitize(genAccs)
genAccs = SanitizeGenesisAccounts(genAccs)
require.False(t, genAccs[0].GetAccountNumber() > genAccs[1].GetAccountNumber())
require.Equal(t, genAccs[1].GetAddress(), addr1)
@ -52,7 +53,7 @@ func TestValidateGenesisDuplicateAccounts(t *testing.T) {
acc1 := NewBaseAccountWithAddress(sdk.AccAddress(addr1))
acc1.Coins = sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 150))
genAccs := make([]exported.GenesisAccount, 2)
genAccs := make(exported.GenesisAccounts, 2)
genAccs[0] = &acc1
genAccs[1] = &acc1
@ -68,7 +69,7 @@ func TestValidateGenesisInvalidAccounts(t *testing.T) {
acc2 := NewBaseAccountWithAddress(sdk.AccAddress(addr2))
acc2.Coins = sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 150))
genAccs := make([]exported.GenesisAccount, 2)
genAccs := make(exported.GenesisAccounts, 2)
genAccs[0] = baseVestingAcc
genAccs[1] = &acc2
@ -80,3 +81,34 @@ func TestValidateGenesisInvalidAccounts(t *testing.T) {
genAccs[0] = NewContinuousVestingAccountRaw(baseVestingAcc, 1548888000)
require.Error(t, validateGenAccounts(genAccs))
}
func TestGenesisAccountIterator(t *testing.T) {
acc1 := NewBaseAccountWithAddress(sdk.AccAddress(addr1))
acc1.Coins = sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 150))
acc2 := NewBaseAccountWithAddress(sdk.AccAddress(addr2))
acc2.Coins = sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 150))
genAccounts := exported.GenesisAccounts{&acc1, &acc2}
authGenState := DefaultGenesisState()
authGenState.Accounts = genAccounts
appGenesis := make(map[string]json.RawMessage)
authGenStateBz, err := ModuleCdc.MarshalJSON(authGenState)
require.NoError(t, err)
appGenesis[ModuleName] = authGenStateBz
var addresses []sdk.AccAddress
GenesisAccountIterator{}.IterateGenesisAccounts(
ModuleCdc, appGenesis, func(acc exported.Account) (stop bool) {
addresses = append(addresses, acc.GetAddress())
return false
},
)
require.Len(t, addresses, 2)
require.Equal(t, addresses[0], acc1.GetAddress())
require.Equal(t, addresses[1], acc2.GetAddress())
}