diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d96d62632fe..5e79ce7e3937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,108 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features +<<<<<<< HEAD +======= +* [\#11430](https://github.com/cosmos/cosmos-sdk/pull/11430) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag. +* (x/upgrade) [\#11116](https://github.com/cosmos/cosmos-sdk/pull/11116) `MsgSoftwareUpgrade` and has been added to support v1beta2 msgs-based gov proposals. +* (x/bank) [\#11417](https://github.com/cosmos/cosmos-sdk/pull/11417) Introduce a new `SpendableBalances` gRPC query that retrieves an account's total (paginated) spendable balances. +* [\#11441](https://github.com/cosmos/cosmos-sdk/pull/11441) Added a new method, `IsLTE`, for `types.Coin`. This method is used to check if a `types.Coin` is less than or equal to another `types.Coin`. +* (x/upgrade) [\#11116](https://github.com/cosmos/cosmos-sdk/pull/11116) `MsgSoftwareUpgrade` and has been added to support v1beta2 msgs-based gov proposals. +* [\#11308](https://github.com/cosmos/cosmos-sdk/pull/11308) Added a mandatory metadata field to Vote in x/gov v1beta2. +* [\#10977](https://github.com/cosmos/cosmos-sdk/pull/10977) Now every cosmos message protobuf definition must be extended with a ``cosmos.msg.v1.signer`` option to signal the signer fields in a language agnostic way. +* [\#10710](https://github.com/cosmos/cosmos-sdk/pull/10710) Chain-id shouldn't be required for creating a transaction with both --generate-only and --offline flags. +* [\#10703](https://github.com/cosmos/cosmos-sdk/pull/10703) Create a new grantee account, if the grantee of an authorization does not exist. +* [\#10592](https://github.com/cosmos/cosmos-sdk/pull/10592) Add a `DecApproxEq` function that checks to see if `|d1 - d2| < tol` for some Dec `d1, d2, tol`. +* [\#9933](https://github.com/cosmos/cosmos-sdk/pull/9933) Introduces the notion of a Cosmos "Scalar" type, which would just be simple aliases that give human-understandable meaning to the underlying type, both in Go code and in Proto definitions. +* [\#9884](https://github.com/cosmos/cosmos-sdk/pull/9884) Provide a new gRPC query handler, `/cosmos/params/v1beta1/subspaces`, that allows the ability to query for all registered subspaces and their respective keys. +* [\#9776](https://github.com/cosmos/cosmos-sdk/pull/9776) Add flag `staking-bond-denom` to specify the staking bond denomination value when initializing a new chain. +* [\#9533](https://github.com/cosmos/cosmos-sdk/pull/9533) Added a new gRPC method, `DenomOwners`, in `x/bank` to query for all account holders of a specific denomination. +* (bank) [\#9618](https://github.com/cosmos/cosmos-sdk/pull/9618) Update bank.Metadata: add URI and URIHash attributes. +* (store) [\#8664](https://github.com/cosmos/cosmos-sdk/pull/8664) Implementation of ADR-038 file StreamingService +* [\#9837](https://github.com/cosmos/cosmos-sdk/issues/9837) `--generate-only` flag will accept the keyname now. +* [\#10326](https://github.com/cosmos/cosmos-sdk/pull/10326) `x/authz` add all grants by granter query. +* [\#10944](https://github.com/cosmos/cosmos-sdk/pull/10944) `x/authz` add all grants by grantee query +* [\#10348](https://github.com/cosmos/cosmos-sdk/pull/10348) Add `fee.{payer,granter}` and `tip` fields to StdSignDoc for signing tipped transactions. +* [\#10208](https://github.com/cosmos/cosmos-sdk/pull/10208) Add `TipsTxMiddleware` for transferring tips. +* [\#10379](https://github.com/cosmos/cosmos-sdk/pull/10379) Add validation to `x/upgrade` CLI `software-upgrade` command `--plan-info` value. +* [\#10507](https://github.com/cosmos/cosmos-sdk/pull/10507) Add middleware for tx priority. +* [\#10311](https://github.com/cosmos/cosmos-sdk/pull/10311) Adds cli to use tips transactions. It adds an `--aux` flag to all CLI tx commands to generate the aux signer data (with optional tip), and a new `tx aux-to-fee` subcommand to let the fee payer gather aux signer data and broadcast the tx +* [\#10430](https://github.com/cosmos/cosmos-sdk/pull/10430) ADR-040: Add store/v2 `MultiStore` implementation +* [\#11019](https://github.com/cosmos/cosmos-sdk/pull/11019) Add `MsgCreatePermanentLockedAccount` and CLI method for creating permanent locked account +* [\#10947](https://github.com/cosmos/cosmos-sdk/pull/10947) Add `AllowancesByGranter` query to the feegrant module +* [\#10407](https://github.com/cosmos/cosmos-sdk/pull/10407) Add validation to `x/upgrade` module's `BeginBlock` to check accidental binary downgrades +* (gov) [\#11036](https://github.com/cosmos/cosmos-sdk/pull/11036) Add in-place migrations for 0.43->0.46. Add a `migrate v0.46` CLI command for v0.43->0.46 JSON genesis migration. +* [\#11006](https://github.com/cosmos/cosmos-sdk/pull/11006) Add `debug pubkey-raw` command to allow inspecting of pubkeys in legacy bech32 format +* (x/authz) [\#10714](https://github.com/cosmos/cosmos-sdk/pull/10714) Add support for pruning expired authorizations +* [\#10015](https://github.com/cosmos/cosmos-sdk/pull/10015) ADR-040: ICS-23 proofs for SMT store +* [\#11240](https://github.com/cosmos/cosmos-sdk/pull/11240) Replace various modules `ModuleCdc` with the global `legacy.Cdc` +* [#11179](https://github.com/cosmos/cosmos-sdk/pull/11179) Add state rollback command. +* [\#10794](https://github.com/cosmos/cosmos-sdk/pull/10794) ADR-040: Add State Sync to V2 Store +* [\#11234](https://github.com/cosmos/cosmos-sdk/pull/11234) Add `GRPCClient` field to Client Context. If `GRPCClient` field is set to nil, the `Invoke` method would use ABCI query, otherwise use gprc. +* [\#10962](https://github.com/cosmos/cosmos-sdk/pull/10962) ADR-040: Add state migration from iavl (v1Store) to smt (v2Store) +* (types) [\#10948](https://github.com/cosmos/cosmos-sdk/issues/10948) Add `app-db-backend` to the `app.toml` config to replace the compile-time `types.DBbackend` variable. +* (authz)[\#11060](https://github.com/cosmos/cosmos-sdk/pull/11060) Support grant with no expire time. + +### API Breaking Changes + +* (store)[\#11152](https://github.com/cosmos/cosmos-sdk/pull/11152) Remove `keep-every` from pruning options. +* [\#10950](https://github.com/cosmos/cosmos-sdk/pull/10950) Add `envPrefix` parameter to `cmd.Execute`. +* (x/mint) [\#10441](https://github.com/cosmos/cosmos-sdk/pull/10441) The `NewAppModule` function now accepts an inflation calculation function as an argument. +* [\#10295](https://github.com/cosmos/cosmos-sdk/pull/10295) Remove store type aliases from /types +* [\#9695](https://github.com/cosmos/cosmos-sdk/pull/9695) Migrate keys from `Info` -> `Record` + * Add new `codec.Codec` argument in: + * `keyring.NewInMemory` + * `keyring.New` + * Rename: + * `SavePubKey` to `SaveOfflineKey`. + * `NewMultiInfo`, `NewLedgerInfo` to `NewLegacyMultiInfo`, `newLegacyLedgerInfo` respectively. Move them into `legacy_info.go`. + * `NewOfflineInfo` to `newLegacyOfflineInfo` and move it to `migration_test.go`. + * Return: + *`keyring.Record, error` in `SaveOfflineKey`, `SaveLedgerKey`, `SaveMultiSig`, `Key` and `KeyByAddress`. + *`keyring.Record` instead of `Info` in `NewMnemonic` and `List`. + * Remove `algo` argument from : + * `SaveOfflineKey` + * Take `keyring.Record` instead of `Info` as first argument in: + * `MkConsKeyOutput` + * `MkValKeyOutput` + * `MkAccKeyOutput` +* [\#10022](https://github.com/cosmos/cosmos-sdk/pull/10022) `AuthKeeper` interface in `x/auth` now includes a function `HasAccount`. +* [\#9759](https://github.com/cosmos/cosmos-sdk/pull/9759) `NewAccountKeeeper` in `x/auth` now takes an additional `bech32Prefix` argument that represents `sdk.Bech32MainPrefix`. +* [\#9628](https://github.com/cosmos/cosmos-sdk/pull/9628) Rename `x/{mod}/legacy` to `x/{mod}/migrations`. +* [\#9571](https://github.com/cosmos/cosmos-sdk/pull/9571) Implemented error handling for staking hooks, which now return an error on failure. +* [\#9427](https://github.com/cosmos/cosmos-sdk/pull/9427) Move simapp `FundAccount` and `FundModuleAccount` to `x/bank/testutil` +* (client/tx) [\#9421](https://github.com/cosmos/cosmos-sdk/pull/9421/) `BuildUnsignedTx`, `BuildSimTx`, `PrintUnsignedStdTx` functions are moved to + the Tx Factory as methods. +* (client/keys) [\#9407](https://github.com/cosmos/cosmos-sdk/pull/9601) Added `keys rename` CLI command and `Keyring.Rename` interface method to rename a key in the keyring. +* (x/slashing) [\#9458](https://github.com/cosmos/cosmos-sdk/pull/9458) Coins burned from slashing is now returned from Slash function and included in Slash event. +* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) The `New` method for the network package now returns an error. +* [\#9519](https://github.com/cosmos/cosmos-sdk/pull/9519) `DeleteDeposits` renamed to `DeleteAndBurnDeposits`, `RefundDeposits` renamed to `RefundAndDeleteDeposits` +* (codec) [\#9521](https://github.com/cosmos/cosmos-sdk/pull/9521) Removed deprecated `clientCtx.JSONCodec` from `client.Context`. +* (codec) [\#9521](https://github.com/cosmos/cosmos-sdk/pull/9521) Rename `EncodingConfig.Marshaler` to `Codec`. +* [\#9594](https://github.com/cosmos/cosmos-sdk/pull/9594) `RESTHandlerFn` argument is removed from the `gov/NewProposalHandler`. +* [\#9594](https://github.com/cosmos/cosmos-sdk/pull/9594) `types/rest` package moved to `testutil/rest`. +* [\#9432](https://github.com/cosmos/cosmos-sdk/pull/9432) `ConsensusParamsKeyTable` moved from `params/keeper` to `params/types` +* [\#9576](https://github.com/cosmos/cosmos-sdk/pull/9576) Add debug error message to `sdkerrors.QueryResult` when enabled +* [\#9650](https://github.com/cosmos/cosmos-sdk/pull/9650) Removed deprecated message handler implementation from the SDK modules. +* [\#10248](https://github.com/cosmos/cosmos-sdk/pull/10248) Remove unused `KeyPowerReduction` variable from x/staking types. +* (x/bank) [\#9832](https://github.com/cosmos/cosmos-sdk/pull/9832) `AddressFromBalancesStore` renamed to `AddressAndDenomFromBalancesStore`. +* (tests) [\#9938](https://github.com/cosmos/cosmos-sdk/pull/9938) `simapp.Setup` accepts additional `testing.T` argument. +* (baseapp) [\#9920](https://github.com/cosmos/cosmos-sdk/pull/9920) BaseApp `{Check,Deliver,Simulate}Tx` methods are now replaced by a middleware stack. + * Replace the Antehandler interface with the `tx.Handler` and `tx.Middleware` interfaces. + * Replace `baseapp.SetAnteHandler` with `baseapp.SetTxHandler`. + * Move Msg routers from BaseApp to middlewares. + * Move Baseapp panic recovery into a middleware. + * Rename simulation helper methods `baseapp.{Check,Deliver}` to `baseapp.Sim{Check,Deliver}**`. +* (x/gov) [\#10373](https://github.com/cosmos/cosmos-sdk/pull/10373) Removed gov `keeper.{MustMarshal, MustUnmarshal}`. +* [\#10348](https://github.com/cosmos/cosmos-sdk/pull/10348) StdSignBytes takes a new argument of type `*tx.Tip` for signing over tips using LEGACY_AMINO_JSON. +* [\#10208](https://github.com/cosmos/cosmos-sdk/pull/10208) The `x/auth/signing.Tx` interface now also includes a new `GetTip() *tx.Tip` method for verifying tipped transactions. The `x/auth/types` expected BankKeeper interface now expects the `SendCoins` method too. +* [\#10612](https://github.com/cosmos/cosmos-sdk/pull/10612) `baseapp.NewBaseApp` constructor function doesn't take the `sdk.TxDecoder` anymore. This logic has been moved into the TxDecoderMiddleware. +* [\#10692](https://github.com/cosmos/cosmos-sdk/pull/10612) `SignerData` takes 2 new fields, `Address` and `PubKey`, which need to get populated when using SIGN_MODE_DIRECT_AUX. +* [\#10748](https://github.com/cosmos/cosmos-sdk/pull/10748) Move legacy `x/gov` api to `v1beta1` directory. +* [\#10816](https://github.com/cosmos/cosmos-sdk/pull/10816) Reuse blocked addresses from the bank module. No need to pass them to distribution. +* [\#10852](https://github.com/cosmos/cosmos-sdk/pull/10852) Move `x/gov/types` to `x/gov/types/v1beta2`. +* [\#10922](https://github.com/cosmos/cosmos-sdk/pull/10922), [/#10957](https://github.com/cosmos/cosmos-sdk/pull/10957) Move key `server.Generate*` functions to testutil and support custom mnemonics in in-process testing network. Moved `TestMnemonic` from `testutil` package to `testdata`. +>>>>>>> 1880a7d17 (feat: grpc-only mode (#11430)) * (x/bank) [\#10771](https://github.com/cosmos/cosmos-sdk/pull/10771) Add safety check on bank module perms to allow module-specific mint restrictions (e.g. only minting a certain denom). * (x/bank) [\#10771](https://github.com/cosmos/cosmos-sdk/pull/10771) Add `bank.BankKeeper.WithMintCoinsRestriction` function to restrict use of bank `MintCoins` usage. This function is not on the bank `Keeper` interface, so it's not API-breaking, but only additive on the keeper implementation. * [\#11124](https://github.com/cosmos/cosmos-sdk/pull/11124) Add `GetAllVersions` to application store diff --git a/server/start.go b/server/start.go index 6ff040da4b57..fae08a89e08b 100644 --- a/server/start.go +++ b/server/start.go @@ -17,6 +17,7 @@ import ( "github.com/tendermint/tendermint/abci/server" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tmos "github.com/tendermint/tendermint/libs/os" + tmservice "github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/p2p" pvm "github.com/tendermint/tendermint/privval" @@ -35,8 +36,8 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" ) -// Tendermint full-node start flags const ( + // Tendermint full-node start flags flagWithTendermint = "with-tendermint" flagAddress = "address" flagTransport = "transport" @@ -56,22 +57,19 @@ const ( FlagPruningInterval = "pruning-interval" FlagIndexEvents = "index-events" FlagMinRetainBlocks = "min-retain-blocks" -) -// GRPC-related flags. -const ( + // state sync-related flags + FlagStateSyncSnapshotInterval = "state-sync.snapshot-interval" + FlagStateSyncSnapshotKeepRecent = "state-sync.snapshot-keep-recent" + + // gRPC-related flags + flagGRPCOnly = "grpc-only" flagGRPCEnable = "grpc.enable" flagGRPCAddress = "grpc.address" flagGRPCWebEnable = "grpc-web.enable" flagGRPCWebAddress = "grpc-web.address" ) -// State sync-related flags. -const ( - FlagStateSyncSnapshotInterval = "state-sync.snapshot-interval" - FlagStateSyncSnapshotKeepRecent = "state-sync.snapshot-keep-recent" -) - // StartCmd runs the service passed in, either stand-alone or in-process with // Tendermint. func StartCmd(appCreator types.AppCreator, defaultNodeHome string) *cobra.Command { @@ -99,6 +97,11 @@ will not be able to commit subsequent blocks. For profiling and benchmarking purposes, CPU profiling can be enabled via the '--cpu-profile' flag which accepts a path for the resulting pprof file. + +The node may be started in a 'query only' mode where only the gRPC and JSON HTTP +API services are enabled via the 'grpc-only' flag. In this mode, Tendermint is +bypassed and can be used when legacy queries are needed after an on-chain upgrade +is performed. Note, when enabled, gRPC will also be automatically enabled. `, PreRunE: func(cmd *cobra.Command, _ []string) error { serverCtx := GetServerContextFromCmd(cmd) @@ -123,8 +126,6 @@ which accepts a path for the resulting pprof file. return startStandAlone(serverCtx, appCreator) } - serverCtx.Logger.Info("starting ABCI with Tendermint") - // amino is needed here for backwards compatibility of REST routes err = startInProcess(serverCtx, clientCtx, appCreator) errCode, ok := err.(ErrorCode) @@ -156,6 +157,7 @@ which accepts a path for the resulting pprof file. cmd.Flags().Uint(FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks") cmd.Flags().Uint64(FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks") + cmd.Flags().Bool(flagGRPCOnly, false, "Start the node in gRPC query only mode (no Tendermint process is started)") cmd.Flags().Bool(flagGRPCEnable, true, "Define if the gRPC server should be enabled") cmd.Flags().String(flagGRPCAddress, config.DefaultGRPCAddress, "the gRPC server address to listen on") @@ -210,7 +212,6 @@ func startStandAlone(ctx *Context, appCreator types.AppCreator) error { return WaitForQuitSignals() } -// legacyAminoCdc is used for the legacy REST API func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.AppCreator) error { cfg := ctx.Config home := cfg.RootDir @@ -259,6 +260,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App return err } +<<<<<<< HEAD genDocProvider := node.DefaultGenesisDocProviderFunc(cfg) tmNode, err := node.NewNode( cfg, @@ -269,22 +271,48 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App node.DefaultDBProvider, node.DefaultMetricsProvider(cfg.Instrumentation), ctx.Logger, +======= + var ( + tmNode tmservice.Service + gRPCOnly = ctx.Viper.GetBool(flagGRPCOnly) +>>>>>>> 1880a7d17 (feat: grpc-only mode (#11430)) ) - if err != nil { - return err - } + if gRPCOnly { + ctx.Logger.Info("starting node in gRPC only mode; Tendermint is disabled") + config.GRPC.Enable = true + } else { + ctx.Logger.Info("starting node with ABCI Tendermint in-process") - ctx.Logger.Debug("initialization: tmNode created") - if err := tmNode.Start(); err != nil { - return err + tmNode, err = node.New(cfg, ctx.Logger, abciclient.NewLocalCreator(app), genDoc) + if err != nil { + return err + } + + if err := tmNode.Start(); err != nil { + return err + } } - ctx.Logger.Debug("initialization: tmNode started") // Add the tx service to the gRPC router. We only need to register this // service if API or gRPC is enabled, and avoid doing so in the general // case, because it spawns a new local tendermint RPC client. +<<<<<<< HEAD if config.API.Enable || config.GRPC.Enable { clientCtx = clientCtx.WithClient(local.New(tmNode)) +======= + if (config.API.Enable || config.GRPC.Enable) && tmNode != nil { + node, ok := tmNode.(local.NodeService) + if !ok { + return fmt.Errorf("unable to set node type; please try re-installing the binary") + } + + localNode, err := local.New(node) + if err != nil { + return err + } + + clientCtx = clientCtx.WithClient(localNode) +>>>>>>> 1880a7d17 (feat: grpc-only mode (#11430)) app.RegisterTxService(clientCtx) app.RegisterTendermintService(clientCtx) @@ -297,10 +325,33 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App return err } - clientCtx := clientCtx. - WithHomeDir(home). - WithChainID(genDoc.ChainID) + clientCtx := clientCtx.WithHomeDir(home).WithChainID(genDoc.ChainID) + +<<<<<<< HEAD +======= + if config.GRPC.Enable { + _, port, err := net.SplitHostPort(config.GRPC.Address) + if err != nil { + return err + } + + grpcAddress := fmt.Sprintf("127.0.0.1:%s", port) + + // If grpc is enabled, configure grpc client for grpc gateway. + grpcClient, err := grpc.Dial( + grpcAddress, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions(grpc.ForceCodec(codec.NewProtoCodec(clientCtx.InterfaceRegistry).GRPCCodec())), + ) + if err != nil { + return err + } + + clientCtx = clientCtx.WithGRPCClient(grpcClient) + ctx.Logger.Debug("grpc client assigned to client context", "target", grpcAddress) + } +>>>>>>> 1880a7d17 (feat: grpc-only mode (#11430)) apiSrv = api.New(clientCtx, ctx.Logger.With("module", "api-server")) app.RegisterAPIRoutes(apiSrv, config.API) errCh := make(chan error) @@ -314,6 +365,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App select { case err := <-errCh: return err + case <-time.After(types.ServerStartTime): // assume server started successfully } } @@ -322,11 +374,13 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App grpcSrv *grpc.Server grpcWebSrv *http.Server ) + if config.GRPC.Enable { grpcSrv, err = servergrpc.StartGRPCServer(clientCtx, app, config.GRPC.Address) if err != nil { return err } + if config.GRPCWeb.Enable { grpcWebSrv, err = servergrpc.StartGRPCWeb(grpcSrv, config) if err != nil { @@ -336,28 +390,40 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } } + // At this point it is safe to block the process if we're in gRPC only mode as + // we do not need to start Rosetta or handle any Tendermint related processes. + if gRPCOnly { + // wait for signal capture and gracefully return + return WaitForQuitSignals() + } + var rosettaSrv crgserver.Server if config.Rosetta.Enable { offlineMode := config.Rosetta.Offline - if !config.GRPC.Enable { // If GRPC is not enabled rosetta cannot work in online mode, so it works in offline mode. + + // If GRPC is not enabled rosetta cannot work in online mode, so it works in + // offline mode. + if !config.GRPC.Enable { offlineMode = true } conf := &rosetta.Config{ - Blockchain: config.Rosetta.Blockchain, - Network: config.Rosetta.Network, - TendermintRPC: ctx.Config.RPC.ListenAddress, - GRPCEndpoint: config.GRPC.Address, - Addr: config.Rosetta.Address, - Retries: config.Rosetta.Retries, - Offline: offlineMode, + Blockchain: config.Rosetta.Blockchain, + Network: config.Rosetta.Network, + TendermintRPC: ctx.Config.RPC.ListenAddress, + GRPCEndpoint: config.GRPC.Address, + Addr: config.Rosetta.Address, + Retries: config.Rosetta.Retries, + Offline: offlineMode, + Codec: clientCtx.Codec.(*codec.ProtoCodec), + InterfaceRegistry: clientCtx.InterfaceRegistry, } - conf.WithCodec(clientCtx.InterfaceRegistry, clientCtx.Codec.(*codec.ProtoCodec)) rosettaSrv, err = rosetta.ServerFromConfig(conf) if err != nil { return err } + errCh := make(chan error) go func() { if err := rosettaSrv.Start(); err != nil { @@ -368,6 +434,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App select { case err := <-errCh: return err + case <-time.After(types.ServerStartTime): // assume server started successfully } } @@ -395,6 +462,6 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App ctx.Logger.Info("exiting...") }() - // Wait for SIGINT or SIGTERM signal + // wait for signal capture and gracefully return return WaitForQuitSignals() }