fix(rpc): align fee history (backport #1611) (#1620)

* fix(rpc): align fee history (#1611)

* update nix

* add next fee in fee history

* fix test

* add change doc

* height + 1 for next fee

* cross check baseFeePerGas len

* Update tests/integration_tests/test_fee_history.py

Co-authored-by: MalteHerrmann <42640438+MalteHerrmann@users.noreply.github.com>

* fix oldestBlock & align earliest input as eth

* update doc

* update nix

* isort test_fee_history.py

* fix test

* align rpc res as eth

* add cross check

* add baseFeePerGas len check

* add oldestBlock check

Co-authored-by: MalteHerrmann <42640438+MalteHerrmann@users.noreply.github.com>
Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
(cherry picked from commit 47fdfd3d8318358c2578b610bc35bc8c1ebb131e)

# Conflicts:
#	CHANGELOG.md

* address merge conflicts

Co-authored-by: mmsqe <mavis@crypto.com>
Co-authored-by: MalteHerrmann <malte@evmos.org>
Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
mergify[bot] 2023-01-20 16:49:30 +01:00 committed by GitHub
parent c1c25b1818
commit 949674e511
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 110 additions and 28 deletions

View File

@ -36,7 +36,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
# Changelog # Changelog
## [v0.21.0-rc2] - 2022-1-20 ## [v0.21.0-rc2] - 2022-01-20
### State Machine Breaking ### State Machine Breaking
@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes ### Bug Fixes
* (rpc) [#1600](https://github.com/evmos/ethermint/pull/1600) Revert changes from `TypedEvents` * (rpc) [#1600](https://github.com/evmos/ethermint/pull/1600) Revert changes from `TypedEvents`
* (rpc) [#1613](https://github.com/evmos/ethermint/pull/1613) Change the default json-rpc listen address to localhost. * (rpc) [#1613](https://github.com/evmos/ethermint/pull/1613) Change the default json-rpc listen address to localhost.
* (rpc) [#1611](https://github.com/evmos/ethermint/pull/1611) Add missing next fee in fee history, fix wrong oldestBlock and align earliest input as ethereum.
* (proto) [#1586](https://github.com/evmos/ethermint/pull/1586) Avoid duplicate register proto type in `evm` & `feemarket` * (proto) [#1586](https://github.com/evmos/ethermint/pull/1586) Avoid duplicate register proto type in `evm` & `feemarket`
## [v0.20.0] - 2022-12-28 ## [v0.20.0] - 2022-12-28

View File

@ -361,8 +361,8 @@ schema = 3
version = "v2.7.0" version = "v2.7.0"
hash = "sha256-BKqQKCsPA73FaQwYpAY+QsWFHIncrG5jgRhC2IiNmCk=" hash = "sha256-BKqQKCsPA73FaQwYpAY+QsWFHIncrG5jgRhC2IiNmCk="
[mod."github.com/onsi/gomega"] [mod."github.com/onsi/gomega"]
version = "v1.24.2" version = "v1.25.0"
hash = "sha256-iascSzzBT1Uv/XybezSblIwwrq78BU4a9BVB5MvK6MM=" hash = "sha256-knaJppfBzKSMD4Gsqzx22SGrti7G5UyDBYrothAqsrs="
[mod."github.com/pelletier/go-toml"] [mod."github.com/pelletier/go-toml"]
version = "v1.9.5" version = "v1.9.5"
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc=" hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="

View File

@ -161,7 +161,7 @@ func (b *Backend) FeeHistory(
) (*rpctypes.FeeHistoryResult, error) { ) (*rpctypes.FeeHistoryResult, error) {
blockEnd := int64(lastBlock) blockEnd := int64(lastBlock)
if blockEnd <= 0 { if blockEnd < 0 {
blockNumber, err := b.BlockNumber() blockNumber, err := b.BlockNumber()
if err != nil { if err != nil {
return nil, err return nil, err
@ -169,36 +169,34 @@ func (b *Backend) FeeHistory(
blockEnd = int64(blockNumber) blockEnd = int64(blockNumber)
} }
userBlockCountInt := int64(userBlockCount) blocks := int64(userBlockCount)
maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap) maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap)
if userBlockCountInt > maxBlockCount { if blocks > maxBlockCount {
return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", userBlockCountInt, maxBlockCount) return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", blocks, maxBlockCount)
} }
blockStart := blockEnd - userBlockCountInt if blockEnd+1 < blocks {
if blockStart < 0 { blocks = blockEnd + 1
blockStart = 0
} }
// Ensure not trying to retrieve before genesis.
blockCount := blockEnd - blockStart blockStart := blockEnd + 1 - blocks
oldestBlock := (*hexutil.Big)(big.NewInt(blockStart)) oldestBlock := (*hexutil.Big)(big.NewInt(blockStart))
// prepare space // prepare space
reward := make([][]*hexutil.Big, blockCount) reward := make([][]*hexutil.Big, blocks)
rewardCount := len(rewardPercentiles) rewardCount := len(rewardPercentiles)
for i := 0; i < int(blockCount); i++ { for i := 0; i < int(blocks); i++ {
reward[i] = make([]*hexutil.Big, rewardCount) reward[i] = make([]*hexutil.Big, rewardCount)
} }
thisBaseFee := make([]*hexutil.Big, blockCount) thisBaseFee := make([]*hexutil.Big, blocks+1)
thisGasUsedRatio := make([]float64, blockCount) thisGasUsedRatio := make([]float64, blocks)
// rewards should only be calculated if reward percentiles were included // rewards should only be calculated if reward percentiles were included
calculateRewards := rewardCount != 0 calculateRewards := rewardCount != 0
// fetch block // fetch block
for blockID := blockStart; blockID < blockEnd; blockID++ { for blockID := blockStart; blockID <= blockEnd; blockID++ {
index := int32(blockID - blockStart) index := int32(blockID - blockStart)
// tendermint block // tendermint block
tendermintblock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(blockID)) tendermintblock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(blockID))
@ -227,6 +225,7 @@ func (b *Backend) FeeHistory(
// copy // copy
thisBaseFee[index] = (*hexutil.Big)(oneFeeHistory.BaseFee) thisBaseFee[index] = (*hexutil.Big)(oneFeeHistory.BaseFee)
thisBaseFee[index+1] = (*hexutil.Big)(oneFeeHistory.NextBaseFee)
thisGasUsedRatio[index] = oneFeeHistory.GasUsedRatio thisGasUsedRatio[index] = oneFeeHistory.GasUsedRatio
if calculateRewards { if calculateRewards {
for j := 0; j < rewardCount; j++ { for j := 0; j < rewardCount; j++ {

View File

@ -337,7 +337,7 @@ func (suite *BackendTestSuite) TestFeeHistory() {
RegisterParamsError(queryClient, &header, ethrpc.BlockNumber(1).Int64()) RegisterParamsError(queryClient, &header, ethrpc.BlockNumber(1).Int64())
}, },
1, 1,
0, -1,
nil, nil,
nil, nil,
false, false,
@ -351,7 +351,7 @@ func (suite *BackendTestSuite) TestFeeHistory() {
RegisterParams(queryClient, &header, ethrpc.BlockNumber(1).Int64()) RegisterParams(queryClient, &header, ethrpc.BlockNumber(1).Int64())
}, },
1, 1,
0, -1,
nil, nil,
nil, nil,
false, false,
@ -405,6 +405,7 @@ func (suite *BackendTestSuite) TestFeeHistory() {
{ {
"pass - Valid FeeHistoryResults object", "pass - Valid FeeHistoryResults object",
func(validator sdk.AccAddress) { func(validator sdk.AccAddress) {
var header metadata.MD
baseFee := sdk.NewInt(1) baseFee := sdk.NewInt(1)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
client := suite.backend.clientCtx.Client.(*mocks.Client) client := suite.backend.clientCtx.Client.(*mocks.Client)
@ -414,12 +415,14 @@ func (suite *BackendTestSuite) TestFeeHistory() {
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
RegisterConsensusParams(client, 1) RegisterConsensusParams(client, 1)
RegisterParams(queryClient, &header, 1)
RegisterParamsWithoutHeader(queryClient, 1)
}, },
1, 1,
1, 1,
&rpc.FeeHistoryResult{ &rpc.FeeHistoryResult{
OldestBlock: (*hexutil.Big)(big.NewInt(0)), OldestBlock: (*hexutil.Big)(big.NewInt(1)),
BaseFee: []*hexutil.Big{(*hexutil.Big)(big.NewInt(1))}, BaseFee: []*hexutil.Big{(*hexutil.Big)(big.NewInt(1)), (*hexutil.Big)(big.NewInt(1))},
GasUsedRatio: []float64{0}, GasUsedRatio: []float64{0},
Reward: [][]*hexutil.Big{{(*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0))}}, Reward: [][]*hexutil.Big{{(*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0)), (*hexutil.Big)(big.NewInt(0))}},
}, },

View File

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/misc"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
@ -132,7 +133,12 @@ func (b *Backend) processBlock(
// set basefee // set basefee
targetOneFeeHistory.BaseFee = blockBaseFee targetOneFeeHistory.BaseFee = blockBaseFee
cfg := b.ChainConfig()
if cfg.IsLondon(big.NewInt(blockHeight + 1)) {
targetOneFeeHistory.NextBaseFee = misc.CalcBaseFee(cfg, b.CurrentHeader())
} else {
targetOneFeeHistory.NextBaseFee = new(big.Int)
}
// set gas used ratio // set gas used ratio
gasLimitUint64, ok := (*ethBlock)["gasLimit"].(hexutil.Uint64) gasLimitUint64, ok := (*ethBlock)["gasLimit"].(hexutil.Uint64)
if !ok { if !ok {

View File

@ -98,7 +98,7 @@ type SignTransactionResult struct {
} }
type OneFeeHistory struct { type OneFeeHistory struct {
BaseFee *big.Int // base fee for each block BaseFee, NextBaseFee *big.Int // base fee for each block
Reward []*big.Int // each element of the array will have the tip provided to miners for the percentile given Reward []*big.Int // each element of the array will have the tip provided to miners for the percentile given
GasUsedRatio float64 // the ratio of gas used to the gas limit for each block GasUsedRatio float64 // the ratio of gas used to the gas limit for each block
} }

View File

@ -0,0 +1,73 @@
from concurrent.futures import ThreadPoolExecutor, as_completed
import pytest
from web3 import Web3
from .network import setup_ethermint
from .utils import ADDRS, send_transaction
@pytest.fixture(scope="module")
def custom_ethermint(tmp_path_factory):
path = tmp_path_factory.mktemp("fee-history")
yield from setup_ethermint(path, 26500, long_timeout_commit=True)
@pytest.fixture(scope="module", params=["ethermint", "geth"])
def cluster(request, custom_ethermint, geth):
"""
run on both ethermint and geth
"""
provider = request.param
if provider == "ethermint":
yield custom_ethermint
elif provider == "geth":
yield geth
else:
raise NotImplementedError
def test_basic(cluster):
w3: Web3 = cluster.w3
call = w3.provider.make_request
tx = {"to": ADDRS["community"], "value": 10, "gasPrice": w3.eth.gas_price}
send_transaction(w3, tx)
size = 4
# size of base fee + next fee
max = size + 1
# only 1 base fee + next fee
min = 2
method = "eth_feeHistory"
field = "baseFeePerGas"
percentiles = [100]
height = w3.eth.block_number
latest = dict(
blocks=["latest", hex(height)],
expect=max,
)
earliest = dict(
blocks=["earliest", "0x0"],
expect=min,
)
for tc in [latest, earliest]:
res = []
with ThreadPoolExecutor(len(tc["blocks"])) as exec:
tasks = [
exec.submit(call, method, [size, b, percentiles]) for b in tc["blocks"]
]
res = [future.result()["result"][field] for future in as_completed(tasks)]
assert len(res) == len(tc["blocks"])
assert res[0] == res[1]
assert len(res[0]) == tc["expect"]
for x in range(max):
i = x + 1
fee_history = call(method, [size, hex(i), percentiles])
# start to reduce diff on i <= size - min
diff = size - min - i
reduce = size - diff
target = reduce if diff >= 0 else max
res = fee_history["result"]
assert len(res[field]) == target
oldest = i + min - max
assert res["oldestBlock"] == hex(oldest if oldest > 0 else 0)

View File

@ -595,8 +595,8 @@ func TestEth_FeeHistory(t *testing.T) {
baseFeePerGas := info["baseFeePerGas"].([]interface{}) baseFeePerGas := info["baseFeePerGas"].([]interface{})
gasUsedRatio := info["gasUsedRatio"].([]interface{}) gasUsedRatio := info["gasUsedRatio"].([]interface{})
require.Equal(t, info["oldestBlock"].(string), "0x6") require.Equal(t, info["oldestBlock"].(string), "0x7")
require.Equal(t, 4, len(gasUsedRatio)) require.Equal(t, 4, len(gasUsedRatio))
require.Equal(t, 4, len(baseFeePerGas)) require.Equal(t, 5, len(baseFeePerGas))
require.Equal(t, 4, len(reward)) require.Equal(t, 4, len(reward))
} }