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

imp(evm): improve performance of EstimateGas #1444

Merged
merged 4 commits into from
Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Improvements

* (evm) [#1444](https://github.com/evmos/ethermint/pull/1444) Improve performance of `eth_estimateGas`
* (ante) [\#1388](https://github.com/evmos/ethermint/pull/1388) Optimize AnteHandler gas consumption
* (lint) [#1298](https://github.com/evmos/ethermint/pull/1298) 150 character line length limit, `gofumpt`, and linting
* (feemarket) [\#1165](https://github.com/evmos/ethermint/pull/1165) Add hint in specs about different gas terminology in Cosmos and Ethereum.
Expand Down
40 changes: 29 additions & 11 deletions x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,31 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type

txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))

// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) (vmerror bool, rsp *types.MsgEthereumTxResponse, err error) {
args.Gas = (*hexutil.Uint64)(&gas)
// convert the tx args to an ethereum message
msg, err := args.ToMessage(req.GasCap, cfg.BaseFee)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

msg, err := args.ToMessage(req.GasCap, cfg.BaseFee)
if err != nil {
return false, nil, err
}
// NOTE: the errors from the executable below should be consistent with go-ethereum,
// so we don't wrap them with the gRPC status code

// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) (vmError bool, rsp *types.MsgEthereumTxResponse, err error) {
// update the message with the new gas value
msg = ethtypes.NewMessage(
msg.From(),
msg.To(),
msg.Nonce(),
msg.Value(),
gas,
msg.GasPrice(),
msg.GasFeeCap(),
msg.GasTipCap(),
msg.Data(),
msg.AccessList(),
msg.IsFake(),
)

// pass false to not commit StateDB
rsp, err = k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig)
Expand All @@ -328,24 +345,25 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
// Execute the binary search and hone in on an executable gas limit
hi, err = types.BinSearch(lo, hi, executable)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
return nil, err
}

// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
failed, result, err := executable(hi)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
return nil, err
}

if failed {
if result != nil && result.VmError != vm.ErrOutOfGas.Error() {
if result.VmError == vm.ErrExecutionReverted.Error() {
return nil, types.NewExecErrorWithReason(result.Ret)
}
return nil, status.Error(codes.Internal, result.VmError)
return nil, errors.New(result.VmError)
}
// Otherwise, the specified gas cap is too low
return nil, status.Error(codes.Internal, fmt.Sprintf("gas required exceeds allowance (%d)", cap))
return nil, fmt.Errorf("gas required exceeds allowance (%d)", cap)
}
}
return &types.EstimateGasResponse{Gas: hi}, nil
Expand Down