Skip to content

Commit

Permalink
fix(rpc): patch gas used api for block less than upgrade height (evmo…
Browse files Browse the repository at this point in the history
…s#1557)

* patch gas used api for block less than upgrade height

* configurable fix-revert-gas-refund-height

* add test

* fix flag

* update dep

* set default FixRevertGasRefundHeight

* minor comments fix

* fix lint

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Freddy Caceres <facs95@gmail.com>
  • Loading branch information
3 people committed Mar 14, 2023
1 parent 48c2a72 commit ea0134c
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 41 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [#1431](https://github.com/evmos/ethermint/pull/1431) Align hex-strings proof fields in `eth_getProof` as Ethereum.
* (rpc) [#1484](https://github.com/evmos/ethermint/pull/1484) Align empty account result for old blocks as ethereum instead of return account not found error.
* (rpc) [#1503](https://github.com/evmos/ethermint/pull/1503) Fix block hashes returned on JSON-RPC filter `eth_newBlockFilter`.
running transaction in `ReCheckMode`
* (rpc) [#1557](https://github.com/evmos/ethermint/pull/1557) Patch GasUsed before the fix of revert gas refund logic when transaction reverted for `eth_getTransactionReceipt`.
* (ante) [#1566](https://github.com/evmos/ethermint/pull/1566) Fix `gasWanted` on `EthGasConsumeDecorator` ante handler when running transaction in `ReCheckMode`
* (rpc) [#1591](https://github.com/evmos/ethermint/pull/1591) Fix block number returned in opcode for debug trace related api.

## [v0.19.3] - 2022-10-14
Expand Down
16 changes: 13 additions & 3 deletions rpc/backend/tx_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backend

import (
"fmt"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -114,6 +115,17 @@ func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC
return nil, nil
}

// GetGasUsed returns gasUsed from transaction
func (b *Backend) GetGasUsed(res *ethermint.TxResult, price *big.Int, gas uint64) uint64 {
// patch gasUsed if tx is reverted and happened before height on which fixed was introduced
// to return real gas charged
// more info at https://github.com/evmos/ethermint/pull/1557
if res.Failed && res.Height < b.cfg.JSONRPC.FixRevertGasRefundHeight {
return new(big.Int).Mul(price, new(big.Int).SetUint64(gas)).Uint64()
}
return res.GasUsed
}

// GetTransactionReceipt returns the transaction receipt identified by hash.
func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
hexTx := hash.Hex()
Expand All @@ -124,7 +136,6 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
b.logger.Debug("tx not found", "hash", hexTx, "error", err.Error())
return nil, nil
}

resBlock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height))
if err != nil {
b.logger.Debug("block not found", "height", res.Height, "error", err.Error())
Expand Down Expand Up @@ -160,7 +171,6 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
} else {
status = hexutil.Uint(ethtypes.ReceiptStatusSuccessful)
}

chainID, err := b.ChainID()
if err != nil {
return nil, err
Expand Down Expand Up @@ -203,7 +213,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
// They are stored in the chain database.
"transactionHash": hash,
"contractAddress": nil,
"gasUsed": hexutil.Uint64(res.GasUsed),
"gasUsed": hexutil.Uint64(b.GetGasUsed(res, txData.GetGasPrice(), txData.GetGas())),

// Inclusion information: These fields provide information about the inclusion of the
// transaction corresponding to this receipt.
Expand Down
64 changes: 64 additions & 0 deletions rpc/backend/tx_info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package backend

import (
"fmt"
"math/big"

ethermint "github.com/evmos/ethermint/types"
)

func (suite *BackendTestSuite) TestGetGasUsed() {
origin := suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight
testCases := []struct {
name string
fixRevertGasRefundHeight int64
txResult *ethermint.TxResult
price *big.Int
gas uint64
exp uint64
}{
{
"success txResult",
1,
&ethermint.TxResult{
Height: 1,
Failed: false,
GasUsed: 53026,
},
new(big.Int).SetUint64(0),
0,
53026,
},
{
"fail txResult before cap",
2,
&ethermint.TxResult{
Height: 1,
Failed: true,
GasUsed: 53026,
},
new(big.Int).SetUint64(200000),
5000000000000,
1000000000000000000,
},
{
"fail txResult after cap",
2,
&ethermint.TxResult{
Height: 3,
Failed: true,
GasUsed: 53026,
},
new(big.Int).SetUint64(200000),
5000000000000,
53026,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight = tc.fixRevertGasRefundHeight
suite.Require().Equal(tc.exp, suite.backend.GetGasUsed(tc.txResult, tc.price, tc.gas))
suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight = origin
})
}
}
80 changes: 45 additions & 35 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const (
// DefaultEVMTracer is the default vm.Tracer type
DefaultEVMTracer = ""

// DefaultFixRevertGasRefundHeight is the default height at which to overwrite gas refund
DefaultFixRevertGasRefundHeight = 0

DefaultMaxTxGasWanted = 0

DefaultGasCap uint64 = 25000000
Expand All @@ -44,14 +47,17 @@ const (
DefaultBlockRangeCap int32 = 10000

DefaultEVMTimeout = 5 * time.Second

// default 1.0 eth
DefaultTxFeeCap float64 = 1.0

DefaultHTTPTimeout = 30 * time.Second

DefaultHTTPIdleTimeout = 120 * time.Second

// DefaultAllowUnprotectedTxs value is false
DefaultAllowUnprotectedTxs = false

// DefaultMaxOpenConnections represents the amount of open connections (unlimited = 0)
DefaultMaxOpenConnections = 0

Expand Down Expand Up @@ -120,6 +126,8 @@ type JSONRPCConfig struct {
MetricsAddress string `mapstructure:"metrics-address"`
// ReturnDataLimit defines maximum number of bytes returned from `eth_call` or similar invocations
ReturnDataLimit int64 `mapstructure:"return-data-limit"`
// FixRevertGasRefundHeight defines the upgrade height for fix of revert gas refund logic when transaction reverted
FixRevertGasRefundHeight int64 `mapstructure:"fix-revert-gas-refund-height"`
}

// TLSConfig defines the certificate and matching private key for the server.
Expand Down Expand Up @@ -205,24 +213,25 @@ func GetAPINamespaces() []string {
// DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default
func DefaultJSONRPCConfig() *JSONRPCConfig {
return &JSONRPCConfig{
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
MetricsAddress: DefaultJSONRPCMetricsAddress,
ReturnDataLimit: DefaultReturnDataLimit,
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
MetricsAddress: DefaultJSONRPCMetricsAddress,
ReturnDataLimit: DefaultReturnDataLimit,
FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight,
}
}

Expand Down Expand Up @@ -316,23 +325,24 @@ func GetConfig(v *viper.Viper) (Config, error) {
MaxTxGasWanted: v.GetUint64("evm.max-tx-gas-wanted"),
},
JSONRPC: JSONRPCConfig{
Enable: v.GetBool("json-rpc.enable"),
API: v.GetStringSlice("json-rpc.api"),
Address: v.GetString("json-rpc.address"),
WsAddress: v.GetString("json-rpc.ws-address"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
MetricsAddress: v.GetString("json-rpc.metrics-address"),
ReturnDataLimit: v.GetInt64("json-rpc.return-data-limit"),
Enable: v.GetBool("json-rpc.enable"),
API: v.GetStringSlice("json-rpc.api"),
Address: v.GetString("json-rpc.address"),
WsAddress: v.GetString("json-rpc.ws-address"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
MetricsAddress: v.GetString("json-rpc.metrics-address"),
ReturnDataLimit: v.GetInt64("json-rpc.return-data-limit"),
FixRevertGasRefundHeight: v.GetInt64("json-rpc.fix-revert-gas-refund-height"),
},
TLS: TLSConfig{
CertificatePath: v.GetString("tls.certificate-path"),
Expand Down
3 changes: 3 additions & 0 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ metrics-address = "{{ .JSONRPC.MetricsAddress }}"
# Maximum number of bytes returned from eth_call or similar invocations.
return-data-limit = {{ .JSONRPC.ReturnDataLimit }}
# Upgrade height for fix of revert gas refund logic when transaction reverted.
fix-revert-gas-refund-height = {{ .JSONRPC.FixRevertGasRefundHeight }}
###############################################################################
### TLS Configuration ###
###############################################################################
Expand Down
5 changes: 3 additions & 2 deletions server/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ const (
// JSONRPCEnableMetrics enables EVM RPC metrics server.
// Set to `metrics` which is hardcoded flag from go-ethereum.
// https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L35-L55
JSONRPCEnableMetrics = "metrics"
JSONRPCReturnDataLimit = "json-rpc.return-data-limit"
JSONRPCEnableMetrics = "metrics"
JSONRPCReturnDataLimit = "json-rpc.return-data-limit"
JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height"
)

// EVM flags
Expand Down
1 change: 1 addition & 0 deletions tests/integration_tests/configs/default.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
'feehistory-cap': 100,
'block-range-cap': 10000,
'logs-cap': 10000,
'fix-revert-gas-refund-height': 1,
},
},
validators: [{
Expand Down

0 comments on commit ea0134c

Please sign in to comment.