github.com/Finschia/finschia-sdk@v0.48.1/x/genutil/client/cli/init.go (about)

     1  package cli
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/cosmos/go-bip39"
    11  	"github.com/pkg/errors"
    12  	"github.com/spf13/cobra"
    13  
    14  	cfg "github.com/Finschia/ostracon/config"
    15  	"github.com/Finschia/ostracon/libs/cli"
    16  	ostos "github.com/Finschia/ostracon/libs/os"
    17  	ostrand "github.com/Finschia/ostracon/libs/rand"
    18  	"github.com/Finschia/ostracon/types"
    19  
    20  	"github.com/Finschia/finschia-sdk/client"
    21  	"github.com/Finschia/finschia-sdk/client/flags"
    22  	"github.com/Finschia/finschia-sdk/client/input"
    23  	"github.com/Finschia/finschia-sdk/server"
    24  	sdk "github.com/Finschia/finschia-sdk/types"
    25  	"github.com/Finschia/finschia-sdk/types/module"
    26  	"github.com/Finschia/finschia-sdk/x/genutil"
    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  
    37  type printInfo struct {
    38  	Moniker    string          `json:"moniker" yaml:"moniker"`
    39  	ChainID    string          `json:"chain_id" yaml:"chain_id"`
    40  	NodeID     string          `json:"node_id" yaml:"node_id"`
    41  	GenTxsDir  string          `json:"gentxs_dir" yaml:"gentxs_dir"`
    42  	AppMessage json.RawMessage `json:"app_message" yaml:"app_message"`
    43  }
    44  
    45  func newPrintInfo(moniker, chainID, nodeID, genTxsDir string, appMessage json.RawMessage) printInfo {
    46  	return printInfo{
    47  		Moniker:    moniker,
    48  		ChainID:    chainID,
    49  		NodeID:     nodeID,
    50  		GenTxsDir:  genTxsDir,
    51  		AppMessage: appMessage,
    52  	}
    53  }
    54  
    55  func displayInfo(info printInfo) error {
    56  	out, err := json.MarshalIndent(info, "", " ")
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	_, err = fmt.Fprintf(os.Stderr, "%s\n", string(sdk.MustSortJSON(out)))
    62  
    63  	return err
    64  }
    65  
    66  // InitCmd returns a command that initializes all files needed for Tendermint
    67  // and the respective application.
    68  func InitCmd(mbm module.BasicManager, defaultNodeHome string) *cobra.Command {
    69  	cmd := &cobra.Command{
    70  		Use:   "init [moniker]",
    71  		Short: "Initialize private validator, p2p, genesis, and application configuration files",
    72  		Long:  `Initialize validators's and node's configuration files.`,
    73  		Args:  cobra.ExactArgs(1),
    74  		RunE: func(cmd *cobra.Command, args []string) error {
    75  			clientCtx := client.GetClientContextFromCmd(cmd)
    76  			cdc := clientCtx.Codec
    77  
    78  			serverCtx := server.GetServerContextFromCmd(cmd)
    79  			config := serverCtx.Config
    80  			config.SetRoot(clientCtx.HomeDir)
    81  
    82  			chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
    83  			if chainID == "" {
    84  				chainID = fmt.Sprintf("test-chain-%v", ostrand.Str(6))
    85  			}
    86  
    87  			// Get bip39 mnemonic
    88  			var mnemonic string
    89  			recover, _ := cmd.Flags().GetBool(FlagRecover)
    90  			if recover {
    91  				inBuf := bufio.NewReader(cmd.InOrStdin())
    92  				value, err := input.GetString("Enter your bip39 mnemonic", inBuf)
    93  				if err != nil {
    94  					return err
    95  				}
    96  
    97  				mnemonic = value
    98  				if !bip39.IsMnemonicValid(mnemonic) {
    99  					return errors.New("invalid mnemonic")
   100  				}
   101  			}
   102  
   103  			nodeID, _, err := genutil.InitializeNodeValidatorFilesFromMnemonic(config, mnemonic)
   104  			if err != nil {
   105  				return err
   106  			}
   107  
   108  			config.Moniker = args[0]
   109  
   110  			genFile := config.GenesisFile()
   111  			overwrite, _ := cmd.Flags().GetBool(FlagOverwrite)
   112  
   113  			if !overwrite && ostos.FileExists(genFile) {
   114  				return fmt.Errorf("genesis.json file already exists: %v", genFile)
   115  			}
   116  
   117  			appState, err := json.MarshalIndent(mbm.DefaultGenesis(cdc), "", " ")
   118  			if err != nil {
   119  				return errors.Wrap(err, "Failed to marshall default genesis state")
   120  			}
   121  
   122  			genDoc := &types.GenesisDoc{}
   123  			if _, err := os.Stat(genFile); err != nil {
   124  				if !os.IsNotExist(err) {
   125  					return err
   126  				}
   127  			} else {
   128  				genDoc, err = types.GenesisDocFromFile(genFile)
   129  				if err != nil {
   130  					return errors.Wrap(err, "Failed to read genesis doc from file")
   131  				}
   132  			}
   133  
   134  			genDoc.ChainID = chainID
   135  			genDoc.Validators = nil
   136  			genDoc.AppState = appState
   137  
   138  			if err = genutil.ExportGenesisFile(genDoc, genFile); err != nil {
   139  				return errors.Wrap(err, "Failed to export gensis file")
   140  			}
   141  
   142  			toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState)
   143  
   144  			cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
   145  			return displayInfo(toPrint)
   146  		},
   147  	}
   148  
   149  	cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory")
   150  	cmd.Flags().BoolP(FlagOverwrite, "o", false, "overwrite the genesis.json file")
   151  	cmd.Flags().Bool(FlagRecover, false, "provide seed phrase to recover existing key instead of creating")
   152  	cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
   153  
   154  	return cmd
   155  }