package cmd import ( "errors" "io" "os" dbm "github.com/cosmos/cosmos-db" "github.com/spf13/cobra" "github.com/spf13/viper" "cosmossdk.io/client/v2/autocli" "cosmossdk.io/log" confixcmd "cosmossdk.io/tools/confix/cmd" "git.cw.tr/mukan-network/mukan-sdk/client" "git.cw.tr/mukan-network/mukan-sdk/client/config" "git.cw.tr/mukan-network/mukan-sdk/client/debug" "git.cw.tr/mukan-network/mukan-sdk/client/flags" "git.cw.tr/mukan-network/mukan-sdk/client/keys" "git.cw.tr/mukan-network/mukan-sdk/client/pruning" "git.cw.tr/mukan-network/mukan-sdk/client/rpc" "git.cw.tr/mukan-network/mukan-sdk/client/snapshot" "git.cw.tr/mukan-network/mukan-sdk/codec" addresscodec "git.cw.tr/mukan-network/mukan-sdk/codec/address" "git.cw.tr/mukan-network/mukan-sdk/server" serverconfig "git.cw.tr/mukan-network/mukan-sdk/server/config" servertypes "git.cw.tr/mukan-network/mukan-sdk/server/types" simtestutil "git.cw.tr/mukan-network/mukan-sdk/testutil/sims" sdk "git.cw.tr/mukan-network/mukan-sdk/types" "git.cw.tr/mukan-network/mukan-sdk/types/module" "git.cw.tr/mukan-network/mukan-sdk/types/tx/signing" authcmd "git.cw.tr/mukan-network/mukan-sdk/x/auth/client/cli" "git.cw.tr/mukan-network/mukan-sdk/x/auth/tx" txmodule "git.cw.tr/mukan-network/mukan-sdk/x/auth/tx/config" "git.cw.tr/mukan-network/mukan-sdk/x/auth/types" "git.cw.tr/mukan-network/mukan-sdk/x/crisis" genutilcli "git.cw.tr/mukan-network/mukan-sdk/x/genutil/client/cli" cmtcfg "git.cw.tr/mukan-network/mukan-consensus/config" "github.com/cosmos/ibc-go/simapp" "github.com/cosmos/ibc-go/simapp/params" ) // NewRootCmd creates a new root command for simd. It is called once in the // main function. func NewRootCmd() *cobra.Command { // we "pre"-instantiate the application for getting the injected/configured encoding configuration // note, this is not necessary when using app wiring, as depinject can be directly used (see root_v2.go) tempApp := simapp.NewSimApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, simtestutil.NewAppOptionsWithFlagHome(tempDir())) encodingConfig := params.EncodingConfig{ InterfaceRegistry: tempApp.InterfaceRegistry(), Codec: tempApp.AppCodec(), TxConfig: tempApp.TxConfig(), Amino: tempApp.LegacyAmino(), } initClientCtx := client.Context{}. WithCodec(encodingConfig.Codec). WithInterfaceRegistry(encodingConfig.InterfaceRegistry). WithLegacyAmino(encodingConfig.Amino). WithInput(os.Stdin). WithAccountRetriever(types.AccountRetriever{}). WithHomeDir(simapp.DefaultNodeHome). WithViper("") // In simapp, we don't use any prefix for env variables. rootCmd := &cobra.Command{ Use: "simd", Short: "simulation app", SilenceErrors: true, PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // set the default command outputs cmd.SetOut(cmd.OutOrStdout()) cmd.SetErr(cmd.ErrOrStderr()) initClientCtx = initClientCtx.WithCmdContext(cmd.Context()) initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags()) if err != nil { return err } initClientCtx, err = config.ReadFromClientConfig(initClientCtx) if err != nil { return err } // This needs to go after ReadFromClientConfig, as that function // sets the RPC client needed for SIGN_MODE_TEXTUAL. This sign mode // is only available if the client is online. if !initClientCtx.Offline { txConfigOpts := tx.ConfigOptions{ EnabledSignModes: append(tx.DefaultSignModes, signing.SignMode_SIGN_MODE_TEXTUAL), TextualCoinMetadataQueryFn: txmodule.NewGRPCCoinMetadataQueryFn(initClientCtx), } txConfigWithTextual, err := tx.NewTxConfigWithOptions( codec.NewProtoCodec(encodingConfig.InterfaceRegistry), txConfigOpts, ) if err != nil { return err } initClientCtx = initClientCtx.WithTxConfig(txConfigWithTextual) } if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil { return err } customAppTemplate, customAppConfig := initAppConfig() customCMTConfig := initCometBFTConfig() return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customCMTConfig) }, } initRootCmd(rootCmd, encodingConfig, tempApp.BasicModuleManager) autoCliOpts, err := enrichAutoCliOpts(tempApp.AutoCliOpts(), initClientCtx) if err != nil { panic(err) } if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil { panic(err) } return rootCmd } func enrichAutoCliOpts(autoCliOpts autocli.AppOptions, clientCtx client.Context) (autocli.AppOptions, error) { autoCliOpts.AddressCodec = addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) autoCliOpts.ValidatorAddressCodec = addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()) autoCliOpts.ConsensusAddressCodec = addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()) var err error clientCtx, err = config.ReadFromClientConfig(clientCtx) if err != nil { return autocli.AppOptions{}, err } autoCliOpts.ClientCtx = clientCtx return autoCliOpts, nil } // initCometBFTConfig helps to override default CometBFT Config values. // return cmtcfg.DefaultConfig if no custom configuration is required for the application. func initCometBFTConfig() *cmtcfg.Config { cfg := cmtcfg.DefaultConfig() // these values put a higher strain on node memory // cfg.P2P.MaxNumInboundPeers = 100 // cfg.P2P.MaxNumOutboundPeers = 40 return cfg } // initAppConfig helps to override default appConfig template and configs. // return "", nil if no custom configuration is required for the application. func initAppConfig() (string, any) { // The following code snippet is just for reference. // WASMConfig defines configuration for the wasm module. type WASMConfig struct { // This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries QueryGasLimit uint64 `mapstructure:"query_gas_limit"` // Address defines the gRPC-web server to listen on LruSize uint64 `mapstructure:"lru_size"` } type CustomAppConfig struct { serverconfig.Config WASM WASMConfig `mapstructure:"wasm"` } // Optionally allow the chain developer to overwrite the SDK's default // server config. srvCfg := serverconfig.DefaultConfig() // The SDK's default minimum gas price is set to "" (empty value) inside // app.toml. If left empty by validators, the node will halt on startup. // However, the chain developer can set a default app.toml value for their // validators here. // // In summary: // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their // own app.toml config, // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their // own app.toml to override, or use this default value. // // In simapp, we set the min gas prices to 0. srvCfg.MinGasPrices = "0stake" // srvCfg.BaseConfig.IAVLDisableFastNode = true // disable fastnode by default customAppConfig := CustomAppConfig{ Config: *srvCfg, WASM: WASMConfig{ LruSize: 1, QueryGasLimit: 300000, }, } customAppTemplate := serverconfig.DefaultConfigTemplate + ` [wasm] # This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries query_gas_limit = 300000 # This is the number of wasm vm instances we keep cached in memory for speed-up # Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally lru_size = 0` return customAppTemplate, customAppConfig } func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, basicManager module.BasicManager) { cfg := sdk.GetConfig() cfg.Seal() rootCmd.AddCommand( genutilcli.InitCmd(basicManager, simapp.DefaultNodeHome), debug.Cmd(), confixcmd.ConfigCommand(), pruning.Cmd(newApp, simapp.DefaultNodeHome), snapshot.Cmd(newApp), server.QueryBlockResultsCmd(), ) server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, appExport, addModuleInitFlags) // add keybase, auxiliary RPC, query, genesis, and tx child commands rootCmd.AddCommand( server.StatusCommand(), genesisCommand(encodingConfig, basicManager), txCommand(), queryCommand(), keys.Commands(), ) } func addModuleInitFlags(startCmd *cobra.Command) { crisis.AddModuleInitFlags(startCmd) } func queryCommand() *cobra.Command { cmd := &cobra.Command{ Use: "query", Aliases: []string{"q"}, Short: "Querying subcommands", DisableFlagParsing: false, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } cmd.AddCommand( rpc.ValidatorCommand(), server.QueryBlockCmd(), authcmd.QueryTxsByEventsCmd(), server.QueryBlocksCmd(), authcmd.QueryTxCmd(), authcmd.GetSimulateCmd(), ) return cmd } func txCommand() *cobra.Command { cmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", DisableFlagParsing: false, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } cmd.AddCommand( authcmd.GetSignCommand(), authcmd.GetSignBatchCommand(), authcmd.GetMultiSignCommand(), authcmd.GetMultiSignBatchCmd(), authcmd.GetValidateSignaturesCommand(), authcmd.GetBroadcastCommand(), authcmd.GetEncodeCommand(), authcmd.GetDecodeCommand(), authcmd.GetSimulateCmd(), ) return cmd } // genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter func genesisCommand(encodingConfig params.EncodingConfig, basicManager module.BasicManager, cmds ...*cobra.Command) *cobra.Command { cmd := genutilcli.Commands(encodingConfig.TxConfig, basicManager, simapp.DefaultNodeHome) for _, subCmd := range cmds { cmd.AddCommand(subCmd) } return cmd } // newApp creates the application func newApp( logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions, ) servertypes.Application { baseappOptions := server.DefaultBaseappOptions(appOpts) return simapp.NewSimApp( logger, db, traceStore, true, appOpts, baseappOptions..., ) } // appExport creates a new simapp (optionally at a given height) and exports state. func appExport( logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOpts servertypes.AppOptions, modulesToExport []string, ) (servertypes.ExportedApp, error) { var simApp *simapp.SimApp // this check is necessary as we use the flag in x/upgrade. // we can exit more gracefully by checking the flag here. homePath, ok := appOpts.Get(flags.FlagHome).(string) if !ok || homePath == "" { return servertypes.ExportedApp{}, errors.New("application home not set") } viperAppOpts, ok := appOpts.(*viper.Viper) if !ok { return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper") } // overwrite the FlagInvCheckPeriod viperAppOpts.Set(server.FlagInvCheckPeriod, 1) appOpts = viperAppOpts if height != -1 { simApp = simapp.NewSimApp(logger, db, traceStore, false, appOpts) if err := simApp.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { simApp = simapp.NewSimApp(logger, db, traceStore, true, appOpts) } return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) } var tempDir = func() string { dir, err := os.MkdirTemp("", "simapp") if err != nil { dir = simapp.DefaultNodeHome } defer os.RemoveAll(dir) return dir }