diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c960cfc29f8..165df31fb4ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,9 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i ### Improvements +* (server) [#19854](https://github.com/cosmos/cosmos-sdk/pull/19854) Add customizability to start command. + * Add `StartCmdOptions` in `server.AddCommands` instead of `servertypes.ModuleInitFlags`. To set custom flags set them in the `StartCmdOptions` struct on the `AddFlags` field. + * Add `StartCommandHandler` to `StartCmdOptions` to allow custom start command handlers. Users now have total control over how the app starts. * (types) [#19672](https://github.com/cosmos/cosmos-sdk/pull/19672) `PreBlock` now returns only an error for consistency with server/v2. The SDK has upgraded x/upgrade accordingly. `ResponsePreBlock` hence has been removed. * (server) [#19455](https://github.com/cosmos/cosmos-sdk/pull/19455) Allow calling back into the application struct in PostSetup. * (types) [#19512](https://github.com/cosmos/cosmos-sdk/pull/19512) The notion of basic manager does not exist anymore (and all related helpers). @@ -102,6 +105,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i ### API Breaking Changes +* (server) [#19854](https://github.com/cosmos/cosmos-sdk/pull/19854) Remove `servertypes.ModuleInitFlags` types and from `server.AddCommands` as `StartCmdOptions` already achieves the same goal. * (types) [#19792](https://github.com/cosmos/cosmos-sdk/pull/19792) In `MsgSimulatorFn` `sdk.Context` argument is replaced for an `address.Codec`. It also returns an error. * (types) [#19742](https://github.com/cosmos/cosmos-sdk/pull/19742) Removes the use of `Accounts.String` * `SimulationState` now has address and validator codecs as fields. diff --git a/UPGRADING.md b/UPGRADING.md index 672bc0468805..fc91c8335e19 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -31,6 +31,13 @@ clientCtx = clientCtx. Refer to SimApp `root_v2.go` and `root.go` for an example with an app v2 and a legacy app. +Additionally, a simplification of the start command leads to the following change: + +```diff +- server.AddCommands(rootCmd, newApp, func(startCmd *cobra.Command) {}) ++ server.AddCommands(rootCmd, newApp, server.StartCmdOptions[servertypes.Application]{}) +``` + #### Server (`app.go`) ##### Module Manager diff --git a/docs/build/building-apps/05-app-testnet.md b/docs/build/building-apps/05-app-testnet.md index c799236872d7..01c1267142d1 100644 --- a/docs/build/building-apps/05-app-testnet.md +++ b/docs/build/building-apps/05-app-testnet.md @@ -195,8 +195,8 @@ Before we can run the testnet we must plug everything together. in `root.go`, in the `initRootCmd` function we add: ```diff - server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, createMerlinAppAndExport, addModuleInitFlags) - ++ server.AddTestnetCreatorCommand(rootCmd, simapp.DefaultNodeHome, newTestnetApp, addModuleInitFlags) +server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, createMerlinAppAndExport) ++server.AddTestnetCreatorCommand(rootCmd, simapp.DefaultNodeHome, newTestnetApp) ``` Next we will add a newTestnetApp helper function: diff --git a/server/start.go b/server/start.go index 85d0fca57a8c..a3cb688df669 100644 --- a/server/start.go +++ b/server/start.go @@ -124,6 +124,8 @@ type StartCmdOptions[T types.Application] struct { PostSetupStandalone func(app T, svrCtx *Context, clientCtx client.Context, ctx context.Context, g *errgroup.Group) error // AddFlags add custom flags to start cmd AddFlags func(cmd *cobra.Command) + // StartCommandHanlder can be used to customize the start command handler + StartCommandHandler func(svrCtx *Context, clientCtx client.Context, appCreator types.AppCreator[T], inProcessConsensus bool, opts StartCmdOptions[T]) error } // StartCmd runs the service passed in, either stand-alone or in-process with @@ -139,6 +141,10 @@ func StartCmdWithOptions[T types.Application](appCreator types.AppCreator[T], op opts.DBOpener = OpenDB } + if opts.StartCommandHandler == nil { + opts.StartCommandHandler = start + } + cmd := &cobra.Command{ Use: "start", Short: "Run the full node", @@ -187,7 +193,7 @@ is performed. Note, when enabled, gRPC will also be automatically enabled. } err = wrapCPUProfile(serverCtx, func() error { - return start(serverCtx, clientCtx, appCreator, withCMT, opts) + return opts.StartCommandHandler(serverCtx, clientCtx, appCreator, withCMT, opts) }) serverCtx.Logger.Debug("received quit signal") @@ -270,10 +276,7 @@ func startStandAlone[T types.Application](svrCtx *Context, svrCfg serverconfig.C return err } - cmtCfg := svrCtx.Config - home := cmtCfg.RootDir - - err = startAPIServer(ctx, g, cmtCfg, svrCfg, clientCtx, svrCtx, app, home, grpcSrv, metrics) + err = startAPIServer(ctx, g, svrCfg, clientCtx, svrCtx, app, svrCtx.Config.RootDir, grpcSrv, metrics) if err != nil { return err } @@ -304,8 +307,6 @@ func startInProcess[T types.Application](svrCtx *Context, svrCfg serverconfig.Co metrics *telemetry.Metrics, opts StartCmdOptions[T], ) error { cmtCfg := svrCtx.Config - home := cmtCfg.RootDir - gRPCOnly := svrCtx.Viper.GetBool(flagGRPCOnly) g, ctx := getCtx(svrCtx, true) @@ -341,7 +342,7 @@ func startInProcess[T types.Application](svrCtx *Context, svrCfg serverconfig.Co return err } - err = startAPIServer(ctx, g, cmtCfg, svrCfg, clientCtx, svrCtx, app, home, grpcSrv, metrics) + err = startAPIServer(ctx, g, svrCfg, clientCtx, svrCtx, app, cmtCfg.RootDir, grpcSrv, metrics) if err != nil { return err } @@ -504,7 +505,6 @@ func startGrpcServer( func startAPIServer( ctx context.Context, g *errgroup.Group, - cmtCfg *cmtcfg.Config, svrCfg serverconfig.Config, clientCtx client.Context, svrCtx *Context, @@ -612,7 +612,7 @@ func startApp[T types.Application](svrCtx *Context, appCreator types.AppCreator[ if isTestnet, ok := svrCtx.Viper.Get(KeyIsTestnet).(bool); ok && isTestnet { var appPtr *T - appPtr, err = testnetify[T](svrCtx, home, appCreator, db, traceWriter) + appPtr, err = testnetify[T](svrCtx, appCreator, db, traceWriter) if err != nil { return app, traceCleanupFn, err } @@ -639,6 +639,10 @@ func InPlaceTestnetCreator[T types.Application](testnetAppCreator types.AppCreat opts.DBOpener = OpenDB } + if opts.StartCommandHandler == nil { + opts.StartCommandHandler = start + } + cmd := &cobra.Command{ Use: "in-place-testnet [newChainID] [newOperatorAddress]", Short: "Create and start a testnet from current local state", @@ -703,7 +707,7 @@ you want to test the upgrade handler itself. serverCtx.Viper.Set(KeyNewOpAddr, newOperatorAddress) err = wrapCPUProfile(serverCtx, func() error { - return start(serverCtx, clientCtx, testnetAppCreator, withCMT, opts) + return opts.StartCommandHandler(serverCtx, clientCtx, testnetAppCreator, withCMT, opts) }) serverCtx.Logger.Debug("received quit signal") @@ -726,7 +730,7 @@ you want to test the upgrade handler itself. // testnetify modifies both state and blockStore, allowing the provided operator address and local validator key to control the network // that the state in the data folder represents. The chainID of the local genesis file is modified to match the provided chainID. -func testnetify[T types.Application](ctx *Context, home string, testnetAppCreator types.AppCreator[T], db dbm.DB, traceWriter io.WriteCloser) (*T, error) { +func testnetify[T types.Application](ctx *Context, testnetAppCreator types.AppCreator[T], db dbm.DB, traceWriter io.WriteCloser) (*T, error) { config := ctx.Config newChainID, ok := ctx.Viper.Get(KeyNewChainID).(string) @@ -772,9 +776,6 @@ func testnetify[T types.Application](ctx *Context, home string, testnetAppCreato return nil, err } validatorAddress := userPubKey.Address() - if err != nil { - return nil, err - } stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: config.Storage.DiscardABCIResponses, diff --git a/server/types/app.go b/server/types/app.go index 8d73f69e13f1..8a0944afca05 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -8,7 +8,6 @@ import ( cmttypes "github.com/cometbft/cometbft/types" dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/gogoproto/grpc" - "github.com/spf13/cobra" "cosmossdk.io/log" "cosmossdk.io/store/snapshots" @@ -68,9 +67,6 @@ type ( // application using various configurations. AppCreator[T Application] func(log.Logger, dbm.DB, io.Writer, AppOptions) T - // ModuleInitFlags takes a start command and adds modules specific init flags. - ModuleInitFlags func(startCmd *cobra.Command) - // ExportedApp represents an exported app state, along with // validators, consensus params and latest app height. ExportedApp struct { diff --git a/server/util.go b/server/util.go index de48b0bad343..4262c288afd5 100644 --- a/server/util.go +++ b/server/util.go @@ -324,7 +324,7 @@ func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customCo } // AddCommands add server commands -func AddCommands[T types.Application](rootCmd *cobra.Command, appCreator types.AppCreator[T], addStartFlags types.ModuleInitFlags) { +func AddCommands[T types.Application](rootCmd *cobra.Command, appCreator types.AppCreator[T], opts StartCmdOptions[T]) { cometCmd := &cobra.Command{ Use: "comet", Aliases: []string{"cometbft", "tendermint"}, @@ -341,11 +341,7 @@ func AddCommands[T types.Application](rootCmd *cobra.Command, appCreator types.A BootstrapStateCmd(appCreator), ) - startCmd := StartCmd(appCreator) - if addStartFlags != nil { - addStartFlags(startCmd) - } - + startCmd := StartCmdWithOptions(appCreator, opts) rootCmd.AddCommand( startCmd, cometCmd, @@ -354,10 +350,15 @@ func AddCommands[T types.Application](rootCmd *cobra.Command, appCreator types.A ) } +// AddCommandsWithStartCmdOptions adds server commands with the provided StartCmdOptions. +// Deprecated: Use AddCommands directly instead. +func AddCommandsWithStartCmdOptions[T types.Application](rootCmd *cobra.Command, appCreator types.AppCreator[T], opts StartCmdOptions[T]) { + AddCommands(rootCmd, appCreator, opts) +} + // AddTestnetCreatorCommand allows chains to create a testnet from the state existing in their node's data directory. -func AddTestnetCreatorCommand[T types.Application](rootCmd *cobra.Command, appCreator types.AppCreator[T], addStartFlags types.ModuleInitFlags) { +func AddTestnetCreatorCommand[T types.Application](rootCmd *cobra.Command, appCreator types.AppCreator[T]) { testnetCreateCmd := InPlaceTestnetCreator(appCreator) - addStartFlags(testnetCreateCmd) rootCmd.AddCommand(testnetCreateCmd) } diff --git a/simapp/simd/cmd/commands.go b/simapp/simd/cmd/commands.go index 40de6d208cf8..d28de5c0eaf2 100644 --- a/simapp/simd/cmd/commands.go +++ b/simapp/simd/cmd/commands.go @@ -23,8 +23,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/pruning" "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/snapshot" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -35,8 +33,6 @@ import ( func initRootCmd( rootCmd *cobra.Command, txConfig client.TxConfig, - interfaceRegistry codectypes.InterfaceRegistry, - appCodec codec.Codec, moduleManager *module.Manager, ) { cfg := sdk.GetConfig() @@ -51,7 +47,7 @@ func initRootCmd( snapshot.Cmd(newApp), ) - server.AddCommands(rootCmd, newApp, func(startCmd *cobra.Command) {}) + server.AddCommands(rootCmd, newApp, server.StartCmdOptions[servertypes.Application]{}) // add keybase, auxiliary RPC, query, genesis, and tx child commands rootCmd.AddCommand( diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index e2c0fec47604..2b66d8cbe577 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -110,7 +110,7 @@ func NewRootCmd() *cobra.Command { }, } - initRootCmd(rootCmd, encodingConfig.TxConfig, encodingConfig.InterfaceRegistry, encodingConfig.Codec, tempApp.ModuleManager) + initRootCmd(rootCmd, encodingConfig.TxConfig, tempApp.ModuleManager) // autocli opts customClientTemplate, customClientConfig := initClientConfig() diff --git a/simapp/simd/cmd/root_di.go b/simapp/simd/cmd/root_di.go index 8f5a535a62cf..cfc8407edc11 100644 --- a/simapp/simd/cmd/root_di.go +++ b/simapp/simd/cmd/root_di.go @@ -87,7 +87,7 @@ func NewRootCmd() *cobra.Command { }, } - initRootCmd(rootCmd, clientCtx.TxConfig, clientCtx.InterfaceRegistry, clientCtx.Codec, moduleManager) + initRootCmd(rootCmd, clientCtx.TxConfig, moduleManager) if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil { panic(err)