-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
refactor: re-implement eth_feeHistory
#3288
Conversation
I am going to test this on a node and compare the results to Erigon to get a sense of if the implementation is flawed or not |
Codecov Report
@@ Coverage Diff @@
## main #3288 +/- ##
==========================================
- Coverage 69.41% 69.27% -0.15%
==========================================
Files 537 537
Lines 71991 72041 +50
==========================================
- Hits 49973 49906 -67
- Misses 22018 22135 +117
Flags with carried forward coverage won't be shown. Click here to find out more.
|
714c97b
to
f661913
Compare
crates/rpc/rpc/src/eth/api/fees.rs
Outdated
self.inner.provider.receipts_by_block(header.number.into())? else { | ||
// If there are no receipts, then we do not have all info on the block | ||
return Err(EthApiError::InvalidBlockRange) | ||
}; | ||
let Some(mut transactions): Option<Vec<_>> = self | ||
.inner | ||
.provider | ||
.transactions_by_block(header.number.into())? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these should make use of the async caching layer I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do I do that?
TL;DR: It matches except in the case of block count of 0, but this case is not defined in the spec.. Comparison between Erigon's impl and Reth's impl. Each example uses the same percentiles (0, 10, 25, 50, 100). Block 17m, block count of 1 Erigon: {
"jsonrpc":"2.0",
"id":1,
"result":{
"oldestBlock":"0x1036640",
"reward":[
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0xb376620",
"0x26df9ef958"
]
],
"baseFeePerGas":[
"0x4cad3abe1",
"0x48f2114b8"
],
"gasUsedRatio":[
0.3053592666666667
]
}
} Reth: {
"jsonrpc":"2.0",
"result":{
"baseFeePerGas":[
"0x4cad3abe1",
"0x48f2114b8"
],
"gasUsedRatio":[
0.3053592666666667
],
"oldestBlock":"0x1036640",
"reward":[
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0xb376620",
"0x26df9ef958"
]
]
},
"id":1
} Block 17m, block count of 0 Erigon: {
"jsonrpc":"2.0",
"id":1,
"result":{
"oldestBlock":"0x0",
"gasUsedRatio":null
}
} Reth: {
"jsonrpc":"2.0",
"result":{
"baseFeePerGas":[
],
"gasUsedRatio":[
],
"oldestBlock":"0x0",
"reward":null
},
"id":1
} Doesn't match, but are logically similar I think Block 17m, block count of 10 Erigon: {
"jsonrpc":"2.0",
"id":1,
"result":{
"oldestBlock":"0x1036637",
"reward":[
[
"0x0",
"0x59a5380",
"0x5f5e100",
"0x11e1a300",
"0xcb7c3cc58"
],
[
"0x0",
"0x1f8dead",
"0x1f8dead",
"0x4a75410",
"0x2cd3a56ad"
],
[
"0x0",
"0x5f5e100",
"0x121738e4",
"0x77359400",
"0x527935f3e"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0x5f5e100",
"0x8680c0212"
],
[
"0x0",
"0x5f5e100",
"0x11e1a300",
"0x3b9aca00",
"0x2b6e7d7f4"
],
[
"0x5f5e100",
"0xa1fa7e6",
"0x2d8dfc0c",
"0x2d8dfc0c",
"0x4cc25aef1"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0x5f5e100",
"0x42a860c240"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0x5f5e100",
"0xdb597ddd3"
],
[
"0x0",
"0x485ce38",
"0x59a5380",
"0xb376620",
"0x419b5992a"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0xb376620",
"0x26df9ef958"
]
],
"baseFeePerGas":[
"0x4475fcda8",
"0x42ee95553",
"0x4b4ae5842",
"0x44d989922",
"0x45200f7f8",
"0x4035437f4",
"0x4839a89b2",
"0x4705ccab0",
"0x4f68b16aa",
"0x4cad3abe1",
"0x48f2114b8"
],
"gasUsedRatio":[
0.4106688,
0.9996475666666667,
0.1577187,
0.5160047666666666,
0.2154628,
0.9994493,
0.43339863333333334,
0.9723170666666666,
0.3623692,
0.3053592666666667
]
}
} Reth: {
"jsonrpc":"2.0",
"result":{
"baseFeePerGas":[
"0x4475fcda8",
"0x42ee95553",
"0x4b4ae5842",
"0x44d989922",
"0x45200f7f8",
"0x4035437f4",
"0x4839a89b2",
"0x4705ccab0",
"0x4f68b16aa",
"0x4cad3abe1",
"0x48f2114b8"
],
"gasUsedRatio":[
0.4106688,
0.9996475666666667,
0.1577187,
0.5160047666666666,
0.2154628,
0.9994493,
0.43339863333333334,
0.9723170666666666,
0.3623692,
0.3053592666666667
],
"oldestBlock":"0x1036637",
"reward":[
[
"0x0",
"0x59a5380",
"0x5f5e100",
"0x11e1a300",
"0xcb7c3cc58"
],
[
"0x0",
"0x1f8dead",
"0x1f8dead",
"0x4a75410",
"0x2cd3a56ad"
],
[
"0x0",
"0x5f5e100",
"0x121738e4",
"0x77359400",
"0x527935f3e"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0x5f5e100",
"0x8680c0212"
],
[
"0x0",
"0x5f5e100",
"0x11e1a300",
"0x3b9aca00",
"0x2b6e7d7f4"
],
[
"0x5f5e100",
"0xa1fa7e6",
"0x2d8dfc0c",
"0x2d8dfc0c",
"0x4cc25aef1"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0x5f5e100",
"0x42a860c240"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0x5f5e100",
"0xdb597ddd3"
],
[
"0x0",
"0x485ce38",
"0x59a5380",
"0xb376620",
"0x419b5992a"
],
[
"0x0",
"0x5f5e100",
"0x5f5e100",
"0xb376620",
"0x26df9ef958"
]
]
},
"id":1
} Pre-EIP 1559 (block 4 with a block count of 4, i.e. Erigon: {
"jsonrpc":"2.0",
"id":1,
"result":{
"oldestBlock":"0x1",
"reward":[
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
]
],
"baseFeePerGas":[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
"gasUsedRatio":[
0,
0,
0,
0
]
}
} Reth: {
"jsonrpc":"2.0",
"result":{
"baseFeePerGas":[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
"gasUsedRatio":[
0.0,
0.0,
0.0,
0.0
],
"oldestBlock":"0x1",
"reward":[
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
],
[
"0x0",
"0x0",
"0x0",
"0x0",
"0x0"
]
]
},
"id":1
} |
reth:
looks like erigon/geth don't return this field if null? but return empty
as null should we mimic this as well? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
left a few suggestions to asyncify this
eef8623
to
887eb41
Compare
@mattsse Now uses the cache and sealed headers |
It's annoying that it responds like that, but I implemented 1:1 compat in af48ee1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm,
pending clippy
suggestions re Option<Vec
crates/rpc/rpc/src/eth/api/fees.rs
Outdated
self.cache().get_receipts(header.hash.into()).await? else { | ||
// If there are no receipts, then we do not have all info on the block | ||
return Err(EthApiError::InvalidBlockRange) | ||
}; | ||
let Some(mut transactions): Option<Vec<_>> = self | ||
.cache() | ||
.get_block_transactions(header.hash).await? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is fine,
I'll add a new helper function that fetches both concurrently.
@mattsse I removed the 1024 limit, it seems I was mistaken and this is not actually part of the spec. |
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
eae486b
to
a14ae6b
Compare
we definitely need to cap it, geth caps it to 1024: |
This is the full node config, i.e. it is capped because it will not have data for more than 1024 blocks at head afaik. Unsure what the best approach is to cap it Edit: Ah, nvm, I see, this is separate from the regular full node config, instead it is a GPO config and these are just the defaults for full node. Do we have some sort of config mechanism for the RPC where we could add this (with a default of 1024)? |
it's always capped, otherwise you can DOS the endpoint it's configurable in geth via config though |
@mattsse used GPO config to cap the length |
we have in in this: reth/crates/rpc/rpc/src/eth/gas_oracle.rs Lines 22 to 33 in 49922bf
which we should be able to query in eth_feeHistory via reth/crates/rpc/rpc/src/eth/api/mod.rs Lines 287 to 288 in 49922bf
|
The existing implementation of
eth_feeHistory
had some issues:header.gas_used
to the percentile threshold, but it should be comparing a cumulative gas usage of transactions to the percentile thresholdreward: []
, but if the request does not include percentiles, then it should not respond with this at allI also opted to remove the fee history cache, since it adds additional overhead, and it is hard to cache this endpoint, as the response can change significantly based on the reward percentiles.
Perhaps we can use some sort of basic cache for the headers only, or the headers and a pre-sorted list of transactions, but I don't think it would really give us much benefit.
Also closes #3328