github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/ante/validator_tx_fee.go (about) 1 package ante 2 3 import ( 4 "math" 5 6 errorsmod "cosmossdk.io/errors" 7 sdkmath "cosmossdk.io/math" 8 9 sdk "github.com/cosmos/cosmos-sdk/types" 10 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 11 ) 12 13 // checkTxFeeWithValidatorMinGasPrices implements the default fee logic, where the minimum price per 14 // unit of gas is fixed and set by each validator, can the tx priority is computed from the gas price. 15 func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) { 16 feeTx, ok := tx.(sdk.FeeTx) 17 if !ok { 18 return nil, 0, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") 19 } 20 21 feeCoins := feeTx.GetFee() 22 gas := feeTx.GetGas() 23 24 // Ensure that the provided fees meet a minimum threshold for the validator, 25 // if this is a CheckTx. This is only for local mempool purposes, and thus 26 // is only ran on check tx. 27 if ctx.IsCheckTx() { 28 minGasPrices := ctx.MinGasPrices() 29 if !minGasPrices.IsZero() { 30 requiredFees := make(sdk.Coins, len(minGasPrices)) 31 32 // Determine the required fees by multiplying each required minimum gas 33 // price by the gas limit, where fee = ceil(minGasPrice * gasLimit). 34 glDec := sdkmath.LegacyNewDec(int64(gas)) 35 for i, gp := range minGasPrices { 36 fee := gp.Amount.Mul(glDec) 37 requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) 38 } 39 40 if !feeCoins.IsAnyGTE(requiredFees) { 41 return nil, 0, errorsmod.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees) 42 } 43 } 44 } 45 46 priority := getTxPriority(feeCoins, int64(gas)) 47 return feeCoins, priority, nil 48 } 49 50 // getTxPriority returns a naive tx priority based on the amount of the smallest denomination of the gas price 51 // provided in a transaction. 52 // NOTE: This implementation should be used with a great consideration as it opens potential attack vectors 53 // where txs with multiple coins could not be prioritize as expected. 54 func getTxPriority(fee sdk.Coins, gas int64) int64 { 55 var priority int64 56 for _, c := range fee { 57 p := int64(math.MaxInt64) 58 gasPrice := c.Amount.QuoRaw(gas) 59 if gasPrice.IsInt64() { 60 p = gasPrice.Int64() 61 } 62 if priority == 0 || p < priority { 63 priority = p 64 } 65 } 66 67 return priority 68 }