From 0a0380ef6f981b091f06d0278ca6883c2c0f291f Mon Sep 17 00:00:00 2001 From: wangzhiyong Date: Fri, 4 Jan 2019 15:34:33 +0800 Subject: [PATCH] =?UTF-8?q?server=20init=20command=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/basecoin/README.md | 68 ++++- example/basecoin/cmd/basecoind/main.go | 34 ++- example/basecoin/types/genesis.go | 75 +---- server/config/config.go | 7 - server/init.go | 397 ------------------------- server/init_cmd.go | 114 +++++++ server/util.go | 61 +++- 7 files changed, 263 insertions(+), 493 deletions(-) delete mode 100644 server/init.go create mode 100644 server/init_cmd.go diff --git a/example/basecoin/README.md b/example/basecoin/README.md index 63c42dd..15d6440 100644 --- a/example/basecoin/README.md +++ b/example/basecoin/README.md @@ -14,23 +14,50 @@ $ go install ``` 2. 初始化 ``` -$ basecoind init --chain-id basecoin --name basecoind-node +$ basecoind init --chain-id basecoin --moniker basecoin-node ``` ``` { - "chain_id": "basecoin", - "node_id": "bada889c78e1a3936863e6a89eb766c28b398032", - "app_message": { - "name": "Jia", - "pass": "12345678", - "secret": "problem dutch dilemma climb endorse clitnt despair ostrich cannon path once suspect place base brisk deposit area spike veteran coin injury dove electric famous" - } + "moniker": "basecoin-node", + "chain_id": "basecoin", + "node_id": "0048c2db694c91b2b3b272ec901cce0636d13ff3", + "gentxs_dir": "", + "app_message": { + "qcps": [ + { + "name": "qstar", + "chain_id": "qstar", + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "ish2+qpPsoHxf7m+uwi8FOAWw6iMaDZgLKl1la4yMAs=" + } + } + ], + "accounts": [ + { + "address": "address1y0nwp6hmxm0g0zhvuglr2jdgglns8tsdctdre6", + "coins": [ + { + "coin_name": "qstar", + "amount": "100000000" + } + ] + } + ] + } } ``` -创建配置文件,以及创世账户“Jia” -3. 创建账户"Liu" +命令执行完成后,配置文件初始化完成并创建了创世账户“address1y0nwp6hmxm0g0zhvuglr2jdgglns8tsdctdre6”. + +> 配置文件默认目录为$HOME/.basecoind/config + +> 创世账户默认名称为`Jia`,密码为`123456`. 可以通过`basecli keys命令进行查看操作` + + + +3. 创建本地账户"Liu" ``` $ basecli keys add Liu @@ -49,7 +76,7 @@ book distance cart design another view olympic orbit leopard indoor tumble dutch ``` $ basecoind start ``` -5. 账户查询状态 +5. 查询账户信息 ``` $ basecli query account Jia ``` @@ -70,8 +97,19 @@ $ basecli query account Jia } ] } -} +} +``` + +``` +$ basecli query account Liu +``` + +``` +ERROR: account not exists ``` + +> 本地账户`Liu`未在链上 + 6. 链内交易 ``` $ basecli tx send --from=Jia --to=Liu --coin-name=qstar --coin-amount=10 @@ -81,7 +119,7 @@ $ basecli tx send --from=Jia --to=Liu --coin-name=qstar --coin-amount=10 Password to sign with 'Jia': {"check_tx":{},"deliver_tx":{},"hash":"0677BB2E156496064960ED759BFEDBE6D09A8282","height":"22"} ``` -7. 账户查询状态 +7. 查询账户信息 ``` $ basecli query account Jia ``` @@ -105,7 +143,7 @@ $ basecli query account Jia } ] } -} +} ``` @@ -129,7 +167,7 @@ $ basecli query account Liu } ] } -} +} ``` 8. 查询交易 diff --git a/example/basecoin/cmd/basecoind/main.go b/example/basecoin/cmd/basecoind/main.go index 22e8ee6..ef6dac9 100644 --- a/example/basecoin/cmd/basecoind/main.go +++ b/example/basecoin/cmd/basecoind/main.go @@ -6,10 +6,13 @@ import ( "github.com/QOSGroup/qbase/server" "github.com/QOSGroup/qbase/version" "github.com/spf13/cobra" + go_amino "github.com/tendermint/go-amino" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/libs/cli" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" + tmtypes "github.com/tendermint/tendermint/types" "io" ) @@ -26,7 +29,10 @@ func main() { // version cmd rootCmd.AddCommand(version.VersionCmd) - server.AddCommands(ctx, cdc, rootCmd, types.BaseCoinInit(), newApp) + //add init command + rootCmd.AddCommand(server.InitCmd(ctx, cdc, genBaseCoindGenesisDoc, types.DefaultNodeHome)) + + server.AddCommands(ctx, cdc, rootCmd, newApp) executor := cli.PrepareBaseCmd(rootCmd, "basecoin", types.DefaultNodeHome) @@ -39,3 +45,29 @@ func main() { func newApp(logger log.Logger, db dbm.DB, storeTracer io.Writer) abci.Application { return app.NewApp(logger, db, storeTracer) } + +func genBaseCoindGenesisDoc(ctx *server.Context, cdc *go_amino.Codec, chainID string, nodeValidatorPubKey crypto.PubKey) (tmtypes.GenesisDoc, error) { + + validator := tmtypes.GenesisValidator{ + PubKey: nodeValidatorPubKey, + Power: 10, + } + + addr, _, err := types.GenerateCoinKey(cdc, types.DefaultCLIHome) + if err != nil { + return tmtypes.GenesisDoc{}, err + } + + genTx := types.BaseCoinGenTx{addr} + appState, err := types.BaseCoinAppGenState(cdc, genTx) + if err != nil { + return tmtypes.GenesisDoc{}, err + } + + return tmtypes.GenesisDoc{ + ChainID: chainID, + Validators: []tmtypes.GenesisValidator{validator}, + AppState: appState, + }, nil + +} diff --git a/example/basecoin/types/genesis.go b/example/basecoin/types/genesis.go index 5d845dc..e980dea 100644 --- a/example/basecoin/types/genesis.go +++ b/example/basecoin/types/genesis.go @@ -2,20 +2,16 @@ package types import ( "encoding/json" - "errors" "fmt" + "os" + "path/filepath" + "github.com/QOSGroup/qbase/account" clikeys "github.com/QOSGroup/qbase/client/keys" "github.com/QOSGroup/qbase/keys" - "github.com/QOSGroup/qbase/server" - "github.com/QOSGroup/qbase/server/config" "github.com/QOSGroup/qbase/types" - "github.com/spf13/pflag" "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/crypto" - tmtypes "github.com/tendermint/tendermint/types" - "os" - "path/filepath" dbm "github.com/tendermint/tendermint/libs/db" ) @@ -60,72 +56,11 @@ func (ga *GenesisAccount) ToAppAccount() (acc *AppAccount, err error) { }, nil } -func BaseCoinInit() server.AppInit { - fsAppGenState := pflag.NewFlagSet("", pflag.ContinueOnError) - - fsAppGenTx := pflag.NewFlagSet("", pflag.ContinueOnError) - fsAppGenTx.String(server.FlagName, "", "validator moniker, required") - fsAppGenTx.String(server.FlagClientHome, DefaultCLIHome, - "home directory for the client, used for key generation") - fsAppGenTx.Bool(server.FlagOWK, false, "overwrite the accounts created") - - return server.AppInit{ - FlagsAppGenState: fsAppGenState, - FlagsAppGenTx: fsAppGenTx, - AppGenTx: BaseCoinAppGenTx, - AppGenState: BaseCoinAppGenState, - } -} - type BaseCoinGenTx struct { Addr types.Address `json:"addr"` } -// Generate a genesis transaction -func BaseCoinAppGenTx(cdc *amino.Codec, pk crypto.PubKey, genTxConfig config.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { - - var addr types.Address - var secret string - addr, secret, err = GenerateCoinKey(cdc, genTxConfig.CliRoot) - if err != nil { - return - } - - var bz []byte - simpleGenTx := BaseCoinGenTx{addr} - bz, err = cdc.MarshalJSON(simpleGenTx) - if err != nil { - return - } - appGenTx = json.RawMessage(bz) - - mm := map[string]string{"name": DefaultAccountName, "pass": DefaultAccountPass, "secret": secret} - bz, err = cdc.MarshalJSON(mm) - if err != nil { - return - } - cliPrint = json.RawMessage(bz) - - validator = tmtypes.GenesisValidator{ - PubKey: pk, - Power: 10, - } - return -} - -func BaseCoinAppGenState(cdc *amino.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { - - if len(appGenTxs) != 1 { - err = errors.New("must provide a single genesis transaction") - return - } - - var genTx BaseCoinGenTx - err = cdc.UnmarshalJSON(appGenTxs[0], &genTx) - if err != nil { - return - } +func BaseCoinAppGenState(cdc *amino.Codec, appGenTxs BaseCoinGenTx) (appState json.RawMessage, err error) { appState = json.RawMessage(fmt.Sprintf(`{ "qcps":[{ @@ -145,7 +80,7 @@ func BaseCoinAppGenState(cdc *amino.Codec, appGenTxs []json.RawMessage) (appStat } ] }] - }`, genTx.Addr)) + }`, appGenTxs.Addr)) return } diff --git a/server/config/config.go b/server/config/config.go index f3c7118..1cbde54 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -17,13 +17,6 @@ const ( defaultMinimumFees = "" ) -type GenTx struct { - Name string - CliRoot string - Overwrite bool - IP string -} - // BaseConfig defines the server's basic configuration type BaseConfig struct { // Tx minimum fee diff --git a/server/init.go b/server/init.go deleted file mode 100644 index 175d82a..0000000 --- a/server/init.go +++ /dev/null @@ -1,397 +0,0 @@ -package server - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "sort" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "github.com/spf13/viper" - - "github.com/tendermint/tendermint/crypto" - - cfg "github.com/tendermint/tendermint/config" - tmcli "github.com/tendermint/tendermint/libs/cli" - cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/p2p" - pvm "github.com/tendermint/tendermint/privval" - tmtypes "github.com/tendermint/tendermint/types" - - serverconfig "github.com/QOSGroup/qbase/server/config" -) - -//Parameter names, for init gen-tx command -var ( - FlagName = "name" - FlagClientHome = "home-client" - FlagOWK = "owk" -) - -//parameter names, init command -var ( - FlagOverwrite = "overwrite" - FlagWithTxs = "with-txs" - FlagIP = "ip" - FlagChainID = "chain-id" -) - -// genesis piece structure for creating combined genesis -type GenesisTx struct { - NodeID string `json:"node_id"` - IP string `json:"ip"` - Validator tmtypes.GenesisValidator `json:"validator"` - AppGenTx json.RawMessage `json:"app_gen_tx"` -} - -// Storage for init command input parameters -type InitConfig struct { - ChainID string - GenTxs bool - GenTxsDir string - Overwrite bool -} - -// get cmd to initialize all files for tendermint and application -func GenTxCmd(ctx *Context, cdc *Codec, appInit AppInit) *cobra.Command { - cmd := &cobra.Command{ - Use: "gen-tx", - Short: "Create genesis transaction file (under [--home]/config/gentx/gentx-[nodeID].json)", - Args: cobra.NoArgs, - RunE: func(_ *cobra.Command, args []string) error { - - config := ctx.Config - config.SetRoot(viper.GetString(tmcli.HomeFlag)) - - ip := viper.GetString(FlagIP) - if len(ip) == 0 { - eip, err := ExternalIP() - if err != nil { - return err - } - ip = eip - } - - genTxConfig := serverconfig.GenTx{ - viper.GetString(FlagName), - viper.GetString(FlagClientHome), - viper.GetBool(FlagOWK), - ip, - } - cliPrint, genTxFile, err := gentxWithConfig(cdc, appInit, config, genTxConfig) - if err != nil { - return err - } - toPrint := struct { - AppMessage json.RawMessage `json:"app_message"` - GenTxFile json.RawMessage `json:"gen_tx_file"` - }{ - cliPrint, - genTxFile, - } - out, err := MarshalJSONIndent(cdc, toPrint) - if err != nil { - return err - } - fmt.Println(string(out)) - return nil - }, - } - cmd.Flags().String(FlagIP, "", "external facing IP to use if left blank IP will be retrieved from this machine") - cmd.Flags().AddFlagSet(appInit.FlagsAppGenTx) - return cmd -} - -func gentxWithConfig(cdc *Codec, appInit AppInit, config *cfg.Config, genTxConfig serverconfig.GenTx) ( - cliPrint json.RawMessage, genTxFile json.RawMessage, err error) { - nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) - if err != nil { - return - } - nodeID := string(nodeKey.ID()) - pubKey := readOrCreatePrivValidator(config) - - appGenTx, cliPrint, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig) - if err != nil { - return - } - - tx := GenesisTx{ - NodeID: nodeID, - IP: genTxConfig.IP, - Validator: validator, - AppGenTx: appGenTx, - } - bz, err := MarshalJSONIndent(cdc, tx) - if err != nil { - return - } - genTxFile = json.RawMessage(bz) - name := fmt.Sprintf("gentx-%v.json", nodeID) - writePath := filepath.Join(config.RootDir, "config", "gentx") - file := filepath.Join(writePath, name) - err = cmn.EnsureDir(writePath, 0700) - if err != nil { - return - } - err = cmn.WriteFile(file, bz, 0644) - if err != nil { - return - } - - // Write updated config with moniker - config.Moniker = genTxConfig.Name - configFilePath := filepath.Join(config.RootDir, "config", "config.toml") - cfg.WriteConfigFile(configFilePath, config) - - return -} - -// get cmd to initialize all files for tendermint and application -func InitCmd(ctx *Context, cdc *Codec, appInit AppInit) *cobra.Command { - cmd := &cobra.Command{ - Use: "init", - Short: "Initialize genesis config, priv-validator file, and p2p-node file", - Args: cobra.NoArgs, - RunE: func(_ *cobra.Command, _ []string) error { - - config := ctx.Config - config.SetRoot(viper.GetString(tmcli.HomeFlag)) - initConfig := InitConfig{ - viper.GetString(FlagChainID), - viper.GetBool(FlagWithTxs), - filepath.Join(config.RootDir, "config", "gentx"), - viper.GetBool(FlagOverwrite), - } - - chainID, nodeID, appMessage, err := initWithConfig(cdc, appInit, config, initConfig) - if err != nil { - return err - } - // print out some key information - toPrint := struct { - ChainID string `json:"chain_id"` - NodeID string `json:"node_id"` - AppMessage json.RawMessage `json:"app_message"` - }{ - chainID, - nodeID, - appMessage, - } - out, err := MarshalJSONIndent(cdc, toPrint) - if err != nil { - return err - } - fmt.Println(string(out)) - return nil - }, - } - cmd.Flags().BoolP(FlagOverwrite, "o", false, "overwrite the genesis.json file") - cmd.Flags().String(FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") - cmd.Flags().String(FlagName, "", "a custom human readable name for this node. required") - cmd.MarkFlagRequired(FlagName) - return cmd -} - -func initWithConfig(cdc *Codec, appInit AppInit, config *cfg.Config, initConfig InitConfig) ( - chainID string, nodeID string, appMessage json.RawMessage, err error) { - nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) - if err != nil { - return - } - nodeID = string(nodeKey.ID()) - pubKey := readOrCreatePrivValidator(config) - - if initConfig.ChainID == "" { - initConfig.ChainID = fmt.Sprintf("test-chain-%v", cmn.RandStr(6)) - } - chainID = initConfig.ChainID - - genFile := config.GenesisFile() - if !initConfig.Overwrite && cmn.FileExists(genFile) { - err = fmt.Errorf("genesis.json file already exists: %v", genFile) - return - } - - // process genesis transactions, or otherwise create one for defaults - var appGenTxs []json.RawMessage - var validators []tmtypes.GenesisValidator - var persistentPeers string - - if initConfig.GenTxs { - validators, appGenTxs, persistentPeers, err = processGenTxs(initConfig.GenTxsDir, cdc) - if err != nil { - return - } - config.P2P.PersistentPeers = persistentPeers - configFilePath := filepath.Join(config.RootDir, "config", "config.toml") - cfg.WriteConfigFile(configFilePath, config) - } else { - genTxConfig := serverconfig.GenTx{ - viper.GetString(FlagName), - viper.GetString(FlagClientHome), - viper.GetBool(FlagOWK), - "127.0.0.1", - } - - // Write updated config with moniker - config.Moniker = genTxConfig.Name - configFilePath := filepath.Join(config.RootDir, "config", "config.toml") - cfg.WriteConfigFile(configFilePath, config) - appGenTx, am, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig) - appMessage = am - if err != nil { - return "", "", nil, err - } - validators = []tmtypes.GenesisValidator{validator} - appGenTxs = []json.RawMessage{appGenTx} - } - - appState, err := appInit.AppGenState(cdc, appGenTxs) - if err != nil { - return - } - - err = writeGenesisFile(cdc, genFile, initConfig.ChainID, validators, appState) - if err != nil { - return - } - - return -} - -// append a genesis-piece -func processGenTxs(genTxsDir string, cdc *Codec) ( - validators []tmtypes.GenesisValidator, appGenTxs []json.RawMessage, persistentPeers string, err error) { - - var fos []os.FileInfo - fos, err = ioutil.ReadDir(genTxsDir) - if err != nil { - return - } - - genTxs := make(map[string]GenesisTx) - var nodeIDs []string - for _, fo := range fos { - filename := path.Join(genTxsDir, fo.Name()) - if !fo.IsDir() && (path.Ext(filename) != ".json") { - continue - } - - // get the genTx - var bz []byte - bz, err = ioutil.ReadFile(filename) - if err != nil { - return - } - var genTx GenesisTx - err = cdc.UnmarshalJSON(bz, &genTx) - if err != nil { - return - } - - genTxs[genTx.NodeID] = genTx - nodeIDs = append(nodeIDs, genTx.NodeID) - } - - sort.Strings(nodeIDs) - - for _, nodeID := range nodeIDs { - genTx := genTxs[nodeID] - - // combine some stuff - validators = append(validators, genTx.Validator) - appGenTxs = append(appGenTxs, genTx.AppGenTx) - - // Add a persistent peer - comma := "," - if len(persistentPeers) == 0 { - comma = "" - } - persistentPeers += fmt.Sprintf("%s%s@%s:26656", comma, genTx.NodeID, genTx.IP) - } - - return -} - -//________________________________________________________________________________________ - -// read of create the private key file for this config -func readOrCreatePrivValidator(tmConfig *cfg.Config) crypto.PubKey { - // private validator - privValFile := tmConfig.PrivValidatorFile() - var privValidator *pvm.FilePV - if cmn.FileExists(privValFile) { - privValidator = pvm.LoadFilePV(privValFile) - } else { - privValidator = pvm.GenFilePV(privValFile) - privValidator.Save() - } - return privValidator.GetPubKey() -} - -// writeGenesisFile creates and writes the genesis configuration to disk. An -// error is returned if building or writing the configuration to file fails. -// nolint: unparam -func writeGenesisFile(cdc *Codec, genesisFile, chainID string, validators []tmtypes.GenesisValidator, appState json.RawMessage) error { - genDoc := tmtypes.GenesisDoc{ - ChainID: chainID, - Validators: validators, - AppState: appState, - } - - if err := genDoc.ValidateAndComplete(); err != nil { - return err - } - - return genDoc.SaveAs(genesisFile) -} - -//_____________________________________________________________________ - -// Core functionality passed from the application to the server init command -type AppInit struct { - // flags required for application init functions - FlagsAppGenState *pflag.FlagSet - FlagsAppGenTx *pflag.FlagSet - - // create the application genesis tx - AppGenTx func(cdc *Codec, pk crypto.PubKey, genTxConfig serverconfig.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) - - // 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, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) -} - -//_____________________________________________________________________ - -// simple default application init -var DefaultAppInit = AppInit{ - AppGenTx: SimpleAppGenTx, - AppGenState: SimpleAppGenState, -} - -// Generate a genesis transaction -func SimpleAppGenTx(cdc *Codec, pk crypto.PubKey, genTxConfig serverconfig.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { - - cliPrint = json.RawMessage("{}") - - validator = tmtypes.GenesisValidator{ - PubKey: pk, - Power: 10, - } - return -} - -// create the genesis app state -func SimpleAppGenState(cdc *Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { - - appState = json.RawMessage("{}") - return -} diff --git a/server/init_cmd.go b/server/init_cmd.go new file mode 100644 index 0000000..24a7d2c --- /dev/null +++ b/server/init_cmd.go @@ -0,0 +1,114 @@ +package server + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + go_amino "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/libs/common" + "github.com/tendermint/tendermint/types" +) + +const ( + flagOverwrite = "overwrite" + flagClientHome = "home-client" + flagMoniker = "moniker" + flagChainID = "chain-id" +) + +type printInfo struct { + Moniker string `json:"moniker"` + ChainID string `json:"chain_id"` + NodeID string `json:"node_id"` + GenTxsDir string `json:"gentxs_dir"` + AppMessage json.RawMessage `json:"app_message"` +} + +//自定义生成GenesisDoc +type CustomGenGenesisDocFunc func(ctx *Context, cdc *go_amino.Codec, chainID string, nodeValidatorPubKey crypto.PubKey) (types.GenesisDoc, error) + +// nolint: errcheck +func displayInfo(cdc *go_amino.Codec, info printInfo) error { + out, err := cdc.MarshalJSONIndent(info, "", " ") + if err != nil { + return err + } + fmt.Fprintf(os.Stderr, "%s\n", string(out)) + return nil +} + +// get cmd to initialize all files for tendermint and application +// nolint +func InitCmd(ctx *Context, cdc *go_amino.Codec, genGenesisDocFun CustomGenGenesisDocFunc, defaultNodeHome string) *cobra.Command { + cmd := &cobra.Command{ + Use: "init", + Short: "Initialize private validator, p2p, genesis, and application configuration files", + 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)) + + chainID := viper.GetString(flagChainID) + if chainID == "" { + chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6)) + } + + nodeID, valPubkey, err := InitializeNodeValidatorFiles(config) + if err != nil { + return err + } + + config.Moniker = viper.GetString(flagMoniker) + + genFile := config.GenesisFile() + + overwrite := viper.GetBool(flagOverwrite) + if !overwrite && common.FileExists(genFile) { + return fmt.Errorf("genesis.json file already exists: %v", genFile) + } + + genesisDoc, err := genGenesisDocFun(ctx, cdc, chainID, valPubkey) + if err != nil { + return err + } + + if err = SaveGenDoc(genFile, genesisDoc); err != nil { + return err + } + + toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", genesisDoc.AppState) + + cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) + + return displayInfo(cdc, toPrint) + }, + } + + cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory") + cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file") + cmd.Flags().String(flagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(flagMoniker, "", "set the validator's moniker") + cmd.MarkFlagRequired(flagMoniker) + + return cmd +} + +func newPrintInfo(moniker, chainID, nodeID, genTxsDir string, + appMessage json.RawMessage) printInfo { + + return printInfo{ + Moniker: moniker, + ChainID: chainID, + NodeID: nodeID, + GenTxsDir: genTxsDir, + AppMessage: appMessage, + } +} diff --git a/server/util.go b/server/util.go index 43842c8..b023976 100644 --- a/server/util.go +++ b/server/util.go @@ -2,6 +2,7 @@ package server import ( "encoding/json" + "io/ioutil" "net" "os" "os/signal" @@ -15,12 +16,17 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" go_amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/libs/common" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/libs/cli" tmflags "github.com/tendermint/tendermint/libs/cli/flags" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/privval" + "github.com/tendermint/tendermint/types" ) // server context @@ -114,8 +120,7 @@ func validateConfig(conf *cfg.Config) error { // add server commands func AddCommands( ctx *Context, cdc *go_amino.Codec, - rootCmd *cobra.Command, appInit AppInit, - appCreator AppCreator) { + rootCmd *cobra.Command, appCreator AppCreator) { rootCmd.PersistentFlags().String("log_level", ctx.Config.LogLevel, "Log level") @@ -131,7 +136,6 @@ func AddCommands( ) rootCmd.AddCommand( - InitCmd(ctx, cdc, appInit), StartCmd(ctx, appCreator), UnsafeResetAllCmd(ctx), tendermintCmd, @@ -225,3 +229,54 @@ func addrToIP(addr net.Addr) net.IP { } return ip } + +func SaveGenDoc(genFile string, genDoc types.GenesisDoc) error { + if err := genDoc.ValidateAndComplete(); err != nil { + return err + } + + return genDoc.SaveAs(genFile) +} + +// read of create the private key file for this config +func ReadOrCreatePrivValidator(privValFile string) crypto.PubKey { + var privValidator *privval.FilePV + + if common.FileExists(privValFile) { + privValidator = privval.LoadFilePV(privValFile) + } else { + privValidator = privval.GenFilePV(privValFile) + privValidator.Save() + } + + return privValidator.GetPubKey() +} + +// InitializeNodeValidatorFiles creates private validator and p2p configuration files. +func InitializeNodeValidatorFiles( + config *cfg.Config) (nodeID string, valPubKey crypto.PubKey, err error, +) { + + nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) + if err != nil { + return nodeID, valPubKey, err + } + + nodeID = string(nodeKey.ID()) + valPubKey = ReadOrCreatePrivValidator(config.PrivValidatorFile()) + + return nodeID, valPubKey, nil +} + +func loadGenesisDoc(cdc *go_amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) { + genContents, err := ioutil.ReadFile(genFile) + if err != nil { + return genDoc, err + } + + if err := cdc.UnmarshalJSON(genContents, &genDoc); err != nil { + return genDoc, err + } + + return genDoc, err +}