179 lines
8.3 KiB
Go
179 lines
8.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
)
|
|
|
|
// HandlerOptions extend the SDK's TxHandler options by requiring the IBC
|
|
// channel keeper, EVM Keeper and Fee Market Keeper.
|
|
type HandlerOptions struct {
|
|
Debug bool
|
|
|
|
Codec codec.Codec
|
|
// TxDecoder is used to decode the raw tx bytes into a sdk.Tx.
|
|
TxDecoder sdk.TxDecoder
|
|
|
|
// IndexEvents defines the set of events in the form {eventType}.{attributeKey},
|
|
// which informs Tendermint what to index. If empty, all events will be indexed.
|
|
IndexEvents map[string]struct{}
|
|
|
|
LegacyRouter sdk.Router
|
|
MsgServiceRouter *authmiddleware.MsgServiceRouter
|
|
|
|
ExtensionOptionChecker authmiddleware.ExtensionOptionChecker
|
|
TxFeeChecker authmiddleware.TxFeeChecker
|
|
|
|
AccountKeeper evmtypes.AccountKeeper
|
|
BankKeeper evmtypes.BankKeeper
|
|
FeeMarketKeeper evmtypes.FeeMarketKeeper
|
|
EvmKeeper EVMKeeper
|
|
FeegrantKeeper authmiddleware.FeegrantKeeper
|
|
SignModeHandler authsigning.SignModeHandler
|
|
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
|
|
MaxTxGasWanted uint64
|
|
}
|
|
|
|
func (options HandlerOptions) Validate() error {
|
|
if options.TxDecoder == nil {
|
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "txDecoder is required for middlewares")
|
|
}
|
|
if options.SignModeHandler == nil {
|
|
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 middlewares")
|
|
}
|
|
if options.BankKeeper == nil {
|
|
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 middlewares")
|
|
}
|
|
if options.FeeMarketKeeper == nil {
|
|
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 middlewares")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func newEthAuthMiddleware(options HandlerOptions) tx.Middleware {
|
|
stack := []tx.Middleware{
|
|
NewEthSetUpContextMiddleware(options.EvmKeeper),
|
|
NewEthMempoolFeeMiddleware(options.EvmKeeper),
|
|
authmiddleware.NewIndexEventsTxMiddleware(options.IndexEvents),
|
|
NewEthValidateBasicMiddleware(options.EvmKeeper),
|
|
NewEthSigVerificationMiddleware(options.EvmKeeper),
|
|
NewEthAccountVerificationMiddleware(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
|
|
NewEthGasConsumeMiddleware(options.EvmKeeper, options.MaxTxGasWanted),
|
|
NewCanTransferMiddleware(options.EvmKeeper),
|
|
NewEthIncrementSenderSequenceMiddleware(options.AccountKeeper),
|
|
}
|
|
return func(txh tx.Handler) tx.Handler {
|
|
return authmiddleware.ComposeMiddlewares(txh, stack...)
|
|
}
|
|
}
|
|
|
|
func newCosmosAuthMiddleware(options HandlerOptions) tx.Middleware {
|
|
stack := []tx.Middleware{
|
|
NewRejectMessagesMiddleware,
|
|
// Set a new GasMeter on sdk.Context.
|
|
//
|
|
// Make sure the Gas middleware is outside of all other middlewares
|
|
// that reads the GasMeter. In our case, the Recovery middleware reads
|
|
// the GasMeter to populate GasInfo.
|
|
authmiddleware.GasTxMiddleware,
|
|
// Recover from panics. Panics outside of this middleware won't be
|
|
// caught, be careful!
|
|
authmiddleware.RecoveryTxMiddleware,
|
|
// Choose which events to index in Tendermint. Make sure no events are
|
|
// emitted outside of this middleware.
|
|
authmiddleware.NewIndexEventsTxMiddleware(options.IndexEvents),
|
|
// Reject all extension options other than the ones needed by the feemarket.
|
|
authmiddleware.NewExtensionOptionsMiddleware(options.ExtensionOptionChecker),
|
|
authmiddleware.ValidateBasicMiddleware,
|
|
authmiddleware.TxTimeoutHeightMiddleware,
|
|
authmiddleware.ValidateMemoMiddleware(options.AccountKeeper),
|
|
authmiddleware.ConsumeTxSizeGasMiddleware(options.AccountKeeper),
|
|
// No gas should be consumed in any middleware above in a "post" handler part. See
|
|
// ComposeMiddlewares godoc for details.
|
|
// `DeductFeeMiddleware` and `IncrementSequenceMiddleware` should be put outside of `WithBranchedStore` middleware,
|
|
// so their storage writes are not discarded when tx fails.
|
|
authmiddleware.DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
|
authmiddleware.SetPubKeyMiddleware(options.AccountKeeper),
|
|
authmiddleware.ValidateSigCountMiddleware(options.AccountKeeper),
|
|
authmiddleware.SigGasConsumeMiddleware(options.AccountKeeper, options.SigGasConsumer),
|
|
authmiddleware.SigVerificationMiddleware(options.AccountKeeper, options.SignModeHandler),
|
|
authmiddleware.IncrementSequenceMiddleware(options.AccountKeeper),
|
|
// Creates a new MultiStore branch, discards downstream writes if the downstream returns error.
|
|
// These kinds of middlewares should be put under this:
|
|
// - Could return error after messages executed succesfully.
|
|
// - Storage writes should be discarded together when tx failed.
|
|
authmiddleware.WithBranchedStore,
|
|
// Consume block gas. All middlewares whose gas consumption after their `next` handler
|
|
// should be accounted for, should go below this middleware.
|
|
authmiddleware.ConsumeBlockGasMiddleware,
|
|
authmiddleware.NewTipMiddleware(options.BankKeeper),
|
|
}
|
|
return func(txh tx.Handler) tx.Handler {
|
|
return authmiddleware.ComposeMiddlewares(txh, stack...)
|
|
}
|
|
}
|
|
|
|
func newCosmosMiddlewareEip712(options HandlerOptions) tx.Middleware {
|
|
stack := []tx.Middleware{
|
|
NewRejectMessagesMiddleware,
|
|
// Set a new GasMeter on sdk.Context.
|
|
//
|
|
// Make sure the Gas middleware is outside of all other middlewares
|
|
// that reads the GasMeter. In our case, the Recovery middleware reads
|
|
// the GasMeter to populate GasInfo.
|
|
authmiddleware.GasTxMiddleware,
|
|
// Recover from panics. Panics outside of this middleware won't be
|
|
// caught, be careful!
|
|
authmiddleware.RecoveryTxMiddleware,
|
|
// Choose which events to index in Tendermint. Make sure no events are
|
|
// emitted outside of this middleware.
|
|
authmiddleware.NewIndexEventsTxMiddleware(options.IndexEvents),
|
|
// Reject all extension options other than the ones needed by the feemarket.
|
|
// authmiddleware.NewExtensionOptionsMiddleware(options.ExtensionOptionChecker),
|
|
authmiddleware.ValidateBasicMiddleware,
|
|
authmiddleware.TxTimeoutHeightMiddleware,
|
|
authmiddleware.ValidateMemoMiddleware(options.AccountKeeper),
|
|
authmiddleware.ConsumeTxSizeGasMiddleware(options.AccountKeeper),
|
|
// No gas should be consumed in any middleware above in a "post" handler part. See
|
|
// ComposeMiddlewares godoc for details.
|
|
// `DeductFeeMiddleware` and `IncrementSequenceMiddleware` should be put outside of `WithBranchedStore` middleware,
|
|
// so their storage writes are not discarded when tx fails.
|
|
authmiddleware.DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
|
authmiddleware.SetPubKeyMiddleware(options.AccountKeeper),
|
|
authmiddleware.ValidateSigCountMiddleware(options.AccountKeeper),
|
|
authmiddleware.SigGasConsumeMiddleware(options.AccountKeeper, options.SigGasConsumer),
|
|
// Note: signature verification uses EIP instead of the cosmos signature validator
|
|
NewEip712SigVerificationMiddleware(options.Codec, options.AccountKeeper, options.SignModeHandler),
|
|
authmiddleware.IncrementSequenceMiddleware(options.AccountKeeper),
|
|
// Creates a new MultiStore branch, discards downstream writes if the downstream returns error.
|
|
// These kinds of middlewares should be put under this:
|
|
// - Could return error after messages executed succesfully.
|
|
// - Storage writes should be discarded together when tx failed.
|
|
authmiddleware.WithBranchedStore,
|
|
// Consume block gas. All middlewares whose gas consumption after their `next` handler
|
|
// should be accounted for, should go below this middleware.
|
|
authmiddleware.ConsumeBlockGasMiddleware,
|
|
authmiddleware.NewTipMiddleware(options.BankKeeper),
|
|
}
|
|
return func(txh tx.Handler) tx.Handler {
|
|
return authmiddleware.ComposeMiddlewares(txh, stack...)
|
|
}
|
|
}
|