github.com/cosmos/cosmos-sdk@v0.50.10/x/genutil/client/cli/init.go (about) 1 package cli 2 3 import ( 4 "bufio" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "os" 9 "path/filepath" 10 11 cfg "github.com/cometbft/cometbft/config" 12 "github.com/cosmos/go-bip39" 13 "github.com/spf13/cobra" 14 15 errorsmod "cosmossdk.io/errors" 16 "cosmossdk.io/math/unsafe" 17 18 "github.com/cosmos/cosmos-sdk/client" 19 "github.com/cosmos/cosmos-sdk/client/flags" 20 "github.com/cosmos/cosmos-sdk/client/input" 21 "github.com/cosmos/cosmos-sdk/server" 22 sdk "github.com/cosmos/cosmos-sdk/types" 23 "github.com/cosmos/cosmos-sdk/types/module" 24 "github.com/cosmos/cosmos-sdk/version" 25 "github.com/cosmos/cosmos-sdk/x/genutil" 26 "github.com/cosmos/cosmos-sdk/x/genutil/types" 27 ) 28 29 const ( 30 // FlagOverwrite defines a flag to overwrite an existing genesis JSON file. 31 FlagOverwrite = "overwrite" 32 33 // FlagSeed defines a flag to initialize the private validator key from a specific seed. 34 FlagRecover = "recover" 35 36 // FlagDefaultBondDenom defines the default denom to use in the genesis file. 37 FlagDefaultBondDenom = "default-denom" 38 ) 39 40 type printInfo struct { 41 Moniker string `json:"moniker" yaml:"moniker"` 42 ChainID string `json:"chain_id" yaml:"chain_id"` 43 NodeID string `json:"node_id" yaml:"node_id"` 44 GenTxsDir string `json:"gentxs_dir" yaml:"gentxs_dir"` 45 AppMessage json.RawMessage `json:"app_message" yaml:"app_message"` 46 } 47 48 func newPrintInfo(moniker, chainID, nodeID, genTxsDir string, appMessage json.RawMessage) printInfo { 49 return printInfo{ 50 Moniker: moniker, 51 ChainID: chainID, 52 NodeID: nodeID, 53 GenTxsDir: genTxsDir, 54 AppMessage: appMessage, 55 } 56 } 57 58 func displayInfo(info printInfo) error { 59 out, err := json.MarshalIndent(info, "", " ") 60 if err != nil { 61 return err 62 } 63 64 _, err = fmt.Fprintf(os.Stderr, "%s\n", out) 65 66 return err 67 } 68 69 // InitCmd returns a command that initializes all files needed for Tendermint 70 // and the respective application. 71 func InitCmd(mbm module.BasicManager, defaultNodeHome string) *cobra.Command { 72 cmd := &cobra.Command{ 73 Use: "init [moniker]", 74 Short: "Initialize private validator, p2p, genesis, and application configuration files", 75 Long: `Initialize validators's and node's configuration files.`, 76 Args: cobra.ExactArgs(1), 77 RunE: func(cmd *cobra.Command, args []string) error { 78 clientCtx := client.GetClientContextFromCmd(cmd) 79 cdc := clientCtx.Codec 80 81 serverCtx := server.GetServerContextFromCmd(cmd) 82 config := serverCtx.Config 83 config.SetRoot(clientCtx.HomeDir) 84 85 chainID, _ := cmd.Flags().GetString(flags.FlagChainID) 86 switch { 87 case chainID != "": 88 case clientCtx.ChainID != "": 89 chainID = clientCtx.ChainID 90 default: 91 chainID = fmt.Sprintf("test-chain-%v", unsafe.Str(6)) 92 } 93 94 // Get bip39 mnemonic 95 var mnemonic string 96 recover, _ := cmd.Flags().GetBool(FlagRecover) 97 if recover { 98 inBuf := bufio.NewReader(cmd.InOrStdin()) 99 value, err := input.GetString("Enter your bip39 mnemonic", inBuf) 100 if err != nil { 101 return err 102 } 103 104 mnemonic = value 105 if !bip39.IsMnemonicValid(mnemonic) { 106 return errors.New("invalid mnemonic") 107 } 108 } 109 110 // Get initial height 111 initHeight, _ := cmd.Flags().GetInt64(flags.FlagInitHeight) 112 if initHeight < 1 { 113 initHeight = 1 114 } 115 116 nodeID, _, err := genutil.InitializeNodeValidatorFilesFromMnemonic(config, mnemonic) 117 if err != nil { 118 return err 119 } 120 121 config.Moniker = args[0] 122 123 genFile := config.GenesisFile() 124 overwrite, _ := cmd.Flags().GetBool(FlagOverwrite) 125 defaultDenom, _ := cmd.Flags().GetString(FlagDefaultBondDenom) 126 127 // use os.Stat to check if the file exists 128 _, err = os.Stat(genFile) 129 if !overwrite && !os.IsNotExist(err) { 130 return fmt.Errorf("genesis.json file already exists: %v", genFile) 131 } 132 133 // Overwrites the SDK default denom for side-effects 134 if defaultDenom != "" { 135 sdk.DefaultBondDenom = defaultDenom 136 } 137 appGenState := mbm.DefaultGenesis(cdc) 138 139 appState, err := json.MarshalIndent(appGenState, "", " ") 140 if err != nil { 141 return errorsmod.Wrap(err, "Failed to marshal default genesis state") 142 } 143 144 appGenesis := &types.AppGenesis{} 145 if _, err := os.Stat(genFile); err != nil { 146 if !os.IsNotExist(err) { 147 return err 148 } 149 } else { 150 appGenesis, err = types.AppGenesisFromFile(genFile) 151 if err != nil { 152 return errorsmod.Wrap(err, "Failed to read genesis doc from file") 153 } 154 } 155 156 appGenesis.AppName = version.AppName 157 appGenesis.AppVersion = version.Version 158 appGenesis.ChainID = chainID 159 appGenesis.AppState = appState 160 appGenesis.InitialHeight = initHeight 161 appGenesis.Consensus = &types.ConsensusGenesis{ 162 Validators: nil, 163 } 164 165 if err = genutil.ExportGenesisFile(appGenesis, genFile); err != nil { 166 return errorsmod.Wrap(err, "Failed to export genesis file") 167 } 168 169 toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState) 170 171 cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) 172 return displayInfo(toPrint) 173 }, 174 } 175 176 cmd.Flags().String(flags.FlagHome, defaultNodeHome, "node's home directory") 177 cmd.Flags().BoolP(FlagOverwrite, "o", false, "overwrite the genesis.json file") 178 cmd.Flags().Bool(FlagRecover, false, "provide seed phrase to recover existing key instead of creating") 179 cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") 180 cmd.Flags().String(FlagDefaultBondDenom, "", "genesis file default denomination, if left blank default value is 'stake'") 181 cmd.Flags().Int64(flags.FlagInitHeight, 1, "specify the initial block height at genesis") 182 183 return cmd 184 }