From 949582ef9b94e4e815a53cc753150f8401d0eeb4 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 18:50:38 -0400 Subject: [PATCH 1/8] updates --- server/start.go | 97 ++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/server/start.go b/server/start.go index 4b8e9c2b1433..c4789b58ac20 100644 --- a/server/start.go +++ b/server/start.go @@ -15,6 +15,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/rpc/client/local" tmtypes "github.com/tendermint/tendermint/types" @@ -33,8 +34,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" @@ -53,22 +54,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 { @@ -120,8 +118,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) @@ -152,6 +148,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") @@ -206,7 +203,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 @@ -253,34 +249,38 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App return err } - tmNode, err := node.New( - cfg, - ctx.Logger, - abciclient.NewLocalCreator(app), - genDoc, - ) - if err != nil { - return err - } + var tmNode tmservice.Service - ctx.Logger.Debug("initialization: tmNode created") - if err := tmNode.Start(); err != nil { - return err + gRPCOnly := ctx.Viper.GetBool(flagGRPCOnly) + if gRPCOnly { + ctx.Logger.Info("starting node in gRPC only mode; Tendermint is not enabled") + } else { + ctx.Logger.Info("starting ABCI with Tendermint") + + 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. - if config.API.Enable || config.GRPC.Enable { + if (config.API.Enable || config.GRPC.Enable) && tmNode != nil { node, ok := tmNode.(local.NodeService) if !ok { - panic("unable to set node type. Please try reinstalling the binary.") + panic("unable to set node type; please try re-installing the binary") } + localNode, err := local.New(node) if err != nil { panic(err) } + clientCtx = clientCtx.WithClient(localNode) app.RegisterTxService(clientCtx) @@ -294,16 +294,16 @@ 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) 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, @@ -313,6 +313,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App if err != nil { return err } + clientCtx = clientCtx.WithGRPCClient(grpcClient) ctx.Logger.Debug("grpc client assigned to client context", "target", grpcAddress) } @@ -330,6 +331,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 } } @@ -338,11 +340,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 { @@ -352,28 +356,38 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } } + 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 { @@ -384,6 +398,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 } } @@ -411,6 +426,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() } From 3e2f48329f9fa73d7b0a3375e81b8706eacd7f7b Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 18:57:10 -0400 Subject: [PATCH 2/8] lint++ --- server/start.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/start.go b/server/start.go index c4789b58ac20..ff43d0606d3a 100644 --- a/server/start.go +++ b/server/start.go @@ -55,7 +55,7 @@ const ( FlagIndexEvents = "index-events" FlagMinRetainBlocks = "min-retain-blocks" - // State sync-related flags. + // state sync-related flags FlagStateSyncSnapshotInterval = "state-sync.snapshot-interval" FlagStateSyncSnapshotKeepRecent = "state-sync.snapshot-keep-recent" @@ -94,6 +94,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. 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 and API must also be enabled in the application configuration. `, PreRunE: func(cmd *cobra.Command, _ []string) error { serverCtx := GetServerContextFromCmd(cmd) From 0174c88c12c7ea8efb4c734296402acc92b7d524 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 19:00:00 -0400 Subject: [PATCH 3/8] updates --- server/start.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/start.go b/server/start.go index ff43d0606d3a..ea86573fba0b 100644 --- a/server/start.go +++ b/server/start.go @@ -95,10 +95,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. 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 and API must also be enabled in the application configuration. +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, either gRPC and/or API must also be enabled in +the application configuration. `, PreRunE: func(cmd *cobra.Command, _ []string) error { serverCtx := GetServerContextFromCmd(cmd) From 5221ad7f101dfe70d3cb2c8b4abb3dcc15ea1278 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 19:11:48 -0400 Subject: [PATCH 4/8] updates --- server/start.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/server/start.go b/server/start.go index ea86573fba0b..a2944b1b73be 100644 --- a/server/start.go +++ b/server/start.go @@ -98,8 +98,8 @@ 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, either gRPC and/or API must also be enabled in -the application configuration. +is performed. Note, when enabled, either gRPC must also be enabled in the +application configuration. `, PreRunE: func(cmd *cobra.Command, _ []string) error { serverCtx := GetServerContextFromCmd(cmd) @@ -258,10 +258,15 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App var tmNode tmservice.Service gRPCOnly := ctx.Viper.GetBool(flagGRPCOnly) - if gRPCOnly { + switch { + case gRPCOnly && !config.GRPC.Enable: + return fmt.Errorf("cannot start '%s' mode; must enable gRPC in application config", flagGRPCOnly) + + case gRPCOnly: ctx.Logger.Info("starting node in gRPC only mode; Tendermint is not enabled") - } else { - ctx.Logger.Info("starting ABCI with Tendermint") + + default: + ctx.Logger.Info("starting node with ABCI Tendermint in-process") tmNode, err = node.New(cfg, ctx.Logger, abciclient.NewLocalCreator(app), genDoc) if err != nil { @@ -279,12 +284,12 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App if (config.API.Enable || config.GRPC.Enable) && tmNode != nil { node, ok := tmNode.(local.NodeService) if !ok { - panic("unable to set node type; please try re-installing the binary") + return fmt.Errorf("unable to set node type; please try re-installing the binary") } localNode, err := local.New(node) if err != nil { - panic(err) + return err } clientCtx = clientCtx.WithClient(localNode) From 4371e9dcb27c275c5b68644f817e6b3c6f521a94 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 19:12:17 -0400 Subject: [PATCH 5/8] updates --- server/start.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/start.go b/server/start.go index a2944b1b73be..5b325a08adbf 100644 --- a/server/start.go +++ b/server/start.go @@ -98,8 +98,8 @@ 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, either gRPC must also be enabled in the -application configuration. +is performed. Note, when enabled, gRPC must also be enabled in the application +configuration. `, PreRunE: func(cmd *cobra.Command, _ []string) error { serverCtx := GetServerContextFromCmd(cmd) From c525da99aed258fb4d0fa20f4dff9071eb0c82b1 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 19:13:55 -0400 Subject: [PATCH 6/8] updates --- server/start.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/start.go b/server/start.go index 5b325a08adbf..792be60737dc 100644 --- a/server/start.go +++ b/server/start.go @@ -367,6 +367,8 @@ 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() From 0d7dac35f792308ad755fcee274f1647ab42e901 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 21 Mar 2022 19:17:29 -0400 Subject: [PATCH 7/8] cl++ --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56d13262093c..832eab8acec9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features +* [\#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. * [\#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. From 9ea433c3011c88ff37bb8d0242654c86fdea365f Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 22 Mar 2022 13:43:12 -0400 Subject: [PATCH 8/8] updates --- server/start.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/server/start.go b/server/start.go index 792be60737dc..c6c6b2b47f6a 100644 --- a/server/start.go +++ b/server/start.go @@ -98,8 +98,7 @@ 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 must also be enabled in the application -configuration. +is performed. Note, when enabled, gRPC will also be automatically enabled. `, PreRunE: func(cmd *cobra.Command, _ []string) error { serverCtx := GetServerContextFromCmd(cmd) @@ -255,17 +254,14 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App return err } - var tmNode tmservice.Service - - gRPCOnly := ctx.Viper.GetBool(flagGRPCOnly) - switch { - case gRPCOnly && !config.GRPC.Enable: - return fmt.Errorf("cannot start '%s' mode; must enable gRPC in application config", flagGRPCOnly) - - case gRPCOnly: - ctx.Logger.Info("starting node in gRPC only mode; Tendermint is not enabled") - - default: + var ( + tmNode tmservice.Service + gRPCOnly = ctx.Viper.GetBool(flagGRPCOnly) + ) + 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") tmNode, err = node.New(cfg, ctx.Logger, abciclient.NewLocalCreator(app), genDoc)