diff --git a/app/app.go b/app/app.go index 247d008a4f..d03b0e7437 100644 --- a/app/app.go +++ b/app/app.go @@ -2388,7 +2388,11 @@ func (app *App) RegisterTendermintService(clientCtx client.Context) { } if app.evmRPCConfig.HTTPEnabled { - evmHTTPServer, err := evmrpc.NewEVMHTTPServer(app.evmRPCConfig, clientCtx.Client, &app.EvmKeeper, app.BeginBlockKeepers, app.BaseApp, app.TracerAnteHandler, app.RPCContextProvider, txConfigProvider, DefaultNodeHome, app.GetStateStore(), nil) + client, err := clientCtx.GetNode() + if err != nil { + panic(err) + } + evmHTTPServer, err := evmrpc.NewEVMHTTPServer(app.evmRPCConfig, client, &app.EvmKeeper, app.BeginBlockKeepers, app.BaseApp, app.TracerAnteHandler, app.RPCContextProvider, txConfigProvider, DefaultNodeHome, app.GetStateStore(), nil) if err != nil { panic(err) } @@ -2401,7 +2405,11 @@ func (app *App) RegisterTendermintService(clientCtx client.Context) { } if app.evmRPCConfig.WSEnabled { - evmWSServer, err := evmrpc.NewEVMWebSocketServer(app.evmRPCConfig, clientCtx.Client, &app.EvmKeeper, app.BeginBlockKeepers, app.BaseApp, app.TracerAnteHandler, app.RPCContextProvider, txConfigProvider, DefaultNodeHome, app.GetStateStore()) + client, err := clientCtx.GetNode() + if err != nil { + panic(err) + } + evmWSServer, err := evmrpc.NewEVMWebSocketServer(app.evmRPCConfig, client, &app.EvmKeeper, app.BeginBlockKeepers, app.BaseApp, app.TracerAnteHandler, app.RPCContextProvider, txConfigProvider, DefaultNodeHome, app.GetStateStore()) if err != nil { panic(err) } diff --git a/docker/localnode/config/config.toml b/docker/localnode/config/config.toml index 43fd4af3b0..2caf572247 100644 --- a/docker/localnode/config/config.toml +++ b/docker/localnode/config/config.toml @@ -2,10 +2,6 @@ ### Main Base Config Options ### ####################################################################### -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy-app = "tcp://127.0.0.1:26658" - # A custom human readable name for this node moniker = "sei-node-0" @@ -59,9 +55,6 @@ genesis-file = "config/genesis.json" # Path to the JSON file containing the private key to use for node authentication in the p2p protocol node-key-file = "config/node_key.json" -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - ####################################################### ### Priv Validator Configuration ### ####################################################### diff --git a/docker/rpcnode/config/config.toml b/docker/rpcnode/config/config.toml index 6f2acc7f24..a280b91989 100644 --- a/docker/rpcnode/config/config.toml +++ b/docker/rpcnode/config/config.toml @@ -2,10 +2,6 @@ ### Main Base Config Options ### ####################################################################### -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy-app = "tcp://127.0.0.1:26658" - # A custom human readable name for this node moniker = "sei-rpc-node" @@ -59,9 +55,6 @@ genesis-file = "config/genesis.json" # Path to the JSON file containing the private key to use for node authentication in the p2p protocol node-key-file = "config/node_key.json" -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - ####################################################### ### Priv Validator Configuration ### ####################################################### diff --git a/docs/migration/seiv2_config_migration.md b/docs/migration/seiv2_config_migration.md index da8e3a936d..5dde0f69db 100644 --- a/docs/migration/seiv2_config_migration.md +++ b/docs/migration/seiv2_config_migration.md @@ -42,10 +42,6 @@ pending-ttl-num-blocks = 0 ### Main Base Config Options ### ####################################################################### -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy-app = "tcp://127.0.0.1:26658" - # A custom human readable name for this node moniker = "demo" @@ -99,9 +95,6 @@ genesis-file = "config/genesis.json" # Path to the JSON file containing the private key to use for node authentication in the p2p protocol node-key-file = "config/node_key.json" -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - ####################################################### ### Priv Validator Configuration ### ####################################################### diff --git a/loadtest/sign.go b/loadtest/sign.go index 3d5afd75d5..b4c1726e86 100644 --- a/loadtest/sign.go +++ b/loadtest/sign.go @@ -21,6 +21,7 @@ import ( "github.com/sei-protocol/sei-chain/sei-cosmos/types/tx/signing" xauthsigning "github.com/sei-protocol/sei-chain/sei-cosmos/x/auth/signing" authtypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/auth/types" + rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client" ) type AccountInfo struct { @@ -226,7 +227,7 @@ func (sc *SignerClient) GetAccountNumberSequenceNumber(privKey cryptotypes.PrivK } context := client.Context{} context = context.WithNodeURI(sc.NodeURI) - context = context.WithClient(cl) + context = client.WithClient[rpcclient.Client](context, cl) context = context.WithInterfaceRegistry(TestConfig.InterfaceRegistry) userHomeDir, _ := os.UserHomeDir() kr, _ := keyring.New(sdk.KeyringServiceName(), "test", filepath.Join(userHomeDir, ".sei"), os.Stdin) diff --git a/sei-cosmos/client/broadcast.go b/sei-cosmos/client/broadcast.go index 4db88cf038..199e9b94e6 100644 --- a/sei-cosmos/client/broadcast.go +++ b/sei-cosmos/client/broadcast.go @@ -48,7 +48,7 @@ func (e ErrMempoolIsFull) Error() string { // based on the context parameters. The result of the broadcast is parsed into // an intermediate structure which is logged if the context has a logger // defined. -func (ctx Context) BroadcastTx(txBytes []byte) (res *sdk.TxResponse, err error) { +func (ctx contextG[C]) BroadcastTx(txBytes []byte) (res *sdk.TxResponse, err error) { switch ctx.BroadcastMode { case flags.BroadcastSync: res, err = ctx.BroadcastTxSync(txBytes) @@ -116,7 +116,7 @@ func CheckTendermintError(err error, tx tmtypes.Tx) *sdk.TxResponse { // NOTE: This should ideally not be used as the request may timeout but the tx // may still be included in a block. Use BroadcastTxAsync or BroadcastTxSync // instead. -func (ctx Context) BroadcastTxCommit(txBytes []byte) (*sdk.TxResponse, error) { +func (ctx contextG[C]) BroadcastTxCommit(txBytes []byte) (*sdk.TxResponse, error) { node, err := ctx.GetNode() if err != nil { return nil, err @@ -135,7 +135,7 @@ func (ctx Context) BroadcastTxCommit(txBytes []byte) (*sdk.TxResponse, error) { // BroadcastTxSync broadcasts transaction bytes to a Tendermint node // synchronously (i.e. returns after CheckTx execution). -func (ctx Context) BroadcastTxSync(txBytes []byte) (*sdk.TxResponse, error) { +func (ctx contextG[C]) BroadcastTxSync(txBytes []byte) (*sdk.TxResponse, error) { node, err := ctx.GetNode() if err != nil { return nil, err @@ -151,7 +151,7 @@ func (ctx Context) BroadcastTxSync(txBytes []byte) (*sdk.TxResponse, error) { // BroadcastTxAsync broadcasts transaction bytes to a Tendermint node // asynchronously (i.e. returns immediately). -func (ctx Context) BroadcastTxAsync(txBytes []byte) (*sdk.TxResponse, error) { +func (ctx contextG[C]) BroadcastTxAsync(txBytes []byte) (*sdk.TxResponse, error) { node, err := ctx.GetNode() if err != nil { return nil, err @@ -167,7 +167,7 @@ func (ctx Context) BroadcastTxAsync(txBytes []byte) (*sdk.TxResponse, error) { // TxServiceBroadcast is a helper function to broadcast a Tx with the correct gRPC types // from the tx service. Calls `clientCtx.BroadcastTx` under the hood. -func TxServiceBroadcast(grpcCtx context.Context, clientCtx Context, req *tx.BroadcastTxRequest) (*tx.BroadcastTxResponse, error) { +func (clientCtx contextG[C]) TxServiceBroadcast(grpcCtx context.Context, req *tx.BroadcastTxRequest) (*tx.BroadcastTxResponse, error) { if req == nil || req.TxBytes == nil { return nil, status.Error(codes.InvalidArgument, "invalid empty tx") } diff --git a/sei-cosmos/client/broadcast_test.go b/sei-cosmos/client/broadcast_test.go index ec04fcc0e1..bdcb55cc58 100644 --- a/sei-cosmos/client/broadcast_test.go +++ b/sei-cosmos/client/broadcast_test.go @@ -13,6 +13,8 @@ import ( "github.com/sei-protocol/sei-chain/sei-cosmos/client/flags" sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors" + "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" + rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client" ) type MockClient struct { @@ -34,8 +36,8 @@ func (c MockClient) BroadcastTxSync(ctx context.Context, tx tmtypes.Tx) (*ctypes func CreateContextWithErrorAndMode(err error, mode string) Context { return Context{ - Client: MockClient{err: err}, - BroadcastMode: mode, + Client: utils.Some[rpcclient.Client](MockClient{err: err}), + contextBase: contextBase{BroadcastMode: mode}, } } diff --git a/sei-cosmos/client/cmd.go b/sei-cosmos/client/cmd.go index 526cd26f2d..7478263ce7 100644 --- a/sei-cosmos/client/cmd.go +++ b/sei-cosmos/client/cmd.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" "github.com/sei-protocol/sei-chain/sei-tendermint/libs/cli" + rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -133,7 +134,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont } } - if clientCtx.Client == nil || flagSet.Changed(flags.FlagNode) { + if !clientCtx.Client.IsPresent() || flagSet.Changed(flags.FlagNode) { rpcURI, _ := flagSet.GetString(flags.FlagNode) if rpcURI != "" { clientCtx = clientCtx.WithNodeURI(rpcURI) @@ -143,7 +144,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont return clientCtx, err } - clientCtx = clientCtx.WithClient(client) + clientCtx = WithClient[rpcclient.Client](clientCtx, client) } } diff --git a/sei-cosmos/client/config/config.go b/sei-cosmos/client/config/config.go index bae915baa7..cf25080b10 100644 --- a/sei-cosmos/client/config/config.go +++ b/sei-cosmos/client/config/config.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/sei-protocol/sei-chain/sei-cosmos/client" + rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client" ) // Default constants @@ -84,13 +85,12 @@ func ReadFromClientConfig(ctx client.Context) (client.Context, error) { ctx = ctx.WithKeyring(keyring) // https://github.com/cosmos/cosmos-sdk/issues/8986 - client, err := client.NewClientFromNode(conf.Node) + c, err := client.NewClientFromNode(conf.Node) if err != nil { return ctx, fmt.Errorf("couldn't get client from nodeURI: %v", err) } - ctx = ctx.WithNodeURI(conf.Node). - WithClient(client). + ctx = client.WithClient[rpcclient.Client](ctx.WithNodeURI(conf.Node), c). WithBroadcastMode(conf.BroadcastMode) return ctx, nil diff --git a/sei-cosmos/client/context.go b/sei-cosmos/client/context.go index b6a70f605e..cd2a497d8f 100644 --- a/sei-cosmos/client/context.go +++ b/sei-cosmos/client/context.go @@ -12,6 +12,7 @@ import ( "gopkg.in/yaml.v2" "github.com/gogo/protobuf/proto" + "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client" "github.com/sei-protocol/sei-chain/sei-cosmos/codec" @@ -20,11 +21,10 @@ import ( sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" ) -// Context implements a typical context created in SDK modules for transaction -// handling and queries. -type Context struct { +type Context = contextG[rpcclient.Client] + +type contextBase struct { FromAddress sdk.AccAddress - Client rpcclient.Client ChainID string // Deprecated: Codec codec will be changed to Codec: codec.Codec JSONCodec codec.JSONCodec @@ -58,20 +58,27 @@ type Context struct { LegacyAmino *codec.LegacyAmino } +// Context implements a typical context created in SDK modules for transaction +// handling and queries. +type contextG[C rpcclient.Client] struct { + contextBase + Client utils.Option[C] +} + // WithKeyring returns a copy of the context with an updated keyring. -func (ctx Context) WithKeyring(k keyring.Keyring) Context { +func (ctx contextG[C]) WithKeyring(k keyring.Keyring) contextG[C] { ctx.Keyring = k return ctx } // WithKeyringOptions returns a copy of the context with an updated keyring. -func (ctx Context) WithKeyringOptions(opts ...keyring.Option) Context { +func (ctx contextG[C]) WithKeyringOptions(opts ...keyring.Option) contextG[C] { ctx.KeyringOptions = opts return ctx } // WithInput returns a copy of the context with an updated input. -func (ctx Context) WithInput(r io.Reader) Context { +func (ctx contextG[C]) WithInput(r io.Reader) contextG[C] { // convert to a bufio.Reader to have a shared buffer between the keyring and the // the Commands, ensuring a read from one advance the read pointer for the other. // see https://github.com/cosmos/cosmos-sdk/issues/9566. @@ -80,7 +87,7 @@ func (ctx Context) WithInput(r io.Reader) Context { } // Deprecated: WithJSONCodec returns a copy of the Context with an updated JSONCodec. -func (ctx Context) WithJSONCodec(m codec.JSONCodec) Context { +func (ctx contextG[C]) WithJSONCodec(m codec.JSONCodec) contextG[C] { ctx.JSONCodec = m // since we are using ctx.Codec everywhere in the SDK, for backward compatibility // we need to try to set it here as well. @@ -91,7 +98,7 @@ func (ctx Context) WithJSONCodec(m codec.JSONCodec) Context { } // WithCodec returns a copy of the Context with an updated Codec. -func (ctx Context) WithCodec(m codec.Codec) Context { +func (ctx contextG[C]) WithCodec(m codec.Codec) contextG[C] { ctx.JSONCodec = m ctx.Codec = m return ctx @@ -99,62 +106,64 @@ func (ctx Context) WithCodec(m codec.Codec) Context { // WithLegacyAmino returns a copy of the context with an updated LegacyAmino codec. // TODO: Deprecated (remove). -func (ctx Context) WithLegacyAmino(cdc *codec.LegacyAmino) Context { +func (ctx contextG[C]) WithLegacyAmino(cdc *codec.LegacyAmino) contextG[C] { ctx.LegacyAmino = cdc return ctx } // WithOutput returns a copy of the context with an updated output writer (e.g. stdout). -func (ctx Context) WithOutput(w io.Writer) Context { +func (ctx contextG[C]) WithOutput(w io.Writer) contextG[C] { ctx.Output = w return ctx } // WithFrom returns a copy of the context with an updated from address or name. -func (ctx Context) WithFrom(from string) Context { +func (ctx contextG[C]) WithFrom(from string) contextG[C] { ctx.From = from return ctx } // WithOutputFormat returns a copy of the context with an updated OutputFormat field. -func (ctx Context) WithOutputFormat(format string) Context { +func (ctx contextG[C]) WithOutputFormat(format string) contextG[C] { ctx.OutputFormat = format return ctx } // WithNodeURI returns a copy of the context with an updated node URI. -func (ctx Context) WithNodeURI(nodeURI string) Context { +func (ctx contextG[C]) WithNodeURI(nodeURI string) contextG[C] { ctx.NodeURI = nodeURI return ctx } // WithHeight returns a copy of the context with an updated height. -func (ctx Context) WithHeight(height int64) Context { +func (ctx contextG[C]) WithHeight(height int64) contextG[C] { ctx.Height = height return ctx } // WithClient returns a copy of the context with an updated RPC client // instance. -func (ctx Context) WithClient(client rpcclient.Client) Context { - ctx.Client = client - return ctx +func WithClient[C2, C1 rpcclient.Client](ctx contextG[C1], client C2) contextG[C2] { + return contextG[C2]{ + contextBase: ctx.contextBase, + Client: utils.Some(client), + } } // WithUseLedger returns a copy of the context with an updated UseLedger flag. -func (ctx Context) WithUseLedger(useLedger bool) Context { +func (ctx contextG[C]) WithUseLedger(useLedger bool) contextG[C] { ctx.UseLedger = useLedger return ctx } // WithChainID returns a copy of the context with an updated chain ID. -func (ctx Context) WithChainID(chainID string) Context { +func (ctx contextG[C]) WithChainID(chainID string) contextG[C] { ctx.ChainID = chainID return ctx } // WithHomeDir returns a copy of the Context with HomeDir set. -func (ctx Context) WithHomeDir(dir string) Context { +func (ctx contextG[C]) WithHomeDir(dir string) contextG[C] { if dir != "" { ctx.HomeDir = dir } @@ -162,91 +171,91 @@ func (ctx Context) WithHomeDir(dir string) Context { } // WithKeyringDir returns a copy of the Context with KeyringDir set. -func (ctx Context) WithKeyringDir(dir string) Context { +func (ctx contextG[C]) WithKeyringDir(dir string) contextG[C] { ctx.KeyringDir = dir return ctx } // WithGenerateOnly returns a copy of the context with updated GenerateOnly value -func (ctx Context) WithGenerateOnly(generateOnly bool) Context { +func (ctx contextG[C]) WithGenerateOnly(generateOnly bool) contextG[C] { ctx.GenerateOnly = generateOnly return ctx } // WithSimulation returns a copy of the context with updated Simulate value -func (ctx Context) WithSimulation(simulate bool) Context { +func (ctx contextG[C]) WithSimulation(simulate bool) contextG[C] { ctx.Simulate = simulate return ctx } // WithOffline returns a copy of the context with updated Offline value. -func (ctx Context) WithOffline(offline bool) Context { +func (ctx contextG[C]) WithOffline(offline bool) contextG[C] { ctx.Offline = offline return ctx } // WithFromName returns a copy of the context with an updated from account name. -func (ctx Context) WithFromName(name string) Context { +func (ctx contextG[C]) WithFromName(name string) contextG[C] { ctx.FromName = name return ctx } // WithFromAddress returns a copy of the context with an updated from account // address. -func (ctx Context) WithFromAddress(addr sdk.AccAddress) Context { +func (ctx contextG[C]) WithFromAddress(addr sdk.AccAddress) contextG[C] { ctx.FromAddress = addr return ctx } // WithFeeGranterAddress returns a copy of the context with an updated fee granter account // address. -func (ctx Context) WithFeeGranterAddress(addr sdk.AccAddress) Context { +func (ctx contextG[C]) WithFeeGranterAddress(addr sdk.AccAddress) contextG[C] { ctx.FeeGranter = addr return ctx } // WithBroadcastMode returns a copy of the context with an updated broadcast // mode. -func (ctx Context) WithBroadcastMode(mode string) Context { +func (ctx contextG[C]) WithBroadcastMode(mode string) contextG[C] { ctx.BroadcastMode = mode return ctx } // WithSignModeStr returns a copy of the context with an updated SignMode // value. -func (ctx Context) WithSignModeStr(signModeStr string) Context { +func (ctx contextG[C]) WithSignModeStr(signModeStr string) contextG[C] { ctx.SignModeStr = signModeStr return ctx } // WithSkipConfirmation returns a copy of the context with an updated SkipConfirm // value. -func (ctx Context) WithSkipConfirmation(skip bool) Context { +func (ctx contextG[C]) WithSkipConfirmation(skip bool) contextG[C] { ctx.SkipConfirm = skip return ctx } // WithTxConfig returns the context with an updated TxConfig -func (ctx Context) WithTxConfig(generator TxConfig) Context { +func (ctx contextG[C]) WithTxConfig(generator TxConfig) contextG[C] { ctx.TxConfig = generator return ctx } // WithAccountRetriever returns the context with an updated AccountRetriever -func (ctx Context) WithAccountRetriever(retriever AccountRetriever) Context { +func (ctx contextG[C]) WithAccountRetriever(retriever AccountRetriever) contextG[C] { ctx.AccountRetriever = retriever return ctx } // WithInterfaceRegistry returns the context with an updated InterfaceRegistry -func (ctx Context) WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry) Context { +func (ctx contextG[C]) WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry) contextG[C] { ctx.InterfaceRegistry = interfaceRegistry return ctx } // WithViper returns the context with Viper field. This Viper instance is used to read // client-side config from the config file. -func (ctx Context) WithViper(prefix string) Context { +func (ctx contextG[C]) WithViper(prefix string) contextG[C] { v := viper.New() v.SetEnvPrefix(prefix) v.AutomaticEnv() @@ -255,13 +264,13 @@ func (ctx Context) WithViper(prefix string) Context { } // PrintString prints the raw string to ctx.Output if it's defined, otherwise to os.Stdout -func (ctx Context) PrintString(str string) error { +func (ctx contextG[C]) PrintString(str string) error { return ctx.PrintBytes([]byte(str)) } // PrintBytes prints the raw bytes to ctx.Output if it's defined, otherwise to os.Stdout. // NOTE: for printing a complex state object, you should use ctx.PrintOutput -func (ctx Context) PrintBytes(o []byte) error { +func (ctx contextG[C]) PrintBytes(o []byte) error { writer := ctx.Output if writer == nil { writer = os.Stdout @@ -274,7 +283,7 @@ func (ctx Context) PrintBytes(o []byte) error { // PrintProto outputs toPrint to the ctx.Output based on ctx.OutputFormat which is // either text or json. If text, toPrint will be YAML encoded. Otherwise, toPrint // will be JSON encoded using ctx.Codec. An error is returned upon failure. -func (ctx Context) PrintProto(toPrint proto.Message) error { +func (ctx contextG[C]) PrintProto(toPrint proto.Message) error { // always serialize JSON initially because proto json can't be directly YAML encoded out, err := ctx.Codec.MarshalAsJSON(toPrint) if err != nil { @@ -286,7 +295,7 @@ func (ctx Context) PrintProto(toPrint proto.Message) error { // PrintObjectLegacy is a variant of PrintProto that doesn't require a proto.Message type // and uses amino JSON encoding. // Deprecated: It will be removed in the near future! -func (ctx Context) PrintObjectLegacy(toPrint interface{}) error { +func (ctx contextG[C]) PrintObjectLegacy(toPrint interface{}) error { out, err := ctx.LegacyAmino.MarshalAsJSON(toPrint) if err != nil { return err @@ -294,7 +303,7 @@ func (ctx Context) PrintObjectLegacy(toPrint interface{}) error { return ctx.printOutput(out) } -func (ctx Context) printOutput(out []byte) error { +func (ctx contextG[C]) printOutput(out []byte) error { if ctx.OutputFormat == "text" { // handle text format by decoding and re-encoding JSON as YAML var j interface{} diff --git a/sei-cosmos/client/grpc_query.go b/sei-cosmos/client/grpc_query.go index a44da6e197..8cbd7f38c1 100644 --- a/sei-cosmos/client/grpc_query.go +++ b/sei-cosmos/client/grpc_query.go @@ -24,7 +24,7 @@ var _ gogogrpc.ClientConn = Context{} var protoCodec = encoding.GetCodec(proto.Name) // Invoke implements the grpc ClientConn.Invoke method -func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply interface{}, opts ...grpc.CallOption) (err error) { +func (ctx contextG[C]) Invoke(grpcCtx gocontext.Context, method string, req, reply interface{}, opts ...grpc.CallOption) (err error) { // Two things can happen here: // 1. either we're broadcasting a Tx, in which call we call Tendermint's broadcast endpoint directly, // 2. or we are querying for state, in which case we call ABCI's Query. @@ -41,7 +41,7 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply i return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxResponse)(nil), req) } - broadcastRes, err := TxServiceBroadcast(grpcCtx, ctx, reqProto) + broadcastRes, err := ctx.TxServiceBroadcast(grpcCtx, reqProto) if err != nil { return err } @@ -111,6 +111,6 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply i } // NewStream implements the grpc ClientConn.NewStream method -func (Context) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { +func (contextG[C]) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { return nil, fmt.Errorf("streaming rpc not supported") } diff --git a/sei-cosmos/client/query.go b/sei-cosmos/client/query.go index 6f2c0fe689..504e43c730 100644 --- a/sei-cosmos/client/query.go +++ b/sei-cosmos/client/query.go @@ -20,32 +20,31 @@ import ( // GetNode returns an RPC client. If the context's client is not defined, an // error is returned. -func (ctx Context) GetNode() (rpcclient.Client, error) { - if ctx.Client == nil { - return nil, errors.New("no RPC client is defined in offline mode") +func (ctx contextG[C]) GetNode() (rpcclient.Client, error) { + if c, ok := ctx.Client.Get(); ok { + return c, nil } - - return ctx.Client, nil + return nil, errors.New("no RPC client is defined in offline mode") } // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx Context) Query(path string) ([]byte, int64, error) { +func (ctx contextG[C]) Query(path string) ([]byte, int64, error) { return ctx.query(path, nil) } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx Context) QueryWithData(path string, data []byte) ([]byte, int64, error) { +func (ctx contextG[C]) QueryWithData(path string, data []byte) ([]byte, int64, error) { return ctx.query(path, data) } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx Context) QueryStore(key tmbytes.HexBytes, storeName string) ([]byte, int64, error) { +func (ctx contextG[C]) QueryStore(key tmbytes.HexBytes, storeName string) ([]byte, int64, error) { return ctx.queryStore(key, storeName, "key") } @@ -53,26 +52,26 @@ func (ctx Context) QueryStore(key tmbytes.HexBytes, storeName string) ([]byte, i // It returns the ResultQuery obtained from the query. The height used to perform // the query is the RequestQuery Height if it is non-zero, otherwise the context // height is used. -func (ctx Context) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { +func (ctx contextG[C]) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { return ctx.queryABCI(req) } // GetFromAddress returns the from address from the context's name. -func (ctx Context) GetFromAddress() sdk.AccAddress { +func (ctx contextG[C]) GetFromAddress() sdk.AccAddress { return ctx.FromAddress } // GetFeeGranterAddress returns the fee granter address from the context -func (ctx Context) GetFeeGranterAddress() sdk.AccAddress { +func (ctx contextG[C]) GetFeeGranterAddress() sdk.AccAddress { return ctx.FeeGranter } // GetFromName returns the key name for the current context. -func (ctx Context) GetFromName() string { +func (ctx contextG[C]) GetFromName() string { return ctx.FromName } -func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { +func (ctx contextG[C]) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { node, err := ctx.GetNode() if err != nil { return abci.ResponseQuery{}, err @@ -124,7 +123,7 @@ func sdkErrorToGRPCError(resp abci.ResponseQuery) error { // query performs a query to a Tendermint node with the provided store name // and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx Context) query(path string, key tmbytes.HexBytes) ([]byte, int64, error) { +func (ctx contextG[C]) query(path string, key tmbytes.HexBytes) ([]byte, int64, error) { resp, err := ctx.queryABCI(abci.RequestQuery{ Path: path, Data: key, @@ -140,7 +139,7 @@ func (ctx Context) query(path string, key tmbytes.HexBytes) ([]byte, int64, erro // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx Context) queryStore(key tmbytes.HexBytes, storeName, endPath string) ([]byte, int64, error) { +func (ctx contextG[C]) queryStore(key tmbytes.HexBytes, storeName, endPath string) ([]byte, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/sei-cosmos/server/README.md b/sei-cosmos/server/README.md index 31926f69c1..dcb8632271 100644 --- a/sei-cosmos/server/README.md +++ b/sei-cosmos/server/README.md @@ -63,8 +63,8 @@ literal that exists in the `server.Context`. All the possible options an applica may use and provide to the construction process are defined by the `StartCmd` and by the application's config file, `app.toml`. -The application can either be started in-process or as an external process. The -former creates a Tendermint service and the latter creates a Tendermint Node. +The application is started in-process with Tendermint. External ABCI process +support via socket or gRPC has been removed. Under the hood, `StartCmd` will call `GetServerContextFromCmd`, which provides the command access to a `server.Context`. This context provides access to the diff --git a/sei-cosmos/server/api/server.go b/sei-cosmos/server/api/server.go index 79495d1c6f..c1ebf09c70 100644 --- a/sei-cosmos/server/api/server.go +++ b/sei-cosmos/server/api/server.go @@ -128,7 +128,10 @@ func (s *Server) Start(cfg config.Config, apiMetrics *telemetry.Metrics) error { func (s *Server) Close() error { s.mtx.Lock() defer s.mtx.Unlock() - return s.listener.Close() + if s.listener != nil { + return s.listener.Close() + } + return nil } func (s *Server) registerGRPCGatewayRoutes() { diff --git a/sei-cosmos/server/start.go b/sei-cosmos/server/start.go index 417fa51085..4fc9426c1e 100644 --- a/sei-cosmos/server/start.go +++ b/sei-cosmos/server/start.go @@ -31,11 +31,11 @@ import ( tcmd "github.com/sei-protocol/sei-chain/sei-tendermint/cmd/tendermint/commands" "github.com/sei-protocol/sei-chain/sei-tendermint/libs/service" "github.com/sei-protocol/sei-chain/sei-tendermint/node" + rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client" "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client/local" tmtypes "github.com/sei-protocol/sei-chain/sei-tendermint/types" "github.com/spf13/cobra" "go.opentelemetry.io/otel/sdk/trace" - "google.golang.org/grpc" ) const ( @@ -86,14 +86,12 @@ const ( FlagChainID = "chain-id" ) -// StartCmd runs the service passed in, either stand-alone or in-process with -// Tendermint. +// StartCmd runs the service passed in with Tendermint in-process. func StartCmd(appCreator types.AppCreator, defaultNodeHome string, tracerProviderOptions []trace.TracerProviderOption) *cobra.Command { cmd := &cobra.Command{ Use: "start", Short: "Run the full node", - Long: `Run the full node application with Tendermint in or out of process. By -default, the application will run with Tendermint in process. + Long: `Run the full node application with Tendermint in process. Pruning options can be provided via the '--pruning' flag or alternatively with '--pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval' together. For '--pruning' the options are as follows: @@ -211,8 +209,6 @@ is performed. Note, when enabled, gRPC will also be automatically enabled. func addStartNodeFlags(cmd *cobra.Command, defaultNodeHome string) { cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") - cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address") - cmd.Flags().String(flagTransport, "socket", "Transport protocol: socket, grpc") cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file") cmd.Flags().String(FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)") cmd.Flags().IntSlice(FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary") @@ -250,6 +246,15 @@ func addStartNodeFlags(cmd *cobra.Command, defaultNodeHome string) { // add support for all Tendermint-specific command line options tcmd.AddNodeFlags(cmd, NewDefaultContext().Config) + mustMarkDeprecated(cmd, flagAddress, "out-of-process ABCI has been removed; this flag is ignored") + mustMarkDeprecated(cmd, flagTransport, "out-of-process ABCI has been removed; this flag is ignored") +} + +func mustMarkDeprecated(cmd *cobra.Command, name, message string) { + cmd.Flags().String(name, "", "") + if err := cmd.Flags().MarkDeprecated(name, message); err != nil { + panic(err) + } } func startInProcess( @@ -264,7 +269,6 @@ func startInProcess( home := cfg.RootDir goCtx, cancel := context.WithCancel(context.Background()) defer cancel() - var cpuProfileCleanup func() if cpuProfile := ctx.Viper.GetString(flagCPUProfile); cpuProfile != "" { f, err := os.Create(filepath.Clean(cpuProfile)) if err != nil { @@ -275,11 +279,11 @@ func startInProcess( return fmt.Errorf("failed to start CPU Profiler %w", err) } - cpuProfileCleanup = func() { + defer func() { logger.Info("stopping CPU profiler", "profile", cpuProfile) pprof.StopCPUProfile() _ = f.Close() - } + }() } traceWriterFile := ctx.Viper.GetString(flagTraceStore) @@ -300,6 +304,12 @@ func startInProcess( "(SDK v0.45). Please explicitly put the desired minimum-gas-prices in your app.toml.") } app := appCreator(nil, traceWriter, ctx.Config, ctx.Viper) + defer func() { + logger.Info("close any other open resource...") + if err := app.Close(); err != nil { + logger.Error("error closing database", "err", err) + } + }() gRPCOnly := ctx.Viper.GetBool(flagGRPCOnly) var tmNode service.Service @@ -350,26 +360,31 @@ func startInProcess( if err := tmNode.Start(goCtx); err != nil { return fmt.Errorf("error starting node: %w", err) } - } + defer func() { + if tmNode.IsRunning() { + tmNode.Wait() + } + }() + // 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 { + localClient, err := local.New(tmNode.(local.NodeService)) + if err != nil { + return err + } + clientCtx = client.WithClient[rpcclient.Client](clientCtx, localClient) - // 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) && tmNode != nil { - localClient, err := local.New(tmNode.(local.NodeService)) - if err != nil { - return err + app.RegisterTxService(clientCtx) + app.RegisterTendermintService(clientCtx) } - clientCtx = clientCtx.WithClient(localClient) - - app.RegisterTxService(clientCtx) - app.RegisterTendermintService(clientCtx) } - var apiSrv *api.Server if config.API.Enable { + var apiSrv *api.Server clientCtx := clientCtx.WithHomeDir(home).WithChainID(clientCtx.ChainID) apiSrv = api.New(clientCtx) + defer apiSrv.Close() app.RegisterAPIRoutes(apiSrv, config.API) errCh := make(chan error) @@ -387,23 +402,20 @@ func startInProcess( } } - var ( - grpcSrv *grpc.Server - grpcWebSrv *http.Server - ) - if config.GRPC.Enable { - grpcSrv, err = servergrpc.StartGRPCServer(clientCtx, app, config.GRPC.Address) + grpcSrv, err := servergrpc.StartGRPCServer(clientCtx, app, config.GRPC.Address) if err != nil { return err } + defer grpcSrv.Stop() if config.GRPCWeb.Enable { - grpcWebSrv, err = servergrpc.StartGRPCWeb(grpcSrv, config) + grpcWebSrv, err := servergrpc.StartGRPCWeb(grpcSrv, config) if err != nil { logger.Error("failed to start grpc-web http server", "err", err) return err } + defer grpcWebSrv.Close() } } @@ -456,33 +468,8 @@ func startInProcess( } } - defer func() { - cancel() - if tmNode.IsRunning() { - tmNode.Wait() - } - - if cpuProfileCleanup != nil { - cpuProfileCleanup() - } - - if apiSrv != nil { - _ = apiSrv.Close() - } - - if grpcSrv != nil { - grpcSrv.Stop() - if grpcWebSrv != nil { - _ = grpcWebSrv.Close() - } - } - - logger.Info("close any other open resource...") - if err := app.Close(); err != nil { - logger.Error("error closing database", "err", err) - } - }() - + // Defer cancelling as the last so that it is called first during unwinding. + defer cancel() // wait for signal capture and gracefully return return WaitForQuitSignals(goCtx, restartCh) } diff --git a/sei-cosmos/testutil/network/util.go b/sei-cosmos/testutil/network/util.go index 5b86ffabcf..7804589eae 100644 --- a/sei-cosmos/testutil/network/util.go +++ b/sei-cosmos/testutil/network/util.go @@ -6,6 +6,7 @@ import ( "path/filepath" "time" + "github.com/sei-protocol/sei-chain/sei-cosmos/client" "github.com/sei-protocol/sei-chain/sei-cosmos/crypto/codec" tmtime "github.com/sei-protocol/sei-chain/sei-cosmos/std" "github.com/sei-protocol/sei-chain/sei-cosmos/telemetry" @@ -77,8 +78,7 @@ func startInProcess(cfg Config, val *Validator) error { // We'll need a RPC client if the validator exposes a gRPC or REST endpoint. if val.APIAddress != "" || val.AppConfig.GRPC.Enable { - val.ClientCtx = val.ClientCtx. - WithClient(val.RPCClient) + val.ClientCtx = client.WithClient(val.ClientCtx, val.RPCClient) // Add the tx service in the gRPC router. app.RegisterTxService(val.ClientCtx) diff --git a/sei-cosmos/x/auth/tx/service.go b/sei-cosmos/x/auth/tx/service.go index 84fa7327a7..53bc85fd6d 100644 --- a/sei-cosmos/x/auth/tx/service.go +++ b/sei-cosmos/x/auth/tx/service.go @@ -240,7 +240,7 @@ func (s txServer) GetBlockWithTxs(ctx context.Context, req *txtypes.GetBlockWith } func (s txServer) BroadcastTx(ctx context.Context, req *txtypes.BroadcastTxRequest) (*txtypes.BroadcastTxResponse, error) { - return client.TxServiceBroadcast(ctx, s.clientCtx, req) + return s.clientCtx.TxServiceBroadcast(ctx, req) } // RegisterTxService registers the tx service on the gRPC router. diff --git a/sei-cosmos/x/genutil/client/rest/query.go b/sei-cosmos/x/genutil/client/rest/query.go index 981633b0b4..555023ff42 100644 --- a/sei-cosmos/x/genutil/client/rest/query.go +++ b/sei-cosmos/x/genutil/client/rest/query.go @@ -14,7 +14,12 @@ import ( // QueryGenesisTxs writes the genesis transactions to the response if no error // occurs. func QueryGenesisTxs(clientCtx client.Context, w http.ResponseWriter) { - resultGenesis, err := clientCtx.Client.Genesis(context.Background()) + client, err := clientCtx.GetNode() + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + resultGenesis, err := client.Genesis(context.Background()) if err != nil { rest.WriteErrorResponse( w, http.StatusInternalServerError, diff --git a/sei-tendermint/cmd/tendermint/commands/run_node.go b/sei-tendermint/cmd/tendermint/commands/run_node.go index 99562f79cd..d8eeeb14ec 100644 --- a/sei-tendermint/cmd/tendermint/commands/run_node.go +++ b/sei-tendermint/cmd/tendermint/commands/run_node.go @@ -37,12 +37,8 @@ func AddNodeFlags(cmd *cobra.Command, conf *cfg.Config) { "consensus votes before joining consensus") // abci flags - cmd.Flags().String( - "proxy-app", - conf.ProxyApp, - "proxy app address, or one of: 'kvstore',"+ - " 'persistent_kvstore', 'e2e' or 'noop' for local testing.") - cmd.Flags().String("abci", conf.ABCI, "specify abci transport (socket | grpc)") + mustMarkDeprecated(cmd, "proxy-app", "out-of-process ABCI has been removed; this flag is ignored") + mustMarkDeprecated(cmd, "abci", "out-of-process ABCI has been removed; this flag is ignored") // rpc flags cmd.Flags().String("rpc.laddr", conf.RPC.ListenAddress, "RPC listen address. Port required") @@ -78,6 +74,13 @@ func AddNodeFlags(cmd *cobra.Command, conf *cfg.Config) { addDBFlags(cmd, conf) } +func mustMarkDeprecated(cmd *cobra.Command, name, message string) { + cmd.Flags().String(name, "", "") + if err := cmd.Flags().MarkDeprecated(name, message); err != nil { + panic(err) + } +} + func addDBFlags(cmd *cobra.Command, conf *cfg.Config) { cmd.Flags().String( "db-backend", diff --git a/sei-tendermint/config/config.go b/sei-tendermint/config/config.go index c946e7abed..99b3b72667 100644 --- a/sei-tendermint/config/config.go +++ b/sei-tendermint/config/config.go @@ -173,8 +173,8 @@ type BaseConfig struct { // This should be set in viper so it can unmarshal into this struct RootDir string `mapstructure:"home"` - // TCP or UNIX socket address of the ABCI application, - // or the name of an ABCI application compiled in with the Tendermint binary + // Deprecated: out-of-process ABCI has been removed and this option no longer + // has any effect. ProxyApp string `mapstructure:"proxy-app"` // A custom human readable name for this node @@ -228,7 +228,8 @@ type BaseConfig struct { // A JSON file containing the private key to use for p2p authenticated encryption NodeKey string `mapstructure:"node-key-file"` - // Mechanism to connect to the ABCI application: socket | grpc + // Deprecated: out-of-process ABCI has been removed and this option no longer + // has any effect. ABCI string `mapstructure:"abci"` // Deprecated: peer filtering via ABCI has been removed and this option no longer has any effect. diff --git a/sei-tendermint/config/toml.go b/sei-tendermint/config/toml.go index 63998e32bb..9ed79f8882 100644 --- a/sei-tendermint/config/toml.go +++ b/sei-tendermint/config/toml.go @@ -88,10 +88,6 @@ const manualConfigTemplate = `# This is a TOML config file. ### Main Base Config Options ### ####################################################################### -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy-app = "{{ .BaseConfig.ProxyApp }}" - # A custom human readable name for this node moniker = "{{ .BaseConfig.Moniker }}" @@ -145,9 +141,6 @@ genesis-file = "{{ js .BaseConfig.Genesis }}" # Path to the JSON file containing the private key to use for node authentication in the p2p protocol node-key-file = "{{ js .BaseConfig.NodeKey }}" -# Mechanism to connect to the ABCI application: socket | grpc -abci = "{{ .BaseConfig.ABCI }}" - ####################################################################### ### Advanced Configuration Options ### ####################################################################### diff --git a/sei-tendermint/config/toml_test.go b/sei-tendermint/config/toml_test.go index cf27c4484a..33f34b754c 100644 --- a/sei-tendermint/config/toml_test.go +++ b/sei-tendermint/config/toml_test.go @@ -63,7 +63,6 @@ func checkConfig(t *testing.T, configFile string) { var elems = []string{ "moniker", "seeds", - "proxy-app", "create-empty-blocks", "peer", "timeout", diff --git a/sei-tendermint/test/e2e/README.md b/sei-tendermint/test/e2e/README.md index 70510b6faa..1797ad5c33 100644 --- a/sei-tendermint/test/e2e/README.md +++ b/sei-tendermint/test/e2e/README.md @@ -162,22 +162,4 @@ tendermint init validator TMHOME=$HOME/.tendermint ./build/node ./node/built-in.toml ``` -To make things simpler the e2e application can also be run in the tendermint binary -by running - -```bash -tendermint start --proxy-app e2e -``` - -However this won't offer the same level of configurability of the application. - -**Socket** - -```bash -make node -tendermint init validator -tendermint start -./build/node ./node.socket.toml -``` - Check `node/config.go` to see how the settings of the test application can be tweaked.