package main import ( "context" "io" "math/big" "os" "path/filepath" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/simapp/params" "github.com/cosmos/cosmos-sdk/snapshots" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/crisis" "github.com/spf13/cast" "github.com/spf13/cobra" tmcli "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/rpc" sdkserver "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/auth/types" vestingcli "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" "github.com/cosmos/ethermint/app" ethermintclient "github.com/cosmos/ethermint/client" ) // NewRootCmd creates a new root command for simd. It is called once in the // main function. func NewRootCmd() (*cobra.Command, params.EncodingConfig) { encodingConfig := app.MakeEncodingConfig() initClientCtx := client.Context{}. WithJSONMarshaler(encodingConfig.Marshaler). WithInterfaceRegistry(encodingConfig.InterfaceRegistry). WithTxConfig(encodingConfig.TxConfig). WithLegacyAmino(encodingConfig.Amino). WithInput(os.Stdin). WithAccountRetriever(types.AccountRetriever{}). WithBroadcastMode(flags.BroadcastBlock). WithHomeDir(app.DefaultNodeHome) rootCmd := &cobra.Command{ Use: "ethermintd", Short: "Ethermint Daemon", PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil { return err } return InterceptConfigsPreRunHandler(cmd) }, } initRootCmd(rootCmd, encodingConfig) return rootCmd, encodingConfig } // Execute executes the root command. func Execute(rootCmd *cobra.Command) error { // Create and set a client.Context on the command's Context. During the pre-run // of the root command, a default initialized client.Context is provided to // seed child command execution with values such as AccountRetriver, Keyring, // and a Tendermint RPC. This requires the use of a pointer reference when // getting and setting the client.Context. Ideally, we utilize // https://github.com/spf13/cobra/pull/1118. ctx := context.Background() ctx = context.WithValue(ctx, client.ClientContextKey, &client.Context{}) ctx = context.WithValue(ctx, sdkserver.ServerContextKey, sdkserver.NewDefaultContext()) executor := tmcli.PrepareBaseCmd(rootCmd, "", app.DefaultNodeHome) return executor.ExecuteContext(ctx) } func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { authclient.Codec = encodingConfig.Marshaler sdk.PowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) rootCmd.AddCommand( ethermintclient.ValidateChainID( genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome), ), genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome), genutilcli.MigrateGenesisCmd(), GenTxCmd(app.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome), genutilcli.ValidateGenesisCmd(app.ModuleBasics), AddGenesisAccountCmd(app.DefaultNodeHome), tmcli.NewCompletionCmd(rootCmd, true), ethermintclient.TestnetCmd(app.ModuleBasics, banktypes.GenesisBalancesIterator{}), debug.Cmd(), ) tendermintCmd := &cobra.Command{ Use: "tendermint", Short: "Tendermint subcommands", } tendermintCmd.AddCommand( sdkserver.ShowNodeIDCmd(), sdkserver.ShowValidatorCmd(), sdkserver.ShowAddressCmd(), sdkserver.VersionCmd(), ) rootCmd.AddCommand( StartCmd(newApp, app.DefaultNodeHome), sdkserver.UnsafeResetAllCmd(), flags.LineBreak, tendermintCmd, sdkserver.ExportCmd(createAppAndExport, app.DefaultNodeHome), flags.LineBreak, version.NewVersionCommand(), ) // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( rpc.StatusCommand(), queryCommand(), txCommand(), ethermintclient.KeyCommands(app.DefaultNodeHome), ) rootCmd = addTxFlags(rootCmd) } func addModuleInitFlags(startCmd *cobra.Command) { crisis.AddModuleInitFlags(startCmd) } func queryCommand() *cobra.Command { cmd := &cobra.Command{ Use: "query", Aliases: []string{"q"}, Short: "Querying subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } cmd.AddCommand( authcmd.GetAccountCmd(), rpc.ValidatorCommand(), rpc.BlockCommand(), authcmd.QueryTxsByEventsCmd(), authcmd.QueryTxCmd(), ) app.ModuleBasics.AddQueryCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd } func txCommand() *cobra.Command { cmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } cmd.AddCommand( authcmd.GetSignCommand(), authcmd.GetSignBatchCommand(), authcmd.GetMultiSignCommand(), authcmd.GetValidateSignaturesCommand(), flags.LineBreak, authcmd.GetBroadcastCommand(), authcmd.GetEncodeCommand(), authcmd.GetDecodeCommand(), flags.LineBreak, vestingcli.GetTxCmd(), ) app.ModuleBasics.AddTxCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd } func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application { var cache sdk.MultiStorePersistentCache if cast.ToBool(appOpts.Get(sdkserver.FlagInterBlockCache)) { cache = store.NewCommitKVStoreCacheManager() } skipUpgradeHeights := make(map[int64]bool) for _, h := range cast.ToIntSlice(appOpts.Get(sdkserver.FlagUnsafeSkipUpgrades)) { skipUpgradeHeights[int64(h)] = true } pruningOpts, err := sdkserver.GetPruningOptionsFromFlags(appOpts) if err != nil { panic(err) } snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDir) if err != nil { panic(err) } snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) if err != nil { panic(err) } ethermintApp := app.NewEthermintApp( logger, db, traceStore, true, skipUpgradeHeights, cast.ToString(appOpts.Get(flags.FlagHome)), cast.ToUint(appOpts.Get(sdkserver.FlagInvCheckPeriod)), app.MakeEncodingConfig(), // Ideally, we would reuse the one created by NewRootCmd. appOpts, baseapp.SetPruning(pruningOpts), baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(sdkserver.FlagMinGasPrices))), baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(sdkserver.FlagHaltHeight))), baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(sdkserver.FlagHaltTime))), baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(sdkserver.FlagMinRetainBlocks))), baseapp.SetInterBlockCache(cache), baseapp.SetTrace(cast.ToBool(appOpts.Get(sdkserver.FlagTrace))), baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))), baseapp.SetSnapshotStore(snapshotStore), baseapp.SetSnapshotInterval(cast.ToUint64(appOpts.Get(sdkserver.FlagStateSyncSnapshotInterval))), baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent))), ) return ethermintApp } // createAppAndExport creates a new Ethermint app (optionally at a given height) // and exports state. func createAppAndExport( logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOpts servertypes.AppOptions, ) (servertypes.ExportedApp, error) { encCfg := app.MakeEncodingConfig() // Ideally, we would reuse the one created by NewRootCmd. encCfg.Marshaler = codec.NewProtoCodec(encCfg.InterfaceRegistry) var ethermintApp *app.EthermintApp if height != -1 { ethermintApp = app.NewEthermintApp(logger, db, traceStore, false, map[int64]bool{}, "", uint(1), encCfg, appOpts) if err := ethermintApp.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { ethermintApp = app.NewEthermintApp(logger, db, traceStore, true, map[int64]bool{}, "", uint(1), encCfg, appOpts) } return ethermintApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs) }