cosmos-sdk/x/auth/middleware/middleware.go

112 lines
3.8 KiB
Go

package middleware
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// ComposeMiddlewares compose multiple middlewares on top of a tx.Handler. The
// middleware order in the variadic arguments is from outer to inner.
//
// Example: Given a base tx.Handler H, and two middlewares A and B, the
// middleware stack:
// ```
// A.pre
// B.pre
// H
// B.post
// A.post
// ```
// is created by calling `ComposeMiddlewares(H, A, B)`.
func ComposeMiddlewares(txHandler tx.Handler, middlewares ...tx.Middleware) tx.Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
txHandler = middlewares[i](txHandler)
}
return txHandler
}
type TxHandlerOptions struct {
Debug bool
// 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 *MsgServiceRouter
AccountKeeper AccountKeeper
BankKeeper types.BankKeeper
FeegrantKeeper FeegrantKeeper
SignModeHandler authsigning.SignModeHandler
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
}
// NewDefaultTxHandler defines a TxHandler middleware stacks that should work
// for most applications.
func NewDefaultTxHandler(options TxHandlerOptions) (tx.Handler, error) {
if options.TxDecoder == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "txDecoder is required for middlewares")
}
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for middlewares")
}
if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for middlewares")
}
if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares")
}
var sigGasConsumer = options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = DefaultSigVerificationGasConsumer
}
return ComposeMiddlewares(
NewRunMsgsTxHandler(options.MsgServiceRouter, options.LegacyRouter),
NewTxDecoderMiddleware(options.TxDecoder),
// 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.
GasTxMiddleware,
// Recover from panics. Panics outside of this middleware won't be
// caught, be careful!
RecoveryTxMiddleware,
// Choose which events to index in Tendermint. Make sure no events are
// emitted outside of this middleware.
NewIndexEventsTxMiddleware(options.IndexEvents),
// Reject all extension options which can optionally be included in the
// tx.
RejectExtensionOptionsMiddleware,
MempoolFeeMiddleware,
ValidateBasicMiddleware,
TxTimeoutHeightMiddleware,
ValidateMemoMiddleware(options.AccountKeeper),
ConsumeTxSizeGasMiddleware(options.AccountKeeper),
// No gas should be consumed in any middleware above in a "post" handler part. See
// ComposeMiddlewares godoc for details.
DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
TxPriorityMiddleware,
SetPubKeyMiddleware(options.AccountKeeper),
ValidateSigCountMiddleware(options.AccountKeeper),
SigGasConsumeMiddleware(options.AccountKeeper, sigGasConsumer),
SigVerificationMiddleware(options.AccountKeeper, options.SignModeHandler),
NewTipMiddleware(options.BankKeeper),
IncrementSequenceMiddleware(options.AccountKeeper),
), nil
}