diff --git a/app/app.go b/app/app.go index ff69c9db..4bb8121b 100644 --- a/app/app.go +++ b/app/app.go @@ -712,10 +712,7 @@ func (app *EthermintApp) setTxHandler(options middleware.HandlerOptions, txConfi options.IndexEvents = indexEvents - txHandler, err := middleware.NewMiddleware(options) - if err != nil { - panic(err) - } + txHandler := middleware.NewTxHandler(options) app.SetTxHandler(txHandler) } diff --git a/app/middleware/middleware.go b/app/middleware/middleware.go index 78425fbe..6d241dd5 100644 --- a/app/middleware/middleware.go +++ b/app/middleware/middleware.go @@ -7,7 +7,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" - authante "github.com/cosmos/cosmos-sdk/x/auth/middleware" + authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/tharsis/ethermint/crypto/ethsecp256k1" ) @@ -16,128 +16,91 @@ const ( secp256k1VerifyCost uint64 = 21000 ) -type MD struct { - ethMiddleware tx.Handler - cosmosMiddleware tx.Handler - cosmoseip712 tx.Handler +type txRouter struct { + eth, cosmos, eip712 tx.Handler } -var _ tx.Handler = MD{} +var _ tx.Handler = txRouter{} -func NewMiddleware(options HandlerOptions) (tx.Handler, error) { - ethMiddleware, err := newEthAuthMiddleware(options) - if err != nil { - return nil, err +func NewTxHandler(options HandlerOptions) tx.Handler { + return authmiddleware.ComposeMiddlewares( + authmiddleware.NewRunMsgsTxHandler(options.MsgServiceRouter, options.LegacyRouter), + authmiddleware.NewTxDecoderMiddleware(options.TxDecoder), + NewTxRouterMiddleware(options), + ) +} + +func NewTxRouterMiddleware(options HandlerOptions) tx.Middleware { + ethMiddleware := newEthAuthMiddleware(options) + cosmoseip712 := newCosmosMiddlewareEip712(options) + cosmosMiddleware := newCosmosAuthMiddleware(options) + return func(txh tx.Handler) tx.Handler { + return txRouter{ + eth: ethMiddleware(txh), + cosmos: cosmosMiddleware(txh), + eip712: cosmoseip712(txh), + } } - cosmoseip712, err := newCosmosAnteHandlerEip712(options) - if err != nil { - return nil, err - } - cosmosMiddleware, err := newCosmosAuthMiddleware(options) - if err != nil { - return nil, err - } - return MD{ - ethMiddleware: ethMiddleware, - cosmosMiddleware: cosmosMiddleware, - cosmoseip712: cosmoseip712, - }, nil } // CheckTx implements tx.Handler -func (md MD) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) { - var anteHandler tx.Handler - reqTx := req.Tx - txWithExtensions, ok := reqTx.(authante.HasExtensionOptionsTx) +func (txh txRouter) route(req tx.Request) (tx.Handler, error) { + txWithExtensions, ok := req.Tx.(authmiddleware.HasExtensionOptionsTx) if ok { opts := txWithExtensions.GetExtensionOptions() if len(opts) > 0 { + var next tx.Handler switch typeURL := opts[0].GetTypeUrl(); typeURL { case "/ethermint.evm.v1.ExtensionOptionsEthereumTx": // handle as *evmtypes.MsgEthereumTx - anteHandler = md.ethMiddleware + next = txh.eth case "/ethermint.types.v1.ExtensionOptionsWeb3Tx": // handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation - anteHandler = md.cosmoseip712 + next = txh.eip712 default: - return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf( + return nil, sdkerrors.Wrapf( sdkerrors.ErrUnknownExtensionOptions, "rejecting tx with unsupported extension option: %s", typeURL, ) } - - return anteHandler.CheckTx(ctx, req, checkReq) + return next, nil } } - // // handle as totally normal Cosmos SDK tx - // _, ok = reqTx.(sdk.Tx) - // if !ok { - // return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", reqTx) + // if _, ok = reqTx.(sdk.Tx); !ok { + // return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", reqTx) // } + return txh.cosmos, nil +} - return md.cosmosMiddleware.CheckTx(ctx, req, checkReq) +// CheckTx implements tx.Handler +func (txh txRouter) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (res tx.Response, rct tx.ResponseCheckTx, err error) { + next, err := txh.route(req) + if err != nil { + return + } + return next.CheckTx(ctx, req, checkReq) } // DeliverTx implements tx.Handler -func (md MD) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) { - var anteHandler tx.Handler - reqTx := req.Tx - txWithExtensions, ok := reqTx.(authante.HasExtensionOptionsTx) - if ok { - opts := txWithExtensions.GetExtensionOptions() - if len(opts) > 0 { - switch typeURL := opts[0].GetTypeUrl(); typeURL { - case "/ethermint.evm.v1.ExtensionOptionsEthereumTx": - // handle as *evmtypes.MsgEthereumTx - anteHandler = md.ethMiddleware - case "/ethermint.types.v1.ExtensionOptionsWeb3Tx": - // handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation - anteHandler = md.cosmoseip712 - default: - return tx.Response{}, sdkerrors.Wrapf( - sdkerrors.ErrUnknownExtensionOptions, - "rejecting tx with unsupported extension option: %s", typeURL, - ) - } - - return anteHandler.DeliverTx(ctx, req) - } +func (txh txRouter) DeliverTx(ctx context.Context, req tx.Request) (res tx.Response, err error) { + next, err := txh.route(req) + if err != nil { + return } - - return md.cosmosMiddleware.DeliverTx(ctx, req) + return next.DeliverTx(ctx, req) } // SimulateTx implements tx.Handler -func (md MD) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) { - var anteHandler tx.Handler - reqTx := req.Tx - txWithExtensions, ok := reqTx.(authante.HasExtensionOptionsTx) - if ok { - opts := txWithExtensions.GetExtensionOptions() - if len(opts) > 0 { - switch typeURL := opts[0].GetTypeUrl(); typeURL { - case "/ethermint.evm.v1.ExtensionOptionsEthereumTx": - // handle as *evmtypes.MsgEthereumTx - anteHandler = md.ethMiddleware - case "/ethermint.types.v1.ExtensionOptionsWeb3Tx": - // handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation - anteHandler = md.cosmoseip712 - default: - return tx.Response{}, sdkerrors.Wrapf( - sdkerrors.ErrUnknownExtensionOptions, - "rejecting tx with unsupported extension option: %s", typeURL, - ) - } - - return anteHandler.SimulateTx(ctx, req) - } +func (txh txRouter) SimulateTx(ctx context.Context, req tx.Request) (res tx.Response, err error) { + next, err := txh.route(req) + if err != nil { + return } - - return md.cosmosMiddleware.SimulateTx(ctx, req) + return next.SimulateTx(ctx, req) } -var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsumer +var _ authmiddleware.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsumer // DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas // for signature verification based upon the public key type. The cost is fetched from the given params and is matched @@ -152,5 +115,5 @@ func DefaultSigVerificationGasConsumer( return nil } - return authante.DefaultSigVerificationGasConsumer(meter, sig, params) + return authmiddleware.DefaultSigVerificationGasConsumer(meter, sig, params) } diff --git a/app/middleware/options.go b/app/middleware/options.go index fd64a789..a6fe6da2 100644 --- a/app/middleware/options.go +++ b/app/middleware/options.go @@ -13,7 +13,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC +// HandlerOptions extend the SDK's TxHandler options by requiring the IBC // channel keeper, EVM Keeper and Fee Market Keeper. type HandlerOptions struct { Debug bool @@ -50,26 +50,25 @@ func (options HandlerOptions) Validate() error { return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares") } if options.AccountKeeper == nil { - return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler") + return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for middlewares") } if options.BankKeeper == nil { - return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler") + return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for middlewares") } if options.SignModeHandler == nil { - return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder") + return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares") } if options.FeeMarketKeeper == nil { - return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler") + return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for middlewares") } if options.EvmKeeper == nil { - return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler") + return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for middlewares") } return nil } -func newEthAuthMiddleware(options HandlerOptions) (tx.Handler, error) { - return authmiddleware.ComposeMiddlewares( - authmiddleware.NewRunMsgsTxHandler(options.MsgServiceRouter, options.LegacyRouter), +func newEthAuthMiddleware(options HandlerOptions) tx.Middleware { + stack := []tx.Middleware{ NewEthSetUpContextMiddleware(options.EvmKeeper), NewEthMempoolFeeMiddleware(options.EvmKeeper), NewEthValidateBasicMiddleware(options.EvmKeeper), @@ -78,13 +77,14 @@ func newEthAuthMiddleware(options HandlerOptions) (tx.Handler, error) { NewEthGasConsumeMiddleware(options.EvmKeeper, options.MaxTxGasWanted), NewCanTransferMiddleware(options.EvmKeeper), NewEthIncrementSenderSequenceMiddleware(options.AccountKeeper), - ), nil + } + return func(txh tx.Handler) tx.Handler { + return authmiddleware.ComposeMiddlewares(txh, stack...) + } } -func newCosmosAuthMiddleware(options HandlerOptions) (tx.Handler, error) { - return authmiddleware.ComposeMiddlewares( - authmiddleware.NewRunMsgsTxHandler(options.MsgServiceRouter, options.LegacyRouter), - authmiddleware.NewTxDecoderMiddleware(options.TxDecoder), +func newCosmosAuthMiddleware(options HandlerOptions) tx.Middleware { + stack := []tx.Middleware{ NewRejectMessagesMiddleware, // Set a new GasMeter on sdk.Context. // @@ -123,15 +123,15 @@ func newCosmosAuthMiddleware(options HandlerOptions) (tx.Handler, error) { // should be accounted for, should go below this middleware. authmiddleware.ConsumeBlockGasMiddleware, authmiddleware.NewTipMiddleware(options.BankKeeper), - ), nil + } + return func(txh tx.Handler) tx.Handler { + return authmiddleware.ComposeMiddlewares(txh, stack...) + } } -func newCosmosAnteHandlerEip712(options HandlerOptions) (tx.Handler, error) { - - return authmiddleware.ComposeMiddlewares( - authmiddleware.NewRunMsgsTxHandler(options.MsgServiceRouter, options.LegacyRouter), +func newCosmosMiddlewareEip712(options HandlerOptions) tx.Middleware { + stack := []tx.Middleware{ NewRejectMessagesMiddleware, - authmiddleware.NewTxDecoderMiddleware(options.TxDecoder), // Set a new GasMeter on sdk.Context. // // Make sure the Gas middleware is outside of all other middlewares @@ -170,5 +170,8 @@ func newCosmosAnteHandlerEip712(options HandlerOptions) (tx.Handler, error) { // should be accounted for, should go below this middleware. authmiddleware.ConsumeBlockGasMiddleware, authmiddleware.NewTipMiddleware(options.BankKeeper), - ), nil + } + return func(txh tx.Handler) tx.Handler { + return authmiddleware.ComposeMiddlewares(txh, stack...) + } } diff --git a/app/middleware/utils_test.go b/app/middleware/utils_test.go index ca90436b..923405b5 100644 --- a/app/middleware/utils_test.go +++ b/app/middleware/utils_test.go @@ -13,7 +13,7 @@ import ( types3 "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/crypto" "github.com/spf13/cast" - ante "github.com/tharsis/ethermint/app/middleware" + "github.com/tharsis/ethermint/app/middleware" "github.com/tharsis/ethermint/ethereum/eip712" "github.com/tharsis/ethermint/server/config" "github.com/tharsis/ethermint/types" @@ -123,7 +123,7 @@ func (suite *MiddlewareTestSuite) SetupTest() { suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig) maxGasWanted := cast.ToUint64(config.DefaultMaxTxGasWanted) - options := ante.HandlerOptions{ + options := middleware.HandlerOptions{ TxDecoder: suite.clientCtx.TxConfig.TxDecoder(), AccountKeeper: suite.app.AccountKeeper, BankKeeper: suite.app.BankKeeper, @@ -135,14 +135,12 @@ func (suite *MiddlewareTestSuite) SetupTest() { MsgServiceRouter: suite.app.MsgSvcRouter, FeeMarketKeeper: suite.app.FeeMarketKeeper, SignModeHandler: suite.clientCtx.TxConfig.SignModeHandler(), - SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + SigGasConsumer: middleware.DefaultSigVerificationGasConsumer, MaxTxGasWanted: maxGasWanted, } suite.Require().NoError(options.Validate()) - middleware, err := ante.NewMiddleware(options) - suite.Require().NoError(err) - suite.anteHandler = middleware + suite.anteHandler = middleware.NewTxHandler(options) suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()) }