diff --git a/CHANGELOG.md b/CHANGELOG.md index f099f6f93..ab5cf91a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,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. ### IMPROVEMENTS diff --git a/evmd/app.go b/evmd/app.go index b255192b3..21528ae0a 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -491,6 +491,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 e4bf7c2ff..1fddbf6cd 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 dbed35ee6..6846c2ce6 100644 --- a/x/vm/keeper/keeper.go +++ b/x/vm/keeper/keeper.go @@ -27,6 +27,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 @@ -77,6 +80,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 @@ -95,6 +101,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 { @@ -123,6 +130,7 @@ func NewKeeper( consensusKeeper: consensusKeeper, erc20Keeper: erc20Keeper, storeKeys: keys, + queryGasLimit: queryGasLimit, } }