8
8
"cosmossdk.io/errors"
9
9
sdk "github.com/cosmos/cosmos-sdk/types"
10
10
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
11
+ "github.com/cosmos/cosmos-sdk/x/authz"
11
12
)
12
13
13
14
// MinGasPFBDecorator helps to prevent a PFB from being included in a block
@@ -29,27 +30,62 @@ func (d MinGasPFBDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool
29
30
return next (ctx , tx , simulate )
30
31
}
31
32
32
- var gasPerByte uint32
33
+ // Skip gas checks during genesis initialization
34
+ if ctx .BlockHeight () == 0 {
35
+ return next (ctx , tx , simulate )
36
+ }
37
+
38
+ gasPerByte := d .getGasPerByte (ctx )
33
39
txGas := ctx .GasMeter ().GasRemaining ()
34
- for _ , m := range tx .GetMsgs () {
35
- // NOTE: here we assume only one PFB per transaction
36
- if pfb , ok := m .(* types.MsgPayForBlobs ); ok {
37
- if gasPerByte == 0 {
38
- if ctx .BlockHeader ().Version .App <= v2 .Version {
39
- // lazily fetch the gas per byte param
40
- gasPerByte = d .k .GasPerBlobByte (ctx )
41
- } else {
42
- gasPerByte = appconsts .GasPerBlobByte (ctx .BlockHeader ().Version .App )
43
- }
40
+ err := d .validatePFBHasEnoughGas (tx .GetMsgs (), gasPerByte , txGas )
41
+ if err != nil {
42
+ return ctx , err
43
+ }
44
+
45
+ return next (ctx , tx , simulate )
46
+ }
47
+
48
+ // validatePFBHasEnoughGas iterates through all the msgs and nested msgs to find
49
+ // a MsgPayForBlobs. If found, it validates that the txGas is enough to pay for
50
+ // the blobs.
51
+ func (d MinGasPFBDecorator ) validatePFBHasEnoughGas (msgs []sdk.Msg , gasPerByte uint32 , txGas uint64 ) error {
52
+ for _ , m := range msgs {
53
+ if execMsg , ok := m .(* authz.MsgExec ); ok {
54
+ // Recursively look for PFBs in nested authz messages.
55
+ nestedMsgs , err := execMsg .GetMessages ()
56
+ if err != nil {
57
+ return err
44
58
}
45
- gasToConsume := pfb .Gas (gasPerByte )
46
- if gasToConsume > txGas {
47
- return ctx , errors .Wrapf (sdkerrors .ErrInsufficientFee , "not enough gas to pay for blobs (minimum: %d, got: %d)" , gasToConsume , txGas )
59
+ err = d .validatePFBHasEnoughGas (nestedMsgs , gasPerByte , txGas )
60
+ if err != nil {
61
+ return err
62
+ }
63
+ }
64
+ if pfb , ok := m .(* types.MsgPayForBlobs ); ok {
65
+ err := validateEnoughGas (pfb , gasPerByte , txGas )
66
+ if err != nil {
67
+ return err
48
68
}
49
69
}
50
70
}
71
+ return nil
72
+ }
51
73
52
- return next (ctx , tx , simulate )
74
+ func (d MinGasPFBDecorator ) getGasPerByte (ctx sdk.Context ) uint32 {
75
+ if ctx .BlockHeader ().Version .App <= v2 .Version {
76
+ return d .k .GasPerBlobByte (ctx )
77
+ }
78
+ return appconsts .GasPerBlobByte (ctx .BlockHeader ().Version .App )
79
+ }
80
+
81
+ // validateEnoughGas returns an error if the gas needed to pay for the blobs is
82
+ // greater than the txGas.
83
+ func validateEnoughGas (msg * types.MsgPayForBlobs , gasPerByte uint32 , txGas uint64 ) error {
84
+ gasToConsume := msg .Gas (gasPerByte )
85
+ if gasToConsume > txGas {
86
+ return errors .Wrapf (sdkerrors .ErrInsufficientFee , "not enough gas to pay for blobs (minimum: %d, got: %d)" , gasToConsume , txGas )
87
+ }
88
+ return nil
53
89
}
54
90
55
91
type BlobKeeper interface {
0 commit comments