Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

refactor: optimize AnteHandler gas consumption #1388

Merged
merged 16 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
// won't see the error message.
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
chainID := esvd.evmKeeper.ChainID()

params := esvd.evmKeeper.GetParams(ctx)

ethCfg := params.ChainConfig.EthereumConfig(chainID)
chainCfg := esvd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(chainID)
blockNum := big.NewInt(ctx.BlockHeight())
signer := ethtypes.MakeSigner(ethCfg, blockNum)

Expand All @@ -53,8 +51,9 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}

allowUnprotectedTxs := esvd.evmKeeper.GetAllowUnprotectedTxs(ctx)
ethTx := msgEthTx.AsTransaction()
if !params.AllowUnprotectedTxs && !ethTx.Protected() {
if allowUnprotectedTxs && !ethTx.Protected() {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrNotSupported,
"rejected unprotected Ethereum txs. Please EIP155 sign your transaction to protect it against replay-attacks")
Expand Down Expand Up @@ -176,15 +175,13 @@ func NewEthGasConsumeDecorator(
// - transaction or block gas meter runs out of gas
// - sets the gas meter limit
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
params := egcd.evmKeeper.GetParams(ctx)

ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
chainCfg := egcd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(egcd.evmKeeper.ChainID())

blockHeight := big.NewInt(ctx.BlockHeight())
homestead := ethCfg.IsHomestead(blockHeight)
istanbul := ethCfg.IsIstanbul(blockHeight)
london := ethCfg.IsLondon(blockHeight)
evmDenom := params.EvmDenom
gasWanted := uint64(0)
var events sdk.Events

Expand Down Expand Up @@ -213,6 +210,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
gasWanted += txData.GetGas()
}

evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
ctx,
*msgEthTx,
Expand Down Expand Up @@ -436,9 +434,9 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
txFee := sdk.Coins{}
txGasLimit := uint64(0)

params := vbd.evmKeeper.GetParams(ctx)
chainCfg := vbd.evmKeeper.GetChainConfig(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
ethCfg := chainCfg.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)

for _, msg := range protoTx.GetMsgs() {
Expand All @@ -460,17 +458,20 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
}

// return error if contract creation or call are disabled through governance
if !params.EnableCreate && txData.GetTo() == nil {
enableCreate := vbd.evmKeeper.GetEnableCreate(ctx)
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
enableCall := vbd.evmKeeper.GetEnableCall(ctx)
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
if !enableCreate && txData.GetTo() == nil {
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
} else if !params.EnableCall && txData.GetTo() != nil {
} else if !enableCall && txData.GetTo() != nil {
return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
}

if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}

txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdkmath.NewIntFromBigInt(txData.Fee())))
evmDenom := vbd.evmKeeper.GetEVMDenom(ctx)
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
txFee = txFee.Add(sdk.NewCoin(evmDenom, sdkmath.NewIntFromBigInt(txData.Fee())))
}

authInfo := protoTx.AuthInfo
Expand Down Expand Up @@ -546,8 +547,8 @@ func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
// It only do the check if london hardfork not enabled or feemarket not enabled, because in that case feemarket will take over the task.
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if ctx.IsCheckTx() && !simulate {
params := mfd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(mfd.evmKeeper.ChainID())
chainCfg := mfd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(mfd.evmKeeper.ChainID())
baseFee := mfd.evmKeeper.GetBaseFee(ctx, ethCfg)
if baseFee == nil {
for _, msg := range tx.GetMsgs() {
Expand All @@ -556,7 +557,7 @@ func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}

evmDenom := params.EvmDenom
evmDenom := mfd.evmKeeper.GetEVMDenom(ctx)
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
feeAmt := ethMsg.GetFee()
glDec := sdk.NewDec(int64(ethMsg.GetGas()))
requiredFee := ctx.MinGasPrices().AmountOf(evmDenom).Mul(glDec)
Expand Down
8 changes: 4 additions & 4 deletions app/ante/fee_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ func NewGasWantedDecorator(
}

func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
params := gwd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(gwd.evmKeeper.ChainID())
chainCfg := gwd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(gwd.evmKeeper.ChainID())

blockHeight := big.NewInt(ctx.BlockHeight())
isLondon := ethCfg.IsLondon(blockHeight)
Expand All @@ -39,10 +39,10 @@ func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
}

gasWanted := feeTx.GetGas()
feeMktParams := gwd.feeMarketKeeper.GetParams(ctx)
isBaseFeeEnabled := gwd.feeMarketKeeper.GetBaseFeeEnabled(ctx)

// Add total gasWanted to cumulative in block transientStore in FeeMarket module
if feeMktParams.IsBaseFeeEnabled(ctx.BlockHeight()) {
if isBaseFeeEnabled {
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store")
}
Expand Down
8 changes: 4 additions & 4 deletions app/ante/fees.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
return next(ctx, tx, simulate)
}

evmParams := mpd.evmKeeper.GetParams(ctx)
evmDenom := mpd.evmKeeper.GetEVMDenom(ctx)
minGasPrices := sdk.DecCoins{
{
Denom: evmParams.EvmDenom,
Denom: evmDenom,
Amount: minGasPrice,
},
}
Expand Down Expand Up @@ -93,8 +93,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
return next(ctx, tx, simulate)
}

paramsEvm := empd.evmKeeper.GetParams(ctx)
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID())
chainCfg := empd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(empd.evmKeeper.ChainID())
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)

for _, msg := range tx.GetMsgs() {
Expand Down
6 changes: 3 additions & 3 deletions app/ante/handler_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type HandlerOptions struct {
AccountKeeper evmtypes.AccountKeeper
BankKeeper evmtypes.BankKeeper
IBCKeeper *ibckeeper.Keeper
FeeMarketKeeper evmtypes.FeeMarketKeeper
FeeMarketKeeper FeeMarketKeeper
EvmKeeper EVMKeeper
FeegrantKeeper ante.FeegrantKeeper
SignModeHandler authsigning.SignModeHandler
Expand Down Expand Up @@ -70,9 +70,9 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(),
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
Expand All @@ -93,9 +93,9 @@ func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
ante.NewSetUpContextDecorator(),
// NOTE: extensions option decorator removed
// ante.NewRejectExtensionOptionsDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
Expand Down
6 changes: 6 additions & 0 deletions app/ante/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ type EVMKeeper interface {
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
ResetTransientGasUsed(ctx sdk.Context)
GetTxIndexTransient(ctx sdk.Context) uint64
GetChainConfig(ctx sdk.Context) evmtypes.ChainConfig
GetEVMDenom(ctx sdk.Context) string
GetEnableCreate(ctx sdk.Context) bool
GetEnableCall(ctx sdk.Context) bool
GetAllowUnprotectedTxs(ctx sdk.Context) bool
}

type protoTxProvider interface {
Expand All @@ -44,4 +49,5 @@ type protoTxProvider interface {
type FeeMarketKeeper interface {
GetParams(ctx sdk.Context) (params feemarkettypes.Params)
AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error)
GetBaseFeeEnabled(ctx sdk.Context) bool
}
35 changes: 35 additions & 0 deletions x/evm/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,38 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSpace.SetParamSet(ctx, &params)
}

// GetChainConfig returns the chain configuration parameter.
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
func (k Keeper) GetChainConfig(ctx sdk.Context) types.ChainConfig {
chainCfg := types.ChainConfig{}
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyChainConfig, &chainCfg)
return chainCfg
}

// GetEVMDenom returns the EVM denom.
func (k Keeper) GetEVMDenom(ctx sdk.Context) string {
evmDenom := ""
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyEVMDenom, &evmDenom)
return evmDenom
}

// GetEnableCall returns true if the EVM Call operation is enabled.
func (k Keeper) GetEnableCall(ctx sdk.Context) bool {
enableCall := false
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyEnableCall, &enableCall)
return enableCall
}

// GetEnableCall returns true if the EVM Create contract operation is enabled.
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
func (k Keeper) GetEnableCreate(ctx sdk.Context) bool {
enableCreate := false
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyEnableCreate, &enableCreate)
return enableCreate
}

// GetAllowUnprotectedTxs returns true if unprotected txs (i.e non-replay protected as per EIP-155) are supported by the chain.
func (k Keeper) GetAllowUnprotectedTxs(ctx sdk.Context) bool {
allowUnprotectedTx := false
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyAllowUnprotectedTxs, &allowUnprotectedTx)
return allowUnprotectedTx
}
12 changes: 10 additions & 2 deletions x/feemarket/keeper/params.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package keeper

import (
"math/big"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/evmos/ethermint/x/feemarket/types"
"math/big"
)

// GetParams returns the total set of fee market parameters.
Expand All @@ -28,6 +27,15 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
// Required by EIP1559 base fee calculation.
// ----------------------------------------------------------------------------

// GetBaseFeeEnabled returns true if base fee is enabled
Vvaradinov marked this conversation as resolved.
Show resolved Hide resolved
func (k Keeper) GetBaseFeeEnabled(ctx sdk.Context) bool {
noBaseFee := false
enableHeight := int64(0)
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyNoBaseFee, &noBaseFee)
k.paramSpace.GetIfExists(ctx, types.ParamStoreKeyEnableHeight, &enableHeight)
return noBaseFee && ctx.BlockHeight() >= enableHeight
}

// GetBaseFee get's the base fee from the paramSpace
// return nil if base fee is not enabled
func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
Expand Down