diff --git a/CHANGELOG.md b/CHANGELOG.md index ab42148ca5..fbaba4dec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ more accurate. * (app) [#483](https://github.com/crypto-org-chain/ethermint/pull/483) Make keyring-backend client config accessible in app. * (deps) [#489](https://github.com/crypto-org-chain/ethermint/pull/489) Update cosmos-sdk to `v0.50.7`. +* (rpc) [#491](https://github.com/crypto-org-chain/ethermint/pull/491) Avoid unnecessary tx decode in tx listener. ## v0.21.x-cronos diff --git a/app/ante/handler_options.go b/app/ante/handler_options.go index 3bc4788430..2d50fcc3f6 100644 --- a/app/ante/handler_options.go +++ b/app/ante/handler_options.go @@ -49,6 +49,7 @@ type HandlerOptions struct { DynamicFeeChecker bool DisabledAuthzMsgs []string ExtraDecorators []sdk.AnteDecorator + PendingTxListener PendingTxListener } func (options HandlerOptions) validate() error { @@ -131,10 +132,13 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler { return ctx, err } - if len(options.ExtraDecorators) > 0 { - return sdk.ChainAnteDecorators(options.ExtraDecorators...)(ctx, tx, simulate) + extraDecorators := options.ExtraDecorators + if options.PendingTxListener != nil { + extraDecorators = append(extraDecorators, newTxListenerDecorator(options.PendingTxListener)) + } + if len(extraDecorators) > 0 { + return sdk.ChainAnteDecorators(extraDecorators...)(ctx, tx, simulate) } - return ctx, nil } } diff --git a/app/ante/tx_listener.go b/app/ante/tx_listener.go new file mode 100644 index 0000000000..43cbd5bbf8 --- /dev/null +++ b/app/ante/tx_listener.go @@ -0,0 +1,33 @@ +package ante + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + evmtypes "github.com/evmos/ethermint/x/evm/types" +) + +type PendingTxListener func(common.Hash) + +type TxListenerDecorator struct { + pendingTxListener PendingTxListener +} + +// newTxListenerDecorator creates a new TxListenerDecorator with the provided PendingTxListener. +// CONTRACT: must be put at the last of the chained decorators +func newTxListenerDecorator(pendingTxListener PendingTxListener) TxListenerDecorator { + return TxListenerDecorator{pendingTxListener} +} + +func (d TxListenerDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { + if ctx.IsReCheckTx() { + return next(ctx, tx, simulate) + } + if ctx.IsCheckTx() && !simulate && d.pendingTxListener != nil { + for _, msg := range tx.GetMsgs() { + if ethTx, ok := msg.(*evmtypes.MsgEthereumTx); ok { + d.pendingTxListener(ethTx.Hash()) + } + } + } + return next(ctx, tx, simulate) +} diff --git a/app/app.go b/app/app.go index 6f2a77844d..df5399df18 100644 --- a/app/app.go +++ b/app/app.go @@ -145,6 +145,7 @@ import ( consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types" + "github.com/ethereum/go-ethereum/common" // Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes _ "github.com/ethereum/go-ethereum/eth/tracers/js" @@ -189,8 +190,6 @@ var ( type GenesisState map[string]json.RawMessage -type PendingTxListener func([]byte) - // var _ server.Application (*EthermintApp)(nil) // EthermintApp implements an extended ABCI application. It is an application @@ -207,7 +206,7 @@ type EthermintApp struct { invCheckPeriod uint - pendingTxListeners []PendingTxListener + pendingTxListeners []ante.PendingTxListener // keys to access the substores keys map[string]*storetypes.KVStoreKey @@ -820,6 +819,7 @@ func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted u sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), sdk.MsgTypeURL(&vestingtypes.MsgCreateVestingAccount{}), }, + PendingTxListener: app.onPendingTx, }) if err != nil { panic(err) @@ -828,6 +828,12 @@ func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted u app.SetAnteHandler(anteHandler) } +func (app *EthermintApp) onPendingTx(hash common.Hash) { + for _, listener := range app.pendingTxListeners { + listener(hash) + } +} + func (app *EthermintApp) setPostHandler() { postHandler, err := posthandler.NewPostHandler( posthandler.HandlerOptions{}, @@ -1067,21 +1073,11 @@ func (app *EthermintApp) GetStoreKey(name string) storetypes.StoreKey { return app.okeys[name] } -// RegisterPendingTxListener is used by json-rpc server to listen to pending transactions in CheckTx. -func (app *EthermintApp) RegisterPendingTxListener(listener PendingTxListener) { +// RegisterPendingTxListener is used by json-rpc server to listen to pending transactions callback. +func (app *EthermintApp) RegisterPendingTxListener(listener ante.PendingTxListener) { app.pendingTxListeners = append(app.pendingTxListeners, listener) } -func (app *EthermintApp) CheckTx(req *abci.RequestCheckTx) (*abci.ResponseCheckTx, error) { - res, err := app.BaseApp.CheckTx(req) - if err == nil && res.Code == 0 && req.Type == abci.CheckTxType_New { - for _, listener := range app.pendingTxListeners { - listener(req.Tx) - } - } - return res, err -} - // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) { root, err := fs.Sub(docs.SwaggerUI, "swagger-ui") diff --git a/rpc/stream/rpc.go b/rpc/stream/rpc.go index 33d39a5fa4..d23388ada7 100644 --- a/rpc/stream/rpc.go +++ b/rpc/stream/rpc.go @@ -113,20 +113,8 @@ func (s *RPCStream) LogStream() *Stream[*ethtypes.Log] { } // ListenPendingTx is a callback passed to application to listen for pending transactions in CheckTx. -func (s *RPCStream) ListenPendingTx(bytes []byte) { - tx, err := s.txDecoder(bytes) - if err != nil { - s.logger.Error("fail to decode tx", "error", err.Error()) - return - } - - var hashes []common.Hash - for _, msg := range tx.GetMsgs() { - if ethTx, ok := msg.(*evmtypes.MsgEthereumTx); ok { - hashes = append(hashes, ethTx.AsTransaction().Hash()) - } - } - s.pendingTxStream.Add(hashes...) +func (s *RPCStream) ListenPendingTx(hash common.Hash) { + s.pendingTxStream.Add(hash) } func (s *RPCStream) start( diff --git a/server/json_rpc.go b/server/json_rpc.go index ab7238eb14..9a18e14333 100644 --- a/server/json_rpc.go +++ b/server/json_rpc.go @@ -29,10 +29,9 @@ import ( "github.com/cosmos/cosmos-sdk/server" ethlog "github.com/ethereum/go-ethereum/log" ethrpc "github.com/ethereum/go-ethereum/rpc" - "github.com/evmos/ethermint/app" + "github.com/evmos/ethermint/app/ante" "github.com/evmos/ethermint/rpc" "github.com/evmos/ethermint/rpc/stream" - "github.com/evmos/ethermint/server/config" ethermint "github.com/evmos/ethermint/types" ) @@ -43,7 +42,7 @@ const ( ) type AppWithPendingTxStream interface { - RegisterPendingTxListener(listener app.PendingTxListener) + RegisterPendingTxListener(listener ante.PendingTxListener) } // StartJSONRPC starts the JSON-RPC server