From b6caf8173147f44c123d09fb80c5bc43c2277b96 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 7 Feb 2019 12:57:24 -0800 Subject: [PATCH 1/6] add support for vesting accounts to the add-genesis-account command --- cmd/gaia/init/genesis_accts.go | 63 +++++++++++++++++++++++++++++++--- cmd/gaia/init/init.go | 18 +++++----- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/cmd/gaia/init/genesis_accts.go b/cmd/gaia/init/genesis_accts.go index 4ec108dcb37d..c5abfc3698fd 100644 --- a/cmd/gaia/init/genesis_accts.go +++ b/cmd/gaia/init/genesis_accts.go @@ -16,11 +16,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" ) -// AddGenesisAccountCmd returns add-genesis-account cobra Command +// AddGenesisAccountCmd returns add-genesis-account cobra Command. func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", - Short: "Add genesis account to genesis.json", + Short: "Add genesis account to a genesis file", Args: cobra.ExactArgs(2), RunE: func(_ *cobra.Command, args []string) error { config := ctx.Config @@ -32,22 +32,35 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command if err != nil { return err } + info, err := kb.Get(args[0]) if err != nil { return err } + addr = info.GetAddress() } + coins, err := sdk.ParseCoins(args[1]) if err != nil { return err } + + vestingStart := viper.GetInt64(flagVestingStart) + vestingEnd := viper.GetInt64(flagVestingEnd) + vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt)) + if err != nil { + return err + } + coins.Sort() + vestingAmt.Sort() genFile := config.GenesisFile() if !common.FileExists(genFile) { return fmt.Errorf("%s does not exist, run `gaiad init` first", genFile) } + genDoc, err := LoadGenesisDoc(cdc, genFile) if err != nil { return err @@ -58,7 +71,7 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command return err } - appState, err = addGenesisAccount(cdc, appState, addr, coins) + appState, err = addGenesisAccount(cdc, appState, addr, coins, vestingAmt, vestingStart, vestingEnd) if err != nil { return err } @@ -74,10 +87,18 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") + cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") + cmd.Flags().Uint64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") + cmd.Flags().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") + return cmd } -func addGenesisAccount(cdc *codec.Codec, appState app.GenesisState, addr sdk.AccAddress, coins sdk.Coins) (app.GenesisState, error) { +func addGenesisAccount( + cdc *codec.Codec, appState app.GenesisState, addr sdk.AccAddress, + coins, vestingAmt sdk.Coins, vestingStart, vestingEnd int64, +) (app.GenesisState, error) { + for _, stateAcc := range appState.Accounts { if stateAcc.Address.Equals(addr) { return appState, fmt.Errorf("the application state already contains account %v", addr) @@ -86,6 +107,38 @@ func addGenesisAccount(cdc *codec.Codec, appState app.GenesisState, addr sdk.Acc acc := auth.NewBaseAccountWithAddress(addr) acc.Coins = coins - appState.Accounts = append(appState.Accounts, app.NewGenesisAccount(&acc)) + + if !vestingAmt.IsZero() { + var vacc auth.VestingAccount + + bvacc := &auth.BaseVestingAccount{ + BaseAccount: &acc, + OriginalVesting: vestingAmt, + EndTime: vestingEnd, + } + + if bvacc.OriginalVesting.IsAllGT(acc.Coins) { + return appState, fmt.Errorf("vesting amount cannot be greater than total amount") + } + if vestingStart >= vestingEnd { + return appState, fmt.Errorf("vesting start time must before end time") + } + + if vestingStart != 0 { + vacc = &auth.ContinuousVestingAccount{ + BaseVestingAccount: bvacc, + StartTime: vestingStart, + } + } else { + vacc = &auth.DelayedVestingAccount{ + BaseVestingAccount: bvacc, + } + } + + appState.Accounts = append(appState.Accounts, app.NewGenesisAccountI(vacc)) + } else { + appState.Accounts = append(appState.Accounts, app.NewGenesisAccount(&acc)) + } + return appState, nil } diff --git a/cmd/gaia/init/init.go b/cmd/gaia/init/init.go index a2af2a1c27e2..506557d3f626 100644 --- a/cmd/gaia/init/init.go +++ b/cmd/gaia/init/init.go @@ -19,8 +19,11 @@ import ( ) const ( - flagOverwrite = "overwrite" - flagClientHome = "home-client" + flagOverwrite = "overwrite" + flagClientHome = "home-client" + flagVestingStart = "vesting-start-time" + flagVestingEnd = "vesting-end-time" + flagVestingAmt = "vesting-amount" ) type printInfo struct { @@ -31,19 +34,19 @@ type printInfo struct { AppMessage json.RawMessage `json:"app_message"` } -// nolint: errcheck func displayInfo(cdc *codec.Codec, info printInfo) error { out, err := codec.MarshalJSONIndent(cdc, info) if err != nil { return err } - fmt.Fprintf(os.Stderr, "%s\n", string(out)) + + fmt.Fprintf(os.Stderr, "%s\n", string(out)) // nolint: errcheck return nil } -// get cmd to initialize all files for tendermint and application -// nolint -func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { +// InitCmd returns a command that initializes all files needed for Tendermint +// and the respective application. +func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { // nolint: golint cmd := &cobra.Command{ Use: "init [moniker]", Short: "Initialize private validator, p2p, genesis, and application configuration files", @@ -80,7 +83,6 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState) cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) - return displayInfo(cdc, toPrint) }, } From bfad9895760035d59023d4d51bc8674c484a73af Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 7 Feb 2019 14:10:10 -0800 Subject: [PATCH 2/6] add a pending log entry --- PENDING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PENDING.md b/PENDING.md index e0b211ad3102..140397dfe38c 100644 --- a/PENDING.md +++ b/PENDING.md @@ -44,6 +44,8 @@ FEATURES * [\#3429](https://github.com/cosmos/cosmos-sdk/issues/3429) Support querying for all delegator distribution rewards. * \#3449 Proof verification now works with absence proofs + * [\#3484](https://github.com/cosmos/cosmos-sdk/issues/3484) Add support + vesting accounts to the add-genesis-account command. * Gaia - [\#3397](https://github.com/cosmos/cosmos-sdk/pull/3397) Implement genesis file sanitization to avoid failures at chain init. From ff7af009bae5462b78c30710328a5f0a28e5a679 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 7 Feb 2019 14:46:08 -0800 Subject: [PATCH 3/6] add vesting account to CLI test fixtures --- cmd/gaia/cli_test/test_helpers.go | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/cmd/gaia/cli_test/test_helpers.go b/cmd/gaia/cli_test/test_helpers.go index f5a71b4afb9e..68182a3eb14f 100644 --- a/cmd/gaia/cli_test/test_helpers.go +++ b/cmd/gaia/cli_test/test_helpers.go @@ -8,6 +8,7 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/stretchr/testify/require" @@ -34,15 +35,22 @@ const ( feeDenom = "feetoken" fee2Denom = "fee2token" keyBaz = "baz" + keyVesting = "vesting" keyFooBarBaz = "foobarbaz" ) -var startCoins = sdk.Coins{ - sdk.NewCoin(feeDenom, staking.TokensFromTendermintPower(1000000)), - sdk.NewCoin(fee2Denom, staking.TokensFromTendermintPower(1000000)), - sdk.NewCoin(fooDenom, staking.TokensFromTendermintPower(1000)), - sdk.NewCoin(denom, staking.TokensFromTendermintPower(150)), -} +var ( + startCoins = sdk.Coins{ + sdk.NewCoin(feeDenom, staking.TokensFromTendermintPower(1000000)), + sdk.NewCoin(fee2Denom, staking.TokensFromTendermintPower(1000000)), + sdk.NewCoin(fooDenom, staking.TokensFromTendermintPower(1000)), + sdk.NewCoin(denom, staking.TokensFromTendermintPower(150)), + } + + vestingCoins = sdk.Coins{ + sdk.NewCoin(feeDenom, staking.TokensFromTendermintPower(500000)), + } +) //___________________________________________________________________________________ // Fixtures @@ -108,6 +116,7 @@ func InitFixtures(t *testing.T) (f *Fixtures) { f.KeysAdd(keyFoo) f.KeysAdd(keyBar) f.KeysAdd(keyBaz) + f.KeysAdd(keyVesting) f.KeysAdd(keyFooBarBaz, "--multisig-threshold=2", fmt.Sprintf( "--multisig=%s,%s,%s", keyFoo, keyBar, keyBaz)) @@ -120,6 +129,12 @@ func InitFixtures(t *testing.T) (f *Fixtures) { // Start an account with tokens f.AddGenesisAccount(f.KeyAddress(keyFoo), startCoins) + f.AddGenesisAccount( + f.KeyAddress(keyVesting), startCoins, + fmt.Sprintf("--vesting-amount=%s", vestingCoins), + fmt.Sprintf("--vesting-start-time=%d", time.Now().UTC().UnixNano()), + fmt.Sprintf("--vesting-end-time=%d", time.Now().Add(60*time.Second).UTC().UnixNano()), + ) f.GenTx(keyFoo) f.CollectGenTxs() return From d46643c12dd8be1b990c47fcc226c9c67410fe77 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 7 Feb 2019 14:53:16 -0800 Subject: [PATCH 4/6] update TestAddGenesisAccount --- cmd/gaia/init/genesis_accts_test.go | 60 ++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/cmd/gaia/init/genesis_accts_test.go b/cmd/gaia/init/genesis_accts_test.go index 42a36b263720..2c17acc54c1e 100644 --- a/cmd/gaia/init/genesis_accts_test.go +++ b/cmd/gaia/init/genesis_accts_test.go @@ -15,9 +15,12 @@ func TestAddGenesisAccount(t *testing.T) { cdc := codec.New() addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) type args struct { - appState app.GenesisState - addr sdk.AccAddress - coins sdk.Coins + appState app.GenesisState + addr sdk.AccAddress + coins sdk.Coins + vestingAmt sdk.Coins + vestingStart int64 + vestingEnd int64 } tests := []struct { name string @@ -30,16 +33,55 @@ func TestAddGenesisAccount(t *testing.T) { app.GenesisState{}, addr1, sdk.Coins{}, + sdk.Coins{}, + 0, + 0, + }, + false, + }, + { + "dup account", + args{ + app.GenesisState{Accounts: []app.GenesisAccount{{Address: addr1}}}, + addr1, + sdk.Coins{}, + sdk.Coins{}, + 0, + 0, + }, + true, + }, + { + "invalid vesting amount", + args{ + app.GenesisState{}, + addr1, + sdk.Coins{sdk.NewInt64Coin("stake", 50)}, + sdk.Coins{sdk.NewInt64Coin("stake", 100)}, + 0, + 0, + }, + true, + }, + { + "invalid vesting times", + args{ + app.GenesisState{}, + addr1, + sdk.Coins{sdk.NewInt64Coin("stake", 50)}, + sdk.Coins{sdk.NewInt64Coin("stake", 50)}, + 1654668078, + 1554668078, }, - false}, - {"dup account", args{ - app.GenesisState{Accounts: []app.GenesisAccount{{Address: addr1}}}, - addr1, - sdk.Coins{}}, true}, + true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := addGenesisAccount(cdc, tt.args.appState, tt.args.addr, tt.args.coins) + _, err := addGenesisAccount( + cdc, tt.args.appState, tt.args.addr, tt.args.coins, + tt.args.vestingAmt, tt.args.vestingStart, tt.args.vestingEnd, + ) require.Equal(t, tt.wantErr, (err != nil)) }) } From aabe6b91bd898a8a1119b0ec25fad4504d3b4c45 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Thu, 7 Feb 2019 17:16:39 -0800 Subject: [PATCH 5/6] Update genesis_accts.go --- cmd/gaia/init/genesis_accts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gaia/init/genesis_accts.go b/cmd/gaia/init/genesis_accts.go index c5abfc3698fd..5522a9745b0a 100644 --- a/cmd/gaia/init/genesis_accts.go +++ b/cmd/gaia/init/genesis_accts.go @@ -20,7 +20,7 @@ import ( func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", - Short: "Add genesis account to a genesis file", + Short: "Add genesis account to genesis.json", Args: cobra.ExactArgs(2), RunE: func(_ *cobra.Command, args []string) error { config := ctx.Config From f7ac6b141e7d61e5d50165015c11f218cfd8b3b1 Mon Sep 17 00:00:00 2001 From: Jack Zampolin Date: Thu, 7 Feb 2019 18:13:06 -0800 Subject: [PATCH 6/6] Remove unnecessary sorts --- cmd/gaia/init/genesis_accts.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/gaia/init/genesis_accts.go b/cmd/gaia/init/genesis_accts.go index 5522a9745b0a..5aa73dae94b4 100644 --- a/cmd/gaia/init/genesis_accts.go +++ b/cmd/gaia/init/genesis_accts.go @@ -53,9 +53,6 @@ func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command return err } - coins.Sort() - vestingAmt.Sort() - genFile := config.GenesisFile() if !common.FileExists(genFile) { return fmt.Errorf("%s does not exist, run `gaiad init` first", genFile)