feat(server): add custom start handler (#19854)
This commit is contained in:
parent
815c9c5652
commit
def211d868
@ -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).
|
||||
@ -103,6 +106,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.
|
||||
|
||||
@ -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
|
||||
|
||||
4
docs/build/building-apps/05-app-testnet.md
vendored
4
docs/build/building-apps/05-app-testnet.md
vendored
@ -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:
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user