diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3ad482b..739b7d045 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - [\#350](https://github.com/cosmos/evm/pull/350) Fix p256 precompile test flakiness - [\#376](https://github.com/cosmos/evm/pull/376) Fix precompile initialization for local node development script - [\#384](https://github.com/cosmos/evm/pull/384) Fix debug_traceTransaction RPC failing with block height mismatch errors +- [\#368](https://github.com/cosmos/evm/pull/368) Support query gas limit flag - [\#441](https://github.com/cosmos/evm/pull/441) Align precompiles map with available static check to Prague. - [\#452](https://github.com/cosmos/evm/pull/452) Cleanup unused cancel function in filter. - [\#454](https://github.com/cosmos/evm/pull/454) Align multi decode functions instead of string contains check in HexAddressFromBech32String. diff --git a/evmd/app.go b/evmd/app.go index 9486d3e1e..41248399b 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -492,6 +492,7 @@ func NewExampleApp( &app.ConsensusParamsKeeper, &app.Erc20Keeper, tracer, + cast.ToUint64(appOpts.Get(server.FlagQueryGasLimit)), ) app.Erc20Keeper = erc20keeper.NewKeeper( diff --git a/evmd/cmd/evmd/cmd/creator.go b/evmd/cmd/evmd/cmd/creator.go index c6238998d..350a089d6 100644 --- a/evmd/cmd/evmd/cmd/creator.go +++ b/evmd/cmd/evmd/cmd/creator.go @@ -86,6 +86,7 @@ func (a appCreator) newApp( baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents))), baseapp.SetSnapshot(snapshotStore, snapshotOptions), baseapp.SetIAVLCacheSize(cast.ToInt(appOpts.Get(server.FlagIAVLCacheSize))), + baseapp.SetQueryGasLimit(cast.ToUint64(appOpts.Get(server.FlagQueryGasLimit))), } return evmd.NewExampleApp( diff --git a/evmd/cmd/evmd/cmd/root.go b/evmd/cmd/evmd/cmd/root.go index 8a540cf0a..16abf20cd 100644 --- a/evmd/cmd/evmd/cmd/root.go +++ b/evmd/cmd/evmd/cmd/root.go @@ -314,6 +314,7 @@ func newApp( baseapp.SetIAVLCacheSize(cast.ToInt(appOpts.Get(sdkserver.FlagIAVLCacheSize))), baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(sdkserver.FlagDisableIAVLFastNode))), baseapp.SetChainID(chainID), + baseapp.SetQueryGasLimit(cast.ToUint64(appOpts.Get(sdkserver.FlagQueryGasLimit))), } return evmd.NewExampleApp( diff --git a/x/vm/keeper/grpc_query.go b/x/vm/keeper/grpc_query.go index eb895079c..93b881a78 100644 --- a/x/vm/keeper/grpc_query.go +++ b/x/vm/keeper/grpc_query.go @@ -246,7 +246,8 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms nonce := k.GetNonce(ctx, args.GetFrom()) args.Nonce = (*hexutil.Uint64)(&nonce) - if err := args.CallDefaults(req.GasCap, cfg.BaseFee, types.GetEthChainConfig().ChainID); err != nil { + gasCap := k.GlobalQueryGasLimit(req) + if err := args.CallDefaults(gasCap, cfg.BaseFee, types.GetEthChainConfig().ChainID); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -291,9 +292,8 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest // Binary search the gas requirement, as it may be higher than the amount used var ( - lo = ethparams.TxGas - 1 - hi uint64 - gasCap uint64 + lo = ethparams.TxGas - 1 + hi uint64 ) // Determine the highest gas limit can be used during the estimation. @@ -310,11 +310,13 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest } // Recap the highest gas allowance with specified gascap. - if req.GasCap != 0 && hi > req.GasCap { - hi = req.GasCap + gasCap := k.GlobalQueryGasLimit(req) + if gasCap != 0 && hi > gasCap { + hi = gasCap + } else { + gasCap = hi } - gasCap = hi cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress)) if err != nil { return nil, status.Error(codes.Internal, "failed to load evm config") @@ -329,7 +331,7 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest if args.Gas == nil { args.Gas = new(hexutil.Uint64) } - if err := args.CallDefaults(req.GasCap, cfg.BaseFee, types.GetEthChainConfig().ChainID); err != nil { + if err := args.CallDefaults(gasCap, cfg.BaseFee, types.GetEthChainConfig().ChainID); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -734,6 +736,19 @@ func (k Keeper) GlobalMinGasPrice(c context.Context, _ *types.QueryGlobalMinGasP return &types.QueryGlobalMinGasPriceResponse{MinGasPrice: minGasPrice}, nil } +// GlobalQueryGasLimit return the minimum between server queryGasLimit and request gascap +func (k Keeper) GlobalQueryGasLimit(req *types.EthCallRequest) uint64 { + gasCap := req.GasCap + if k.queryGasLimit != GasNoLimit { + if gasCap == 0 { + gasCap = k.queryGasLimit + } else if k.queryGasLimit < gasCap { + gasCap = k.queryGasLimit + } + } + return gasCap +} + // Config implements the Query/Config gRPC method func (k Keeper) Config(_ context.Context, _ *types.QueryConfigRequest) (*types.QueryConfigResponse, error) { config := types.GetChainConfig() diff --git a/x/vm/keeper/keeper.go b/x/vm/keeper/keeper.go index 774598fb2..132cce004 100644 --- a/x/vm/keeper/keeper.go +++ b/x/vm/keeper/keeper.go @@ -28,6 +28,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// GasNoLimit is the value for keeper.queryGasLimit in case there is no limit +const GasNoLimit = 0 + // Keeper grants access to the EVM module state and implements the go-ethereum StateDB interface. type Keeper struct { // Protobuf codec @@ -78,6 +81,9 @@ type Keeper struct { // parameters. precompiles map[common.Address]vm.PrecompiledContract + // queryGasLimit max amount of gas allowed on queries, 0 means no limit + queryGasLimit uint64 + // evmMempool is the custom EVM appside mempool // if it is nil, the default comet mempool will be used evmMempool *evmmempool.ExperimentalEVMMempool @@ -96,6 +102,7 @@ func NewKeeper( consensusKeeper types.ConsensusParamsKeeper, erc20Keeper types.Erc20Keeper, tracer string, + queryGasLimit uint64, ) *Keeper { // ensure evm module account is set if addr := ak.GetModuleAddress(types.ModuleName); addr == nil { @@ -124,6 +131,7 @@ func NewKeeper( consensusKeeper: consensusKeeper, erc20Keeper: erc20Keeper, storeKeys: keys, + queryGasLimit: queryGasLimit, } }