package cli import ( "encoding/json" "fmt" "os" "path/filepath" "github.com/pkg/errors" "github.com/spf13/cobra" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/cli" tmos "github.com/tendermint/tendermint/libs/os" tmrand "github.com/tendermint/tendermint/libs/rand" "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/genutil" ) const ( flagOverwrite = "overwrite" flagClientHome = "home-client" ) type printInfo struct { Moniker string `json:"moniker" yaml:"moniker"` ChainID string `json:"chain_id" yaml:"chain_id"` NodeID string `json:"node_id" yaml:"node_id"` GenTxsDir string `json:"gentxs_dir" yaml:"gentxs_dir"` AppMessage json.RawMessage `json:"app_message" yaml:"app_message"` } func newPrintInfo(moniker, chainID, nodeID, genTxsDir string, appMessage json.RawMessage) printInfo { return printInfo{ Moniker: moniker, ChainID: chainID, NodeID: nodeID, GenTxsDir: genTxsDir, AppMessage: appMessage, } } func displayInfo(cdc codec.JSONMarshaler, info printInfo) error { out, err := codec.MarshalJSONIndent(cdc, info) if err != nil { return err } _, err = fmt.Fprintf(os.Stderr, "%s\n", string(sdk.MustSortJSON(out))) return err } // InitCmd returns a command that initializes all files needed for Tendermint // and the respective application. func InitCmd(mbm module.BasicManager, defaultNodeHome string) *cobra.Command { cmd := &cobra.Command{ Use: "init [moniker]", Short: "Initialize private validator, p2p, genesis, and application configuration files", Long: `Initialize validators's and node's configuration files.`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx := client.GetClientContextFromCmd(cmd) cdc := clientCtx.JSONMarshaler serverCtx := server.GetServerContextFromCmd(cmd) config := serverCtx.Config config.SetRoot(clientCtx.HomeDir) chainID, _ := cmd.Flags().GetString(flags.FlagChainID) if chainID == "" { chainID = fmt.Sprintf("test-chain-%v", tmrand.Str(6)) } nodeID, _, err := genutil.InitializeNodeValidatorFiles(config) if err != nil { return err } config.Moniker = args[0] genFile := config.GenesisFile() overwrite, _ := cmd.Flags().GetBool(flagOverwrite) if !overwrite && tmos.FileExists(genFile) { return fmt.Errorf("genesis.json file already exists: %v", genFile) } appState, err := codec.MarshalJSONIndent(cdc, mbm.DefaultGenesis(cdc)) if err != nil { return errors.Wrap(err, "Failed to marshall default genesis state") } genDoc := &types.GenesisDoc{} if _, err := os.Stat(genFile); err != nil { if !os.IsNotExist(err) { return err } } else { genDoc, err = types.GenesisDocFromFile(genFile) if err != nil { return errors.Wrap(err, "Failed to read genesis doc from file") } } genDoc.ChainID = chainID genDoc.Validators = nil genDoc.AppState = appState if err = genutil.ExportGenesisFile(genDoc, genFile); err != nil { return errors.Wrap(err, "Failed to export gensis file") } toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", 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(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") return cmd }