diff --git a/app/app.go b/app/app.go index d35af313d..b1122feb2 100644 --- a/app/app.go +++ b/app/app.go @@ -24,6 +24,8 @@ import ( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" + "cosmossdk.io/client/v2/autocli" + "cosmossdk.io/core/appmodule" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/evidence" evidencekeeper "cosmossdk.io/x/evidence/keeper" @@ -36,6 +38,7 @@ import ( upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node" "github.com/cosmos/cosmos-sdk/codec" @@ -43,6 +46,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/runtime" runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services" + "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" @@ -152,6 +156,17 @@ import ( // FIXME remove this line, dummy const appName = "chain-maind" +func getGovProposalHandlers() []govclient.ProposalHandler { + var govProposalHandlers []govclient.ProposalHandler + // this line is used by starport scaffolding # stargate/app/govProposalHandlers + + govProposalHandlers = append(govProposalHandlers, + paramsclient.ProposalHandler, + ) + + return govProposalHandlers +} + var ( // DefaultNodeHome default home directories for the application daemon DefaultNodeHome string @@ -219,6 +234,7 @@ type ChainApp struct { *baseapp.BaseApp legacyAmino *codec.LegacyAmino appCodec codec.Codec + txConfig client.TxConfig interfaceRegistry types.InterfaceRegistry invCheckPeriod uint @@ -265,7 +281,8 @@ type ChainApp struct { ScopedICAAuthKeeper capabilitykeeper.ScopedKeeper // the module manager - mm *module.Manager + mm *module.Manager + BasicModuleManager module.BasicManager // simulation manager sm *module.SimulationManager @@ -291,18 +308,17 @@ func New( db dbm.DB, traceStore io.Writer, loadLatest bool, - skipUpgradeHeights map[int64]bool, - homePath string, - invCheckPeriod uint, - encodingConfig appparams.EncodingConfig, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), ) *ChainApp { // TODO: Remove cdc in favor of appCodec once all modules are migrated. + encodingConfig := MakeEncodingConfig() appCodec := encodingConfig.Marshaler legacyAmino := encodingConfig.Amino + txConfig := encodingConfig.TxConfig interfaceRegistry := encodingConfig.InterfaceRegistry + homePath := cast.ToString(appOpts.Get(flags.FlagHome)) baseAppOptions = memiavlstore.SetupMemIAVL(logger, homePath, appOpts, false, false, baseAppOptions) // NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx // Setup Mempool and Proposal Handlers @@ -320,11 +336,13 @@ func New( keys, memKeys, tkeys, okeys := StoreKeys() + invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)) app := &ChainApp{ BaseApp: bApp, legacyAmino: legacyAmino, appCodec: appCodec, interfaceRegistry: interfaceRegistry, + txConfig: txConfig, invCheckPeriod: invCheckPeriod, keys: keys, tkeys: tkeys, @@ -413,6 +431,12 @@ func New( runtime.NewKVStoreService(keys[feegrant.StoreKey]), app.AccountKeeper, ) + + // get skipUpgradeHeights from the app options + skipUpgradeHeights := map[int64]bool{} + for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) { + skipUpgradeHeights[int64(h)] = true + } app.UpgradeKeeper = *upgradekeeper.NewKeeper(skipUpgradeHeights, runtime.NewKVStoreService(keys[upgradetypes.StoreKey]), appCodec, homePath, app.BaseApp, authAddr) // register the staking hooks @@ -598,6 +622,20 @@ func New( supply.NewAppModule(app.SupplyKeeper), nft.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper), ) + + // BasicModuleManager defines the module BasicManager is in charge of setting up basic, + // non-dependant module elements, such as codec registration and genesis verification. + // By default it is composed of all the module from the module manager. + // Additionally, app module basics can be overwritten by passing them as argument. + app.BasicModuleManager = module.NewBasicManagerFromManager( + app.mm, + map[string]module.AppModuleBasic{ + genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + govtypes.ModuleName: gov.NewAppModuleBasic(getGovProposalHandlers()), + }) + app.BasicModuleManager.RegisterLegacyAminoCodec(encodingConfig.Amino) + app.BasicModuleManager.RegisterInterfaces(interfaceRegistry) + app.mm.SetOrderPreBlockers( upgradetypes.ModuleName, ) @@ -891,6 +929,39 @@ func (app *ChainApp) InterfaceRegistry() types.InterfaceRegistry { return app.interfaceRegistry } +func (app *ChainApp) TxConfig() client.TxConfig { + return app.txConfig +} + +func (app *ChainApp) EncodingConfig() appparams.EncodingConfig { + return appparams.EncodingConfig{ + InterfaceRegistry: app.InterfaceRegistry(), + Marshaler: app.AppCodec(), + TxConfig: app.TxConfig(), + Amino: app.LegacyAmino(), + } +} + +// AutoCliOpts returns the autocli options for the app. +func (app *ChainApp) AutoCliOpts() autocli.AppOptions { + modules := make(map[string]appmodule.AppModule, 0) + for _, m := range app.mm.Modules { + if moduleWithName, ok := m.(module.HasName); ok { + moduleName := moduleWithName.Name() + if appModule, ok := moduleWithName.(appmodule.AppModule); ok { + modules[moduleName] = appModule + } + } + } + return autocli.AppOptions{ + Modules: modules, + ModuleOptions: runtimeservices.ExtractAutoCLIOptions(app.mm.Modules), + AddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), + ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), + } +} + // GetKey returns the KVStoreKey for the provided store key. // // NOTE: This is solely to be used for testing purposes. diff --git a/app/encoding.go b/app/encoding.go index e2a139c8e..90b8f378b 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -10,7 +10,5 @@ func MakeEncodingConfig() params.EncodingConfig { encodingConfig := params.MakeEncodingConfig() std.RegisterLegacyAminoCodec(encodingConfig.Amino) std.RegisterInterfaces(encodingConfig.InterfaceRegistry) - ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino) - ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry) return encodingConfig } diff --git a/cmd/chain-maind/app/app.go b/cmd/chain-maind/app/app.go index 8ab9c54da..5ba4cc9d4 100644 --- a/cmd/chain-maind/app/app.go +++ b/cmd/chain-maind/app/app.go @@ -9,7 +9,9 @@ import ( "time" conf "github.com/cosmos/cosmos-sdk/client/config" + "github.com/cosmos/cosmos-sdk/crypto/keyring" serverconfig "github.com/cosmos/cosmos-sdk/server/config" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" "github.com/cosmos/cosmos-sdk/types/module" "cosmossdk.io/log" @@ -53,7 +55,12 @@ const EnvPrefix = "CRO" // main function. func NewRootCmd() (*cobra.Command, params.EncodingConfig) { config.SetConfig() - encodingConfig := app.MakeEncodingConfig() + + tempApp := app.New( + log.NewNopLogger(), dbm.NewMemDB(), nil, true, + simtestutil.NewAppOptionsWithFlagHome(app.DefaultNodeHome), + ) + encodingConfig := tempApp.EncodingConfig() initClientCtx := client.Context{}. WithCodec(encodingConfig.Marshaler). WithInterfaceRegistry(encodingConfig.InterfaceRegistry). @@ -91,7 +98,15 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) { }, } - initRootCmd(rootCmd, encodingConfig) + initRootCmd(rootCmd, encodingConfig, tempApp.BasicModuleManager) + + autoCliOpts := tempApp.AutoCliOpts() + autoCliOpts.Keyring, _ = keyring.NewAutoCLIKeyring(initClientCtx.Keyring) + autoCliOpts.ClientCtx = initClientCtx + + if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil { + panic(err) + } return rootCmd, encodingConfig } @@ -120,12 +135,12 @@ func initAppConfig() (string, interface{}) { return serverconfig.DefaultConfigTemplate + memiavlcfg.DefaultConfigTemplate, customAppConfig } -func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { +func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, basicManager module.BasicManager) { // authclient.Codec = encodingConfig.Marshaler cfg := sdk.GetConfig() cfg.Seal() - initCmd := genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome) + initCmd := genutilcli.InitCmd(basicManager, app.DefaultNodeHome) initCmd.PreRun = func(cmd *cobra.Command, args []string) { serverCtx := server.GetServerContextFromCmd(cmd) serverCtx.Config.Consensus.TimeoutCommit = 3 * time.Second @@ -218,7 +233,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { initCmd, chainmaincli.AddGenesisAccountCmd(app.DefaultNodeHome), tmcli.NewCompletionCmd(rootCmd, true), - chainmaincli.AddTestnetCmd(app.ModuleBasics, banktypes.GenesisBalancesIterator{}), + chainmaincli.AddTestnetCmd(basicManager, banktypes.GenesisBalancesIterator{}), debug.Cmd(), confixcmd.ConfigCommand(), pruning.Cmd(newApp, app.DefaultNodeHome), @@ -230,7 +245,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( server.StatusCommand(), - genesisCommand(encodingConfig.TxConfig, app.ModuleBasics), + genesisCommand(encodingConfig.TxConfig, basicManager), queryCommand(), txCommand(), keys.Commands(), @@ -264,7 +279,7 @@ func queryCommand() *cobra.Command { Use: "query", Aliases: []string{"q"}, Short: "Querying subcommands", - DisableFlagParsing: true, + DisableFlagParsing: false, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } @@ -280,9 +295,6 @@ func queryCommand() *cobra.Command { chainmaincli.QueryAllTxCmd(), ) - app.ModuleBasics.AddQueryCommands(cmd) - cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") - return cmd } @@ -290,7 +302,7 @@ func txCommand() *cobra.Command { cmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", - DisableFlagParsing: true, + DisableFlagParsing: false, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } @@ -305,11 +317,9 @@ func txCommand() *cobra.Command { authcmd.GetBroadcastCommand(), authcmd.GetEncodeCommand(), authcmd.GetDecodeCommand(), + authcmd.GetSimulateCmd(), ) - app.ModuleBasics.AddTxCommands(cmd) - cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") - return cmd } @@ -321,14 +331,7 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts serverty } baseappOptions := server.DefaultBaseappOptions(appOpts) - return app.New( - logger, db, traceStore, true, skipUpgradeHeights, - cast.ToString(appOpts.Get(flags.FlagHome)), - cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), - app.MakeEncodingConfig(), // Ideally, we would reuse the one created by NewRootCmd. - appOpts, - baseappOptions..., - ) + return app.New(logger, db, traceStore, true, appOpts, baseappOptions...) } // exportAppStateAndTMValidators creates a new chain app (optionally at a given height) @@ -345,13 +348,13 @@ func exportAppStateAndTMValidators( var a *app.ChainApp if height != -1 { - a = app.New(logger, db, traceStore, false, map[int64]bool{}, "", uint(1), encCfg, appOpts) + a = app.New(logger, db, traceStore, false, appOpts) if err := a.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { - a = app.New(logger, db, traceStore, true, map[int64]bool{}, "", uint(1), encCfg, appOpts) + a = app.New(logger, db, traceStore, true, appOpts) } return a.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) diff --git a/config/config_test.go b/config/config_test.go index 5c34fb541..b81c73d40 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -49,7 +49,7 @@ func TestConversion(t *testing.T) { result sdk.Coin expErr bool }{ - {sdk.NewCoin("foo", sdk.ZeroInt()), config.HumanCoinUnit, sdk.Coin{}, true}, + {sdk.NewCoin("foo", sdkmath.ZeroInt()), config.HumanCoinUnit, sdk.Coin{}, true}, {sdk.NewCoin(config.HumanCoinUnit, sdkmath.ZeroInt()), "foo", sdk.Coin{}, true}, {sdk.NewCoin(config.HumanCoinUnit, sdkmath.ZeroInt()), "FOO", sdk.Coin{}, true},