Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(rpc): patch gas used api for block less than upgrade height (backport: #1557) #222

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
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