ante: refactor (#1113)

This commit is contained in:
Federico Kunze Küllmer 2022-06-06 10:15:10 +02:00 committed by GitHub
parent 707b49d0fb
commit 23f88315e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 69 deletions

View File

@ -40,25 +40,25 @@ Ref: https://keepachangelog.com/en/1.0.0/
### State Machine Breaking ### State Machine Breaking
- (feemarket) [tharsis#1105](https://github.com/tharsis/ethermint/pull/1105) Update `BaseFee` calculation based on `GasWanted` instead of `GasUsed`. * (feemarket) [tharsis#1105](https://github.com/tharsis/ethermint/pull/1105) Update `BaseFee` calculation based on `GasWanted` instead of `GasUsed`.
### API Breaking ### API Breaking
- (feemarket) [tharsis#1104](https://github.com/tharsis/ethermint/pull/1104) Enforce a minimum gas price for Cosmos and EVM transactions through the `MinGasPrice` parameter. * (feemarket) [tharsis#1104](https://github.com/tharsis/ethermint/pull/1104) Enforce a minimum gas price for Cosmos and EVM transactions through the `MinGasPrice` parameter.
- (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) Deduplicate some json-rpc logic codes, cleanup several dead functions. * (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) Deduplicate some json-rpc logic codes, cleanup several dead functions.
- (ante) [tharsis#1062](https://github.com/tharsis/ethermint/pull/1062) Emit event of eth tx hash in ante handler to support query failed transactions. * (ante) [tharsis#1062](https://github.com/tharsis/ethermint/pull/1062) Emit event of eth tx hash in ante handler to support query failed transactions.
- (analytics) [tharsis#1106](https://github.com/tharsis/ethermint/pull/1106) Update telemetry to Ethermint modules. * (analytics) [tharsis#1106](https://github.com/tharsis/ethermint/pull/1106) Update telemetry to Ethermint modules.
- (rpc) [tharsis#1108](https://github.com/tharsis/ethermint/pull/1108) Update GetGasPrice RPC endpoint with global `MinGasPrice` * (rpc) [tharsis#1108](https://github.com/tharsis/ethermint/pull/1108) Update GetGasPrice RPC endpoint with global `MinGasPrice`
### Improvements ### Improvements
* (cli) [tharsis#1086](https://github.com/tharsis/ethermint/pull/1086) Add rollback command. * (cli) [tharsis#1086](https://github.com/tharsis/ethermint/pull/1086) Add rollback command.
* (specs) [tharsis#1095](https://github.com/tharsis/ethermint/pull/1095) Add more evm specs concepts. * (specs) [tharsis#1095](https://github.com/tharsis/ethermint/pull/1095) Add more evm specs concepts.
* (evm) [tharsis#1101](https://github.com/tharsis/ethermint/pull/1101) Add tx_type, gas and counter telemetry for ethereum txs. * (evm) [tharsis#1101](https://github.com/tharsis/ethermint/pull/1101) Add tx_type, gas and counter telemetry for ethereum txs.
### Bug Fixes ### Bug Fixes
* (rpc) [tharsis#1082](https://github.com/tharsis/ethermint/pull/1082) fix gas price returned in getTransaction api. * (rpc) [tharsis#1082](https://github.com/tharsis/ethermint/pull/1082) fix gas price returned in getTransaction api.
* (evm) [tharsis#1088](https://github.com/tharsis/ethermint/pull/1088) Fix ability to append log in tx post processing. * (evm) [tharsis#1088](https://github.com/tharsis/ethermint/pull/1088) Fix ability to append log in tx post processing.
* (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions. * (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
* (ante) [tharsis#1111](https://github.com/tharsis/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator * (ante) [tharsis#1111](https://github.com/tharsis/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
@ -279,9 +279,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [tharsis#661](https://github.com/tharsis/ethermint/pull/661) Fix OOM bug when creating too many filters using JSON-RPC. * (rpc) [tharsis#661](https://github.com/tharsis/ethermint/pull/661) Fix OOM bug when creating too many filters using JSON-RPC.
* (evm) [tharsis#660](https://github.com/tharsis/ethermint/pull/660) Fix `nil` pointer panic in `ApplyNativeMessage`. * (evm) [tharsis#660](https://github.com/tharsis/ethermint/pull/660) Fix `nil` pointer panic in `ApplyNativeMessage`.
* (evm, test) [tharsis#649](https://github.com/tharsis/ethermint/pull/649) Test DynamicFeeTx. * (evm, test) [tharsis#649](https://github.com/tharsis/ethermint/pull/649) Test DynamicFeeTx.
* (evm) [tharsis#702](https://github.com/tharsis/ethermint/pull/702) Fix panic in web3 RPC handlers * (evm) [tharsis#702](https://github.com/tharsis/ethermint/pull/702) Fix panic in web3 RPC handlers
* (rpc) [tharsis#720](https://github.com/tharsis/ethermint/pull/720) Fix `debug_traceTransaction` failure * (rpc) [tharsis#720](https://github.com/tharsis/ethermint/pull/720) Fix `debug_traceTransaction` failure
* (rpc) [tharsis#741](https://github.com/tharsis/ethermint/pull/741) Fix `eth_getBlockByNumberAndHash` return with non eth txs * (rpc) [tharsis#741](https://github.com/tharsis/ethermint/pull/741) Fix `eth_getBlockByNumberAndHash` return with non eth txs
* (rpc) [tharsis#743](https://github.com/tharsis/ethermint/pull/743) Fix debug JSON RPC handler crash on non-existing block * (rpc) [tharsis#743](https://github.com/tharsis/ethermint/pull/743) Fix debug JSON RPC handler crash on non-existing block
### Improvements ### Improvements

View File

@ -31,17 +31,20 @@ func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
ethCfg := params.ChainConfig.EthereumConfig(gwd.evmKeeper.ChainID()) ethCfg := params.ChainConfig.EthereumConfig(gwd.evmKeeper.ChainID())
blockHeight := big.NewInt(ctx.BlockHeight()) blockHeight := big.NewInt(ctx.BlockHeight())
london := ethCfg.IsLondon(blockHeight) isLondon := ethCfg.IsLondon(blockHeight)
feeTx, ok := tx.(sdk.FeeTx) feeTx, ok := tx.(sdk.FeeTx)
if ok && london { if !ok || !isLondon {
gasWanted := feeTx.GetGas() return next(ctx, tx, simulate)
feeMktParams := gwd.feeMarketKeeper.GetParams(ctx) }
// Add total gasWanted to cumulative in block transientStore in FeeMarket module
if feeMktParams.IsBaseFeeEnabled(ctx.BlockHeight()) { gasWanted := feeTx.GetGas()
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil { feeMktParams := gwd.feeMarketKeeper.GetParams(ctx)
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store")
} // Add total gasWanted to cumulative in block transientStore in FeeMarket module
if feeMktParams.IsBaseFeeEnabled(ctx.BlockHeight()) {
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store")
} }
} }

View File

@ -1,6 +1,8 @@
package ante package ante
import ( import (
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -23,36 +25,46 @@ func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecora
} }
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
minGasPrices := sdk.DecCoins{sdk.DecCoin{
Denom: mpd.evmKeeper.GetParams(ctx).EvmDenom,
Amount: minGasPrice,
}}
feeTx, ok := tx.(sdk.FeeTx) feeTx, ok := tx.(sdk.FeeTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
} }
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
// short-circuit if min gas price is 0
if minGasPrice.IsZero() {
return next(ctx, tx, simulate)
}
evmParams := mpd.evmKeeper.GetParams(ctx)
minGasPrices := sdk.DecCoins{
{
Denom: evmParams.EvmDenom,
Amount: minGasPrice,
},
}
feeCoins := feeTx.GetFee() feeCoins := feeTx.GetFee()
gas := feeTx.GetGas() gas := feeTx.GetGas()
if !minGasPrices.IsZero() { requiredFees := make(sdk.Coins, 0)
requiredFees := make(sdk.Coins, len(minGasPrices))
// Determine the required fees by multiplying each required minimum gas // Determine the required fees by multiplying each required minimum gas
// price by the gas limit, where fee = ceil(minGasPrice * gasLimit). // price by the gas limit, where fee = ceil(minGasPrice * gasLimit).
gasLimit := sdk.NewDec(int64(gas)) gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(gas))
for i, gp := range minGasPrices {
fee := gp.Amount.Mul(gasLimit)
requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
}
if !feeCoins.IsAnyGTE(requiredFees) { for _, gp := range minGasPrices {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "provided fee < minimum global fee (%s < %s). Please increase the gas price.", feeCoins, requiredFees) fee := gp.Amount.Mul(gasLimit).Ceil().RoundInt()
if fee.IsPositive() {
requiredFees = requiredFees.Add(sdk.Coin{Denom: gp.Denom, Amount: fee})
} }
} }
if !feeCoins.IsAnyGTE(requiredFees) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "provided fee < minimum global fee (%s < %s). Please increase the gas price.", feeCoins, requiredFees)
}
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
@ -73,40 +85,55 @@ func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPrice
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
if !minGasPrice.IsZero() { // short-circuit if min gas price is 0
for _, msg := range tx.GetMsgs() { if minGasPrice.IsZero() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) return next(ctx, tx, simulate)
if !ok { }
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
feeAmt := ethMsg.GetFee() paramsEvm := empd.evmKeeper.GetParams(ctx)
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID())
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
// For dynamic transactions, GetFee() uses the GasFeeCap value, which for _, msg := range tx.GetMsgs() {
// is the maximum gas price that the signer can pay. In practice, the ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
// signer can pay less, if the block's BaseFee is lower. So, in this case, if !ok {
// we use the EffectiveFee. If the feemarket formula results in a BaseFee return ctx, sdkerrors.Wrapf(
// that lowers EffectivePrice until it is < MinGasPrices, the users must sdkerrors.ErrUnknownRequest,
// increase the GasTipCap (priority fee) until EffectivePrice > MinGasPrices. "invalid message type %T, expected %T",
// Transactions with MinGasPrices * gasUsed < tx fees < EffectiveFee are rejected msg, (*evmtypes.MsgEthereumTx)(nil),
// by the feemarket AnteHandle )
txData, err := evmtypes.UnpackTxData(ethMsg.Data) }
if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
}
if txData.TxType() != ethtypes.LegacyTxType {
paramsEvm := empd.evmKeeper.GetParams(ctx)
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID())
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
feeAmt = ethMsg.GetEffectiveFee(baseFee)
}
gasLimit := sdk.NewDec(int64(ethMsg.GetGas())) feeAmt := ethMsg.GetFee()
requiredFee := minGasPrice.Mul(gasLimit)
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) { // For dynamic transactions, GetFee() uses the GasFeeCap value, which
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "provided fee < minimum global fee (%s < %s). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", feeAmt, requiredFee) // is the maximum gas price that the signer can pay. In practice, the
} // signer can pay less, if the block's BaseFee is lower. So, in this case,
// we use the EffectiveFee. If the feemarket formula results in a BaseFee
// that lowers EffectivePrice until it is < MinGasPrices, the users must
// increase the GasTipCap (priority fee) until EffectivePrice > MinGasPrices.
// Transactions with MinGasPrices * gasUsed < tx fees < EffectiveFee are rejected
// by the feemarket AnteHandle
txData, err := evmtypes.UnpackTxData(ethMsg.Data)
if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
}
if txData.TxType() != ethtypes.LegacyTxType {
feeAmt = ethMsg.GetEffectiveFee(baseFee)
}
gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(ethMsg.GetGas()))
requiredFee := minGasPrice.Mul(gasLimit)
fee := sdk.NewDecFromBigInt(feeAmt)
if fee.LT(requiredFee) {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee,
"provided fee < minimum global fee (%s < %s). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)",
fee, requiredFee,
)
} }
} }

View File

@ -58,8 +58,8 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
NewCanTransferDecorator(options.EvmKeeper), NewCanTransferDecorator(options.EvmKeeper),
NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted), NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted),
NewEthIncrementSenderSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator. NewEthIncrementSenderSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator.
NewEthEmitEventDecorator(options.EvmKeeper), // emit eth tx hash and index at the very last ante handler.
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper), NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
NewEthEmitEventDecorator(options.EvmKeeper), // emit eth tx hash and index at the very last ante handler.
) )
} }