diff --git a/PENDING.md b/PENDING.md index 84a08a5abe26..35537b610a7c 100644 --- a/PENDING.md +++ b/PENDING.md @@ -7,6 +7,7 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * Gaia + * [gaiad init] \#2602 New genesis workflow * SDK * [simulation] \#2665 only argument to simulation.Invariant is now app diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 2a81239ac69c..39c76865cc0a 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -214,6 +214,7 @@ func InitializeTestLCD( genTxs := []json.RawMessage{} // append any additional (non-proposing) validators + var accs []gapp.GenesisAccount for i := 0; i < nValidators; i++ { operPrivKey := secp256k1.GenPrivKey() operAddr := operPrivKey.PubKey().Address() @@ -242,9 +243,17 @@ func InitializeTestLCD( genTxs = append(genTxs, txBytes) valConsPubKeys = append(valConsPubKeys, pubKey) valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr)) + + accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(operAddr)) + accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 150)} + accs = append(accs, gapp.NewGenesisAccount(&accAuth)) } - genesisState, err := gapp.GaiaAppGenState(cdc, genTxs) + appGenState := gapp.NewDefaultGenesisState() + appGenState.Accounts = accs + genDoc.AppState, err = cdc.MarshalJSON(appGenState) + require.NoError(t, err) + genesisState, err := gapp.GaiaAppGenState(cdc, *genDoc, genTxs) require.NoError(t, err) // add some tokens to init accounts diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 21ef855f026a..fec668943eb3 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -273,7 +273,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci // sanity check if len(req.Validators) > 0 { if len(req.Validators) != len(validators) { - panic(fmt.Errorf("len(RequestInitChain.Validators) != len(validators) (%d != %d) ", len(req.Validators), len(validators))) + panic(fmt.Errorf("len(RequestInitChain.Validators) != len(validators) (%d != %d)", + len(req.Validators), len(validators))) } sort.Sort(abci.ValidatorUpdates(req.Validators)) sort.Sort(abci.ValidatorUpdates(validators)) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index df28bcf6c163..cfbbe5cc2edd 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -26,6 +26,7 @@ var ( // bonded tokens given to genesis validators/accounts freeFermionVal = int64(100) freeFermionsAcc = sdk.NewInt(150) + bondDenom = "steak" ) // State to Unmarshal @@ -90,58 +91,60 @@ func GaiaAppInit() server.AppInit { // Create the core parameters for genesis initialization for gaia // note that the pubkey input is this machines pubkey -func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisState GenesisState, err error) { - if len(appGenTxs) == 0 { - err = errors.New("must provide at least genesis transaction") - return - } +func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( + genesisState GenesisState, err error) { - // start with the default staking genesis state - stakeData := stake.DefaultGenesisState() - slashingData := slashing.DefaultGenesisState() + if err = cdc.UnmarshalJSON(genDoc.AppState, &genesisState); err != nil { + return genesisState, err + } - // get genesis flag account information - genaccs := make([]GenesisAccount, len(appGenTxs)) + // if there are no gen txs to be processed, return the default empty state + if len(appGenTxs) == 0 { + return genesisState, errors.New("there must be at least one genesis tx") + } + stakeData := genesisState.StakeData for i, genTx := range appGenTxs { var tx auth.StdTx - err = cdc.UnmarshalJSON(genTx, &tx) - if err != nil { - return + if err := cdc.UnmarshalJSON(genTx, &tx); err != nil { + return genesisState, err } msgs := tx.GetMsgs() if len(msgs) != 1 { - err = errors.New("must provide genesis StdTx with exactly 1 CreateValidator message") - return + return genesisState, errors.New( + "must provide genesis StdTx with exactly 1 CreateValidator message") } - msg := msgs[0].(stake.MsgCreateValidator) + if _, ok := msgs[0].(stake.MsgCreateValidator); !ok { + return genesisState, fmt.Errorf( + "Genesis transaction %v does not contain a MsgCreateValidator", i) + } + } + for _, acc := range genesisState.Accounts { // create the genesis account, give'm few steaks and a buncha token with there name - genaccs[i] = genesisAccountFromMsgCreateValidator(msg, freeFermionsAcc) - stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply + for _, coin := range acc.Coins { + if coin.Denom == bondDenom { + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens. + Add(sdk.NewDecFromInt(coin.Amount)) // increase the supply + } + } } + genesisState.StakeData = stakeData + genesisState.GenTxs = appGenTxs + return genesisState, nil +} - // create the final app state - genesisState = GenesisState{ - Accounts: genaccs, - StakeData: stakeData, +// NewDefaultGenesisState generates the default state for gaia. +func NewDefaultGenesisState() GenesisState { + return GenesisState{ + Accounts: nil, + StakeData: stake.DefaultGenesisState(), MintData: mint.DefaultGenesisState(), DistrData: distr.DefaultGenesisState(), GovData: gov.DefaultGenesisState(), - SlashingData: slashingData, - GenTxs: appGenTxs, - } - - return -} - -func genesisAccountFromMsgCreateValidator(msg stake.MsgCreateValidator, amount sdk.Int) GenesisAccount { - accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(msg.ValidatorAddr)) - accAuth.Coins = []sdk.Coin{ - {msg.Description.Moniker + "Token", sdk.NewInt(1000)}, - {"steak", amount}, + SlashingData: slashing.DefaultGenesisState(), + GenTxs: nil, } - return NewGenesisAccount(&accAuth) } // GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants @@ -175,27 +178,43 @@ func validateGenesisStateAccounts(accs []GenesisAccount) (err error) { } // GaiaAppGenState but with JSON -func GaiaAppGenStateJSON(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { +func GaiaAppGenStateJSON(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( + appState json.RawMessage, err error) { // create the final app state - genesisState, err := GaiaAppGenState(cdc, appGenTxs) + genesisState, err := GaiaAppGenState(cdc, genDoc, appGenTxs) if err != nil { return nil, err } - appState, err = codec.MarshalJSONIndent(cdc, genesisState) - return + return codec.MarshalJSONIndent(cdc, genesisState) } -// CollectStdTxs processes and validates application's genesis StdTxs and returns the list of validators, -// appGenTxs, and persistent peers required to generate genesis.json. -func CollectStdTxs(moniker string, genTxsDir string, cdc *codec.Codec) ( - validators []tmtypes.GenesisValidator, appGenTxs []auth.StdTx, persistentPeers string, err error) { +// CollectStdTxs processes and validates application's genesis StdTxs and returns +// the list of appGenTxs, and persistent peers required to generate genesis.json. +func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tmtypes.GenesisDoc) ( + appGenTxs []auth.StdTx, persistentPeers string, err error) { + var fos []os.FileInfo fos, err = ioutil.ReadDir(genTxsDir) if err != nil { - return + return appGenTxs, persistentPeers, err } - var addresses []string + // prepare a map of all accounts in genesis state to then validate + // against the validators addresses + var appState GenesisState + if err := cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil { + return appGenTxs, persistentPeers, err + } + addrMap := make(map[string]GenesisAccount, len(appState.Accounts)) + for i := 0; i < len(appState.Accounts); i++ { + acc := appState.Accounts[i] + strAddr := string(acc.Address) + addrMap[strAddr] = acc + } + + // addresses and IPs (and port) validator server info + var addressesIPs []string + for _, fo := range fos { filename := filepath.Join(genTxsDir, fo.Name()) if !fo.IsDir() && (filepath.Ext(filename) != ".json") { @@ -204,48 +223,55 @@ func CollectStdTxs(moniker string, genTxsDir string, cdc *codec.Codec) ( // get the genStdTx var jsonRawTx []byte - jsonRawTx, err = ioutil.ReadFile(filename) - if err != nil { - return + if jsonRawTx, err = ioutil.ReadFile(filename); err != nil { + return appGenTxs, persistentPeers, err } var genStdTx auth.StdTx - err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx) - if err != nil { - return + if err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx); err != nil { + return appGenTxs, persistentPeers, err } appGenTxs = append(appGenTxs, genStdTx) - nodeAddr := genStdTx.GetMemo() - if len(nodeAddr) == 0 { - err = fmt.Errorf("couldn't find node's address in %s", fo.Name()) - return + // the memo flag is used to store + // the ip and node-id, for example this may be: + // "528fd3df22b31f4969b05652bfe8f0fe921321d5@192.168.2.37:26656" + nodeAddrIP := genStdTx.GetMemo() + if len(nodeAddrIP) == 0 { + return appGenTxs, persistentPeers, fmt.Errorf( + "couldn't find node's address and IP in %s", fo.Name()) } + // genesis transactions must be single-message msgs := genStdTx.GetMsgs() if len(msgs) != 1 { - err = errors.New("each genesis transaction must provide a single genesis message") - return + + return appGenTxs, persistentPeers, errors.New( + "each genesis transaction must provide a single genesis message") } - // TODO: this could be decoupled from stake.MsgCreateValidator - // TODO: and we likely want to do it for real world Gaia + // validate the validator address and funds against the accounts in the state msg := msgs[0].(stake.MsgCreateValidator) - validators = append(validators, tmtypes.GenesisValidator{ - PubKey: msg.PubKey, - Power: freeFermionVal, - Name: msg.Description.Moniker, - }) + addr := string(sdk.AccAddress(msg.ValidatorAddr)) + acc, ok := addrMap[addr] + if !ok { + return appGenTxs, persistentPeers, fmt.Errorf( + "account %v not in genesis.json: %+v", addr, addrMap) + } + if acc.Coins.AmountOf(msg.Delegation.Denom).LT(msg.Delegation.Amount) { + err = fmt.Errorf("insufficient fund for the delegation: %s < %s", + acc.Coins.AmountOf(msg.Delegation.Denom), msg.Delegation.Amount) + } // exclude itself from persistent peers if msg.Description.Moniker != moniker { - addresses = append(addresses, nodeAddr) + addressesIPs = append(addressesIPs, nodeAddrIP) } } - sort.Strings(addresses) - persistentPeers = strings.Join(addresses, ",") + sort.Strings(addressesIPs) + persistentPeers = strings.Join(addressesIPs, ",") - return + return appGenTxs, persistentPeers, nil } func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount { diff --git a/cmd/gaia/app/genesis_test.go b/cmd/gaia/app/genesis_test.go index 1acc9f39314b..6c331856c345 100644 --- a/cmd/gaia/app/genesis_test.go +++ b/cmd/gaia/app/genesis_test.go @@ -1,11 +1,13 @@ package app import ( + "encoding/json" + "github.com/tendermint/tendermint/crypto/secp256k1" + tmtypes "github.com/tendermint/tendermint/types" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/stake" stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/stretchr/testify/require" @@ -27,7 +29,8 @@ var ( func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState { // start with the default staking genesis state - stakeData := stake.DefaultGenesisState() + appState := NewDefaultGenesisState() + stakeData := appState.StakeData genAccs := make([]GenesisAccount, len(genTxs)) for i, genTx := range genTxs { @@ -35,17 +38,15 @@ func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState { require.Equal(t, 1, len(msgs)) msg := msgs[0].(stake.MsgCreateValidator) - // get genesis flag account information - genAccs[i] = genesisAccountFromMsgCreateValidator(msg, freeFermionsAcc) - stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply + acc := auth.NewBaseAccountWithAddress(sdk.AccAddress(msg.ValidatorAddr)) + acc.Coins = sdk.Coins{sdk.NewInt64Coin(bondDenom, 150)} + genAccs[i] = NewGenesisAccount(&acc) + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(150)) // increase the supply } // create the final app state - return GenesisState{ - Accounts: genAccs, - StakeData: stakeData, - GovData: gov.DefaultGenesisState(), - } + appState.Accounts = genAccs + return appState } func TestToAccount(t *testing.T) { @@ -68,6 +69,19 @@ func TestGaiaAppGenTx(t *testing.T) { func TestGaiaAppGenState(t *testing.T) { cdc := MakeCodec() _ = cdc + var genDoc tmtypes.GenesisDoc + + // test unmarshalling error + _, err := GaiaAppGenState(cdc, genDoc, []json.RawMessage{}) + require.Error(t, err) + + appState := makeGenesisState(t, []auth.StdTx{}) + genDoc.AppState, err = json.Marshal(appState) + require.NoError(t, err) + + // test validation error + _, err = GaiaAppGenState(cdc, genDoc, []json.RawMessage{}) + require.Error(t, err) // TODO test must provide at least genesis transaction // TODO test with both one and two genesis transactions: @@ -77,7 +91,8 @@ func TestGaiaAppGenState(t *testing.T) { func makeMsg(name string, pk crypto.PubKey) auth.StdTx { desc := stake.NewDescription(name, "", "", "") comm := stakeTypes.CommissionMsg{} - msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin("steak", 50), desc, comm) + msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(bondDenom, + 50), desc, comm) return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "") } @@ -106,3 +121,10 @@ func TestGaiaGenesisValidation(t *testing.T) { err = GaiaValidateGenesisState(genesisState) require.NotNil(t, err) } + +func TestNewDefaultGenesisAccount(t *testing.T) { + addr := secp256k1.GenPrivKeySecp256k1([]byte("")).PubKey().Address() + acc := NewDefaultGenesisAccount(sdk.AccAddress(addr)) + require.Equal(t, sdk.NewInt(1000), acc.Coins.AmountOf("fooToken")) + require.Equal(t, sdk.NewInt(150), acc.Coins.AmountOf(bondDenom)) +} diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index b4791bf126b0..c80b597c75e0 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -5,9 +5,11 @@ package clitest import ( "encoding/json" "fmt" + "github.com/tendermint/tendermint/types" "io/ioutil" "os" "path" + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -207,7 +209,7 @@ func TestGaiaCLIGasAuto(t *testing.T) { func TestGaiaCLICreateValidator(t *testing.T) { chainID, servAddr, port := initializeFixtures(t) - flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) + flags := fmt.Sprintf("--home=%s --chain-id=%v --node=%s", gaiacliHome, chainID, servAddr) // start gaiad server proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) @@ -544,7 +546,7 @@ func TestGaiaCLIConfig(t *testing.T) { servAddr, port, err := server.FreeTCPAddr() require.NoError(t, err) node := fmt.Sprintf("%s:%s", servAddr, port) - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) + chainID := executeInit(t, fmt.Sprintf("gaiad init -o --moniker=foo --home=%s", gaiadHome)) executeWrite(t, fmt.Sprintf("gaiacli --home=%s config", gaiadHome), gaiacliHome, node, "y") config, err := ioutil.ReadFile(path.Join(gaiacliHome, "config", "config.toml")) require.NoError(t, err) @@ -594,12 +596,27 @@ func initializeFixtures(t *testing.T) (chainID, servAddr, port string) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) - - chainID = executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s foo", gaiacliHome), app.DefaultKeyPass) executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) - + fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf( + "gaiacli keys show foo --output=json --home=%s", gaiacliHome)) + chainID = executeInit(t, fmt.Sprintf("gaiad init -o --moniker=foo --home=%s", gaiadHome)) + genFile := filepath.Join(gaiadHome, "config", "genesis.json") + genDoc := readGenesisFile(t, genFile) + var appState app.GenesisState + err := codec.Cdc.UnmarshalJSON(genDoc.AppState, &appState) + require.NoError(t, err) + appState.Accounts = []app.GenesisAccount{app.NewDefaultGenesisAccount(fooAddr)} + appStateJSON, err := codec.Cdc.MarshalJSON(appState) + require.NoError(t, err) + genDoc.AppState = appStateJSON + genDoc.SaveAs(genFile) + executeWrite(t, fmt.Sprintf( + "gaiad gentx --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome), + app.DefaultKeyPass) + executeWrite(t, fmt.Sprintf("gaiad collect-gentxs --home=%s", gaiadHome), app.DefaultKeyPass) // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() + servAddr, port, err = server.FreeTCPAddr() require.NoError(t, err) return } @@ -618,6 +635,18 @@ func writeToNewTempFile(t *testing.T, s string) *os.File { return fp } +func readGenesisFile(t *testing.T, genFile string) types.GenesisDoc { + var genDoc types.GenesisDoc + fp, err := os.Open(genFile) + require.NoError(t, err) + fileContents, err := ioutil.ReadAll(fp) + require.NoError(t, err) + defer fp.Close() + err = codec.Cdc.UnmarshalJSON(fileContents, &genDoc) + require.NoError(t, err) + return genDoc +} + //___________________________________________________________________________________ // executors diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index ed777bf478b2..ae076571b504 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -39,7 +39,8 @@ func main() { } appInit := app.GaiaAppInit() rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit)) - rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, appInit)) + rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc)) + rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, server.AppInit{})) rootCmd.AddCommand(gaiaInit.GenTxCmd(ctx, cdc)) server.AddCommands(ctx, cdc, rootCmd, appInit, diff --git a/cmd/gaia/init/collect.go b/cmd/gaia/init/collect.go new file mode 100644 index 000000000000..34b65e560bce --- /dev/null +++ b/cmd/gaia/init/collect.go @@ -0,0 +1,119 @@ +package init + +import ( + "encoding/json" + "io/ioutil" + "path/filepath" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/tendermint/go-amino" + cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/cli" + "github.com/tendermint/tendermint/types" +) + +type initConfig struct { + ChainID string + GenTxsDir string + Name string + NodeID string + ValPubKey crypto.PubKey +} + +// nolint +func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "collect-gentxs", + Short: "Collect genesis txs and output a genesis.json file", + RunE: func(_ *cobra.Command, _ []string) error { + config := ctx.Config + config.SetRoot(viper.GetString(cli.HomeFlag)) + + name := viper.GetString(client.FlagName) + nodeID, valPubKey, err := InitializeNodeValidatorFiles(config) + if err != nil { + return err + } + genDoc, err := loadGenesisDoc(cdc, config.GenesisFile()) + if err != nil { + return err + } + + toPrint := printInfo{ + Moniker: config.Moniker, + ChainID: genDoc.ChainID, + NodeID: nodeID, + } + + initCfg := initConfig{ + ChainID: genDoc.ChainID, + GenTxsDir: filepath.Join(config.RootDir, "config", "gentx"), + Name: name, + NodeID: nodeID, + ValPubKey: valPubKey, + } + appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc) + if err != nil { + return err + } + + toPrint.AppMessage = appMessage + // print out some key information + return displayInfo(cdc, toPrint) + }, + } + + cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") + return cmd +} + +func genAppStateFromConfig(cdc *codec.Codec, config *cfg.Config, initCfg initConfig, + genDoc types.GenesisDoc) (appState json.RawMessage, err error) { + + genFile := config.GenesisFile() + // process genesis transactions, else create default genesis.json + var appGenTxs []auth.StdTx + var persistentPeers string + var genTxs []json.RawMessage + var jsonRawTx json.RawMessage + + appGenTxs, persistentPeers, err = app.CollectStdTxs( + cdc, config.Moniker, initCfg.GenTxsDir, genDoc) + if err != nil { + return + } + genTxs = make([]json.RawMessage, len(appGenTxs)) + config.P2P.PersistentPeers = persistentPeers + for i, stdTx := range appGenTxs { + jsonRawTx, err = cdc.MarshalJSON(stdTx) + if err != nil { + return + } + genTxs[i] = jsonRawTx + } + + cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) + appState, err = app.GaiaAppGenStateJSON(cdc, genDoc, genTxs) + if err != nil { + return + } + + err = WriteGenesisFile(genFile, initCfg.ChainID, nil, appState) + return +} + +func loadGenesisDoc(cdc *amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) { + genContents, err := ioutil.ReadFile(genFile) + if err != nil { + return + } + err = cdc.UnmarshalJSON(genContents, &genDoc) + return +} diff --git a/cmd/gaia/init/gentx.go b/cmd/gaia/init/gentx.go index 1b24a357688f..7ed8203754b5 100644 --- a/cmd/gaia/init/gentx.go +++ b/cmd/gaia/init/gentx.go @@ -55,9 +55,20 @@ following delegation and commission default parameters: if err != nil { return err } + genDoc, err := loadGenesisDoc(cdc, config.GenesisFile()) + if err != nil { + return err + } + // Read --pubkey, if empty take it from priv_validator.json + if valPubKeyString := viper.GetString(cli.FlagPubKey); valPubKeyString != "" { + valPubKey, err = sdk.GetConsPubKeyBech32(valPubKeyString) + if err != nil { + return err + } + } // Run gaiad tx create-validator - prepareFlagsForTxCreateValidator(config, nodeID, ip, valPubKey) + prepareFlagsForTxCreateValidator(config, nodeID, ip, genDoc.ChainID, valPubKey) createValidatorCmd := cli.GetCmdCreateValidator(cdc) w, err := ioutil.TempFile("", "gentx") @@ -82,28 +93,41 @@ following delegation and commission default parameters: }, } + cmd.Flags().String(tmcli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") - cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id") cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx") + cmd.Flags().AddFlagSet(cli.FsCommissionCreate) + cmd.Flags().AddFlagSet(cli.FsAmount) + cmd.Flags().AddFlagSet(cli.FsPk) cmd.MarkFlagRequired(client.FlagName) return cmd } -func prepareFlagsForTxCreateValidator(config *cfg.Config, nodeID, ip string, valPubKey crypto.PubKey) { - viper.Set(tmcli.HomeFlag, viper.GetString(flagClientHome)) // --home +func prepareFlagsForTxCreateValidator(config *cfg.Config, nodeID, ip, chainID string, + valPubKey crypto.PubKey) { + viper.Set(tmcli.HomeFlag, viper.GetString(flagClientHome)) // --home + viper.Set(client.FlagChainID, chainID) viper.Set(client.FlagFrom, viper.GetString(client.FlagName)) // --from viper.Set(cli.FlagNodeID, nodeID) // --node-id viper.Set(cli.FlagIP, ip) // --ip viper.Set(cli.FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey)) // --pubkey - viper.Set(cli.FlagAmount, defaultAmount) // --amount - viper.Set(cli.FlagCommissionRate, defaultCommissionRate) - viper.Set(cli.FlagCommissionMaxRate, defaultCommissionMaxRate) - viper.Set(cli.FlagCommissionMaxChangeRate, defaultCommissionMaxChangeRate) - viper.Set(cli.FlagGenesisFormat, true) // --genesis-format - viper.Set(cli.FlagMoniker, config.Moniker) // --moniker + viper.Set(cli.FlagGenesisFormat, true) // --genesis-format + viper.Set(cli.FlagMoniker, config.Moniker) // --moniker if config.Moniker == "" { viper.Set(cli.FlagMoniker, viper.GetString(client.FlagName)) } + if viper.GetString(cli.FlagAmount) == "" { + viper.Set(cli.FlagAmount, defaultAmount) + } + if viper.GetString(cli.FlagCommissionRate) == "" { + viper.Set(cli.FlagCommissionRate, defaultCommissionRate) + } + if viper.GetString(cli.FlagCommissionMaxRate) == "" { + viper.Set(cli.FlagCommissionMaxRate, defaultCommissionMaxRate) + } + if viper.GetString(cli.FlagCommissionMaxChangeRate) == "" { + viper.Set(cli.FlagCommissionMaxChangeRate, defaultCommissionMaxChangeRate) + } } func prepareFlagsForTxSign() { diff --git a/cmd/gaia/init/init.go b/cmd/gaia/init/init.go index 467ea3fc2e1e..0290ae4fb2bb 100644 --- a/cmd/gaia/init/init.go +++ b/cmd/gaia/init/init.go @@ -2,24 +2,19 @@ package init import ( "encoding/json" - "errors" "fmt" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/cmd/gaia/app" - "github.com/cosmos/cosmos-sdk/x/auth" - authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" - "github.com/cosmos/cosmos-sdk/x/stake" - "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/privval" "os" "path/filepath" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" "github.com/spf13/viper" cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/p2p" @@ -27,26 +22,11 @@ import ( ) const ( - flagWithTxs = "with-txs" - flagOverwrite = "overwrite" - flagClientHome = "home-client" - flagOverwriteKey = "overwrite-key" - flagSkipGenesis = "skip-genesis" - flagMoniker = "moniker" + flagOverwrite = "overwrite" + flagClientHome = "home-client" + flagMoniker = "moniker" ) -type initConfig struct { - ChainID string - GenTxsDir string - Name string - NodeID string - ClientHome string - WithTxs bool - Overwrite bool - OverwriteKey bool - ValPubKey crypto.PubKey -} - type printInfo struct { Moniker string `json:"moniker"` ChainID string `json:"chain_id"` @@ -70,22 +50,16 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob cmd := &cobra.Command{ Use: "init", Short: "Initialize private validator, p2p, genesis, and application configuration files", - Long: `Initialize validators's and node's configuration files. - -Note that only node's configuration files will be written if the flag --skip-genesis is -enabled, and the genesis file will not be generated. -`, - Args: cobra.NoArgs, + Long: `Initialize validators's and node's configuration files.`, + Args: cobra.NoArgs, RunE: func(_ *cobra.Command, _ []string) error { config := ctx.Config config.SetRoot(viper.GetString(cli.HomeFlag)) - - name := viper.GetString(client.FlagName) chainID := viper.GetString(client.FlagChainID) if chainID == "" { chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6)) } - nodeID, valPubKey, err := InitializeNodeValidatorFiles(config) + nodeID, _, err := InitializeNodeValidatorFiles(config) if err != nil { return err } @@ -93,37 +67,26 @@ enabled, and the genesis file will not be generated. if viper.GetString(flagMoniker) != "" { config.Moniker = viper.GetString(flagMoniker) } - if config.Moniker == "" && name != "" { - config.Moniker = name - } - toPrint := printInfo{ - ChainID: chainID, - Moniker: config.Moniker, - NodeID: nodeID, - } - if viper.GetBool(flagSkipGenesis) { - cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) - return displayInfo(cdc, toPrint) - } - initCfg := initConfig{ - ChainID: chainID, - GenTxsDir: filepath.Join(config.RootDir, "config", "gentx"), - Name: name, - NodeID: nodeID, - ClientHome: viper.GetString(flagClientHome), - WithTxs: viper.GetBool(flagWithTxs), - Overwrite: viper.GetBool(flagOverwrite), - OverwriteKey: viper.GetBool(flagOverwriteKey), - ValPubKey: valPubKey, + var appState json.RawMessage + genFile := config.GenesisFile() + if appState, err = initializeEmptyGenesis(cdc, genFile, chainID, + viper.GetBool(flagOverwrite)); err != nil { + return err } - appMessage, err := initWithConfig(cdc, config, initCfg) - // print out some key information - if err != nil { + if err = WriteGenesisFile(genFile, chainID, nil, appState); err != nil { return err } - toPrint.AppMessage = appMessage + toPrint := printInfo{ + ChainID: chainID, + Moniker: config.Moniker, + NodeID: nodeID, + AppMessage: appState, + } + + cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) + return displayInfo(cdc, toPrint) }, } @@ -131,12 +94,7 @@ enabled, and the genesis file will not be generated. cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file") cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") - cmd.Flags().Bool(flagWithTxs, false, "apply existing genesis transactions from [--home]/config/gentx/") - cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx") - cmd.Flags().String(flagMoniker, "", "overrides --name flag and set the validator's moniker to a different value; ignored if it runs without the --with-txs flag") - cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") - cmd.Flags().Bool(flagOverwriteKey, false, "overwrite client's key") - cmd.Flags().Bool(flagSkipGenesis, false, "do not create genesis.json") + cmd.Flags().String(flagMoniker, "", "set the validator's moniker") return cmd } @@ -151,105 +109,6 @@ func InitializeNodeValidatorFiles(config *cfg.Config) (nodeID string, valPubKey return } -func initWithConfig(cdc *codec.Codec, config *cfg.Config, initCfg initConfig) ( - appMessage json.RawMessage, err error) { - genFile := config.GenesisFile() - if !initCfg.Overwrite && common.FileExists(genFile) { - err = fmt.Errorf("genesis.json file already exists: %v", genFile) - return - } - - // process genesis transactions, else create default genesis.json - var appGenTxs []auth.StdTx - var persistentPeers string - var genTxs []json.RawMessage - var appState json.RawMessage - var jsonRawTx json.RawMessage - chainID := initCfg.ChainID - - if initCfg.WithTxs { - _, appGenTxs, persistentPeers, err = app.CollectStdTxs(config.Moniker, initCfg.GenTxsDir, cdc) - if err != nil { - return - } - genTxs = make([]json.RawMessage, len(appGenTxs)) - config.P2P.PersistentPeers = persistentPeers - for i, stdTx := range appGenTxs { - jsonRawTx, err = cdc.MarshalJSON(stdTx) - if err != nil { - return - } - genTxs[i] = jsonRawTx - } - } else { - var ip, keyPass, secret string - var addr sdk.AccAddress - var signedTx auth.StdTx - - if initCfg.Name == "" { - err = errors.New("must specify validator's moniker (--name)") - return - } - - config.Moniker = initCfg.Name - ip, err = server.ExternalIP() - if err != nil { - return - } - memo := fmt.Sprintf("%s@%s:26656", initCfg.NodeID, ip) - buf := client.BufferStdin() - prompt := fmt.Sprintf("Password for account %q (default: %q):", initCfg.Name, app.DefaultKeyPass) - keyPass, err = client.GetPassword(prompt, buf) - if err != nil && keyPass != "" { - // An error was returned that either failed to read the password from - // STDIN or the given password is not empty but failed to meet minimum - // length requirements. - return - } - if keyPass == "" { - keyPass = app.DefaultKeyPass - } - - addr, secret, err = server.GenerateSaveCoinKey(initCfg.ClientHome, initCfg.Name, keyPass, initCfg.OverwriteKey) - if err != nil { - return - } - appMessage, err = json.Marshal(map[string]string{"secret": secret}) - if err != nil { - return - } - - msg := stake.NewMsgCreateValidator( - sdk.ValAddress(addr), - initCfg.ValPubKey, - sdk.NewInt64Coin("steak", 100), - stake.NewDescription(config.Moniker, "", "", ""), - stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), - ) - txBldr := authtx.NewTxBuilderFromCLI().WithCodec(cdc).WithMemo(memo).WithChainID(chainID) - signedTx, err = txBldr.SignStdTx( - initCfg.Name, keyPass, auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo), false, - ) - if err != nil { - return - } - jsonRawTx, err = cdc.MarshalJSON(signedTx) - if err != nil { - return - } - genTxs = []json.RawMessage{jsonRawTx} - } - - cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) - appState, err = app.GaiaAppGenStateJSON(cdc, genTxs) - if err != nil { - return - } - err = WriteGenesisFile(genFile, chainID, nil, appState) - - return -} - // WriteGenesisFile creates and writes the genesis configuration to disk. An // error is returned if building or writing the configuration to file fails. // nolint: unparam @@ -279,3 +138,13 @@ func ReadOrCreatePrivValidator(privValFile string) crypto.PubKey { } return privValidator.GetPubKey() } + +func initializeEmptyGenesis(cdc *codec.Codec, genFile string, chainID string, + overwrite bool) (appState json.RawMessage, err error) { + if !overwrite && common.FileExists(genFile) { + err = fmt.Errorf("genesis.json file already exists: %v", genFile) + return + } + + return codec.MarshalJSONIndent(cdc, app.NewDefaultGenesisState()) +} diff --git a/cmd/gaia/init/init_test.go b/cmd/gaia/init/init_test.go index 48a5d9247c35..bd5274c26113 100644 --- a/cmd/gaia/init/init_test.go +++ b/cmd/gaia/init/init_test.go @@ -42,7 +42,6 @@ func setupClientHome(t *testing.T) func() { clientDir, err := ioutil.TempDir("", "mock-sdk-cmd") require.Nil(t, err) viper.Set(flagClientHome, clientDir) - viper.Set(flagOverwriteKey, true) return func() { if err := os.RemoveAll(clientDir); err != nil { // TODO: Handle with #870 diff --git a/cmd/gaia/init/testnet.go b/cmd/gaia/init/testnet.go index 3002b83a0e2a..5f729b0a4b7e 100644 --- a/cmd/gaia/init/testnet.go +++ b/cmd/gaia/init/testnet.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/tendermint/tendermint/types" "net" "os" "path/filepath" @@ -35,7 +36,9 @@ var ( const nodeDirPerm = 0755 // get cmd to initialize all files for tendermint testnet and application -func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command { +func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec, + appInit server.AppInit) *cobra.Command { + cmd := &cobra.Command{ Use: "testnet", Short: "Initialize files for a Gaiad testnet", @@ -50,7 +53,7 @@ Example: `, RunE: func(_ *cobra.Command, _ []string) error { config := ctx.Config - return testnetWithConfig(config, cdc, appInit) + return testnetWithConfig(config, cdc) }, } cmd.Flags().Int(nValidators, 4, @@ -69,7 +72,7 @@ Example: return cmd } -func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppInit) error { +func testnetWithConfig(config *cfg.Config, cdc *codec.Codec) error { outDir := viper.GetString(outputDir) numValidators := viper.GetInt(nValidators) @@ -80,6 +83,8 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI valPubKeys := make([]crypto.PubKey, numValidators) // Generate private key, node ID, initial transaction + var accs []app.GenesisAccount + var genFiles []string for i := 0; i < numValidators; i++ { nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i) nodeDaemonHomeName := viper.GetString(nodeDaemonHome) @@ -115,8 +120,12 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI } memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip) + // write genesis + genFiles = append(genFiles, config.GenesisFile()) + buf := client.BufferStdin() - prompt := fmt.Sprintf("Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass) + prompt := fmt.Sprintf( + "Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass) keyPass, err := client.GetPassword(prompt, buf) if err != nil && keyPass != "" { // An error was returned that either failed to read the password from @@ -138,12 +147,20 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI if err != nil { return err } - // Save private key seed words + // save private key seed words err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint) if err != nil { return err } + accs = append(accs, app.GenesisAccount{ + Address: addr, + Coins: sdk.Coins{ + sdk.NewInt64Coin(fmt.Sprintf("%sToken", nodeDirName), 1000), + sdk.NewInt64Coin("steak", 150), + }, + }) + msg := stake.NewMsgCreateValidator( sdk.ValAddress(addr), valPubKeys[i], @@ -173,8 +190,27 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI } } + // Generate empty genesis.json + appGenState := app.NewDefaultGenesisState() + appGenState.Accounts = accs + appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState) + if err != nil { + return err + } + genDoc := types.GenesisDoc{ + ChainID: chainID, + AppState: appGenStateJSON, + Validators: nil, + } + + // Save all genesis.json files for i := 0; i < numValidators; i++ { + if err := genDoc.SaveAs(genFiles[i]); err != nil { + return err + } + } + for i := 0; i < numValidators; i++ { nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i) nodeDaemonHomeName := viper.GetString(nodeDaemonHome) nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName) @@ -186,16 +222,17 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppI nodeID, valPubKey := nodeIDs[i], valPubKeys[i] // Run `init` and generate genesis.json and config.toml initCfg := initConfig{ - ChainID: chainID, - GenTxsDir: gentxsDir, - Name: moniker, - WithTxs: true, - Overwrite: true, - OverwriteKey: false, - NodeID: nodeID, - ValPubKey: valPubKey, - } - if _, err := initWithConfig(cdc, config, initCfg); err != nil { + ChainID: chainID, + GenTxsDir: gentxsDir, + Name: moniker, + NodeID: nodeID, + ValPubKey: valPubKey, + } + genDoc, err := loadGenesisDoc(cdc, config.GenesisFile()) + if err != nil { + return err + } + if _, err := genAppStateFromConfig(cdc, config, initCfg, genDoc); err != nil { return err } } diff --git a/examples/basecoin/cmd/basecoind/main.go b/examples/basecoin/cmd/basecoind/main.go index fc23db78fdc7..4f40a145094e 100644 --- a/examples/basecoin/cmd/basecoind/main.go +++ b/examples/basecoin/cmd/basecoind/main.go @@ -41,7 +41,6 @@ func main() { appInit := server.DefaultAppInit rootCmd.AddCommand(InitCmd(ctx, cdc, appInit)) - rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, appInit)) server.AddCommands(ctx, cdc, rootCmd, appInit, newApp, exportAppStateAndTMValidators) @@ -85,7 +84,8 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob return err } - appState, err := appInit.AppGenState(cdc, []json.RawMessage{genTx}) + appState, err := appInit.AppGenState( + cdc, tmtypes.GenesisDoc{}, []json.RawMessage{genTx}) if err != nil { return err } @@ -108,13 +108,15 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob return err } fmt.Fprintf(os.Stderr, "%s\n", string(out)) - return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID, []tmtypes.GenesisValidator{validator}, appStateJSON) + return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID, + []tmtypes.GenesisValidator{validator}, appStateJSON) }, } cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") - cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(client.FlagChainID, "", + "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(client.FlagName, "", "validator's moniker") cmd.MarkFlagRequired(client.FlagName) return cmd @@ -124,7 +126,8 @@ func newApp(logger log.Logger, db dbm.DB, storeTracer io.Writer) abci.Applicatio return app.NewBasecoinApp(logger, db, baseapp.SetPruning(viper.GetString("pruning"))) } -func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error) { +func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer) ( + json.RawMessage, []tmtypes.GenesisValidator, error) { bapp := app.NewBasecoinApp(logger, db) return bapp.ExportAppStateAndValidators() } diff --git a/examples/democoin/cmd/democoind/main.go b/examples/democoin/cmd/democoind/main.go index b0256b1749dc..2f48a64f34c9 100644 --- a/examples/democoin/cmd/democoind/main.go +++ b/examples/democoin/cmd/democoind/main.go @@ -36,8 +36,9 @@ var CoolAppInit = server.AppInit{ } // coolGenAppParams sets up the app_state and appends the cool app state -func CoolAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { - appState, err = server.SimpleAppGenState(cdc, appGenTxs) +func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( + appState json.RawMessage, err error) { + appState, err = server.SimpleAppGenState(cdc, tmtypes.GenesisDoc{}, appGenTxs) if err != nil { return } @@ -90,7 +91,8 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob return err } - appState, err := appInit.AppGenState(cdc, []json.RawMessage{genTx}) + appState, err := appInit.AppGenState(cdc, tmtypes.GenesisDoc{}, + []json.RawMessage{genTx}) if err != nil { return err } @@ -113,13 +115,15 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cob return err } fmt.Fprintf(os.Stderr, "%s\n", string(out)) - return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID, []tmtypes.GenesisValidator{validator}, appStateJSON) + return gaiaInit.WriteGenesisFile(config.GenesisFile(), chainID, + []tmtypes.GenesisValidator{validator}, appStateJSON) }, } cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory") cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory") - cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(client.FlagChainID, "", + "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(client.FlagName, "", "validator's moniker") cmd.MarkFlagRequired(client.FlagName) return cmd @@ -129,7 +133,8 @@ func newApp(logger log.Logger, db dbm.DB, _ io.Writer) abci.Application { return app.NewDemocoinApp(logger, db) } -func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error) { +func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer) ( + json.RawMessage, []tmtypes.GenesisValidator, error) { dapp := app.NewDemocoinApp(logger, db) return dapp.ExportAppStateAndValidators() } diff --git a/server/init.go b/server/init.go index 6a5d821c1729..75e13f452653 100644 --- a/server/init.go +++ b/server/init.go @@ -19,7 +19,8 @@ import ( type AppInit struct { // AppGenState creates the core parameters initialization. It takes in a // pubkey meant to represent the pubkey of the validator of this machine. - AppGenState func(cdc *codec.Codec, appGenTx []json.RawMessage) (appState json.RawMessage, err error) + AppGenState func(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( + appState json.RawMessage, err error) } // SimpleGenTx is a simple genesis tx @@ -35,7 +36,8 @@ var DefaultAppInit = AppInit{ } // Generate a genesis transaction -func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (appGenTx, cliPrint json.RawMessage, validator types.GenesisValidator, err error) { +func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) ( + appGenTx, cliPrint json.RawMessage, validator types.GenesisValidator, err error) { var addr sdk.AccAddress var secret string addr, secret, err = GenerateCoinKey() @@ -63,7 +65,8 @@ func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (appGenTx, cliPrint json } // create the genesis app state -func SimpleAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { +func SimpleAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( + appState json.RawMessage, err error) { if len(appGenTxs) != 1 { err = errors.New("must provide a single genesis transaction") diff --git a/server/mock/app.go b/server/mock/app.go index 18afa164ec64..dd8f3f5aba7a 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -3,6 +3,7 @@ package mock import ( "encoding/json" "fmt" + "github.com/tendermint/tendermint/types" "path/filepath" abci "github.com/tendermint/tendermint/abci/types" @@ -102,7 +103,8 @@ func InitChainer(key sdk.StoreKey) func(sdk.Context, abci.RequestInitChain) abci // AppGenState can be passed into InitCmd, returns a static string of a few // key-values that can be parsed by InitChainer -func AppGenState(_ *codec.Codec, _ []json.RawMessage) (appState json.RawMessage, err error) { +func AppGenState(_ *codec.Codec, _ types.GenesisDoc, _ []json.RawMessage) (appState json. + RawMessage, err error) { appState = json.RawMessage(`{ "values": [ { @@ -119,7 +121,8 @@ func AppGenState(_ *codec.Codec, _ []json.RawMessage) (appState json.RawMessage, } // AppGenStateEmpty returns an empty transaction state for mocking. -func AppGenStateEmpty(_ *codec.Codec, _ []json.RawMessage) (appState json.RawMessage, err error) { +func AppGenStateEmpty(_ *codec.Codec, _ types.GenesisDoc, _ []json.RawMessage) ( + appState json.RawMessage, err error) { appState = json.RawMessage(``) return } diff --git a/server/mock/app_test.go b/server/mock/app_test.go index 05ec86521943..a5f2a078b263 100644 --- a/server/mock/app_test.go +++ b/server/mock/app_test.go @@ -1,6 +1,7 @@ package mock import ( + "github.com/tendermint/tendermint/types" "testing" "github.com/stretchr/testify/require" @@ -20,7 +21,7 @@ func TestInitApp(t *testing.T) { require.NoError(t, err) // initialize it future-way - appState, err := AppGenState(nil, nil) + appState, err := AppGenState(nil, types.GenesisDoc{}, nil) require.NoError(t, err) //TODO test validators in the init chain? diff --git a/x/stake/client/cli/flags.go b/x/stake/client/cli/flags.go index e4948f945628..d571bef9eb0c 100644 --- a/x/stake/client/cli/flags.go +++ b/x/stake/client/cli/flags.go @@ -35,11 +35,11 @@ const ( // common flagsets to add to various functions var ( - fsPk = flag.NewFlagSet("", flag.ContinueOnError) - fsAmount = flag.NewFlagSet("", flag.ContinueOnError) + FsPk = flag.NewFlagSet("", flag.ContinueOnError) + FsAmount = flag.NewFlagSet("", flag.ContinueOnError) fsShares = flag.NewFlagSet("", flag.ContinueOnError) fsDescriptionCreate = flag.NewFlagSet("", flag.ContinueOnError) - fsCommissionCreate = flag.NewFlagSet("", flag.ContinueOnError) + FsCommissionCreate = flag.NewFlagSet("", flag.ContinueOnError) fsCommissionUpdate = flag.NewFlagSet("", flag.ContinueOnError) fsDescriptionEdit = flag.NewFlagSet("", flag.ContinueOnError) fsValidator = flag.NewFlagSet("", flag.ContinueOnError) @@ -48,8 +48,8 @@ var ( ) func init() { - fsPk.String(FlagPubKey, "", "Go-Amino encoded hex PubKey of the validator. For Ed25519 the go-amino prepend hex is 1624de6220") - fsAmount.String(FlagAmount, "", "Amount of coins to bond") + FsPk.String(FlagPubKey, "", "Bech32-encoded PubKey of the validator. ") + FsAmount.String(FlagAmount, "", "Amount of coins to bond") fsShares.String(FlagSharesAmount, "", "Amount of source-shares to either unbond or redelegate as a positive integer or decimal") fsShares.String(FlagSharesFraction, "", "Fraction of source-shares to either unbond or redelegate as a positive integer or decimal >0 and <=1") fsDescriptionCreate.String(FlagMoniker, "", "validator name") @@ -57,9 +57,9 @@ func init() { fsDescriptionCreate.String(FlagWebsite, "", "optional website") fsDescriptionCreate.String(FlagDetails, "", "optional details") fsCommissionUpdate.String(FlagCommissionRate, "", "The new commission rate percentage") - fsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage") - fsCommissionCreate.String(FlagCommissionMaxRate, "", "The maximum commission rate percentage") - fsCommissionCreate.String(FlagCommissionMaxChangeRate, "", "The maximum commission change rate percentage (per day)") + FsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage") + FsCommissionCreate.String(FlagCommissionMaxRate, "", "The maximum commission rate percentage") + FsCommissionCreate.String(FlagCommissionMaxChangeRate, "", "The maximum commission change rate percentage (per day)") fsDescriptionEdit.String(FlagMoniker, types.DoNotModifyDesc, "validator name") fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website") diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index c43e1276e3e7..3b8d8e2009fa 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -103,10 +103,10 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command { }, } - cmd.Flags().AddFlagSet(fsPk) - cmd.Flags().AddFlagSet(fsAmount) + cmd.Flags().AddFlagSet(FsPk) + cmd.Flags().AddFlagSet(FsAmount) cmd.Flags().AddFlagSet(fsDescriptionCreate) - cmd.Flags().AddFlagSet(fsCommissionCreate) + cmd.Flags().AddFlagSet(FsCommissionCreate) cmd.Flags().AddFlagSet(fsDelegator) cmd.Flags().Bool(FlagGenesisFormat, false, "Export the transaction in gen-tx format; it implies --generate-only") cmd.Flags().String(FlagIP, "", fmt.Sprintf("Node's public IP. It takes effect only when used in combination with --%s", FlagGenesisFormat)) @@ -204,7 +204,7 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command { }, } - cmd.Flags().AddFlagSet(fsAmount) + cmd.Flags().AddFlagSet(FsAmount) cmd.Flags().AddFlagSet(fsValidator) return cmd