Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADR 11: Generalize Gen Accounts implementation #5017

Merged
merged 26 commits into from
Sep 12, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
40ed336
ADR 11: Generalize Gen Accounts implementation
fedekunze Sep 9, 2019
90a3882
move CLI cmd to auth
fedekunze Sep 10, 2019
8e92e02
delete genaccount module
fedekunze Sep 10, 2019
e1e4993
add some tests
fedekunze Sep 10, 2019
84f92dd
more fixes
fedekunze Sep 10, 2019
19fd7c8
register codec
fedekunze Sep 10, 2019
7085b9c
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into fe…
fedekunze Sep 10, 2019
0b6bbb5
Apply suggestions from code review
fedekunze Sep 11, 2019
e6bf7c4
address comments from review
fedekunze Sep 11, 2019
ac7aaef
Merge branch 'fedekunze/ADR-11-generalize-gen-accs' of https://github…
fedekunze Sep 11, 2019
e9d215a
remove genaccounts command
fedekunze Sep 11, 2019
5a69363
keep legacy genaccount migrations
fedekunze Sep 11, 2019
6c4b702
update genutil migration
fedekunze Sep 11, 2019
4e5e1a2
format
fedekunze Sep 11, 2019
6288793
migrate
fedekunze Sep 12, 2019
fe125bf
iterator
fedekunze Sep 12, 2019
1198733
Update godoc
alexanderbez Sep 12, 2019
f07fabc
Update godoc
alexanderbez Sep 12, 2019
2979564
Remove RegisterAccountTypeCodec call from supply
alexanderbez Sep 12, 2019
3636574
Merge branch 'master' into fedekunze/ADR-11-generalize-gen-accs
alexanderbez Sep 12, 2019
da91323
re-add RegisterAccountTypeCodec
alexanderbez Sep 12, 2019
42b04ee
Update godoc
alexanderbez Sep 12, 2019
7cef4d1
Add sim genesis concrete type
alexanderbez Sep 12, 2019
ae1569f
Fix migration
alexanderbez Sep 12, 2019
3d924db
Add ref for https://github.com/cosmos/cosmos-sdk/issues/5041
alexanderbez Sep 12, 2019
1d16d34
Add changelog entries
alexanderbez Sep 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/architecture/adr-011-generalize-genesis-accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ func ExportGenesis(ctx sdk.Context, ak AccountKeeper) GenesisState {

accounts := ak.GetAllAccounts(ctx)
// convert accounts to []GenesisAccounts type
genAccounts := make([]GenesisAccounts, len(accounts))
genAccounts := make([]GenesisAccount, len(accounts))
for i := range accounts {
ga := accounts[i].(GenesisAccount) // will panic if an account doesn't implement GenesisAccount
genAccounts[i] = ga
}

return NewGenesisState(params, accounts)
return NewGenesisState(params, genAccounts)
}
```

Expand All @@ -64,11 +64,11 @@ The `auth` codec must have all custom account types registered to marshal them.
An example custom account definition:

```go
import authTypes "github.com/cosmos/cosmos-sdk/x/auth/types"
import authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"

// Register the module account type with the auth module codec so it can decode module accounts stored in a genesis file
func init() {
authTypes.RegisterAccountTypeCodec(ModuleAccount{}, "cosmos-sdk/ModuleAccount")
authtypes.RegisterAccountTypeCodec(ModuleAccount{}, "cosmos-sdk/ModuleAccount")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally we should provided a function: SealAccountTypeCodec to be used after all auth types have been registered

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this function is necessary. The application will call {module}.ModuleCdc.Seal() somewhere near the end in the app constructor (e.g. gov.ModuleCdc.Seal()).

}

type ModuleAccount struct {
Expand Down
12 changes: 4 additions & 8 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/crisis"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/genaccounts"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mint"
Expand All @@ -43,9 +42,9 @@ var (
// non-dependant module elements, such as codec registration
// and genesis verification.
ModuleBasics = module.NewBasicManager(
genaccounts.AppModuleBasic{},
genutil.AppModuleBasic{},
auth.AppModuleBasic{},
supply.AppModuleBasic{},
genutil.AppModuleBasic{},
bank.AppModuleBasic{},
staking.AppModuleBasic{},
mint.AppModuleBasic{},
Expand All @@ -55,7 +54,6 @@ var (
crisis.AppModuleBasic{},
slashing.AppModuleBasic{},
nft.AppModuleBasic{},
supply.AppModuleBasic{},
)

// module account permissions
Expand Down Expand Up @@ -178,7 +176,6 @@ func NewSimApp(
// NOTE: Any module instantiated in the module manager that is later modified
// must be passed by reference here.
app.mm = module.NewManager(
genaccounts.NewAppModule(app.AccountKeeper),
genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx),
auth.NewAppModule(app.AccountKeeper),
bank.NewAppModule(app.BankKeeper, app.AccountKeeper),
Expand All @@ -202,8 +199,8 @@ func NewSimApp(
// NOTE: The genutils moodule must occur after staking so that pools are
// properly initialized with tokens from genesis accounts.
app.mm.SetOrderInitGenesis(
genaccounts.ModuleName, distr.ModuleName, staking.ModuleName,
auth.ModuleName, bank.ModuleName, slashing.ModuleName, gov.ModuleName,
auth.ModuleName, distr.ModuleName, staking.ModuleName,
bank.ModuleName, slashing.ModuleName, gov.ModuleName,
mint.ModuleName, supply.ModuleName, crisis.ModuleName, nft.ModuleName,
genutil.ModuleName,
)
Expand All @@ -216,7 +213,6 @@ func NewSimApp(
// NOTE: this is not required apps that don't use the simulator for fuzz testing
// transactions
app.sm = module.NewSimulationManager(
genaccounts.NewAppModule(app.AccountKeeper),
auth.NewAppModule(app.AccountKeeper),
bank.NewAppModule(app.BankKeeper, app.AccountKeeper),
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper),
Expand Down
11 changes: 7 additions & 4 deletions simapp/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/genaccounts"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

Expand Down Expand Up @@ -126,9 +126,12 @@ func AppStateFromGenesisFileFn(r *rand.Rand, cdc *codec.Codec, genesisFile strin
var appState GenesisState
cdc.MustUnmarshalJSON(genesis.AppState, &appState)

accounts := genaccounts.GetGenesisStateFromAppState(cdc, appState)
var authGenesis auth.GenesisState
if appState[auth.ModuleName] != nil {
cdc.MustUnmarshalJSON(appState[auth.ModuleName], &authGenesis)
}

for _, acc := range accounts {
for _, acc := range authGenesis.Accounts {
// Pick a random private key, since we don't know the actual key
// This should be fine as it's only used for mock Tendermint validators
// and these keys are never actually used to sign by mock Tendermint.
Expand All @@ -140,7 +143,7 @@ func AppStateFromGenesisFileFn(r *rand.Rand, cdc *codec.Codec, genesisFile strin
privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed)

// create simulator accounts
simAcc := simulation.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.Address}
simAcc := simulation.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.GetAddress()}
newAccs = append(newAccs, simAcc)
}

Expand Down
10 changes: 7 additions & 3 deletions simapp/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/genaccounts"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/supply"
)

Expand Down Expand Up @@ -45,13 +45,17 @@ func Setup(isCheckTx bool) *SimApp {

// SetupWithGenesisAccounts initializes a new SimApp with the passed in
// genesis accounts.
func SetupWithGenesisAccounts(genAccs genaccounts.GenesisAccounts) *SimApp {
func SetupWithGenesisAccounts(genAccs []authexported.GenesisAccount) *SimApp {
db := dbm.NewMemDB()
app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, 0)

// initialize the chain with the passed in genesis accounts
genesisState := NewDefaultGenesisState()
genesisState = genaccounts.SetGenesisStateInAppState(app.Codec(), genesisState, genaccounts.GenesisState(genAccs))

authGenesis := auth.NewGenesisState(auth.DefaultParams(), genAccs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are the default params here btw?

genesisStateBz := app.cdc.MustMarshalJSON(authGenesis)
genesisState[auth.ModuleName] = genesisStateBz

stateBytes, err := codec.MarshalJSONIndent(app.cdc, genesisState)
if err != nil {
panic(err)
Expand Down
3 changes: 3 additions & 0 deletions x/auth/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ var (
NewDelayedVestingAccount = types.NewDelayedVestingAccount
NewAccountRetriever = types.NewAccountRetriever
RegisterCodec = types.RegisterCodec
RegisterAccountTypeCodec = types.RegisterAccountTypeCodec
RegisterAccountType = types.RegisterAccountType
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
Sanitize = types.Sanitize
AddressStoreKey = types.AddressStoreKey
NewParams = types.NewParams
ParamKeyTable = types.ParamKeyTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/cli"

"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/genaccounts"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
)

Expand All @@ -33,6 +36,7 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec,
config := ctx.Config
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
config.SetRoot(viper.GetString(cli.HomeFlag))

var pubkey crypto.PubKey
addr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
kb, err := keys.NewKeyBaseFromDir(viper.GetString(flagClientHome))
Expand All @@ -45,6 +49,7 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec,
return err
}

pubkey = info.GetPubKey()
addr = info.GetAddress()
}

Expand All @@ -60,8 +65,27 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec,
return err
}

genAcc := genaccounts.NewGenesisAccountRaw(addr, coins, vestingAmt, vestingStart, vestingEnd, "", "")
if err := genAcc.Validate(); err != nil {
var genesisAcc exported.GenesisAccount
baseAcc := types.NewBaseAccount(addr, coins.Sort(), pubkey, 0, 0)
if !vestingAmt.IsZero() {
baseVestingAcc := types.NewBaseVestingAccount(
baseAcc, vestingAmt.Sort(), sdk.Coins{},
sdk.Coins{}, vestingEnd,
)

switch {
case vestingStart != 0 && vestingEnd != 0:
genesisAcc = types.NewContinuousVestingAccountRaw(baseVestingAcc, vestingStart)
case vestingEnd != 0:
genesisAcc = types.NewDelayedVestingAccountRaw(baseVestingAcc)
default:
panic(fmt.Sprintf("invalid genesis vesting account: %+v", baseVestingAcc))
}
} else {
genesisAcc = baseAcc
}

if err := genesisAcc.Validate(); err != nil {
return err
}

Expand All @@ -73,18 +97,19 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec,
}

// add genesis account to the app state
var genesisAccounts genaccounts.GenesisAccounts

cdc.MustUnmarshalJSON(appState[genaccounts.ModuleName], &genesisAccounts)
var authGenesis types.GenesisState
cdc.MustUnmarshalJSON(appState[types.ModuleName], &authGenesis)

if genesisAccounts.Contains(addr) {
return fmt.Errorf("cannot add account at existing address %v", addr)
for _, acc := range authGenesis.Accounts {
if acc.GetAddress().Equals(addr) {
return fmt.Errorf("cannot add account at existing address %s", addr)
}
}

genesisAccounts = append(genesisAccounts, genAcc)
authGenesis.Accounts = append(authGenesis.Accounts, genesisAcc)

genesisStateBz := cdc.MustMarshalJSON(genaccounts.GenesisState(genesisAccounts))
appState[genaccounts.ModuleName] = genesisStateBz
genesisStateBz := cdc.MustMarshalJSON(authGenesis)
appState[types.ModuleName] = genesisStateBz

appStateJSON, err := cdc.MarshalJSON(appState)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions x/auth/exported/exported.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ type VestingAccount interface {
GetDelegatedFree() sdk.Coins
GetDelegatedVesting() sdk.Coins
}

// GenesisAccount defines an Account with a validation function.
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
type GenesisAccount interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! I'm a fan of this pattern

Account
Validate() error
}
18 changes: 17 additions & 1 deletion x/auth/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package auth

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
)

// InitGenesis - Init store state from genesis data
Expand All @@ -10,10 +11,25 @@ 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)
// load the accounts
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
data.Accounts = Sanitize(data.Accounts)

for _, a := range data.Accounts {
acc := ak.NewAccount(ctx, a) // set account number
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
ak.SetAccount(ctx, acc)
}
}

// ExportGenesis returns a GenesisState for a given context and keeper
func ExportGenesis(ctx sdk.Context, ak AccountKeeper) GenesisState {
params := ak.GetParams(ctx)
return NewGenesisState(params)
accounts := ak.GetAllAccounts(ctx)
// convert each Account to []GenesisAccount type
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
genAccounts := make([]exported.GenesisAccount, len(accounts))
for i := range accounts {
ga := accounts[i].(exported.GenesisAccount) // will panic if an account doesn't implement GenesisAccount
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
genAccounts[i] = ga
}

return NewGenesisState(params, genAccounts)
}
53 changes: 49 additions & 4 deletions x/auth/simulation/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"math/rand"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
Expand Down Expand Up @@ -78,11 +80,54 @@ func RandomizedGenState(simState *module.SimulationState) {
func(r *rand.Rand) { sigVerifyCostED25519 = GenSigVerifyCostSECP256K1(r) },
)

authGenesis := types.NewGenesisState(
types.NewParams(maxMemoChars, txSigLimit, txSizeCostPerByte,
sigVerifyCostED25519, sigVerifyCostSECP256K1),
)
params := types.NewParams(maxMemoChars, txSigLimit, txSizeCostPerByte,
sigVerifyCostED25519, sigVerifyCostSECP256K1)
genesisAccs := RandomGenesisAccounts(simState)

authGenesis := types.NewGenesisState(params, genesisAccs)

fmt.Printf("Selected randomly generated auth parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, authGenesis.Params))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(authGenesis)
}

// RandomGenesisAccounts returns randomly generated genesis accounts
func RandomGenesisAccounts(simState *module.SimulationState) (genesisAccs []exported.GenesisAccount) {
for i, acc := range simState.Accounts {
coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(simState.InitialStake))}
bacc := types.NewBaseAccountWithAddress(acc.Address)
if err := bacc.SetCoins(coins); err != nil {
panic(err)
}

var gacc exported.GenesisAccount
gacc = &bacc

// Only consider making a vesting account once the initial bonded validator
// set is exhausted due to needing to track DelegatedVesting.
if int64(i) > simState.NumBonded && simState.Rand.Intn(100) < 50 {
var endTime int64

startTime := simState.GenTimestamp.Unix()

// Allow for some vesting accounts to vest very quickly while others very slowly.
if simState.Rand.Intn(100) < 50 {
endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime), int(startTime+(60*60*24*30))))
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
} else {
endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime), int(startTime+(60*60*12))))
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
}

if startTime == endTime {
endTime++
}
fedekunze marked this conversation as resolved.
Show resolved Hide resolved

if simState.Rand.Intn(100) < 50 {
gacc = types.NewContinuousVestingAccount(&bacc, startTime, endTime)
} else {
gacc = types.NewDelayedVestingAccount(&bacc, endTime)
}
}
genesisAccs = append(genesisAccs, gacc)
}

return
}
Loading