-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
middleware.go
130 lines (114 loc) · 4.85 KB
/
middleware.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
ExtensionOptionChecker ExtensionOptionChecker
TxFeeChecker TxFeeChecker
}
// 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
}
var extensionOptionChecker = options.ExtensionOptionChecker
if extensionOptionChecker == nil {
extensionOptionChecker = rejectExtensionOption
}
var txFeeChecker = options.TxFeeChecker
if txFeeChecker == nil {
txFeeChecker = checkTxFeeWithValidatorMinGasPrices
}
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 other than the ones needed by the feemarket.
NewExtensionOptionsMiddleware(extensionOptionChecker),
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` and `IncrementSequenceMiddleware` should be put outside of `WithBranchedStore` middleware,
// so their storage writes are not discarded when tx fails.
DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, txFeeChecker),
SetPubKeyMiddleware(options.AccountKeeper),
ValidateSigCountMiddleware(options.AccountKeeper),
SigGasConsumeMiddleware(options.AccountKeeper, sigGasConsumer),
SigVerificationMiddleware(options.AccountKeeper, options.SignModeHandler),
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.
WithBranchedStore,
// Consume block gas. All middlewares whose gas consumption after their `next` handler
// should be accounted for, should go below this middleware.
ConsumeBlockGasMiddleware,
NewTipMiddleware(options.BankKeeper),
), nil
}