mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
Compare commits
312 Commits
yk/worker-
...
bal-devnet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
830125e95a | ||
|
|
0bc0a6b7c3 | ||
|
|
068ef0c681 | ||
|
|
6e00b99b67 | ||
|
|
1d389cfe7a | ||
|
|
2e62387469 | ||
|
|
31133255fe | ||
|
|
a6b9472d1c | ||
|
|
6636d2a2ad | ||
|
|
ab6854d159 | ||
|
|
5a274fc939 | ||
|
|
c9431b224b | ||
|
|
8cbfd91db0 | ||
|
|
43f9942ba7 | ||
|
|
06adc3ee0c | ||
|
|
fbf6be4cf2 | ||
|
|
21d61d40d1 | ||
|
|
cf7d709358 | ||
|
|
e9355caba5 | ||
|
|
fdd9d5bb40 | ||
|
|
9eeba7e6b3 | ||
|
|
0085acc868 | ||
|
|
c697147f90 | ||
|
|
7388d6636d | ||
|
|
0b859c0735 | ||
|
|
a8e0606fa7 | ||
|
|
969689d9b6 | ||
|
|
ad2081493a | ||
|
|
abfb6d3965 | ||
|
|
49249ed2c8 | ||
|
|
c72163de43 | ||
|
|
41c02695d5 | ||
|
|
6f626fd6d2 | ||
|
|
b222cc64cd | ||
|
|
b89ef781f7 | ||
|
|
0f0eb7a531 | ||
|
|
71cd419f7f | ||
|
|
4f1e486b4f | ||
|
|
05307d088c | ||
|
|
245cca7ce2 | ||
|
|
28d6996fc4 | ||
|
|
0eaffdf489 | ||
|
|
9c141cac4b | ||
|
|
fc6ab35c5c | ||
|
|
f88bf4e427 | ||
|
|
3d330caf36 | ||
|
|
5a43e77771 | ||
|
|
5b3c479ed5 | ||
|
|
dc06b47abe | ||
|
|
e9cd7cc003 | ||
|
|
f633efc969 | ||
|
|
fdaf3403e0 | ||
|
|
331e8ca110 | ||
|
|
3a1e2e23a9 | ||
|
|
3fbe585448 | ||
|
|
2f55b1c30f | ||
|
|
d8b13adacd | ||
|
|
26cc128546 | ||
|
|
cdd2298da4 | ||
|
|
b5391deeca | ||
|
|
d753e1983d | ||
|
|
87cc04ee7b | ||
|
|
d7dc2586b6 | ||
|
|
6056f9ec1a | ||
|
|
778af94ecc | ||
|
|
5d21b42dcd | ||
|
|
5c60cb42d4 | ||
|
|
de3f6ebd6f | ||
|
|
b3863e4bf0 | ||
|
|
3f38f77fc3 | ||
|
|
b2c31b0f7c | ||
|
|
4724cec28d | ||
|
|
6824f4726b | ||
|
|
092600c6d8 | ||
|
|
4163e4ea4a | ||
|
|
1cbd53ea4f | ||
|
|
4cba143822 | ||
|
|
41d2276755 | ||
|
|
7603ac7e23 | ||
|
|
1164e11600 | ||
|
|
796c19cc57 | ||
|
|
016b36c918 | ||
|
|
efd198246d | ||
|
|
495a3b3bd1 | ||
|
|
1fc48d4291 | ||
|
|
ae3f950135 | ||
|
|
18cee16f54 | ||
|
|
eb2dc5e84b | ||
|
|
4bb38df3eb | ||
|
|
869306a2ae | ||
|
|
43f4fef490 | ||
|
|
e048909f74 | ||
|
|
67ba84edab | ||
|
|
b4f405a7b2 | ||
|
|
0ff2a51eab | ||
|
|
e63a2521a3 | ||
|
|
63ef0734f7 | ||
|
|
02e3c2b768 | ||
|
|
925b57abcb | ||
|
|
20af62849e | ||
|
|
d6281dc72e | ||
|
|
2aaa8a844b | ||
|
|
c1d056b7e3 | ||
|
|
f13e9d840d | ||
|
|
498889f094 | ||
|
|
0ac3973352 | ||
|
|
54b66df732 | ||
|
|
6bcc0a6887 | ||
|
|
112ff19582 | ||
|
|
d3cb07f256 | ||
|
|
5aa81f9487 | ||
|
|
d0f4238163 | ||
|
|
41393b1f83 | ||
|
|
a7a0d85527 | ||
|
|
9f83a91baf | ||
|
|
5186797a2f | ||
|
|
4012a60bd0 | ||
|
|
d79125dd9b | ||
|
|
3ac602a366 | ||
|
|
f96a37a4ed | ||
|
|
c469ef9337 | ||
|
|
6bb9df9dbb | ||
|
|
bd59f50d49 | ||
|
|
2c554a0cc3 | ||
|
|
b775368d85 | ||
|
|
b755ea39a3 | ||
|
|
5393381863 | ||
|
|
3a30b97774 | ||
|
|
57269e281e | ||
|
|
976c4255e2 | ||
|
|
a1466e3a6e | ||
|
|
db1ee1dfea | ||
|
|
79c0b81b7e | ||
|
|
2eb460d74a | ||
|
|
cf8ba329c7 | ||
|
|
8105616931 | ||
|
|
4795e66fbd | ||
|
|
82771ebdd2 | ||
|
|
78eeb03c43 | ||
|
|
62b12c9587 | ||
|
|
b0f4154455 | ||
|
|
a914ed6b56 | ||
|
|
aaff3a32d5 | ||
|
|
d92f818086 | ||
|
|
9bcfcbf0d4 | ||
|
|
beade650c4 | ||
|
|
96c0db1b87 | ||
|
|
bf064424c2 | ||
|
|
12ce5b43fb | ||
|
|
830b98da64 | ||
|
|
0875ba0f57 | ||
|
|
77133f1c3c | ||
|
|
fc64e9228d | ||
|
|
a9248d78d0 | ||
|
|
a27af7f6f5 | ||
|
|
f296e727a7 | ||
|
|
b06f731410 | ||
|
|
1e9fb40156 | ||
|
|
00d2f8ae32 | ||
|
|
3633c97fc0 | ||
|
|
383421ee2f | ||
|
|
a6a07b7df5 | ||
|
|
cc3fd77982 | ||
|
|
8ac93babb5 | ||
|
|
fa03006830 | ||
|
|
ca9dddc8ee | ||
|
|
c5989637cf | ||
|
|
7fee43bc26 | ||
|
|
54debce9ed | ||
|
|
4ca9cb597f | ||
|
|
e1cf800c5c | ||
|
|
80c3d60fbd | ||
|
|
c54f402150 | ||
|
|
b6891d06c6 | ||
|
|
469dfe0fb3 | ||
|
|
d732c18f74 | ||
|
|
819b6d6704 | ||
|
|
252de71a38 | ||
|
|
a58cd20438 | ||
|
|
d014918119 | ||
|
|
d8b7450f9c | ||
|
|
e5c8922760 | ||
|
|
c937af1584 | ||
|
|
5af61ef057 | ||
|
|
548187ce22 | ||
|
|
90801b954e | ||
|
|
cfc29f0463 | ||
|
|
1be4b9a631 | ||
|
|
dfcb3d1013 | ||
|
|
f0e4d6b364 | ||
|
|
7084be96ff | ||
|
|
9dcedec746 | ||
|
|
cb83eeb13e | ||
|
|
118e58f9a0 | ||
|
|
8574dcc05b | ||
|
|
a7608944ae | ||
|
|
cfada9b6dd | ||
|
|
dc8def7d69 | ||
|
|
1c78c1b98a | ||
|
|
d0f9d47fac | ||
|
|
7ec0deeadd | ||
|
|
4b19ca268b | ||
|
|
4acd90b199 | ||
|
|
02ef365987 | ||
|
|
751ee7c769 | ||
|
|
32b2240884 | ||
|
|
51900de33a | ||
|
|
9ed37ccc93 | ||
|
|
8cff2b0f4c | ||
|
|
e9f7790965 | ||
|
|
03736e7784 | ||
|
|
11378180a8 | ||
|
|
ae8ec3df2b | ||
|
|
660352fba2 | ||
|
|
ebb5955b43 | ||
|
|
f691ab2796 | ||
|
|
2b8eaf1fed | ||
|
|
f7570a35d2 | ||
|
|
08b8138748 | ||
|
|
f84984becd | ||
|
|
258cad74d6 | ||
|
|
c4c30cede4 | ||
|
|
727ece434e | ||
|
|
8d29344af5 | ||
|
|
96d24307b3 | ||
|
|
f229f6eba9 | ||
|
|
9ee16c502a | ||
|
|
dcd5be6723 | ||
|
|
d07ee9a155 | ||
|
|
4199058437 | ||
|
|
87d2b12ac3 | ||
|
|
faa1b3698a | ||
|
|
07e8192b12 | ||
|
|
0046f50d97 | ||
|
|
1bd3f6bbc8 | ||
|
|
a827c71b9c | ||
|
|
d5ab87825a | ||
|
|
f611af3d4d | ||
|
|
7c2f715e72 | ||
|
|
c86a4169b9 | ||
|
|
d1566e5553 | ||
|
|
50f3254028 | ||
|
|
b52f8556ca | ||
|
|
ff68980619 | ||
|
|
7ced848feb | ||
|
|
2d43e96247 | ||
|
|
b562c6d6a5 | ||
|
|
f3091094ec | ||
|
|
27e89becee | ||
|
|
56b8e290a4 | ||
|
|
692683c79a | ||
|
|
ab3e7ac98f | ||
|
|
d4f669f629 | ||
|
|
a811bacaf3 | ||
|
|
e9ac5d1a59 | ||
|
|
cbe50f5c2f | ||
|
|
be21b256b8 | ||
|
|
455f06e3cd | ||
|
|
3205700a7a | ||
|
|
513a04d71b | ||
|
|
ffbab127e3 | ||
|
|
eba128111b | ||
|
|
608b80ee41 | ||
|
|
fd66ebc158 | ||
|
|
a320b422d8 | ||
|
|
2faac6ccf5 | ||
|
|
fb88af7c1c | ||
|
|
b7e306d3c1 | ||
|
|
e20e17c77e | ||
|
|
3970778f6a | ||
|
|
dbeeca2e65 | ||
|
|
7022049391 | ||
|
|
0b8b942c5d | ||
|
|
01840bc18f | ||
|
|
609a7dd2ea | ||
|
|
f5bc91f69d | ||
|
|
1aa7ff44dc | ||
|
|
162c845fa1 | ||
|
|
2986f97a1b | ||
|
|
1362feeef6 | ||
|
|
be4eb84ae9 | ||
|
|
286dc161a8 | ||
|
|
984bdeb37e | ||
|
|
43e74235cf | ||
|
|
c846db2af6 | ||
|
|
b0af2848c3 | ||
|
|
522ad9a508 | ||
|
|
3cbf46c0c3 | ||
|
|
cc83bfb7f1 | ||
|
|
582ba3b810 | ||
|
|
9b2d6c89ac | ||
|
|
a5e42e8d29 | ||
|
|
e4cd20aa4b | ||
|
|
25e8b03a22 | ||
|
|
28d2c7982a | ||
|
|
6c37352e6c | ||
|
|
67c37d0a9c | ||
|
|
94f996ae8a | ||
|
|
57654fd2aa | ||
|
|
3275939438 | ||
|
|
f3e353a0a6 | ||
|
|
e1a42b815c | ||
|
|
a66a9df95f | ||
|
|
f4d64fbf64 | ||
|
|
f72a467468 | ||
|
|
3cbb9a90e5 | ||
|
|
8da02d7f38 | ||
|
|
29e9696ff4 | ||
|
|
1b797c97a5 | ||
|
|
194d8b6c36 | ||
|
|
b527e56e00 | ||
|
|
e1b0884bab |
7
.github/actionlint.yaml
vendored
Normal file
7
.github/actionlint.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
self-hosted-runner:
|
||||
labels:
|
||||
- depot-ubuntu-latest
|
||||
- depot-ubuntu-latest-2
|
||||
- depot-ubuntu-latest-4
|
||||
- depot-ubuntu-latest-8
|
||||
- depot-ubuntu-latest-16
|
||||
9
.github/assets/hive/build_simulators.sh
vendored
9
.github/assets/hive/build_simulators.sh
vendored
@@ -11,14 +11,17 @@ go build .
|
||||
|
||||
# Run each hive command in the background for each simulator and wait
|
||||
echo "Building images"
|
||||
# TODO: test code has been moved from https://github.com/ethereum/execution-spec-tests to https://github.com/ethereum/execution-specs we need to pin eels branch with `--sim.buildarg branch=<release-branch-name>` once we have the fusaka release tagged on the new repo
|
||||
./hive -client reth --sim "ethereum/eels" --sim.buildarg fixtures=https://github.com/ethereum/execution-spec-tests/releases/download/v5.3.0/fixtures_develop.tar.gz -sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "ethereum/eels" \
|
||||
--sim.buildarg fixtures=https://github.com/ethereum/execution-spec-tests/releases/download/bal@v1.8.0/fixtures_bal.tar.gz \
|
||||
--sim.buildarg branch=eips/amsterdam/eip-7928 \
|
||||
--sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "ethereum/engine" -sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "devp2p" -sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "ethereum/rpc-compat" -sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "smoke/genesis" -sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "smoke/network" -sim.timelimit 1s || true &
|
||||
./hive -client reth --sim "ethereum/sync" -sim.timelimit 1s || true &
|
||||
|
||||
wait
|
||||
|
||||
# Run docker save in parallel, wait and exit on error
|
||||
@@ -37,7 +40,7 @@ for pid in "${saving_pids[@]}"; do
|
||||
wait "$pid" || exit
|
||||
done
|
||||
|
||||
# Make sure we don't rebuild images on the CI jobs
|
||||
# Make sure we don't rebuild images on the CI jobs
|
||||
git apply ../.github/assets/hive/no_sim_build.diff
|
||||
go build .
|
||||
mv ./hive ../hive_assets/
|
||||
|
||||
2
.github/assets/hive/load_images.sh
vendored
2
.github/assets/hive/load_images.sh
vendored
@@ -24,4 +24,4 @@ done
|
||||
|
||||
wait
|
||||
|
||||
docker image ls -a
|
||||
docker image ls -a
|
||||
7
.github/workflows/bench.yml
vendored
7
.github/workflows/bench.yml
vendored
@@ -3,9 +3,9 @@
|
||||
on:
|
||||
pull_request:
|
||||
# TODO: Disabled temporarily for https://github.com/CodSpeedHQ/runner/issues/55
|
||||
# merge_group:
|
||||
# merge_group :
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -15,8 +15,7 @@ env:
|
||||
name: bench
|
||||
jobs:
|
||||
codspeed:
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
|
||||
4
.github/workflows/book.yml
vendored
4
.github/workflows/book.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -69,4 +69,4 @@ jobs:
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
uses: actions/deploy-pages@v4
|
||||
5
.github/workflows/compact.yml
vendored
5
.github/workflows/compact.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -17,8 +17,7 @@ env:
|
||||
name: compact-codec
|
||||
jobs:
|
||||
compact-codec:
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
strategy:
|
||||
matrix:
|
||||
bin:
|
||||
|
||||
6
.github/workflows/e2e.yml
vendored
6
.github/workflows/e2e.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -19,8 +19,7 @@ concurrency:
|
||||
jobs:
|
||||
test:
|
||||
name: e2e-testsuite
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
timeout-minutes: 90
|
||||
@@ -43,4 +42,3 @@ jobs:
|
||||
--exclude 'op-reth' \
|
||||
--exclude 'reth' \
|
||||
-E 'binary(e2e_testsuite)'
|
||||
|
||||
|
||||
64
.github/workflows/hive.yml
vendored
64
.github/workflows/hive.yml
vendored
@@ -6,7 +6,9 @@ on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 */6 * * *"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
@@ -24,14 +26,14 @@ jobs:
|
||||
prepare-hive:
|
||||
if: github.repository == 'paradigmxyz/reth'
|
||||
timeout-minutes: 45
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Checkout hive tests
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: ethereum/hive
|
||||
ref: master
|
||||
path: hivetests
|
||||
|
||||
- name: Get hive commit hash
|
||||
@@ -68,7 +70,7 @@ jobs:
|
||||
chmod +x hive
|
||||
|
||||
- name: Upload hive assets
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hive_assets
|
||||
path: ./hive_assets
|
||||
@@ -116,27 +118,29 @@ jobs:
|
||||
# eth_ rpc methods
|
||||
- sim: ethereum/rpc-compat
|
||||
include:
|
||||
- eth_blockNumber
|
||||
# - eth_blockNumber
|
||||
- eth_call
|
||||
- eth_chainId
|
||||
- eth_createAccessList
|
||||
- eth_estimateGas
|
||||
- eth_feeHistory
|
||||
- eth_getBalance
|
||||
- eth_getBlockBy
|
||||
- eth_getBlockTransactionCountBy
|
||||
- eth_getCode
|
||||
- eth_getProof
|
||||
- eth_getStorage
|
||||
- eth_getTransactionBy
|
||||
- eth_getTransactionCount
|
||||
- eth_getTransactionReceipt
|
||||
- eth_sendRawTransaction
|
||||
- eth_syncing
|
||||
# debug_ rpc methods
|
||||
- debug_
|
||||
# - eth_chainId
|
||||
# - eth_createAccessList
|
||||
# - eth_estimateGas
|
||||
# - eth_feeHistory
|
||||
# - eth_getBalance
|
||||
# - eth_getBlockBy
|
||||
# - eth_getBlockTransactionCountBy
|
||||
# - eth_getCode
|
||||
# - eth_getProof
|
||||
# - eth_getStorage
|
||||
# - eth_getTransactionBy
|
||||
# - eth_getTransactionCount
|
||||
# - eth_getTransactionReceipt
|
||||
# - eth_sendRawTransaction
|
||||
# - eth_syncing
|
||||
# # debug_ rpc methods
|
||||
# - debug_
|
||||
|
||||
# consume-engine
|
||||
- sim: ethereum/eels/consume-engine
|
||||
limit: .*tests/amsterdam.*
|
||||
- sim: ethereum/eels/consume-engine
|
||||
limit: .*tests/osaka.*
|
||||
- sim: ethereum/eels/consume-engine
|
||||
@@ -153,10 +157,10 @@ jobs:
|
||||
limit: .*tests/homestead.*
|
||||
- sim: ethereum/eels/consume-engine
|
||||
limit: .*tests/frontier.*
|
||||
- sim: ethereum/eels/consume-engine
|
||||
limit: .*tests/paris.*
|
||||
|
||||
# consume-rlp
|
||||
- sim: ethereum/eels/consume-rlp
|
||||
limit: .*tests/amsterdam.*
|
||||
- sim: ethereum/eels/consume-rlp
|
||||
limit: .*tests/osaka.*
|
||||
- sim: ethereum/eels/consume-rlp
|
||||
@@ -173,14 +177,11 @@ jobs:
|
||||
limit: .*tests/homestead.*
|
||||
- sim: ethereum/eels/consume-rlp
|
||||
limit: .*tests/frontier.*
|
||||
- sim: ethereum/eels/consume-rlp
|
||||
limit: .*tests/paris.*
|
||||
needs:
|
||||
- prepare-reth
|
||||
- prepare-hive
|
||||
name: run ${{ matrix.scenario.sim }}${{ matrix.scenario.limit && format(' - {0}', matrix.scenario.limit) }}
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
@@ -189,13 +190,13 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download hive assets
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: hive_assets
|
||||
path: /tmp
|
||||
|
||||
- name: Download reth image
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: artifacts
|
||||
path: /tmp
|
||||
@@ -247,8 +248,7 @@ jobs:
|
||||
notify-on-error:
|
||||
needs: test
|
||||
if: failure()
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
steps:
|
||||
- name: Slack Webhook Action
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
5
.github/workflows/integration.yml
vendored
5
.github/workflows/integration.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
schedule:
|
||||
# Run once a day at 3:00 UTC
|
||||
- cron: "0 3 * * *"
|
||||
@@ -23,8 +23,7 @@ jobs:
|
||||
test:
|
||||
name: test / ${{ matrix.network }}
|
||||
if: github.event_name != 'schedule'
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
strategy:
|
||||
|
||||
9
.github/workflows/kurtosis-op.yml
vendored
9
.github/workflows/kurtosis-op.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
- "*"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -32,8 +32,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
name: run kurtosis
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
needs:
|
||||
- prepare-reth
|
||||
steps:
|
||||
@@ -83,12 +82,10 @@ jobs:
|
||||
kurtosis service logs -a op-devnet op-cl-2151908-2-op-node-op-reth-op-kurtosis
|
||||
exit 1
|
||||
|
||||
|
||||
notify-on-error:
|
||||
needs: test
|
||||
if: failure()
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
steps:
|
||||
- name: Slack Webhook Action
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
10
.github/workflows/kurtosis.yml
vendored
10
.github/workflows/kurtosis.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
- "*"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -30,8 +30,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
name: run kurtosis
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
needs:
|
||||
- prepare-reth
|
||||
steps:
|
||||
@@ -54,13 +53,12 @@ jobs:
|
||||
- name: Run kurtosis
|
||||
uses: ethpandaops/kurtosis-assertoor-github-action@v1
|
||||
with:
|
||||
ethereum_package_args: '.github/assets/kurtosis_network_params.yaml'
|
||||
ethereum_package_args: ".github/assets/kurtosis_network_params.yaml"
|
||||
|
||||
notify-on-error:
|
||||
needs: test
|
||||
if: failure()
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
steps:
|
||||
- name: Slack Webhook Action
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
42
.github/workflows/lint.yml
vendored
42
.github/workflows/lint.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -12,7 +12,7 @@ env:
|
||||
jobs:
|
||||
clippy-binaries:
|
||||
name: clippy binaries / ${{ matrix.type }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
clippy:
|
||||
name: clippy
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
RUSTFLAGS: -D warnings
|
||||
|
||||
wasm:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
.github/assets/check_wasm.sh
|
||||
|
||||
riscv:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
|
||||
crate-checks:
|
||||
name: crate-checks (${{ matrix.partition }}/${{ matrix.total_partitions }})
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
strategy:
|
||||
matrix:
|
||||
partition: [1, 2]
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
|
||||
msrv:
|
||||
name: MSRV
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
|
||||
docs:
|
||||
name: docs
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
|
||||
fmt:
|
||||
name: fmt
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
|
||||
udeps:
|
||||
name: udeps
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -177,7 +177,7 @@ jobs:
|
||||
|
||||
book:
|
||||
name: book
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -232,10 +232,14 @@ jobs:
|
||||
- name: Ensure no arbitrary or proptest dependency on default build
|
||||
run: cargo tree --package reth -e=features,no-dev | grep -Eq "arbitrary|proptest" && exit 1 || exit 0
|
||||
|
||||
# Checks that selected rates can compile with power set of features
|
||||
# Checks that selected crates can compile with power set of features
|
||||
features:
|
||||
name: features
|
||||
runs-on: ubuntu-latest
|
||||
name: features (${{ matrix.partition }}/${{ matrix.total_partitions }})
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
strategy:
|
||||
matrix:
|
||||
partition: [1, 2]
|
||||
total_partitions: [2]
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -246,13 +250,19 @@ jobs:
|
||||
cache-on-failure: true
|
||||
- name: cargo install cargo-hack
|
||||
uses: taiki-e/install-action@cargo-hack
|
||||
- run: make check-features
|
||||
- run: |
|
||||
cargo hack check \
|
||||
--package reth-codecs \
|
||||
--package reth-primitives-traits \
|
||||
--package reth-primitives \
|
||||
--feature-powerset \
|
||||
--partition ${{ matrix.partition }}/${{ matrix.total_partitions }}
|
||||
env:
|
||||
RUSTFLAGS: -D warnings
|
||||
|
||||
# Check crates correctly propagate features
|
||||
feature-propagation:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
3
.github/workflows/prepare-reth.yml
vendored
3
.github/workflows/prepare-reth.yml
vendored
@@ -26,8 +26,7 @@ jobs:
|
||||
prepare-reth:
|
||||
if: github.repository == 'paradigmxyz/reth'
|
||||
timeout-minutes: 45
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: mkdir artifacts
|
||||
|
||||
2
.github/workflows/release-dist.yml
vendored
2
.github/workflows/release-dist.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update Homebrew formula
|
||||
uses: dawidd6/action-homebrew-bump-formula@v6
|
||||
uses: dawidd6/action-homebrew-bump-formula@v7
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW }}
|
||||
no_fork: true
|
||||
|
||||
5
.github/workflows/stage.yml
vendored
5
.github/workflows/stage.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -22,8 +22,7 @@ jobs:
|
||||
name: stage-run-test
|
||||
# Only run stage commands test in merge groups
|
||||
if: github.event_name == 'merge_group'
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
env:
|
||||
RUST_LOG: info,sync=error
|
||||
RUST_BACKTRACE: 1
|
||||
|
||||
5
.github/workflows/sync-era.yml
vendored
5
.github/workflows/sync-era.yml
vendored
@@ -17,8 +17,7 @@ concurrency:
|
||||
jobs:
|
||||
sync:
|
||||
name: sync (${{ matrix.chain.bin }})
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
env:
|
||||
RUST_LOG: info,sync=error
|
||||
RUST_BACKTRACE: 1
|
||||
@@ -64,4 +63,4 @@ jobs:
|
||||
${{ matrix.chain.bin }} stage unwind num-blocks 100 --chain ${{ matrix.chain.chain }}
|
||||
- name: Run stage unwind to block hash
|
||||
run: |
|
||||
${{ matrix.chain.bin }} stage unwind to-block ${{ matrix.chain.unwind-target }} --chain ${{ matrix.chain.chain }}
|
||||
${{ matrix.chain.bin }} stage unwind to-block ${{ matrix.chain.unwind-target }} --chain ${{ matrix.chain.chain }}
|
||||
|
||||
5
.github/workflows/sync.yml
vendored
5
.github/workflows/sync.yml
vendored
@@ -17,8 +17,7 @@ concurrency:
|
||||
jobs:
|
||||
sync:
|
||||
name: sync (${{ matrix.chain.bin }})
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest
|
||||
env:
|
||||
RUST_LOG: info,sync=error
|
||||
RUST_BACKTRACE: 1
|
||||
@@ -63,4 +62,4 @@ jobs:
|
||||
${{ matrix.chain.bin }} stage unwind num-blocks 100 --chain ${{ matrix.chain.chain }}
|
||||
- name: Run stage unwind to block hash
|
||||
run: |
|
||||
${{ matrix.chain.bin }} stage unwind to-block ${{ matrix.chain.unwind-target }} --chain ${{ matrix.chain.chain }}
|
||||
${{ matrix.chain.bin }} stage unwind to-block ${{ matrix.chain.unwind-target }} --chain ${{ matrix.chain.chain }}
|
||||
|
||||
12
.github/workflows/unit.yml
vendored
12
.github/workflows/unit.yml
vendored
@@ -4,9 +4,10 @@ name: unit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -19,8 +20,7 @@ concurrency:
|
||||
jobs:
|
||||
test:
|
||||
name: test / ${{ matrix.type }} (${{ matrix.partition }}/${{ matrix.total_partitions }})
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
strategy:
|
||||
@@ -65,8 +65,7 @@ jobs:
|
||||
|
||||
state:
|
||||
name: Ethereum state tests
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest-4
|
||||
env:
|
||||
RUST_LOG: info,sync=error
|
||||
RUST_BACKTRACE: 1
|
||||
@@ -100,8 +99,7 @@ jobs:
|
||||
|
||||
doc:
|
||||
name: doc tests
|
||||
runs-on:
|
||||
group: Reth
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
timeout-minutes: 30
|
||||
|
||||
8
.github/workflows/windows.yml
vendored
8
.github/workflows/windows.yml
vendored
@@ -4,14 +4,14 @@ name: windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: ["**"]
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
check-reth:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
run: cargo check --target x86_64-pc-windows-gnu
|
||||
|
||||
check-op-reth:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: depot-ubuntu-latest-16
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
|
||||
328
Cargo.lock
generated
328
Cargo.lock
generated
@@ -97,9 +97,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "alloy-chains"
|
||||
version = "0.2.20"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bc32535569185cbcb6ad5fa64d989a47bccb9a08e27284b1f2a3ccf16e6d010"
|
||||
checksum = "35d744058a9daa51a8cf22a3009607498fcf82d3cf4c5444dd8056cdf651f471"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
@@ -112,9 +112,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-consensus"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6440213a22df93a87ed512d2f668e7dc1d62a05642d107f82d61edc9e12370"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-eips",
|
||||
"alloy-primitives",
|
||||
@@ -140,9 +139,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-consensus-any"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15d0bea09287942405c4f9d2a4f22d1e07611c2dbd9d5bf94b75366340f9e6e0"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
@@ -155,9 +153,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-contract"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d69af404f1d00ddb42f2419788fa87746a4cd13bab271916d7726fda6c792d94"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-dyn-abi",
|
||||
@@ -238,15 +235,27 @@ dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-eip7928"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/alloy-rs/eips.git#2197bdb48ae842b00f43b2cb29d59f20b29ec419"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"arbitrary",
|
||||
"borsh",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-eips"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bd2c7ae05abcab4483ce821f12f285e01c0b33804e6883dd9ca1569a87ee2be"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-eip2124",
|
||||
"alloy-eip2930",
|
||||
"alloy-eip7702",
|
||||
"alloy-eip7928",
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"alloy-serde",
|
||||
@@ -267,8 +276,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "alloy-evm"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01be36ba6f5e6e62563b369e03ca529eac46aea50677f84655084b4750816574"
|
||||
source = "git+https://github.com/Rimeeeeee/evm?branch=new-approach4#2b07037ef61397244f23fa832aee8e593a840201"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
@@ -284,13 +292,13 @@ dependencies = [
|
||||
"op-revm",
|
||||
"revm",
|
||||
"thiserror 2.0.17",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-genesis"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc47eaae86488b07ea8e20236184944072a78784a1f4993f8ec17b3aa5d08c21"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-eips",
|
||||
"alloy-primitives",
|
||||
@@ -329,9 +337,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-json-rpc"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "003f46c54f22854a32b9cc7972660a476968008ad505427eabab49225309ec40"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-sol-types",
|
||||
@@ -344,9 +351,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-network"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f4029954d9406a40979f3a3b46950928a0fdcfe3ea8a9b0c17490d57e8aa0e3"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-consensus-any",
|
||||
@@ -370,9 +376,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-network-primitives"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7805124ad69e57bbae7731c9c344571700b2a18d351bda9e0eba521c991d1bcb"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
@@ -384,8 +389,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "alloy-op-evm"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "231262d7e06000f3fb642d32d38ca75e09e78e04977c10be0a07a5ee2c869cfd"
|
||||
source = "git+https://github.com/Rimeeeeee/evm?branch=new-approach4#2b07037ef61397244f23fa832aee8e593a840201"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
@@ -401,9 +405,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-op-hardforks"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ac97adaba4c26e17192d81f49186ac20c1e844e35a00e169c8d3d58bc84e6b"
|
||||
checksum = "f96fb2fce4024ada5b2c11d4076acf778a0d3e4f011c6dfd2ffce6d0fcf84ee9"
|
||||
dependencies = [
|
||||
"alloy-chains",
|
||||
"alloy-hardforks",
|
||||
@@ -420,6 +424,7 @@ checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28"
|
||||
dependencies = [
|
||||
"alloy-rlp",
|
||||
"arbitrary",
|
||||
"borsh",
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
"const-hex",
|
||||
@@ -444,9 +449,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-provider"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d369e12c92870d069e0c9dc5350377067af8a056e29e3badf8446099d7e00889"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-chains",
|
||||
"alloy-consensus",
|
||||
@@ -489,9 +493,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-pubsub"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f77d20cdbb68a614c7a86b3ffef607b37d087bb47a03c58f4c3f8f99bc3ace3b"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-json-rpc",
|
||||
"alloy-primitives",
|
||||
@@ -533,9 +536,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-client"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c89883fe6b7381744cbe80fef638ac488ead4f1956a4278956a1362c71cd2e"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-json-rpc",
|
||||
"alloy-primitives",
|
||||
@@ -559,9 +561,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64e279e6d40ee40fe8f76753b678d8d5d260cb276dc6c8a8026099b16d2b43f4"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rpc-types-engine",
|
||||
@@ -572,9 +573,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-admin"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bcf50ccb65d29b8599f8f5e23dcac685f1d79459654c830cba381345760e901"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-genesis",
|
||||
"alloy-primitives",
|
||||
@@ -584,9 +584,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-anvil"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e176c26fdd87893b6afeb5d92099d8f7e7a1fe11d6f4fe0883d6e33ac5f31ba"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rpc-types-eth",
|
||||
@@ -596,9 +595,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-any"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b43c1622aac2508d528743fd4cfdac1dea92d5a8fa894038488ff7edd0af0b32"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus-any",
|
||||
"alloy-rpc-types-eth",
|
||||
@@ -607,9 +605,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-beacon"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1786681640d4c60f22b6b8376b0f3fa200360bf1c3c2cb913e6c97f51928eb1b"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-eips",
|
||||
"alloy-primitives",
|
||||
@@ -627,9 +624,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-debug"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b2ca3a434a6d49910a7e8e51797eb25db42ef8a5578c52d877fcb26d0afe7bc"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"derive_more",
|
||||
@@ -639,9 +635,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-engine"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4c53a8b0905d931e7921774a1830609713bd3e8222347963172b03a3ecc68"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
@@ -660,9 +655,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-eth"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed5fafb741c19b3cca4cdd04fa215c89413491f9695a3e928dee2ae5657f607e"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-consensus-any",
|
||||
@@ -682,9 +676,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-mev"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49a97bfc6d9b411c85bb08e1174ddd3e5d61b10d3bd13f529d6609f733cb2f6f"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
@@ -697,9 +690,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-trace"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c55324323aa634b01bdecb2d47462a8dce05f5505b14a6e5db361eef16eda476"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rpc-types-eth",
|
||||
@@ -711,9 +703,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-rpc-types-txpool"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b1aa28effb6854be356ce92ed64cea3b323acd04c3f8bfb5126e2839698043"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rpc-types-eth",
|
||||
@@ -723,9 +714,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-serde"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6f180c399ca7c1e2fe17ea58343910cad0090878a696ff5a50241aee12fc529"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"arbitrary",
|
||||
@@ -735,9 +725,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-signer"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecc39ad2c0a3d2da8891f4081565780703a593f090f768f884049aa3aa929cbc"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"async-trait",
|
||||
@@ -750,9 +739,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-signer-local"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "930e17cb1e46446a193a593a3bfff8d0ecee4e510b802575ebe300ae2e43ef75"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-network",
|
||||
@@ -839,9 +827,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-transport"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cae82426d98f8bc18f53c5223862907cac30ab8fc5e4cd2bb50808e6d3ab43d8"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-json-rpc",
|
||||
"auto_impl",
|
||||
@@ -862,9 +849,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-transport-http"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90aa6825760905898c106aba9c804b131816a15041523e80b6d4fe7af6380ada"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-json-rpc",
|
||||
"alloy-transport",
|
||||
@@ -877,9 +863,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-transport-ipc"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ace83a4a6bb896e5894c3479042e6ba78aa5271dde599aa8c36a021d49cc8cc"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-json-rpc",
|
||||
"alloy-pubsub",
|
||||
@@ -897,9 +882,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-transport-ws"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86c9ab4c199e3a8f3520b60ba81aa67bb21fed9ed0d8304e0569094d0758a56f"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"alloy-pubsub",
|
||||
"alloy-transport",
|
||||
@@ -935,9 +919,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-tx-macros"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae109e33814b49fc0a62f2528993aa8a2dd346c26959b151f05441dc0b9da292"
|
||||
version = "1.1.3"
|
||||
source = "git+https://github.com/Soubhik-10/alloy?branch=bal#34c5b093a4a9e889634c1c20de5365bb6a7477ef"
|
||||
dependencies = [
|
||||
"darling 0.21.3",
|
||||
"proc-macro2",
|
||||
@@ -1369,9 +1352,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.34"
|
||||
version = "0.4.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e86f6d3dc9dc4352edeea6b8e499e13e3f5dc3b964d7ca5fd411415a3498473"
|
||||
checksum = "07a926debf178f2d355197f9caddb08e54a9329d44748034bba349c5848cb519"
|
||||
dependencies = [
|
||||
"compression-codecs",
|
||||
"compression-core",
|
||||
@@ -1529,9 +1512,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a"
|
||||
|
||||
[[package]]
|
||||
name = "bech32"
|
||||
@@ -1627,15 +1610,15 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin-io"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf"
|
||||
checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953"
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.14.0"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16"
|
||||
checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b"
|
||||
dependencies = [
|
||||
"bitcoin-io",
|
||||
"hex-conservative",
|
||||
@@ -2377,9 +2360,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compression-codecs"
|
||||
version = "0.4.33"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302266479cb963552d11bd042013a58ef1adc56768016c8b82b4199488f2d4ad"
|
||||
checksum = "34a3cbbb8b6eca96f3a5c4bf6938d5b27ced3675d69f95bb51948722870bc323"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"compression-core",
|
||||
@@ -2471,9 +2454,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.7.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7"
|
||||
checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
@@ -2978,22 +2961,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "2.0.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
|
||||
checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618"
|
||||
dependencies = [
|
||||
"derive_more-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more-impl"
|
||||
version = "2.0.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
|
||||
checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version 0.4.1",
|
||||
"syn 2.0.111",
|
||||
"unicode-xid",
|
||||
]
|
||||
@@ -3670,6 +3654,17 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-custom-rpc-middleware"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"jsonrpsee",
|
||||
"reth-ethereum",
|
||||
"tower",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-db-access"
|
||||
version = "0.0.0"
|
||||
@@ -4277,9 +4272,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "git2"
|
||||
version = "0.20.2"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110"
|
||||
checksum = "3e2b37e2f62729cdada11f0e6b3b6fe383c69c29fc619e391223e12856af308c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"libc",
|
||||
@@ -4704,9 +4699,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.18"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56"
|
||||
checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -5416,15 +5411,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.18.2+1.9.1"
|
||||
version = "0.18.3+1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c42fe03df2bd3c53a3a9c7317ad91d80c81cd1fb0caec8d7cc4cd2bfa10c222"
|
||||
checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -5450,9 +5445,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "libp2p-identity"
|
||||
version = "0.2.12"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3104e13b51e4711ff5738caa1fb54467c8604c2e94d607e27745bcf709068774"
|
||||
checksum = "f0c7892c221730ba55f7196e98b0b8ba5e04b4155651736036628e9f73ed6fc3"
|
||||
dependencies = [
|
||||
"asn1_der",
|
||||
"bs58",
|
||||
@@ -5569,9 +5564,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
@@ -5839,9 +5834,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@@ -6328,8 +6323,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "op-revm"
|
||||
version = "14.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1475a779c73999fc803778524042319691b31f3d6699d2b560c4ed8be1db802a"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"auto_impl",
|
||||
"revm",
|
||||
@@ -6792,7 +6786,7 @@ version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
||||
dependencies = [
|
||||
"toml_edit 0.23.7",
|
||||
"toml_edit 0.23.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7338,9 +7332,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.24"
|
||||
version = "0.12.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
|
||||
checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -7769,11 +7763,13 @@ dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"rand 0.9.2",
|
||||
"reth-chainspec",
|
||||
"reth-consensus",
|
||||
"reth-ethereum-primitives",
|
||||
"reth-primitives-traits",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8281,6 +8277,7 @@ dependencies = [
|
||||
"reth-primitives-traits",
|
||||
"reth-revm",
|
||||
"reth-storage-api",
|
||||
"revm",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
@@ -8496,6 +8493,7 @@ dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-eips",
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"reth-chainspec",
|
||||
"reth-consensus",
|
||||
"reth-consensus-common",
|
||||
@@ -8634,6 +8632,7 @@ dependencies = [
|
||||
"alloy-evm",
|
||||
"alloy-genesis",
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"alloy-rpc-types-engine",
|
||||
"derive_more",
|
||||
"parking_lot",
|
||||
@@ -11036,8 +11035,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm"
|
||||
version = "33.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c85ed0028f043f87b3c88d4a4cb6f0a76440085523b6a8afe5ff003cf418054"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"revm-bytecode",
|
||||
"revm-context",
|
||||
@@ -11055,8 +11053,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-bytecode"
|
||||
version = "7.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2c6b5e6e8dd1e28a4a60e5f46615d4ef0809111c9e63208e55b5c7058200fb0"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"phf",
|
||||
@@ -11067,8 +11064,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-context"
|
||||
version = "12.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f038f0c9c723393ac897a5df9140b21cfa98f5753a2cb7d0f28fa430c4118abf"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"cfg-if",
|
||||
@@ -11084,8 +11080,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-context-interface"
|
||||
version = "13.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "431c9a14e4ef1be41ae503708fd02d974f80ef1f2b6b23b5e402e8d854d1b225"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"alloy-eip2930",
|
||||
"alloy-eip7702",
|
||||
@@ -11100,8 +11095,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-database"
|
||||
version = "9.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "980d8d6bba78c5dd35b83abbb6585b0b902eb25ea4448ed7bfba6283b0337191"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"alloy-eips",
|
||||
"revm-bytecode",
|
||||
@@ -11114,21 +11108,20 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-database-interface"
|
||||
version = "8.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cce03e3780287b07abe58faf4a7f5d8be7e81321f93ccf3343c8f7755602bae"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"auto_impl",
|
||||
"either",
|
||||
"revm-primitives",
|
||||
"revm-state",
|
||||
"serde",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revm-handler"
|
||||
version = "14.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d44f8f6dbeec3fecf9fe55f78ef0a758bdd92ea46cd4f1ca6e2a946b32c367f3"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"auto_impl",
|
||||
"derive-where",
|
||||
@@ -11146,8 +11139,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-inspector"
|
||||
version = "14.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5617e49216ce1ca6c8826bcead0386bc84f49359ef67cde6d189961735659f93"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"auto_impl",
|
||||
"either",
|
||||
@@ -11184,8 +11176,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-interpreter"
|
||||
version = "31.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26ec36405f7477b9dccdc6caa3be19adf5662a7a0dffa6270cdb13a090c077e5"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"revm-bytecode",
|
||||
"revm-context-interface",
|
||||
@@ -11197,8 +11188,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-precompile"
|
||||
version = "31.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a62958af953cc4043e93b5be9b8497df84cc3bd612b865c49a7a7dfa26a84e2"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"ark-bls12-381",
|
||||
"ark-bn254",
|
||||
@@ -11222,8 +11212,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-primitives"
|
||||
version = "21.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29e161db429d465c09ba9cbff0df49e31049fe6b549e28eb0b7bd642fcbd4412"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"num_enum",
|
||||
@@ -11234,9 +11223,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "revm-state"
|
||||
version = "8.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8be953b7e374dbdea0773cf360debed8df394ea8d82a8b240a6b5da37592fc"
|
||||
source = "git+https://github.com/Rimeeeeee/revm?branch=rakita%2Fbal#d86e05673463cb83e0fb0c69e39b3119ba5916bd"
|
||||
dependencies = [
|
||||
"alloy-eip7928",
|
||||
"bitflags 2.10.0",
|
||||
"revm-bytecode",
|
||||
"revm-primitives",
|
||||
@@ -11411,6 +11400,7 @@ dependencies = [
|
||||
"ark-ff 0.3.0",
|
||||
"ark-ff 0.4.2",
|
||||
"ark-ff 0.5.0",
|
||||
"borsh",
|
||||
"bytes",
|
||||
"fastrlp 0.3.1",
|
||||
"fastrlp 0.4.0",
|
||||
@@ -12047,9 +12037,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
@@ -12787,9 +12777,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.23.7"
|
||||
version = "0.23.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d"
|
||||
checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832"
|
||||
dependencies = [
|
||||
"indexmap 2.12.1",
|
||||
"toml_datetime 0.7.3",
|
||||
@@ -12871,9 +12861,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.7"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"
|
||||
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"base64 0.22.1",
|
||||
@@ -13303,9 +13293,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.1"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||
checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"js-sys",
|
||||
@@ -14282,18 +14272,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.30"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.30"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
149
Cargo.toml
149
Cargo.toml
@@ -153,6 +153,7 @@ members = [
|
||||
"examples/custom-node-components/",
|
||||
"examples/custom-payload-builder/",
|
||||
"examples/custom-rlpx-subprotocol",
|
||||
"examples/custom-rpc-middleware",
|
||||
"examples/custom-node",
|
||||
"examples/db-access",
|
||||
"examples/engine-api-access",
|
||||
@@ -474,7 +475,7 @@ reth-ress-provider = { path = "crates/ress/provider" }
|
||||
# revm
|
||||
revm = { version = "33.1.0", default-features = false }
|
||||
revm-bytecode = { version = "7.1.1", default-features = false }
|
||||
revm-database = { version = "9.0.5", default-features = false }
|
||||
revm-database = { version = "9.0.6", default-features = false }
|
||||
revm-state = { version = "8.1.1", default-features = false }
|
||||
revm-primitives = { version = "21.0.2", default-features = false }
|
||||
revm-interpreter = { version = "31.1.0", default-features = false }
|
||||
@@ -483,11 +484,12 @@ op-revm = { version = "14.1.0", default-features = false }
|
||||
revm-inspectors = "0.33.1"
|
||||
|
||||
# eth
|
||||
|
||||
alloy-primitives = { version = "1.4.1", default-features = false, features = ["map-foldhash"] }
|
||||
alloy-chains = { version = "0.2.5", default-features = false }
|
||||
alloy-evm = { version = "0.24.2", default-features = false }
|
||||
alloy-dyn-abi = "1.4.1"
|
||||
alloy-eip2124 = { version = "0.2.0", default-features = false }
|
||||
alloy-evm = { version = "0.24.1", default-features = false }
|
||||
alloy-primitives = { version = "1.4.1", default-features = false, features = ["map-foldhash"] }
|
||||
alloy-rlp = { version = "0.3.10", default-features = false, features = ["core-net"] }
|
||||
alloy-sol-macro = "1.4.1"
|
||||
alloy-sol-types = { version = "1.4.1", default-features = false }
|
||||
@@ -495,42 +497,42 @@ alloy-trie = { version = "0.9.1", default-features = false }
|
||||
|
||||
alloy-hardforks = "0.4.5"
|
||||
|
||||
alloy-consensus = { version = "1.1.2", default-features = false }
|
||||
alloy-contract = { version = "1.1.2", default-features = false }
|
||||
alloy-eips = { version = "1.1.2", default-features = false }
|
||||
alloy-genesis = { version = "1.1.2", default-features = false }
|
||||
alloy-json-rpc = { version = "1.1.2", default-features = false }
|
||||
alloy-network = { version = "1.1.2", default-features = false }
|
||||
alloy-network-primitives = { version = "1.1.2", default-features = false }
|
||||
alloy-provider = { version = "1.1.2", features = ["reqwest", "debug-api"], default-features = false }
|
||||
alloy-pubsub = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-client = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types = { version = "1.1.2", features = ["eth"], default-features = false }
|
||||
alloy-rpc-types-admin = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-anvil = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-beacon = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-debug = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-engine = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-eth = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-mev = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-trace = { version = "1.1.2", default-features = false }
|
||||
alloy-rpc-types-txpool = { version = "1.1.2", default-features = false }
|
||||
alloy-serde = { version = "1.1.2", default-features = false }
|
||||
alloy-signer = { version = "1.1.2", default-features = false }
|
||||
alloy-signer-local = { version = "1.1.2", default-features = false }
|
||||
alloy-transport = { version = "1.1.2" }
|
||||
alloy-transport-http = { version = "1.1.2", features = ["reqwest-rustls-tls"], default-features = false }
|
||||
alloy-transport-ipc = { version = "1.1.2", default-features = false }
|
||||
alloy-transport-ws = { version = "1.1.2", default-features = false }
|
||||
alloy-consensus = { version = "1.1.3", default-features = false }
|
||||
alloy-contract = { version = "1.1.3", default-features = false }
|
||||
alloy-eips = { version = "1.1.3", default-features = false }
|
||||
alloy-genesis = { version = "1.1.3", default-features = false }
|
||||
alloy-json-rpc = { version = "1.1.3", default-features = false }
|
||||
alloy-network = { version = "1.1.3", default-features = false }
|
||||
alloy-network-primitives = { version = "1.1.3", default-features = false }
|
||||
alloy-provider = { version = "1.1.3", features = ["reqwest", "debug-api"], default-features = false }
|
||||
alloy-pubsub = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-client = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types = { version = "1.1.3", features = ["eth"], default-features = false }
|
||||
alloy-rpc-types-admin = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-anvil = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-beacon = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-debug = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-engine = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-eth = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-mev = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-trace = { version = "1.1.3", default-features = false }
|
||||
alloy-rpc-types-txpool = { version = "1.1.3", default-features = false }
|
||||
alloy-serde = { version = "1.1.3", default-features = false }
|
||||
alloy-signer = { version = "1.1.3", default-features = false }
|
||||
alloy-signer-local = { version = "1.1.3", default-features = false }
|
||||
alloy-transport = { version = "1.1.3" }
|
||||
alloy-transport-http = { version = "1.1.3", features = ["reqwest-rustls-tls"], default-features = false }
|
||||
alloy-transport-ipc = { version = "1.1.3", default-features = false }
|
||||
alloy-transport-ws = { version = "1.1.3", default-features = false }
|
||||
|
||||
# op
|
||||
alloy-op-evm = { version = "0.24.1", default-features = false }
|
||||
alloy-op-hardforks = "0.4.4"
|
||||
op-alloy-rpc-types = { version = "0.22.4", default-features = false }
|
||||
op-alloy-rpc-types-engine = { version = "0.22.4", default-features = false }
|
||||
op-alloy-network = { version = "0.22.4", default-features = false }
|
||||
op-alloy-consensus = { version = "0.22.4", default-features = false }
|
||||
op-alloy-rpc-jsonrpsee = { version = "0.22.4", default-features = false }
|
||||
alloy-op-evm = { version = "0.24.2", default-features = false }
|
||||
alloy-op-hardforks = "0.4.3"
|
||||
op-alloy-rpc-types = { version = "0.22.0", default-features = false }
|
||||
op-alloy-rpc-types-engine = { version = "0.22.0", default-features = false }
|
||||
op-alloy-network = { version = "0.22.0", default-features = false }
|
||||
op-alloy-consensus = { version = "0.22.0", default-features = false }
|
||||
op-alloy-rpc-jsonrpsee = { version = "0.22.0", default-features = false }
|
||||
op-alloy-flz = { version = "0.13.1", default-features = false }
|
||||
|
||||
# misc
|
||||
@@ -734,39 +736,40 @@ vergen = "9.0.4"
|
||||
visibility = "0.1.1"
|
||||
walkdir = "2.3.3"
|
||||
vergen-git2 = "1.0.5"
|
||||
|
||||
# networking
|
||||
ipnet = "2.11"
|
||||
|
||||
# [patch.crates-io]
|
||||
# alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-contract = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-genesis = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-network-primitives = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-pubsub = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-admin = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-anvil = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-beacon = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-debug = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-engine = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-eth = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-mev = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-trace = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-rpc-types-txpool = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-serde = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-signer = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-signer-local = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
# alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "3049f232fbb44d1909883e154eb38ec5962f53a3" }
|
||||
[patch.crates-io]
|
||||
alloy-consensus = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-contract = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-eips = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-genesis = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-json-rpc = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-network = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-network-primitives = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-provider = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-pubsub = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-client = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-admin = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-anvil = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-beacon = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-debug = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-engine = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-eth = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-mev = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-trace = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-rpc-types-txpool = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-serde = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-signer = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-signer-local = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-transport = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-transport-http = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-transport-ipc = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
alloy-transport-ws = { git = "https://github.com/Soubhik-10/alloy", branch = "bal" }
|
||||
# alloy-hardforks = { git = "https://github.com/Rimeeeeee/hardforks", branch = "amsterdam" }
|
||||
|
||||
# alloy-op-hardforks = { git = "https://github.com/Rimeeeeee/hardforks", branch = "amsterdam" }
|
||||
# op-alloy-consensus = { git = "https://github.com/alloy-rs/op-alloy", rev = "a79d6fc" }
|
||||
# op-alloy-network = { git = "https://github.com/alloy-rs/op-alloy", rev = "a79d6fc" }
|
||||
# op-alloy-rpc-types = { git = "https://github.com/alloy-rs/op-alloy", rev = "a79d6fc" }
|
||||
@@ -774,6 +777,20 @@ ipnet = "2.11"
|
||||
# op-alloy-rpc-jsonrpsee = { git = "https://github.com/alloy-rs/op-alloy", rev = "a79d6fc" }
|
||||
#
|
||||
# revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "1207e33" }
|
||||
# need to change to bluealloy rakita/bal
|
||||
revm = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
alloy-evm = { git = "https://github.com/Rimeeeeee/evm", branch = "new-approach4" }
|
||||
alloy-op-evm = { git = "https://github.com/Rimeeeeee/evm", branch = "new-approach4" }
|
||||
revm-bytecode = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-database = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-state = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-primitives = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-interpreter = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-inspector = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-context = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-context-interface = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
revm-database-interface = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
op-revm = { git = "https://github.com/Rimeeeeee/revm", branch = "rakita/bal" }
|
||||
#
|
||||
# jsonrpsee = { git = "https://github.com/paradigmxyz/jsonrpsee", branch = "matt/make-rpc-service-pub" }
|
||||
# jsonrpsee-core = { git = "https://github.com/paradigmxyz/jsonrpsee", branch = "matt/make-rpc-service-pub" }
|
||||
|
||||
5
Makefile
5
Makefile
@@ -523,8 +523,3 @@ pr:
|
||||
make test
|
||||
|
||||
check-features:
|
||||
cargo hack check \
|
||||
--package reth-codecs \
|
||||
--package reth-primitives-traits \
|
||||
--package reth-primitives \
|
||||
--feature-powerset
|
||||
|
||||
@@ -506,8 +506,8 @@ async fn run_warmup_phase(
|
||||
// Build additional args with conditional --debug.startup-sync-state-idle flag
|
||||
let additional_args = args.build_additional_args("warmup", args.baseline_args.as_ref());
|
||||
|
||||
// Start reth node for warmup
|
||||
let mut node_process =
|
||||
// Start reth node for warmup (command is not stored for warmup phase)
|
||||
let (mut node_process, _warmup_command) =
|
||||
node_manager.start_node(&binary_path, warmup_ref, "warmup", &additional_args).await?;
|
||||
|
||||
// Wait for node to be ready and get its current tip
|
||||
@@ -607,8 +607,8 @@ async fn run_benchmark_workflow(
|
||||
// Build additional args with conditional --debug.startup-sync-state-idle flag
|
||||
let additional_args = args.build_additional_args(ref_type, base_args_str);
|
||||
|
||||
// Start reth node
|
||||
let mut node_process =
|
||||
// Start reth node and capture the command for reporting
|
||||
let (mut node_process, reth_command) =
|
||||
node_manager.start_node(&binary_path, git_ref, ref_type, &additional_args).await?;
|
||||
|
||||
// Wait for node to be ready and get its current tip (wherever it is)
|
||||
@@ -645,8 +645,9 @@ async fn run_benchmark_workflow(
|
||||
// Store results for comparison
|
||||
comparison_generator.add_ref_results(ref_type, &output_dir)?;
|
||||
|
||||
// Set the benchmark run timestamps
|
||||
// Set the benchmark run timestamps and reth command
|
||||
comparison_generator.set_ref_timestamps(ref_type, benchmark_start, benchmark_end)?;
|
||||
comparison_generator.set_ref_command(ref_type, reth_command)?;
|
||||
|
||||
info!("Completed {} reference benchmark", ref_type);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ pub(crate) struct ComparisonGenerator {
|
||||
feature_ref_name: String,
|
||||
baseline_results: Option<BenchmarkResults>,
|
||||
feature_results: Option<BenchmarkResults>,
|
||||
baseline_command: Option<String>,
|
||||
feature_command: Option<String>,
|
||||
}
|
||||
|
||||
/// Represents the results from a single benchmark run
|
||||
@@ -89,6 +91,7 @@ pub(crate) struct RefInfo {
|
||||
pub summary: BenchmarkSummary,
|
||||
pub start_timestamp: Option<DateTime<Utc>>,
|
||||
pub end_timestamp: Option<DateTime<Utc>>,
|
||||
pub reth_command: Option<String>,
|
||||
}
|
||||
|
||||
/// Summary of the comparison between references.
|
||||
@@ -142,6 +145,8 @@ impl ComparisonGenerator {
|
||||
feature_ref_name: args.feature_ref.clone(),
|
||||
baseline_results: None,
|
||||
feature_results: None,
|
||||
baseline_command: None,
|
||||
feature_command: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +211,21 @@ impl ComparisonGenerator {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the reth command for a reference
|
||||
pub(crate) fn set_ref_command(&mut self, ref_type: &str, command: String) -> Result<()> {
|
||||
match ref_type {
|
||||
"baseline" => {
|
||||
self.baseline_command = Some(command);
|
||||
}
|
||||
"feature" => {
|
||||
self.feature_command = Some(command);
|
||||
}
|
||||
_ => return Err(eyre!("Unknown reference type: {}", ref_type)),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate the final comparison report
|
||||
pub(crate) async fn generate_comparison_report(&self) -> Result<()> {
|
||||
info!("Generating comparison report...");
|
||||
@@ -230,12 +250,14 @@ impl ComparisonGenerator {
|
||||
summary: baseline.summary.clone(),
|
||||
start_timestamp: baseline.start_timestamp,
|
||||
end_timestamp: baseline.end_timestamp,
|
||||
reth_command: self.baseline_command.clone(),
|
||||
},
|
||||
feature: RefInfo {
|
||||
ref_name: feature.ref_name.clone(),
|
||||
summary: feature.summary.clone(),
|
||||
start_timestamp: feature.start_timestamp,
|
||||
end_timestamp: feature.end_timestamp,
|
||||
reth_command: self.feature_command.clone(),
|
||||
},
|
||||
comparison_summary,
|
||||
per_block_comparisons,
|
||||
@@ -599,6 +621,9 @@ impl ComparisonGenerator {
|
||||
end.format("%Y-%m-%d %H:%M:%S UTC")
|
||||
);
|
||||
}
|
||||
if let Some(ref cmd) = report.baseline.reth_command {
|
||||
println!(" Command: {}", cmd);
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("Feature Summary:");
|
||||
@@ -628,6 +653,9 @@ impl ComparisonGenerator {
|
||||
end.format("%Y-%m-%d %H:%M:%S UTC")
|
||||
);
|
||||
}
|
||||
if let Some(ref cmd) = report.feature.reth_command {
|
||||
println!(" Command: {}", cmd);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,19 +240,24 @@ impl NodeManager {
|
||||
}
|
||||
|
||||
/// Start a reth node using the specified binary path and return the process handle
|
||||
/// along with the formatted reth command string for reporting.
|
||||
pub(crate) async fn start_node(
|
||||
&mut self,
|
||||
binary_path: &std::path::Path,
|
||||
_git_ref: &str,
|
||||
ref_type: &str,
|
||||
additional_args: &[String],
|
||||
) -> Result<tokio::process::Child> {
|
||||
) -> Result<(tokio::process::Child, String)> {
|
||||
// Store the binary path for later use (e.g., in unwind_to_block)
|
||||
self.binary_path = Some(binary_path.to_path_buf());
|
||||
|
||||
let binary_path_str = binary_path.to_string_lossy();
|
||||
let (reth_args, _) = self.build_reth_args(&binary_path_str, additional_args, ref_type);
|
||||
|
||||
// Format the reth command string for reporting
|
||||
let reth_command = shlex::try_join(reth_args.iter().map(|s| s.as_str()))
|
||||
.wrap_err("Failed to format reth command string")?;
|
||||
|
||||
// Log additional arguments if any
|
||||
if !self.additional_reth_args.is_empty() {
|
||||
info!("Using common additional reth arguments: {:?}", self.additional_reth_args);
|
||||
@@ -346,7 +351,7 @@ impl NodeManager {
|
||||
// Give the node a moment to start up
|
||||
sleep(Duration::from_secs(5)).await;
|
||||
|
||||
Ok(child)
|
||||
Ok((child, reth_command))
|
||||
}
|
||||
|
||||
/// Wait for the node to be ready and return its current tip
|
||||
|
||||
@@ -80,7 +80,7 @@ RUSTFLAGS="-C target-cpu=native" cargo build --profile profiling --no-default-fe
|
||||
### Run the Benchmark:
|
||||
First, start the reth node. Here is an example that runs `reth` compiled with the `profiling` profile, runs `samply`, and configures `reth` to run with metrics enabled:
|
||||
```bash
|
||||
samply record -p 3001 target/profiling/reth node --metrics localhost:9001 --authrpc.jwt-secret <jwt_file_path>
|
||||
samply record -p 3001 target/profiling/reth node --metrics localhost:9001 --authrpc.jwtsecret <jwt_file_path>
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -143,5 +143,5 @@ To reproduce the benchmark, first re-set the node to the block that the benchmar
|
||||
- **RPC Configuration**: The RPC endpoints should be accessible and configured correctly, specifically the RPC endpoint must support `eth_getBlockByNumber` and support fetching full transactions. The benchmark will make one RPC query per block as fast as possible, so ensure the RPC endpoint does not rate limit or block requests after a certain volume.
|
||||
- **Reproducibility**: Ensure that the node is at the same state before attempting to retry a benchmark. The `new-payload-fcu` command specifically will commit to the database, so the node must be rolled back using `reth stage unwind` to reproducibly retry benchmarks.
|
||||
- **Profiling tools**: If you are collecting CPU profiles, tools like [`samply`](https://github.com/mstange/samply) and [`perf`](https://perf.wiki.kernel.org/index.php/Main_Page) can be useful for analyzing node performance.
|
||||
- **Benchmark Data**: `reth-bench` additionally contains a `--benchmark.output` flag, which will output gas used benchmarks across the benchmark range in CSV format. This may be useful for further data analysis.
|
||||
- **Benchmark Data**: `reth-bench` additionally contains a `--output` flag, which will output gas used benchmarks across the benchmark range in CSV format. This may be useful for further data analysis.
|
||||
- **Platform Information**: To ensure accurate and reproducible benchmarking, document the platform details, including hardware specifications, OS version, and any other relevant information before publishing any benchmarks.
|
||||
|
||||
@@ -150,6 +150,45 @@ pub(crate) fn block_to_new_payload(
|
||||
let (payload, sidecar) = ExecutionPayload::from_block_slow(&block);
|
||||
|
||||
let (version, params) = match payload {
|
||||
ExecutionPayload::V4(payload) => {
|
||||
let cancun = sidecar.cancun().unwrap();
|
||||
|
||||
if let Some(prague) = sidecar.prague() {
|
||||
if is_optimism {
|
||||
(
|
||||
EngineApiMessageVersion::V4,
|
||||
serde_json::to_value((
|
||||
OpExecutionPayloadV4 {
|
||||
payload_inner: payload.payload_inner,
|
||||
withdrawals_root: block.withdrawals_root.unwrap(),
|
||||
},
|
||||
cancun.versioned_hashes.clone(),
|
||||
cancun.parent_beacon_block_root,
|
||||
Requests::default(),
|
||||
))?,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
EngineApiMessageVersion::V4,
|
||||
serde_json::to_value((
|
||||
payload,
|
||||
cancun.versioned_hashes.clone(),
|
||||
cancun.parent_beacon_block_root,
|
||||
prague.requests.requests_hash(),
|
||||
))?,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
(
|
||||
EngineApiMessageVersion::V3,
|
||||
serde_json::to_value((
|
||||
payload,
|
||||
cancun.versioned_hashes.clone(),
|
||||
cancun.parent_beacon_block_root,
|
||||
))?,
|
||||
)
|
||||
}
|
||||
}
|
||||
ExecutionPayload::V3(payload) => {
|
||||
let cancun = sidecar.cancun().unwrap();
|
||||
|
||||
@@ -244,7 +283,10 @@ pub(crate) async fn call_forkchoice_updated<N, P: EngineApiValidWaitExt<N>>(
|
||||
payload_attributes: Option<PayloadAttributes>,
|
||||
) -> TransportResult<ForkchoiceUpdated> {
|
||||
match message_version {
|
||||
EngineApiMessageVersion::V3 | EngineApiMessageVersion::V4 | EngineApiMessageVersion::V5 => {
|
||||
EngineApiMessageVersion::V3 |
|
||||
EngineApiMessageVersion::V4 |
|
||||
EngineApiMessageVersion::V5 |
|
||||
EngineApiMessageVersion::V6 => {
|
||||
provider.fork_choice_updated_v3_wait(forkchoice_state, payload_attributes).await
|
||||
}
|
||||
EngineApiMessageVersion::V2 => {
|
||||
|
||||
@@ -18,7 +18,7 @@ use reth_primitives_traits::{
|
||||
};
|
||||
use reth_storage_api::StateProviderBox;
|
||||
use reth_trie::{updates::TrieUpdatesSorted, HashedPostStateSorted, TrieInputSorted};
|
||||
use std::{collections::BTreeMap, sync::Arc, time::Instant};
|
||||
use std::{collections::BTreeMap, ops::Deref, sync::Arc, time::Instant};
|
||||
use tokio::sync::{broadcast, watch};
|
||||
|
||||
/// Size of the broadcast channel used to notify canonical state events.
|
||||
@@ -634,6 +634,8 @@ impl<N: NodePrimitives> BlockState<N> {
|
||||
/// We assume that the `Receipts` in the executed block `ExecutionOutcome`
|
||||
/// has only one element corresponding to the executed block associated to
|
||||
/// the state.
|
||||
///
|
||||
/// This clones the vector of receipts. To avoid it, use [`Self::executed_block_receipts_ref`].
|
||||
pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
|
||||
let receipts = self.receipts();
|
||||
|
||||
@@ -646,6 +648,22 @@ impl<N: NodePrimitives> BlockState<N> {
|
||||
receipts.first().cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns a slice of `Receipt` of executed block that determines the state.
|
||||
/// We assume that the `Receipts` in the executed block `ExecutionOutcome`
|
||||
/// has only one element corresponding to the executed block associated to
|
||||
/// the state.
|
||||
pub fn executed_block_receipts_ref(&self) -> &[N::Receipt] {
|
||||
let receipts = self.receipts();
|
||||
|
||||
debug_assert!(
|
||||
receipts.len() <= 1,
|
||||
"Expected at most one block's worth of receipts, found {}",
|
||||
receipts.len()
|
||||
);
|
||||
|
||||
receipts.first().map(|receipts| receipts.deref()).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns a vector of __parent__ `BlockStates`.
|
||||
///
|
||||
/// The block state order in the output vector is newest to oldest (highest to lowest):
|
||||
|
||||
@@ -173,6 +173,7 @@ impl<N: NodePrimitives> TestBlockBuilder<N> {
|
||||
transactions: transactions.into_iter().map(|tx| tx.into_inner()).collect(),
|
||||
ommers: Vec::new(),
|
||||
withdrawals: Some(vec![].into()),
|
||||
block_access_list: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ use reth_network_peers::{
|
||||
};
|
||||
use reth_primitives_traits::{sync::LazyLock, BlockHeader, SealedHeader};
|
||||
|
||||
/// The hash of an empty block access list.
|
||||
const EMPTY_BLOCK_ACCESS_LIST_HASH: B256 =
|
||||
b256!("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347");
|
||||
|
||||
/// Helper method building a [`Header`] given [`Genesis`] and [`ChainHardforks`].
|
||||
pub fn make_genesis_header(genesis: &Genesis, hardforks: &ChainHardforks) -> Header {
|
||||
// If London is activated at genesis, we set the initial base fee as per EIP-1559.
|
||||
@@ -79,6 +83,12 @@ pub fn make_genesis_header(genesis: &Genesis, hardforks: &ChainHardforks) -> Hea
|
||||
.active_at_timestamp(genesis.timestamp)
|
||||
.then_some(EMPTY_REQUESTS_HASH);
|
||||
|
||||
// If Amsterdam is activated at genesis we set block access list hash empty hash.
|
||||
let block_access_list_hash = hardforks
|
||||
.fork(EthereumHardfork::Amsterdam)
|
||||
.active_at_timestamp(genesis.timestamp)
|
||||
.then_some(EMPTY_BLOCK_ACCESS_LIST_HASH);
|
||||
|
||||
Header {
|
||||
gas_limit: genesis.gas_limit,
|
||||
difficulty: genesis.difficulty,
|
||||
@@ -94,6 +104,7 @@ pub fn make_genesis_header(genesis: &Genesis, hardforks: &ChainHardforks) -> Hea
|
||||
blob_gas_used,
|
||||
excess_blob_gas,
|
||||
requests_hash,
|
||||
block_access_list_hash,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@@ -298,6 +309,7 @@ pub fn create_chain_config(
|
||||
cancun_time: timestamp(EthereumHardfork::Cancun),
|
||||
prague_time: timestamp(EthereumHardfork::Prague),
|
||||
osaka_time: timestamp(EthereumHardfork::Osaka),
|
||||
amsterdam_time: timestamp(EthereumHardfork::Amsterdam),
|
||||
bpo1_time: timestamp(EthereumHardfork::Bpo1),
|
||||
bpo2_time: timestamp(EthereumHardfork::Bpo2),
|
||||
bpo3_time: timestamp(EthereumHardfork::Bpo3),
|
||||
@@ -887,6 +899,7 @@ impl From<Genesis> for ChainSpec {
|
||||
(EthereumHardfork::Bpo3.boxed(), genesis.config.bpo3_time),
|
||||
(EthereumHardfork::Bpo4.boxed(), genesis.config.bpo4_time),
|
||||
(EthereumHardfork::Bpo5.boxed(), genesis.config.bpo5_time),
|
||||
(EthereumHardfork::Amsterdam.boxed(), genesis.config.amsterdam_time),
|
||||
];
|
||||
|
||||
let mut time_hardforks = time_hardfork_opts
|
||||
@@ -1193,6 +1206,19 @@ impl ChainSpecBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Amsterdam at genesis.
|
||||
pub fn amsterdam_activated(mut self) -> Self {
|
||||
self = self.osaka_activated();
|
||||
self.hardforks.insert(EthereumHardfork::Amsterdam, ForkCondition::Timestamp(0));
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Amsterdam at the given timestamp.
|
||||
pub fn with_amsterdam_at(mut self, timestamp: u64) -> Self {
|
||||
self.hardforks.insert(EthereumHardfork::Amsterdam, ForkCondition::Timestamp(timestamp));
|
||||
self
|
||||
}
|
||||
|
||||
/// Build the resulting [`ChainSpec`].
|
||||
///
|
||||
/// # Panics
|
||||
|
||||
@@ -8,12 +8,17 @@ use reth_db::{
|
||||
RawDupSort,
|
||||
};
|
||||
use reth_db_api::{
|
||||
table::{Decompress, DupSort, Table},
|
||||
tables, RawKey, RawTable, Receipts, TableViewer, Transactions,
|
||||
cursor::{DbCursorRO, DbDupCursorRO},
|
||||
database::Database,
|
||||
table::{Compress, Decompress, DupSort, Table},
|
||||
tables,
|
||||
transaction::DbTx,
|
||||
RawKey, RawTable, Receipts, TableViewer, Transactions,
|
||||
};
|
||||
use reth_db_common::DbTool;
|
||||
use reth_node_api::{HeaderTy, ReceiptTy, TxTy};
|
||||
use reth_node_builder::NodeTypesWithDB;
|
||||
use reth_primitives_traits::ValueWithSubKey;
|
||||
use reth_provider::{providers::ProviderNodeTypes, StaticFileProviderFactory};
|
||||
use reth_static_file_types::StaticFileSegment;
|
||||
use tracing::error;
|
||||
@@ -39,6 +44,14 @@ enum Subcommand {
|
||||
#[arg(value_parser = maybe_json_value_parser)]
|
||||
subkey: Option<String>,
|
||||
|
||||
/// Optional end key for range query (exclusive upper bound)
|
||||
#[arg(value_parser = maybe_json_value_parser)]
|
||||
end_key: Option<String>,
|
||||
|
||||
/// Optional end subkey for range query (exclusive upper bound)
|
||||
#[arg(value_parser = maybe_json_value_parser)]
|
||||
end_subkey: Option<String>,
|
||||
|
||||
/// Output bytes instead of human-readable decoded value
|
||||
#[arg(long)]
|
||||
raw: bool,
|
||||
@@ -61,8 +74,8 @@ impl Command {
|
||||
/// Execute `db get` command
|
||||
pub fn execute<N: ProviderNodeTypes>(self, tool: &DbTool<N>) -> eyre::Result<()> {
|
||||
match self.subcommand {
|
||||
Subcommand::Mdbx { table, key, subkey, raw } => {
|
||||
table.view(&GetValueViewer { tool, key, subkey, raw })?
|
||||
Subcommand::Mdbx { table, key, subkey, end_key, end_subkey, raw } => {
|
||||
table.view(&GetValueViewer { tool, key, subkey, end_key, end_subkey, raw })?
|
||||
}
|
||||
Subcommand::StaticFile { segment, key, raw } => {
|
||||
let (key, mask): (u64, _) = match segment {
|
||||
@@ -154,6 +167,8 @@ struct GetValueViewer<'a, N: NodeTypesWithDB> {
|
||||
tool: &'a DbTool<N>,
|
||||
key: String,
|
||||
subkey: Option<String>,
|
||||
end_key: Option<String>,
|
||||
end_subkey: Option<String>,
|
||||
raw: bool,
|
||||
}
|
||||
|
||||
@@ -163,53 +178,158 @@ impl<N: ProviderNodeTypes> TableViewer<()> for GetValueViewer<'_, N> {
|
||||
fn view<T: Table>(&self) -> Result<(), Self::Error> {
|
||||
let key = table_key::<T>(&self.key)?;
|
||||
|
||||
let content = if self.raw {
|
||||
self.tool
|
||||
.get::<RawTable<T>>(RawKey::from(key))?
|
||||
.map(|content| hex::encode_prefixed(content.raw_value()))
|
||||
} else {
|
||||
self.tool.get::<T>(key)?.as_ref().map(serde_json::to_string_pretty).transpose()?
|
||||
};
|
||||
// A non-dupsort table cannot have subkeys. The `subkey` arg becomes the `end_key`. First we
|
||||
// check that `end_key` and `end_subkey` weren't previously given, as that wouldn't be
|
||||
// valid.
|
||||
if self.end_key.is_some() || self.end_subkey.is_some() {
|
||||
return Err(eyre::eyre!("Only END_KEY can be given for non-DUPSORT tables"));
|
||||
}
|
||||
|
||||
match content {
|
||||
Some(content) => {
|
||||
println!("{content}");
|
||||
}
|
||||
None => {
|
||||
error!(target: "reth::cli", "No content for the given table key.");
|
||||
}
|
||||
};
|
||||
let end_key = self.subkey.clone();
|
||||
|
||||
// Check if we're doing a range query
|
||||
if let Some(ref end_key_str) = end_key {
|
||||
let end_key = table_key::<T>(end_key_str)?;
|
||||
|
||||
// Use walk_range to iterate over the range
|
||||
self.tool.provider_factory.db_ref().view(|tx| {
|
||||
let mut cursor = tx.cursor_read::<T>()?;
|
||||
let walker = cursor.walk_range(key..end_key)?;
|
||||
|
||||
for result in walker {
|
||||
let (k, v) = result?;
|
||||
let json_val = if self.raw {
|
||||
let raw_key = RawKey::from(k);
|
||||
serde_json::json!({
|
||||
"key": hex::encode_prefixed(raw_key.raw_key()),
|
||||
"val": hex::encode_prefixed(v.compress().as_ref()),
|
||||
})
|
||||
} else {
|
||||
serde_json::json!({
|
||||
"key": &k,
|
||||
"val": &v,
|
||||
})
|
||||
};
|
||||
|
||||
println!("{}", serde_json::to_string_pretty(&json_val)?);
|
||||
}
|
||||
|
||||
Ok::<_, eyre::Report>(())
|
||||
})??;
|
||||
} else {
|
||||
// Single key lookup
|
||||
let content = if self.raw {
|
||||
self.tool
|
||||
.get::<RawTable<T>>(RawKey::from(key))?
|
||||
.map(|content| hex::encode_prefixed(content.raw_value()))
|
||||
} else {
|
||||
self.tool.get::<T>(key)?.as_ref().map(serde_json::to_string_pretty).transpose()?
|
||||
};
|
||||
|
||||
match content {
|
||||
Some(content) => {
|
||||
println!("{content}");
|
||||
}
|
||||
None => {
|
||||
error!(target: "reth::cli", "No content for the given table key.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn view_dupsort<T: DupSort>(&self) -> Result<(), Self::Error> {
|
||||
fn view_dupsort<T: DupSort>(&self) -> Result<(), Self::Error>
|
||||
where
|
||||
T::Value: reth_primitives_traits::ValueWithSubKey<SubKey = T::SubKey>,
|
||||
{
|
||||
// get a key for given table
|
||||
let key = table_key::<T>(&self.key)?;
|
||||
|
||||
// process dupsort table
|
||||
let subkey = table_subkey::<T>(self.subkey.as_deref())?;
|
||||
|
||||
let content = if self.raw {
|
||||
self.tool
|
||||
.get_dup::<RawDupSort<T>>(RawKey::from(key), RawKey::from(subkey))?
|
||||
.map(|content| hex::encode_prefixed(content.raw_value()))
|
||||
} else {
|
||||
self.tool
|
||||
.get_dup::<T>(key, subkey)?
|
||||
// Check if we're doing a range query
|
||||
if let Some(ref end_key_str) = self.end_key {
|
||||
let end_key = table_key::<T>(end_key_str)?;
|
||||
let start_subkey = table_subkey::<T>(Some(
|
||||
self.subkey.as_ref().expect("must have been given if end_key is given").as_str(),
|
||||
))?;
|
||||
let end_subkey_parsed = self
|
||||
.end_subkey
|
||||
.as_ref()
|
||||
.map(serde_json::to_string_pretty)
|
||||
.transpose()?
|
||||
};
|
||||
.map(|s| table_subkey::<T>(Some(s.as_str())))
|
||||
.transpose()?;
|
||||
|
||||
match content {
|
||||
Some(content) => {
|
||||
println!("{content}");
|
||||
}
|
||||
None => {
|
||||
error!(target: "reth::cli", "No content for the given table subkey.");
|
||||
}
|
||||
};
|
||||
self.tool.provider_factory.db_ref().view(|tx| {
|
||||
let mut cursor = tx.cursor_dup_read::<T>()?;
|
||||
|
||||
// Seek to the starting key. If there is actually a key at the starting key then
|
||||
// seek to the subkey within it.
|
||||
if let Some((decoded_key, _)) = cursor.seek(key.clone())? &&
|
||||
decoded_key == key
|
||||
{
|
||||
cursor.seek_by_key_subkey(key.clone(), start_subkey.clone())?;
|
||||
}
|
||||
|
||||
// Get the current position to start iteration
|
||||
let mut current = cursor.current()?;
|
||||
|
||||
while let Some((decoded_key, decoded_value)) = current {
|
||||
// Extract the subkey using the ValueWithSubKey trait
|
||||
let decoded_subkey = decoded_value.get_subkey();
|
||||
|
||||
// Check if we've reached the end (exclusive)
|
||||
if (&decoded_key, Some(&decoded_subkey)) >=
|
||||
(&end_key, end_subkey_parsed.as_ref())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Output the entry with both key and subkey
|
||||
let json_val = if self.raw {
|
||||
let raw_key = RawKey::from(decoded_key.clone());
|
||||
serde_json::json!({
|
||||
"key": hex::encode_prefixed(raw_key.raw_key()),
|
||||
"val": hex::encode_prefixed(decoded_value.compress().as_ref()),
|
||||
})
|
||||
} else {
|
||||
serde_json::json!({
|
||||
"key": &decoded_key,
|
||||
"val": &decoded_value,
|
||||
})
|
||||
};
|
||||
|
||||
println!("{}", serde_json::to_string_pretty(&json_val)?);
|
||||
|
||||
// Move to next entry
|
||||
current = cursor.next()?;
|
||||
}
|
||||
|
||||
Ok::<_, eyre::Report>(())
|
||||
})??;
|
||||
} else {
|
||||
// Single key/subkey lookup
|
||||
let subkey = table_subkey::<T>(self.subkey.as_deref())?;
|
||||
|
||||
let content = if self.raw {
|
||||
self.tool
|
||||
.get_dup::<RawDupSort<T>>(RawKey::from(key), RawKey::from(subkey))?
|
||||
.map(|content| hex::encode_prefixed(content.raw_value()))
|
||||
} else {
|
||||
self.tool
|
||||
.get_dup::<T>(key, subkey)?
|
||||
.as_ref()
|
||||
.map(serde_json::to_string_pretty)
|
||||
.transpose()?
|
||||
};
|
||||
|
||||
match content {
|
||||
Some(content) => {
|
||||
println!("{content}");
|
||||
}
|
||||
None => {
|
||||
error!(target: "reth::cli", "No content for the given table subkey.");
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ impl Command {
|
||||
let mut settings @ StorageSettings {
|
||||
receipts_in_static_files: _,
|
||||
transaction_senders_in_static_files: _,
|
||||
storages_history_in_rocksdb: _,
|
||||
} = settings.unwrap_or_else(StorageSettings::legacy);
|
||||
|
||||
// Update the setting based on the key
|
||||
|
||||
@@ -110,7 +110,7 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> InitStateC
|
||||
static_file_provider.commit()?;
|
||||
} else if last_block_number > 0 && last_block_number < header.number() {
|
||||
return Err(eyre::eyre!(
|
||||
"Data directory should be empty when calling init-state with --without-evm-history."
|
||||
"Data directory should be empty when calling init-state with --without-evm."
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ impl<C: ChainSpecParser> Command<C> {
|
||||
tx.clear::<tables::TransactionBlocks>()?;
|
||||
tx.clear::<tables::BlockOmmers<HeaderTy<N>>>()?;
|
||||
tx.clear::<tables::BlockWithdrawals>()?;
|
||||
tx.clear::<tables::BlockAccessLists>()?;
|
||||
reset_stage_checkpoint(tx, StageId::Bodies)?;
|
||||
|
||||
insert_genesis_header(&provider_rw, &self.env.chain)?;
|
||||
|
||||
@@ -531,8 +531,12 @@ impl PruneConfig {
|
||||
self.segments.receipts.is_some() || !self.segments.receipts_log_filter.is_empty()
|
||||
}
|
||||
|
||||
/// Merges another `PruneConfig` into this one, taking values from the other config if and only
|
||||
/// if the corresponding value in this config is not set.
|
||||
/// Merges values from `other` into `self`.
|
||||
/// - `Option<PruneMode>` fields: set from `other` only if `self` is `None`.
|
||||
/// - `block_interval`: set from `other` only if `self.block_interval ==
|
||||
/// DEFAULT_BLOCK_INTERVAL`.
|
||||
/// - `merkle_changesets`: always set from `other`.
|
||||
/// - `receipts_log_filter`: set from `other` only if `self` is empty and `other` is non-empty.
|
||||
pub fn merge(&mut self, other: Self) {
|
||||
let Self {
|
||||
block_interval,
|
||||
@@ -561,7 +565,7 @@ impl PruneConfig {
|
||||
self.segments.account_history = self.segments.account_history.or(account_history);
|
||||
self.segments.storage_history = self.segments.storage_history.or(storage_history);
|
||||
self.segments.bodies_history = self.segments.bodies_history.or(bodies_history);
|
||||
// Merkle changesets is not optional, so we just replace it if provided
|
||||
// Merkle changesets is not optional; always take the value from `other`
|
||||
self.segments.merkle_changesets = merkle_changesets;
|
||||
|
||||
if self.segments.receipts_log_filter.0.is_empty() && !receipts_log_filter.0.is_empty() {
|
||||
|
||||
@@ -14,11 +14,14 @@ workspace = true
|
||||
# reth
|
||||
reth-chainspec.workspace = true
|
||||
reth-consensus.workspace = true
|
||||
tracing.workspace = true
|
||||
|
||||
# ethereum
|
||||
reth-primitives-traits.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
alloy-primitives.workspace = true
|
||||
alloy-eips.workspace = true
|
||||
alloy-rlp.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
alloy-primitives = { workspace = true, features = ["rand"] }
|
||||
@@ -35,4 +38,6 @@ std = [
|
||||
"reth-primitives-traits/std",
|
||||
"reth-ethereum-primitives/std",
|
||||
"alloy-primitives/std",
|
||||
"alloy-rlp/std",
|
||||
"tracing/std",
|
||||
]
|
||||
|
||||
@@ -69,6 +69,29 @@ pub fn validate_shanghai_withdrawals<B: Block>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate that block access lists are present in Amsterdam
|
||||
///
|
||||
/// [EIP-7928]: https://eips.ethereum.org/EIPS/eip-7928
|
||||
#[inline]
|
||||
pub fn validate_amsterdam_block_access_lists<B: Block>(
|
||||
block: &SealedBlock<B>,
|
||||
) -> Result<(), ConsensusError> {
|
||||
let bal = block.body().block_access_list().ok_or(ConsensusError::BlockAccessListMissing)?;
|
||||
let bal_hash = alloy_primitives::keccak256(alloy_rlp::encode(bal));
|
||||
let header_bal_hash =
|
||||
block.block_access_list_hash().ok_or(ConsensusError::BlockAccessListHashMissing)?;
|
||||
if bal_hash != header_bal_hash {
|
||||
tracing::error!(
|
||||
target: "consensus",
|
||||
?header_bal_hash,
|
||||
?bal,
|
||||
"Block access list hash mismatch in validation.rs in L81"
|
||||
);
|
||||
return Err(ConsensusError::InvalidBalHash);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate that blob gas is present in the block if Cancun is active.
|
||||
///
|
||||
/// See [EIP-4844]: Shard Blob Transactions
|
||||
@@ -131,6 +154,21 @@ where
|
||||
}
|
||||
_ => return Err(ConsensusError::WithdrawalsRootUnexpected),
|
||||
}
|
||||
if let (Some(expected_hash), Some(body_bal)) =
|
||||
(header.block_access_list_hash(), body.block_access_list())
|
||||
{
|
||||
let got_hash = alloy_primitives::keccak256(alloy_rlp::encode(body_bal));
|
||||
|
||||
if got_hash != expected_hash {
|
||||
tracing::error!(
|
||||
target: "consensus",
|
||||
?expected_hash,
|
||||
?body_bal,
|
||||
"Block access list hash mismatch in validation.rs in L164"
|
||||
);
|
||||
return Err(ConsensusError::InvalidBalHash);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -217,6 +255,10 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
if chain_spec.is_amsterdam_active_at_timestamp(block.header().timestamp()) {
|
||||
validate_amsterdam_block_access_lists(block)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -327,7 +369,7 @@ pub fn validate_against_parent_eip1559_base_fee<ChainSpec: EthChainSpec + Ethere
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates the timestamp against the parent to make sure it is in the past.
|
||||
/// Validates that the block timestamp is greater than the parent block timestamp.
|
||||
#[inline]
|
||||
pub fn validate_against_parent_timestamp<H: BlockHeader>(
|
||||
header: &H,
|
||||
@@ -484,6 +526,7 @@ mod tests {
|
||||
transactions: vec![transaction],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Withdrawals::default()),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
let block = SealedBlock::seal_slow(alloy_consensus::Block { header, body });
|
||||
|
||||
@@ -404,9 +404,41 @@ pub enum ConsensusError {
|
||||
/// The maximum allowed RLP length.
|
||||
max_rlp_length: usize,
|
||||
},
|
||||
|
||||
/// Error when the hash of block access list is different from the expected hash.
|
||||
#[error("Block header's BAL hash does not match the computed BAL hash.")]
|
||||
InvalidBalHash,
|
||||
|
||||
/// Error when the block access list hash is missing.
|
||||
#[error("block access list hash missing")]
|
||||
BlockAccessListHashMissing,
|
||||
|
||||
/// Error when the block access list is different from the expected access list.
|
||||
#[error("Block's access list is invalid.")]
|
||||
InvalidBlockAccessList,
|
||||
|
||||
/// Error when the block access list is missing.
|
||||
#[error("block access list missing")]
|
||||
BlockAccessListMissing,
|
||||
|
||||
/// Error when the block access list hash is unexpected.
|
||||
#[error("block access list hash unexpected")]
|
||||
BlockAccessListHashUnexpected,
|
||||
|
||||
/// Error when the block access list contains an account change that is not present in the
|
||||
/// computed access list.
|
||||
#[error("Block BAL contains an account change that is not present in the computed BAL.")]
|
||||
InvalidBalExtraAccount,
|
||||
|
||||
/// Error when the block access list is missing an account change that is present in the
|
||||
/// computed access list.
|
||||
#[error("Block BAL is missing an account change that is present in the computed BAL.")]
|
||||
InvalidBalMissingAccount,
|
||||
|
||||
/// EIP-7825: Transaction gas limit exceeds maximum allowed
|
||||
#[error(transparent)]
|
||||
TransactionGasLimitTooHigh(Box<TxGasLimitTooHighErr>),
|
||||
|
||||
/// Other, likely an injected L2 error.
|
||||
#[error("{0}")]
|
||||
Other(String),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::BlockProvider;
|
||||
use alloy_provider::{Network, Provider, ProviderBuilder};
|
||||
use alloy_provider::{ConnectionConfig, Network, Provider, ProviderBuilder};
|
||||
use alloy_transport::TransportResult;
|
||||
use futures::{Stream, StreamExt};
|
||||
use reth_node_api::Block;
|
||||
@@ -25,7 +25,14 @@ impl<N: Network, PrimitiveBlock> RpcBlockProvider<N, PrimitiveBlock> {
|
||||
convert: impl Fn(N::BlockResponse) -> PrimitiveBlock + Send + Sync + 'static,
|
||||
) -> eyre::Result<Self> {
|
||||
Ok(Self {
|
||||
provider: Arc::new(ProviderBuilder::default().connect(rpc_url).await?),
|
||||
provider: Arc::new(
|
||||
ProviderBuilder::default()
|
||||
.connect_with_config(
|
||||
rpc_url,
|
||||
ConnectionConfig::default().with_max_retries(u32::MAX),
|
||||
)
|
||||
.await?,
|
||||
),
|
||||
url: rpc_url.to_string(),
|
||||
convert: Arc::new(convert),
|
||||
})
|
||||
|
||||
@@ -56,6 +56,7 @@ pub fn generate_test_blocks(chain_spec: &ChainSpec, count: u64) -> Vec<SealedBlo
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash: None,
|
||||
};
|
||||
|
||||
// Set required fields based on chain spec
|
||||
@@ -106,6 +107,7 @@ pub fn generate_test_blocks(chain_spec: &ChainSpec, count: u64) -> Vec<SealedBlo
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: header.withdrawals_root.is_some().then(Withdrawals::default),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
// Create the block
|
||||
|
||||
@@ -448,12 +448,14 @@ mod tests {
|
||||
nonce: account.nonce,
|
||||
code_hash: account.bytecode_hash.unwrap_or_default(),
|
||||
code: None,
|
||||
storage_id: None,
|
||||
}),
|
||||
original_info: (i == 0).then(|| AccountInfo {
|
||||
balance: account.balance.checked_div(U256::from(2)).unwrap_or(U256::ZERO),
|
||||
nonce: 0,
|
||||
code_hash: account.bytecode_hash.unwrap_or_default(),
|
||||
code: None,
|
||||
storage_id: None,
|
||||
}),
|
||||
storage,
|
||||
status: AccountStatus::default(),
|
||||
@@ -839,6 +841,7 @@ mod tests {
|
||||
receipts: vec![],
|
||||
requests: Requests::default(),
|
||||
gas_used: 0,
|
||||
block_access_list: Default::default(),
|
||||
blob_gas_used: 0,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -204,7 +204,7 @@ where
|
||||
EngineApiMessageVersion::default(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
tracing::debug!(target: "engine::local", "FCU result: {res:?}");
|
||||
if !res.is_valid() {
|
||||
eyre::bail!("Invalid payload status")
|
||||
}
|
||||
|
||||
@@ -61,7 +61,8 @@ pub trait EngineTypes:
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV2>
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV3>
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV4>
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV5>,
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV5>
|
||||
+ TryInto<Self::ExecutionPayloadEnvelopeV6>,
|
||||
> + DeserializeOwned
|
||||
+ Serialize
|
||||
{
|
||||
@@ -105,6 +106,14 @@ pub trait EngineTypes:
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static;
|
||||
/// Execution Payload V6 envelope type.
|
||||
type ExecutionPayloadEnvelopeV6: DeserializeOwned
|
||||
+ Serialize
|
||||
+ Clone
|
||||
+ Unpin
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static;
|
||||
}
|
||||
|
||||
/// Type that validates the payloads processed by the engine API.
|
||||
|
||||
@@ -26,10 +26,12 @@ fn create_bench_state(num_accounts: usize) -> EvmState {
|
||||
nonce: 10,
|
||||
code_hash: B256::from_slice(&rng.random::<[u8; 32]>()),
|
||||
code: Default::default(),
|
||||
storage_id: None,
|
||||
},
|
||||
storage,
|
||||
status: AccountStatus::empty(),
|
||||
transaction_id: 0,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let address = Address::with_last_byte(i as u8);
|
||||
|
||||
@@ -62,6 +62,7 @@ fn create_bench_state_updates(params: &BenchParams) -> Vec<EvmState> {
|
||||
storage: HashMap::default(),
|
||||
status: AccountStatus::SelfDestructed,
|
||||
transaction_id: 0,
|
||||
..Default::default()
|
||||
}
|
||||
} else {
|
||||
RevmAccount {
|
||||
@@ -70,6 +71,7 @@ fn create_bench_state_updates(params: &BenchParams) -> Vec<EvmState> {
|
||||
nonce: rng.random::<u64>(),
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code: Some(Default::default()),
|
||||
storage_id: None,
|
||||
},
|
||||
storage: (0..rng.random_range(0..=params.storage_slots_per_account))
|
||||
.map(|_| {
|
||||
@@ -85,6 +87,7 @@ fn create_bench_state_updates(params: &BenchParams) -> Vec<EvmState> {
|
||||
.collect(),
|
||||
status: AccountStatus::Touched,
|
||||
transaction_id: 0,
|
||||
..Default::default()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -229,9 +232,15 @@ fn bench_state_root(c: &mut Criterion) {
|
||||
black_box({
|
||||
let mut handle = payload_processor.spawn(
|
||||
Default::default(),
|
||||
core::iter::empty::<
|
||||
Result<Recovered<TransactionSigned>, core::convert::Infallible>,
|
||||
>(),
|
||||
(
|
||||
core::iter::empty::<
|
||||
Result<
|
||||
Recovered<TransactionSigned>,
|
||||
core::convert::Infallible,
|
||||
>,
|
||||
>(),
|
||||
std::convert::identity,
|
||||
),
|
||||
StateProviderBuilder::new(provider.clone(), genesis_hash, None),
|
||||
OverlayStateProviderFactory::new(provider),
|
||||
&TreeConfig::default(),
|
||||
|
||||
@@ -146,17 +146,26 @@ impl<S: StateProvider> StateProvider for CachedStateProvider<S> {
|
||||
storage_key: StorageKey,
|
||||
) -> ProviderResult<Option<StorageValue>> {
|
||||
match self.caches.get_storage(&account, &storage_key) {
|
||||
SlotStatus::NotCached => {
|
||||
self.metrics.storage_cache_misses.increment(1);
|
||||
(SlotStatus::NotCached, maybe_cache) => {
|
||||
let final_res = self.state_provider.storage(account, storage_key)?;
|
||||
self.caches.insert_storage(account, storage_key, final_res);
|
||||
let account_cache = maybe_cache.unwrap_or_default();
|
||||
account_cache.insert_storage(storage_key, final_res);
|
||||
// we always need to insert the value to update the weights.
|
||||
// Note: there exists a race when the storage cache did not exist yet and two
|
||||
// consumers looking up the a storage value for this account for the first time,
|
||||
// however we can assume that this will only happen for the very first (mostlikely
|
||||
// the same) value, and don't expect that this will accidentally
|
||||
// replace an account storage cache with additional values.
|
||||
self.caches.insert_storage_cache(account, account_cache);
|
||||
|
||||
self.metrics.storage_cache_misses.increment(1);
|
||||
Ok(final_res)
|
||||
}
|
||||
SlotStatus::Empty => {
|
||||
(SlotStatus::Empty, _) => {
|
||||
self.metrics.storage_cache_hits.increment(1);
|
||||
Ok(None)
|
||||
}
|
||||
SlotStatus::Value(value) => {
|
||||
(SlotStatus::Value(value), _) => {
|
||||
self.metrics.storage_cache_hits.increment(1);
|
||||
Ok(Some(value))
|
||||
}
|
||||
@@ -311,18 +320,28 @@ pub(crate) struct ExecutionCache {
|
||||
impl ExecutionCache {
|
||||
/// Get storage value from hierarchical cache.
|
||||
///
|
||||
/// Returns a `SlotStatus` indicating whether:
|
||||
/// - `NotCached`: The account's storage cache doesn't exist
|
||||
/// - `Empty`: The slot exists in the account's cache but is empty
|
||||
/// - `Value`: The slot exists and has a specific value
|
||||
pub(crate) fn get_storage(&self, address: &Address, key: &StorageKey) -> SlotStatus {
|
||||
/// Returns a tuple of:
|
||||
/// - `SlotStatus` indicating whether:
|
||||
/// - `NotCached`: The account's storage cache doesn't exist
|
||||
/// - `Empty`: The slot exists in the account's cache but is empty
|
||||
/// - `Value`: The slot exists and has a specific value
|
||||
/// - `Option<Arc<AccountStorageCache>>`: The account's storage cache if it exists
|
||||
pub(crate) fn get_storage(
|
||||
&self,
|
||||
address: &Address,
|
||||
key: &StorageKey,
|
||||
) -> (SlotStatus, Option<Arc<AccountStorageCache>>) {
|
||||
match self.storage_cache.get(address) {
|
||||
None => SlotStatus::NotCached,
|
||||
Some(account_cache) => account_cache.get_storage(key),
|
||||
None => (SlotStatus::NotCached, None),
|
||||
Some(account_cache) => {
|
||||
let status = account_cache.get_storage(key);
|
||||
(status, Some(account_cache))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert storage value into hierarchical cache
|
||||
#[cfg(test)]
|
||||
pub(crate) fn insert_storage(
|
||||
&self,
|
||||
address: Address,
|
||||
@@ -351,6 +370,15 @@ impl ExecutionCache {
|
||||
self.storage_cache.insert(address, account_cache);
|
||||
}
|
||||
|
||||
/// Inserts the [`AccountStorageCache`].
|
||||
pub(crate) fn insert_storage_cache(
|
||||
&self,
|
||||
address: Address,
|
||||
storage_cache: Arc<AccountStorageCache>,
|
||||
) {
|
||||
self.storage_cache.insert(address, storage_cache);
|
||||
}
|
||||
|
||||
/// Invalidate storage for specific account
|
||||
pub(crate) fn invalidate_account_storage(&self, address: &Address) {
|
||||
self.storage_cache.invalidate(address);
|
||||
@@ -800,7 +828,7 @@ mod tests {
|
||||
caches.insert_storage(address, storage_key, Some(storage_value));
|
||||
|
||||
// check that the storage returns the cached value
|
||||
let slot_status = caches.get_storage(&address, &storage_key);
|
||||
let (slot_status, _) = caches.get_storage(&address, &storage_key);
|
||||
assert_eq!(slot_status, SlotStatus::Value(storage_value));
|
||||
}
|
||||
|
||||
@@ -814,7 +842,7 @@ mod tests {
|
||||
let caches = ExecutionCacheBuilder::default().build_caches(1000);
|
||||
|
||||
// check that the storage is not cached
|
||||
let slot_status = caches.get_storage(&address, &storage_key);
|
||||
let (slot_status, _) = caches.get_storage(&address, &storage_key);
|
||||
assert_eq!(slot_status, SlotStatus::NotCached);
|
||||
}
|
||||
|
||||
@@ -830,7 +858,7 @@ mod tests {
|
||||
caches.insert_storage(address, storage_key, None);
|
||||
|
||||
// check that the storage is empty
|
||||
let slot_status = caches.get_storage(&address, &storage_key);
|
||||
let (slot_status, _) = caches.get_storage(&address, &storage_key);
|
||||
assert_eq!(slot_status, SlotStatus::Empty);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ impl EngineApiMetrics {
|
||||
pub(crate) fn execute_metered<E, DB>(
|
||||
&self,
|
||||
executor: E,
|
||||
transactions: impl Iterator<Item = Result<impl ExecutableTx<E>, BlockExecutionError>>,
|
||||
mut transactions: impl Iterator<Item = Result<impl ExecutableTx<E>, BlockExecutionError>>,
|
||||
state_hook: Box<dyn OnStateHook>,
|
||||
) -> Result<(BlockExecutionOutput<E::Receipt>, Vec<Address>), BlockExecutionError>
|
||||
where
|
||||
@@ -79,27 +79,42 @@ impl EngineApiMetrics {
|
||||
let mut executor = executor.with_state_hook(Some(Box::new(wrapper)));
|
||||
|
||||
let f = || {
|
||||
let start = Instant::now();
|
||||
debug_span!(target: "engine::tree", "pre execution")
|
||||
.entered()
|
||||
.in_scope(|| executor.apply_pre_execution_changes())?;
|
||||
self.executor.pre_execution_histogram.record(start.elapsed());
|
||||
|
||||
let exec_span = debug_span!(target: "engine::tree", "execution").entered();
|
||||
for tx in transactions {
|
||||
loop {
|
||||
let start = Instant::now();
|
||||
let Some(tx) = transactions.next() else { break };
|
||||
self.executor.transaction_wait_histogram.record(start.elapsed());
|
||||
|
||||
let tx = tx?;
|
||||
senders.push(*tx.signer());
|
||||
|
||||
let span =
|
||||
debug_span!(target: "engine::tree", "execute tx", tx_hash=?tx.tx().tx_hash());
|
||||
let enter = span.entered();
|
||||
trace!(target: "engine::tree", "Executing transaction");
|
||||
senders.push(*tx.signer());
|
||||
let start = Instant::now();
|
||||
let gas_used = executor.execute_transaction(tx)?;
|
||||
self.executor.transaction_execution_histogram.record(start.elapsed());
|
||||
|
||||
// record the tx gas used
|
||||
enter.record("gas_used", gas_used);
|
||||
}
|
||||
drop(exec_span);
|
||||
debug_span!(target: "engine::tree", "finish")
|
||||
|
||||
let start = Instant::now();
|
||||
let result = debug_span!(target: "engine::tree", "finish")
|
||||
.entered()
|
||||
.in_scope(|| executor.finish())
|
||||
.map(|(evm, result)| (evm.into_db(), result))
|
||||
.map(|(evm, result)| (evm.into_db(), result));
|
||||
self.executor.post_execution_histogram.record(start.elapsed());
|
||||
|
||||
result
|
||||
};
|
||||
|
||||
// Use metered to execute and track timing/gas metrics
|
||||
@@ -462,6 +477,7 @@ mod tests {
|
||||
receipts: vec![],
|
||||
requests: Requests::default(),
|
||||
gas_used: 1000,
|
||||
block_access_list: None,
|
||||
blob_gas_used: 0,
|
||||
},
|
||||
))
|
||||
@@ -555,10 +571,12 @@ mod tests {
|
||||
nonce: 10,
|
||||
code_hash: B256::random(),
|
||||
code: Default::default(),
|
||||
storage_id: None,
|
||||
},
|
||||
storage,
|
||||
status: AccountStatus::default(),
|
||||
transaction_id: 0,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
state
|
||||
|
||||
@@ -536,7 +536,7 @@ where
|
||||
// null}` if the expected and the actual arrays don't match.
|
||||
//
|
||||
// This validation **MUST** be instantly run in all cases even during active sync process.
|
||||
|
||||
tracing::debug!("Payload received {:?}", payload);
|
||||
let num_hash = payload.num_hash();
|
||||
let engine_event = ConsensusEngineEvent::BlockReceived(num_hash);
|
||||
self.emit_event(EngineApiEvent::BeaconConsensus(engine_event));
|
||||
@@ -545,6 +545,7 @@ where
|
||||
|
||||
// Check for invalid ancestors
|
||||
if let Some(invalid) = self.find_invalid_ancestor(&payload) {
|
||||
tracing::debug!(target: "engine::tree", ?invalid, "found invalid ancestor for payload");
|
||||
let status = self.handle_invalid_ancestor_payload(payload, invalid)?;
|
||||
return Ok(TreeOutcome::new(status));
|
||||
}
|
||||
@@ -553,6 +554,7 @@ where
|
||||
self.metrics.block_validation.record_payload_validation(start.elapsed().as_secs_f64());
|
||||
|
||||
let status = if self.backfill_sync_state.is_idle() {
|
||||
tracing::debug!(target: "engine::tree", "inserting payload directly");
|
||||
self.try_insert_payload(payload)?
|
||||
} else {
|
||||
self.try_buffer_payload(payload)?
|
||||
@@ -591,7 +593,7 @@ where
|
||||
let parent_hash = payload.parent_hash();
|
||||
let mut latest_valid_hash = None;
|
||||
|
||||
match self.insert_payload(payload) {
|
||||
match self.insert_payload(payload.clone()) {
|
||||
Ok(status) => {
|
||||
let status = match status {
|
||||
InsertPayloadOk::Inserted(BlockStatus::Valid) => {
|
||||
@@ -613,7 +615,10 @@ where
|
||||
Ok(PayloadStatus::new(status, latest_valid_hash))
|
||||
}
|
||||
Err(error) => match error {
|
||||
InsertPayloadError::Block(error) => Ok(self.on_insert_block_error(error)?),
|
||||
InsertPayloadError::Block(error) => {
|
||||
tracing::debug!("payload in new payload l 617 {:?}", payload);
|
||||
Ok(self.on_insert_block_error(error)?)
|
||||
}
|
||||
InsertPayloadError::Payload(error) => {
|
||||
Ok(self.on_new_payload_error(error, num_hash, parent_hash)?)
|
||||
}
|
||||
@@ -1901,6 +1906,16 @@ where
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if the given hash is part of the last received sync target fork choice update.
|
||||
///
|
||||
/// See [`ForkchoiceStateTracker::sync_target_state`]
|
||||
fn is_any_sync_target(&self, block_hash: B256) -> bool {
|
||||
if let Some(target) = self.state.forkchoice_state_tracker.sync_target_state() {
|
||||
return target.contains(block_hash)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Checks if the given `check` hash points to an invalid header, inserting the given `head`
|
||||
/// block into the invalid header cache if the `check` hash has a known invalid ancestor.
|
||||
///
|
||||
@@ -2040,9 +2055,12 @@ where
|
||||
match self.insert_block(child) {
|
||||
Ok(res) => {
|
||||
debug!(target: "engine::tree", child =?child_num_hash, ?res, "connected buffered block");
|
||||
if self.is_sync_target_head(child_num_hash.hash) &&
|
||||
if self.is_any_sync_target(child_num_hash.hash) &&
|
||||
matches!(res, InsertPayloadOk::Inserted(BlockStatus::Valid))
|
||||
{
|
||||
debug!(target: "engine::tree", child =?child_num_hash, "connected sync target block");
|
||||
// we just inserted a block that we know is part of the canonical chain, so
|
||||
// we can make it canonical
|
||||
self.make_canonical(child_num_hash.hash)?;
|
||||
}
|
||||
}
|
||||
@@ -2348,11 +2366,15 @@ where
|
||||
// try to append the block
|
||||
match self.insert_block(block) {
|
||||
Ok(InsertPayloadOk::Inserted(BlockStatus::Valid)) => {
|
||||
if self.is_sync_target_head(block_num_hash.hash) {
|
||||
trace!(target: "engine::tree", "appended downloaded sync target block");
|
||||
// check if we just inserted a block that's part of sync targets,
|
||||
// i.e. head, safe, or finalized
|
||||
if let Some(sync_target) = self.state.forkchoice_state_tracker.sync_target_state() &&
|
||||
sync_target.contains(block_num_hash.hash)
|
||||
{
|
||||
debug!(target: "engine::tree", ?sync_target, "appended downloaded sync target block");
|
||||
|
||||
// we just inserted the current sync target block, we can try to make it
|
||||
// canonical
|
||||
// we just inserted a block that we know is part of the canonical chain, so we
|
||||
// can make it canonical
|
||||
return Ok(Some(TreeEvent::TreeAction(TreeAction::MakeCanonical {
|
||||
sync_target_head: block_num_hash.hash,
|
||||
})))
|
||||
|
||||
@@ -21,6 +21,7 @@ use executor::WorkloadExecutor;
|
||||
use multiproof::{SparseTrieUpdate, *};
|
||||
use parking_lot::RwLock;
|
||||
use prewarm::PrewarmMetrics;
|
||||
use rayon::iter::{ParallelBridge, ParallelIterator};
|
||||
use reth_engine_primitives::ExecutableTxIterator;
|
||||
use reth_evm::{
|
||||
execute::{ExecutableTxFor, WithTxEnv},
|
||||
@@ -40,6 +41,7 @@ use reth_trie_sparse::{
|
||||
};
|
||||
use reth_trie_sparse_parallel::{ParallelSparseTrie, ParallelismThresholds};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
sync::{
|
||||
atomic::AtomicBool,
|
||||
mpsc::{self, channel},
|
||||
@@ -312,21 +314,50 @@ where
|
||||
mpsc::Receiver<Result<WithTxEnv<TxEnvFor<Evm>, I::Tx>, I::Error>>,
|
||||
usize,
|
||||
) {
|
||||
let (transactions, convert) = transactions.into();
|
||||
let transactions = transactions.into_iter();
|
||||
// Get the transaction count for prewarming task
|
||||
// Use upper bound if available (more accurate), otherwise use lower bound
|
||||
let (lower, upper) = transactions.size_hint();
|
||||
let transaction_count_hint = upper.unwrap_or(lower);
|
||||
|
||||
// Spawn a task that iterates through all transactions in parallel and sends them to the
|
||||
// main task.
|
||||
let (tx, rx) = mpsc::channel();
|
||||
self.executor.spawn_blocking(move || {
|
||||
transactions.enumerate().par_bridge().for_each_with(tx, |sender, (idx, tx)| {
|
||||
let tx = convert(tx);
|
||||
let tx = tx.map(|tx| WithTxEnv { tx_env: tx.to_tx_env(), tx: Arc::new(tx) });
|
||||
let _ = sender.send((idx, tx));
|
||||
});
|
||||
});
|
||||
|
||||
// Spawn a task that processes out-of-order transactions from the task above and sends them
|
||||
// to prewarming and execution tasks.
|
||||
let (prewarm_tx, prewarm_rx) = mpsc::channel();
|
||||
let (execute_tx, execute_rx) = mpsc::channel();
|
||||
self.executor.spawn_blocking(move || {
|
||||
for tx in transactions {
|
||||
let tx = tx.map(|tx| WithTxEnv { tx_env: tx.to_tx_env(), tx: Arc::new(tx) });
|
||||
let mut next_for_execution = 0;
|
||||
let mut queue = BTreeMap::new();
|
||||
while let Ok((idx, tx)) = rx.recv() {
|
||||
// only send Ok(_) variants to prewarming task
|
||||
if let Ok(tx) = &tx {
|
||||
let _ = prewarm_tx.send(tx.clone());
|
||||
}
|
||||
let _ = execute_tx.send(tx);
|
||||
|
||||
if next_for_execution == idx {
|
||||
let _ = execute_tx.send(tx);
|
||||
next_for_execution += 1;
|
||||
|
||||
while let Some(entry) = queue.first_entry() &&
|
||||
*entry.key() == next_for_execution
|
||||
{
|
||||
let _ = execute_tx.send(entry.remove());
|
||||
next_for_execution += 1;
|
||||
}
|
||||
} else {
|
||||
queue.insert(idx, tx);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -941,10 +972,12 @@ mod tests {
|
||||
nonce: rng.random::<u64>(),
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code: Some(Default::default()),
|
||||
storage_id: None,
|
||||
},
|
||||
storage,
|
||||
status: AccountStatus::Touched,
|
||||
transaction_id: 0,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
state_update.insert(address, account);
|
||||
@@ -1017,13 +1050,19 @@ mod tests {
|
||||
|
||||
let provider_factory = BlockchainProvider::new(factory).unwrap();
|
||||
|
||||
let mut handle = payload_processor.spawn(
|
||||
Default::default(),
|
||||
core::iter::empty::<Result<Recovered<TransactionSigned>, core::convert::Infallible>>(),
|
||||
StateProviderBuilder::new(provider_factory.clone(), genesis_hash, None),
|
||||
OverlayStateProviderFactory::new(provider_factory),
|
||||
&TreeConfig::default(),
|
||||
);
|
||||
let mut handle =
|
||||
payload_processor.spawn(
|
||||
Default::default(),
|
||||
(
|
||||
core::iter::empty::<
|
||||
Result<Recovered<TransactionSigned>, core::convert::Infallible>,
|
||||
>(),
|
||||
std::convert::identity,
|
||||
),
|
||||
StateProviderBuilder::new(provider_factory.clone(), genesis_hash, None),
|
||||
OverlayStateProviderFactory::new(provider_factory),
|
||||
&TreeConfig::default(),
|
||||
);
|
||||
|
||||
let mut state_hook = handle.state_hook();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -213,16 +213,31 @@ where
|
||||
Evm: ConfigureEngineEvm<T::ExecutionData, Primitives = N>,
|
||||
{
|
||||
match input {
|
||||
BlockOrPayload::Payload(payload) => Ok(Either::Left(
|
||||
self.evm_config
|
||||
BlockOrPayload::Payload(payload) => {
|
||||
let (iter, convert) = self
|
||||
.evm_config
|
||||
.tx_iterator_for_payload(payload)
|
||||
.map_err(NewPayloadError::other)?
|
||||
.map(|res| res.map(Either::Left).map_err(NewPayloadError::other)),
|
||||
)),
|
||||
.into();
|
||||
|
||||
let iter = Either::Left(iter.into_iter().map(Either::Left));
|
||||
let convert = move |tx| {
|
||||
let Either::Left(tx) = tx else { unreachable!() };
|
||||
convert(tx).map(Either::Left).map_err(Either::Left)
|
||||
};
|
||||
|
||||
// Box the closure to satisfy the `Fn` bound both here and in the branch below
|
||||
Ok((iter, Box::new(convert) as Box<dyn Fn(_) -> _ + Send + Sync + 'static>))
|
||||
}
|
||||
BlockOrPayload::Block(block) => {
|
||||
Ok(Either::Right(block.body().clone_transactions().into_iter().map(|tx| {
|
||||
Ok(Either::Right(tx.try_into_recovered().map_err(NewPayloadError::other)?))
|
||||
})))
|
||||
let iter =
|
||||
Either::Right(block.body().clone_transactions().into_iter().map(Either::Right));
|
||||
let convert = move |tx: Either<_, N::SignedTx>| {
|
||||
let Either::Right(tx) = tx else { unreachable!() };
|
||||
tx.try_into_recovered().map(Either::Right).map_err(Either::Right)
|
||||
};
|
||||
|
||||
Ok((iter, Box::new(convert)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -587,12 +602,14 @@ where
|
||||
Evm: ConfigureEngineEvm<T::ExecutionData, Primitives = N>,
|
||||
{
|
||||
debug!(target: "engine::tree::payload_validator", "Executing block");
|
||||
|
||||
let mut db = State::builder()
|
||||
.with_database(StateProviderDatabase::new(&state_provider))
|
||||
.with_bundle_update()
|
||||
.with_bal_builder() //TODO
|
||||
.without_state_clear()
|
||||
.build();
|
||||
db.bal_state.bal_index = 0;
|
||||
db.bal_state.bal_builder = Some(revm::state::bal::Bal::new());
|
||||
|
||||
let evm = self.evm_config.evm_with_env(&mut db, env.evm_env.clone());
|
||||
let ctx =
|
||||
|
||||
@@ -276,9 +276,9 @@ mod tests {
|
||||
let dyn_precompile: DynPrecompile = (|_input: PrecompileInput<'_>| -> PrecompileResult {
|
||||
Ok(PrecompileOutput {
|
||||
gas_used: 0,
|
||||
gas_refunded: 0,
|
||||
bytes: Bytes::default(),
|
||||
reverted: false,
|
||||
gas_refunded: 0,
|
||||
})
|
||||
})
|
||||
.into();
|
||||
@@ -288,9 +288,9 @@ mod tests {
|
||||
|
||||
let output = PrecompileOutput {
|
||||
gas_used: 50,
|
||||
gas_refunded: 0,
|
||||
bytes: alloy_primitives::Bytes::copy_from_slice(b"cached_result"),
|
||||
reverted: false,
|
||||
gas_refunded: 0,
|
||||
};
|
||||
|
||||
let key = CacheKey::new(SpecId::PRAGUE, b"test_input".into());
|
||||
@@ -321,9 +321,9 @@ mod tests {
|
||||
|
||||
Ok(PrecompileOutput {
|
||||
gas_used: 5000,
|
||||
gas_refunded: 0,
|
||||
bytes: alloy_primitives::Bytes::copy_from_slice(b"output_from_precompile_1"),
|
||||
reverted: false,
|
||||
gas_refunded: 0,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -336,9 +336,9 @@ mod tests {
|
||||
|
||||
Ok(PrecompileOutput {
|
||||
gas_used: 7000,
|
||||
gas_refunded: 0,
|
||||
bytes: alloy_primitives::Bytes::copy_from_slice(b"output_from_precompile_2"),
|
||||
reverted: false,
|
||||
gas_refunded: 0,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -27,6 +27,9 @@ reth-payload-primitives.workspace = true
|
||||
alloy-rpc-types-engine.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
|
||||
# revm
|
||||
revm.workspace = true
|
||||
|
||||
# async
|
||||
tokio = { workspace = true, default-features = false }
|
||||
tokio-util.workspace = true
|
||||
|
||||
@@ -283,8 +283,12 @@ where
|
||||
let mut state = State::builder()
|
||||
.with_database_ref(StateProviderDatabase::new(&state_provider))
|
||||
.with_bundle_update()
|
||||
.with_bal_builder()
|
||||
.build();
|
||||
|
||||
state.bal_state.bal_index = 0;
|
||||
state.bal_state.bal_builder = Some(revm::state::bal::Bal::new());
|
||||
|
||||
let ctx = evm_config.context_for_block(&reorg_target).map_err(RethError::other)?;
|
||||
let evm = evm_config.evm_for_block(&mut state, &reorg_target).map_err(RethError::other)?;
|
||||
let mut builder = evm_config.create_block_builder(evm, &reorg_target_parent, ctx);
|
||||
|
||||
@@ -252,7 +252,7 @@ where
|
||||
|
||||
/// Extracts block headers and bodies from `iter` and appends them using `writer` and `provider`.
|
||||
///
|
||||
/// Adds on to `total_difficulty` and collects hash to height using `hash_collector`.
|
||||
/// Collects hash to height using `hash_collector`.
|
||||
///
|
||||
/// Skips all blocks below the [`start_bound`] of `block_numbers` and stops when reaching past the
|
||||
/// [`end_bound`] or the end of the file.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
//! transactions: vec![Bytes::from(vec![1, 2, 3])],
|
||||
//! ommers: vec![],
|
||||
//! withdrawals: None,
|
||||
//! block_access_list: None,
|
||||
//! };
|
||||
//! // Compress the body: rlp encoding and snappy compression
|
||||
//! let compressed_body = CompressedBody::from_body(&body)?;
|
||||
@@ -581,8 +582,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_block_body_conversion() {
|
||||
let block_body: BlockBody<Bytes> =
|
||||
BlockBody { transactions: vec![], ommers: vec![], withdrawals: None };
|
||||
let block_body: BlockBody<Bytes> = BlockBody {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: None,
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
let compressed_body = CompressedBody::from_body(&block_body).unwrap();
|
||||
|
||||
@@ -637,7 +642,8 @@ mod tests {
|
||||
|
||||
let withdrawals = Some(Withdrawals(vec![]));
|
||||
|
||||
let block_body = BlockBody { transactions, ommers: vec![], withdrawals };
|
||||
let block_body =
|
||||
BlockBody { transactions, ommers: vec![], withdrawals, block_access_list: None };
|
||||
|
||||
let block = Block::new(header, block_body);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ pub(crate) fn create_header() -> Header {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +139,7 @@ pub(crate) fn create_test_block_with_compressed_data(number: BlockNumber) -> Blo
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash: None,
|
||||
};
|
||||
|
||||
// Create test body
|
||||
@@ -145,6 +147,7 @@ pub(crate) fn create_test_block_with_compressed_data(number: BlockNumber) -> Blo
|
||||
transactions: vec![Bytes::from(vec![(number % 256) as u8; 10])],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Withdrawals(vec![])),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
// Create test receipt list with bloom
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
//! Simple decoding and decompressing tests
|
||||
//! for mainnet era files
|
||||
|
||||
use reth_era::{
|
||||
common::file_ops::{StreamReader, StreamWriter},
|
||||
era::file::{EraReader, EraWriter},
|
||||
};
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::{EraTestDownloader, HOODI};
|
||||
|
||||
// Helper function to test decompression and decoding for a specific era file
|
||||
async fn test_era_file_decompression_and_decoding(
|
||||
downloader: &EraTestDownloader,
|
||||
filename: &str,
|
||||
network: &str,
|
||||
) -> eyre::Result<()> {
|
||||
println!("\nTesting file: {filename}");
|
||||
let file = downloader.open_era_file(filename, network).await?;
|
||||
|
||||
// Handle genesis era separately
|
||||
if file.group.is_genesis() {
|
||||
// Genesis has no blocks
|
||||
assert_eq!(file.group.blocks.len(), 0, "Genesis should have no blocks");
|
||||
assert!(file.group.slot_index.is_none(), "Genesis should not have block slot index");
|
||||
|
||||
// Test genesis state decompression
|
||||
let state_data = file.group.era_state.decompress()?;
|
||||
assert!(!state_data.is_empty(), "Genesis state should decompress to non-empty data");
|
||||
|
||||
// Verify state slot index
|
||||
assert_eq!(
|
||||
file.group.state_slot_index.slot_count(),
|
||||
1,
|
||||
"Genesis state index should have count of 1"
|
||||
);
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
{
|
||||
let mut writer = EraWriter::new(&mut buffer);
|
||||
writer.write_file(&file)?;
|
||||
}
|
||||
|
||||
let reader = EraReader::new(Cursor::new(&buffer));
|
||||
let read_back_file = reader.read(file.id.network_name.clone())?;
|
||||
|
||||
assert_eq!(
|
||||
file.group.era_state.decompress()?,
|
||||
read_back_file.group.era_state.decompress()?,
|
||||
"Genesis state data should be identical"
|
||||
);
|
||||
|
||||
println!("Genesis era verified successfully");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Non-genesis era - test beacon blocks
|
||||
println!(
|
||||
" Non-genesis era with {} beacon blocks, starting at slot {}",
|
||||
file.group.blocks.len(),
|
||||
file.group.starting_slot()
|
||||
);
|
||||
|
||||
// Test beacon block decompression across different positions
|
||||
let test_block_indices = [
|
||||
0, // First block
|
||||
file.group.blocks.len() / 2, // Middle block
|
||||
file.group.blocks.len() - 1, // Last block
|
||||
];
|
||||
|
||||
for &block_idx in &test_block_indices {
|
||||
let block = &file.group.blocks[block_idx];
|
||||
let slot = file.group.starting_slot() + block_idx as u64;
|
||||
|
||||
println!(
|
||||
"\n Testing beacon block at slot {}, compressed size: {} bytes",
|
||||
slot,
|
||||
block.data.len()
|
||||
);
|
||||
|
||||
// Test beacon block decompression
|
||||
let block_data = block.decompress()?;
|
||||
assert!(
|
||||
!block_data.is_empty(),
|
||||
"Beacon block at slot {slot} decompression should produce non-empty data"
|
||||
);
|
||||
}
|
||||
|
||||
// Test era state decompression
|
||||
let state_data = file.group.era_state.decompress()?;
|
||||
assert!(!state_data.is_empty(), "Era state decompression should produce non-empty data");
|
||||
println!(" Era state decompressed: {} bytes", state_data.len());
|
||||
|
||||
// Verify slot indices
|
||||
if let Some(ref block_slot_index) = file.group.slot_index {
|
||||
println!(
|
||||
" Block slot index: starting_slot={}, count={}",
|
||||
block_slot_index.starting_slot,
|
||||
block_slot_index.slot_count()
|
||||
);
|
||||
|
||||
// Check for empty slots
|
||||
let empty_slots: Vec<usize> = (0..block_slot_index.slot_count())
|
||||
.filter(|&i| !block_slot_index.has_data_at_slot(i))
|
||||
.collect();
|
||||
|
||||
if !empty_slots.is_empty() {
|
||||
println!(
|
||||
" Found {} empty slots (first few): {:?}",
|
||||
empty_slots.len(),
|
||||
&empty_slots[..empty_slots.len().min(5)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Test round-trip serialization
|
||||
let mut buffer = Vec::new();
|
||||
{
|
||||
let mut writer = EraWriter::new(&mut buffer);
|
||||
writer.write_file(&file)?;
|
||||
}
|
||||
|
||||
// Read back from buffer
|
||||
let reader = EraReader::new(Cursor::new(&buffer));
|
||||
let read_back_file = reader.read(file.id.network_name.clone())?;
|
||||
|
||||
// Verify basic properties are preserved
|
||||
assert_eq!(file.id.network_name, read_back_file.id.network_name);
|
||||
assert_eq!(file.id.start_slot, read_back_file.id.start_slot);
|
||||
assert_eq!(file.id.slot_count, read_back_file.id.slot_count);
|
||||
assert_eq!(file.group.blocks.len(), read_back_file.group.blocks.len());
|
||||
|
||||
// Test data preservation for beacon blocks
|
||||
for &idx in &test_block_indices {
|
||||
let original_block = &file.group.blocks[idx];
|
||||
let read_back_block = &read_back_file.group.blocks[idx];
|
||||
let slot = file.group.starting_slot() + idx as u64;
|
||||
|
||||
// Test that decompressed data is identical
|
||||
assert_eq!(
|
||||
original_block.decompress()?,
|
||||
read_back_block.decompress()?,
|
||||
"Beacon block data should be identical for slot {slot}"
|
||||
);
|
||||
}
|
||||
|
||||
// Test state data preservation
|
||||
assert_eq!(
|
||||
file.group.era_state.decompress()?,
|
||||
read_back_file.group.era_state.decompress()?,
|
||||
"Era state data should be identical"
|
||||
);
|
||||
|
||||
// Test slot indices preservation
|
||||
if let (Some(original_index), Some(read_index)) =
|
||||
(&file.group.slot_index, &read_back_file.group.slot_index)
|
||||
{
|
||||
assert_eq!(
|
||||
original_index.starting_slot, read_index.starting_slot,
|
||||
"Block slot index starting slot should match"
|
||||
);
|
||||
assert_eq!(
|
||||
original_index.offsets, read_index.offsets,
|
||||
"Block slot index offsets should match"
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
file.group.state_slot_index.starting_slot,
|
||||
read_back_file.group.state_slot_index.starting_slot,
|
||||
"State slot index starting slot should match"
|
||||
);
|
||||
assert_eq!(
|
||||
file.group.state_slot_index.offsets, read_back_file.group.state_slot_index.offsets,
|
||||
"State slot index offsets should match"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case::test_case("hoodi-00000-212f13fc.era"; "era_dd_hoodi_0")]
|
||||
#[test_case::test_case("hoodi-00021-857e418b.era"; "era_dd_hoodi_21")]
|
||||
#[test_case::test_case("hoodi-00175-202aaa6d.era"; "era_dd_hoodi_175")]
|
||||
#[test_case::test_case("hoodi-00201-0d521fc8.era"; "era_dd_hoodi_201")]
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore = "download intensive"]
|
||||
async fn test_hoodi_era1_file_decompression_and_decoding(filename: &str) -> eyre::Result<()> {
|
||||
let downloader = EraTestDownloader::new().await?;
|
||||
test_era_file_decompression_and_decoding(&downloader, filename, HOODI).await
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
mod dd;
|
||||
mod genesis;
|
||||
mod roundtrip;
|
||||
|
||||
228
crates/era/tests/it/era/roundtrip.rs
Normal file
228
crates/era/tests/it/era/roundtrip.rs
Normal file
@@ -0,0 +1,228 @@
|
||||
//! Roundtrip tests for `.era` files.
|
||||
//!
|
||||
//! These tests verify the full lifecycle of era files by:
|
||||
//! - Reading files from their original source
|
||||
//! - Decompressing their contents
|
||||
//! - Re-compressing the data
|
||||
//! - Writing the data back to a new file
|
||||
//! - Confirming that all original data is preserved throughout the process
|
||||
//!
|
||||
//!
|
||||
//! Only a couple of era files are downloaded from `https://mainnet.era.nimbus.team/` for mainnet
|
||||
//! and `https://hoodi.era.nimbus.team/` for hoodi to keep the tests efficient.
|
||||
|
||||
use reth_era::{
|
||||
common::file_ops::{EraFileFormat, StreamReader, StreamWriter},
|
||||
era::{
|
||||
file::{EraFile, EraReader, EraWriter},
|
||||
types::{
|
||||
consensus::{CompressedBeaconState, CompressedSignedBeaconBlock},
|
||||
group::{EraGroup, EraId},
|
||||
},
|
||||
},
|
||||
};
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::{EraTestDownloader, HOODI, MAINNET};
|
||||
|
||||
// Helper function to test roundtrip compression/encoding for a specific file
|
||||
async fn test_era_file_roundtrip(
|
||||
downloader: &EraTestDownloader,
|
||||
filename: &str,
|
||||
network: &str,
|
||||
) -> eyre::Result<()> {
|
||||
println!("\nTesting roundtrip for file: {filename}");
|
||||
|
||||
let original_file = downloader.open_era_file(filename, network).await?;
|
||||
|
||||
if original_file.group.is_genesis() {
|
||||
println!("Genesis era detected, using special handling");
|
||||
assert_eq!(original_file.group.blocks.len(), 0, "Genesis should have no blocks");
|
||||
assert!(
|
||||
original_file.group.slot_index.is_none(),
|
||||
"Genesis should not have block slot index"
|
||||
);
|
||||
|
||||
let state_data = original_file.group.era_state.decompress()?;
|
||||
println!(" Genesis state decompressed: {} bytes", state_data.len());
|
||||
|
||||
// File roundtrip test
|
||||
let mut buffer = Vec::new();
|
||||
{
|
||||
let mut writer = EraWriter::new(&mut buffer);
|
||||
writer.write_file(&original_file)?;
|
||||
}
|
||||
|
||||
let reader = EraReader::new(Cursor::new(&buffer));
|
||||
let roundtrip_file = reader.read(network.to_string())?;
|
||||
|
||||
assert_eq!(
|
||||
original_file.group.era_state.decompress()?,
|
||||
roundtrip_file.group.era_state.decompress()?,
|
||||
"Genesis state data should be identical after roundtrip"
|
||||
);
|
||||
|
||||
println!("Genesis era verified successfully");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// non genesis start
|
||||
let original_state_data = original_file.group.era_state.decompress()?;
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
{
|
||||
let mut writer = EraWriter::new(&mut buffer);
|
||||
writer.write_file(&original_file)?;
|
||||
}
|
||||
|
||||
// Read back from buffer
|
||||
let reader = EraReader::new(Cursor::new(&buffer));
|
||||
let roundtrip_file = reader.read(network.to_string())?;
|
||||
|
||||
assert_eq!(
|
||||
original_file.id.network_name, roundtrip_file.id.network_name,
|
||||
"Network name should match after roundtrip"
|
||||
);
|
||||
assert_eq!(
|
||||
original_file.id.start_slot, roundtrip_file.id.start_slot,
|
||||
"Start slot should match after roundtrip"
|
||||
);
|
||||
assert_eq!(
|
||||
original_file.group.blocks.len(),
|
||||
roundtrip_file.group.blocks.len(),
|
||||
"Block count should match after roundtrip"
|
||||
);
|
||||
|
||||
// Select a few blocks to test
|
||||
let test_block_indices = [
|
||||
0, // First block
|
||||
original_file.group.blocks.len() / 2, // Middle block
|
||||
original_file.group.blocks.len() - 1, // Last block
|
||||
];
|
||||
|
||||
// Test individual beacon blocks
|
||||
for &block_idx in &test_block_indices {
|
||||
let original_block = &original_file.group.blocks[block_idx];
|
||||
let roundtrip_block = &roundtrip_file.group.blocks[block_idx];
|
||||
|
||||
let original_block_data = original_block.decompress()?;
|
||||
let roundtrip_block_data = roundtrip_block.decompress()?;
|
||||
|
||||
// Verify file roundtrip preserves data
|
||||
assert_eq!(
|
||||
original_block_data, roundtrip_block_data,
|
||||
"Block {block_idx} data should be identical after file roundtrip"
|
||||
);
|
||||
|
||||
// Verify compression roundtrip
|
||||
let recompressed_block = CompressedSignedBeaconBlock::from_ssz(&original_block_data)?;
|
||||
let recompressed_block_data = recompressed_block.decompress()?;
|
||||
|
||||
assert_eq!(
|
||||
original_block_data, recompressed_block_data,
|
||||
"Block {block_idx} should be identical after re-compression cycle"
|
||||
);
|
||||
}
|
||||
|
||||
let roundtrip_state_data = roundtrip_file.group.era_state.decompress()?;
|
||||
|
||||
assert_eq!(
|
||||
original_state_data, roundtrip_state_data,
|
||||
"Era state data should be identical after roundtrip"
|
||||
);
|
||||
|
||||
let recompressed_state = CompressedBeaconState::from_ssz(&roundtrip_state_data)?;
|
||||
let recompressed_state_data = recompressed_state.decompress()?;
|
||||
|
||||
assert_eq!(
|
||||
original_state_data, recompressed_state_data,
|
||||
"Era state data should be identical after re-compression cycle"
|
||||
);
|
||||
|
||||
let recompressed_blocks: Vec<CompressedSignedBeaconBlock> = roundtrip_file
|
||||
.group
|
||||
.blocks
|
||||
.iter()
|
||||
.map(|block| {
|
||||
let data = block.decompress()?;
|
||||
CompressedSignedBeaconBlock::from_ssz(&data)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let new_group = if let Some(ref block_index) = roundtrip_file.group.slot_index {
|
||||
EraGroup::with_block_index(
|
||||
recompressed_blocks,
|
||||
recompressed_state,
|
||||
block_index.clone(),
|
||||
roundtrip_file.group.state_slot_index.clone(),
|
||||
)
|
||||
} else {
|
||||
EraGroup::new(
|
||||
recompressed_blocks,
|
||||
recompressed_state,
|
||||
roundtrip_file.group.state_slot_index,
|
||||
)
|
||||
};
|
||||
|
||||
let (start_slot, slot_count) = new_group.slot_range();
|
||||
let new_file = EraFile::new(new_group, EraId::new(network, start_slot, slot_count));
|
||||
|
||||
let mut reconstructed_buffer = Vec::new();
|
||||
{
|
||||
let mut writer = EraWriter::new(&mut reconstructed_buffer);
|
||||
writer.write_file(&new_file)?;
|
||||
}
|
||||
|
||||
let reader = EraReader::new(Cursor::new(&reconstructed_buffer));
|
||||
let reconstructed_file = reader.read(network.to_string())?;
|
||||
|
||||
assert_eq!(
|
||||
original_file.group.blocks.len(),
|
||||
reconstructed_file.group.blocks.len(),
|
||||
"Block count should match after full reconstruction"
|
||||
);
|
||||
|
||||
// Verify all reconstructed blocks match
|
||||
for (idx, (orig, recon)) in
|
||||
original_file.group.blocks.iter().zip(reconstructed_file.group.blocks.iter()).enumerate()
|
||||
{
|
||||
assert_eq!(
|
||||
orig.decompress()?,
|
||||
recon.decompress()?,
|
||||
"Block {idx} should match after full reconstruction"
|
||||
);
|
||||
}
|
||||
|
||||
// Verify reconstructed state matches
|
||||
assert_eq!(
|
||||
original_state_data,
|
||||
reconstructed_file.group.era_state.decompress()?,
|
||||
"State should match after full reconstruction"
|
||||
);
|
||||
|
||||
println!("File {filename} roundtrip successful");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case::test_case("mainnet-00000-4b363db9.era"; "era_roundtrip_mainnet_0")]
|
||||
#[test_case::test_case("mainnet-00178-0d0a5290.era"; "era_roundtrip_mainnet_178")]
|
||||
#[test_case::test_case("mainnet-01070-7616e3e2.era"; "era_roundtrip_mainnet_1070")]
|
||||
#[test_case::test_case("mainnet-01267-e3ddc749.era"; "era_roundtrip_mainnet_1267")]
|
||||
#[test_case::test_case("mainnet-01592-d4dc8b98.era"; "era_roundtrip_mainnet_1592")]
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore = "download intensive"]
|
||||
async fn test_roundtrip_compression_encoding_mainnet(filename: &str) -> eyre::Result<()> {
|
||||
let downloader = EraTestDownloader::new().await?;
|
||||
test_era_file_roundtrip(&downloader, filename, MAINNET).await
|
||||
}
|
||||
|
||||
#[test_case::test_case("hoodi-00000-212f13fc.era"; "era_roundtrip_hoodi_0")]
|
||||
#[test_case::test_case("hoodi-00021-857e418b.era"; "era_roundtrip_hoodi_21")]
|
||||
#[test_case::test_case("hoodi-00175-202aaa6d.era"; "era_roundtrip_hoodi_175")]
|
||||
#[test_case::test_case("hoodi-00201-0d521fc8.era"; "era_roundtrip_hoodi_201")]
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore = "download intensive"]
|
||||
async fn test_roundtrip_compression_encoding_hoodi(filename: &str) -> eyre::Result<()> {
|
||||
let downloader = EraTestDownloader::new().await?;
|
||||
test_era_file_roundtrip(&downloader, filename, HOODI).await
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
//! Simple decoding and decompressing tests
|
||||
//! for mainnet era1 files
|
||||
|
||||
use alloy_consensus::{BlockBody, Header};
|
||||
use alloy_primitives::U256;
|
||||
use reth_era::{
|
||||
common::file_ops::{StreamReader, StreamWriter},
|
||||
e2s::types::IndexEntry,
|
||||
era1::{
|
||||
file::{Era1Reader, Era1Writer},
|
||||
types::execution::CompressedBody,
|
||||
},
|
||||
};
|
||||
use reth_ethereum_primitives::TransactionSigned;
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::{EraTestDownloader, MAINNET};
|
||||
|
||||
// Helper function to test decompression and decoding for a specific era1 file
|
||||
async fn test_file_decompression(
|
||||
downloader: &EraTestDownloader,
|
||||
filename: &str,
|
||||
) -> eyre::Result<()> {
|
||||
println!("\nTesting file: {filename}");
|
||||
let file = downloader.open_era1_file(filename, MAINNET).await?;
|
||||
|
||||
// Test block decompression across different positions in the file
|
||||
let test_block_indices = [
|
||||
0, // First block
|
||||
file.group.blocks.len() / 2, // Middle block
|
||||
file.group.blocks.len() - 1, // Last block
|
||||
];
|
||||
|
||||
for &block_idx in &test_block_indices {
|
||||
let block = &file.group.blocks[block_idx];
|
||||
let block_number = file.group.block_index.starting_number() + block_idx as u64;
|
||||
|
||||
println!(
|
||||
"\n Testing block {}, compressed body size: {} bytes",
|
||||
block_number,
|
||||
block.body.data.len()
|
||||
);
|
||||
|
||||
// Test header decompression and decoding
|
||||
let header_data = block.header.decompress()?;
|
||||
assert!(
|
||||
!header_data.is_empty(),
|
||||
"Block {block_number} header decompression should produce non-empty data"
|
||||
);
|
||||
|
||||
let header = block.header.decode_header()?;
|
||||
assert_eq!(header.number, block_number, "Decoded header should have correct block number");
|
||||
println!("Header decompression and decoding successful");
|
||||
|
||||
// Test body decompression
|
||||
let body_data = block.body.decompress()?;
|
||||
assert!(
|
||||
!body_data.is_empty(),
|
||||
"Block {block_number} body decompression should produce non-empty data"
|
||||
);
|
||||
println!("Body decompression successful ({} bytes)", body_data.len());
|
||||
|
||||
let decoded_body: BlockBody<TransactionSigned> =
|
||||
CompressedBody::decode_body_from_decompressed::<TransactionSigned, Header>(&body_data)
|
||||
.expect("Failed to decode body");
|
||||
|
||||
println!(
|
||||
"Body decoding successful: {} transactions, {} ommers, withdrawals: {}",
|
||||
decoded_body.transactions.len(),
|
||||
decoded_body.ommers.len(),
|
||||
decoded_body.withdrawals.is_some()
|
||||
);
|
||||
|
||||
// Test receipts decompression
|
||||
let receipts_data = block.receipts.decompress()?;
|
||||
assert!(
|
||||
!receipts_data.is_empty(),
|
||||
"Block {block_number} receipts decompression should produce non-empty data"
|
||||
);
|
||||
println!("Receipts decompression successful ({} bytes)", receipts_data.len());
|
||||
|
||||
assert!(
|
||||
block.total_difficulty.value > U256::ZERO,
|
||||
"Block {block_number} should have non-zero difficulty"
|
||||
);
|
||||
println!("Total difficulty verified: {}", block.total_difficulty.value);
|
||||
}
|
||||
|
||||
// Test round-trip serialization
|
||||
println!("\n Testing data preservation roundtrip...");
|
||||
let mut buffer = Vec::new();
|
||||
{
|
||||
let mut writer = Era1Writer::new(&mut buffer);
|
||||
writer.write_file(&file)?;
|
||||
}
|
||||
|
||||
// Read back from buffer
|
||||
let reader = Era1Reader::new(Cursor::new(&buffer));
|
||||
let read_back_file = reader.read(file.id.network_name.clone())?;
|
||||
|
||||
// Verify basic properties are preserved
|
||||
assert_eq!(file.id.network_name, read_back_file.id.network_name);
|
||||
assert_eq!(file.id.start_block, read_back_file.id.start_block);
|
||||
assert_eq!(file.group.blocks.len(), read_back_file.group.blocks.len());
|
||||
assert_eq!(file.group.accumulator.root, read_back_file.group.accumulator.root);
|
||||
|
||||
// Test data preservation for some blocks
|
||||
for &idx in &test_block_indices {
|
||||
let original_block = &file.group.blocks[idx];
|
||||
let read_back_block = &read_back_file.group.blocks[idx];
|
||||
let block_number = file.group.block_index.starting_number() + idx as u64;
|
||||
|
||||
println!("Block {block_number} details:");
|
||||
println!(" Header size: {} bytes", original_block.header.data.len());
|
||||
println!(" Body size: {} bytes", original_block.body.data.len());
|
||||
println!(" Receipts size: {} bytes", original_block.receipts.data.len());
|
||||
|
||||
// Test that decompressed data is identical
|
||||
assert_eq!(
|
||||
original_block.header.decompress()?,
|
||||
read_back_block.header.decompress()?,
|
||||
"Header data should be identical for block {block_number}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
original_block.body.decompress()?,
|
||||
read_back_block.body.decompress()?,
|
||||
"Body data should be identical for block {block_number}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
original_block.receipts.decompress()?,
|
||||
read_back_block.receipts.decompress()?,
|
||||
"Receipts data should be identical for block {block_number}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
original_block.total_difficulty.value, read_back_block.total_difficulty.value,
|
||||
"Total difficulty should be identical for block {block_number}"
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case::test_case("mainnet-00000-5ec1ffb8.era1"; "era_dd_mainnet_0")]
|
||||
#[test_case::test_case("mainnet-00003-d8b8a40b.era1"; "era_dd_mainnet_3")]
|
||||
#[test_case::test_case("mainnet-00151-e322efe1.era1"; "era_dd_mainnet_151")]
|
||||
#[test_case::test_case("mainnet-00293-0d6c5812.era1"; "era_dd_mainnet_293")]
|
||||
#[test_case::test_case("mainnet-00443-ea71b6f9.era1"; "era_dd_mainnet_443")]
|
||||
#[test_case::test_case("mainnet-01367-d7efc68f.era1"; "era_dd_mainnet_1367")]
|
||||
#[test_case::test_case("mainnet-01610-99fdde4b.era1"; "era_dd_mainnet_1610")]
|
||||
#[test_case::test_case("mainnet-01895-3f81607c.era1"; "era_dd_mainnet_1895")]
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore = "download intensive"]
|
||||
async fn test_mainnet_era1_file_decompression_and_decoding(filename: &str) -> eyre::Result<()> {
|
||||
let downloader = EraTestDownloader::new().await?;
|
||||
test_file_decompression(&downloader, filename).await
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
mod dd;
|
||||
mod genesis;
|
||||
mod roundtrip;
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
//! - Re-encoding and recompressing the data
|
||||
//! - Writing the data back to a new file
|
||||
//! - Confirming that all original data is preserved throughout the process
|
||||
//!
|
||||
//! Only a couple of era1 files are downloaded from <https://era.ithaca.xyz/era1/> for mainnet
|
||||
//! and <https://era.ithaca.xyz/sepolia-era1/> for sepolia to keep the tests efficient.
|
||||
|
||||
use alloy_consensus::{BlockBody, BlockHeader, Header, ReceiptEnvelope};
|
||||
use reth_era::{
|
||||
@@ -27,7 +30,7 @@ use std::io::Cursor;
|
||||
use crate::{EraTestDownloader, MAINNET, SEPOLIA};
|
||||
|
||||
// Helper function to test roundtrip compression/encoding for a specific file
|
||||
async fn test_file_roundtrip(
|
||||
async fn test_era1_file_roundtrip(
|
||||
downloader: &EraTestDownloader,
|
||||
filename: &str,
|
||||
network: &str,
|
||||
@@ -252,27 +255,27 @@ async fn test_file_roundtrip(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case::test_case("mainnet-00000-5ec1ffb8.era1"; "era_mainnet_0")]
|
||||
#[test_case::test_case("mainnet-00151-e322efe1.era1"; "era_mainnet_151")]
|
||||
#[test_case::test_case("mainnet-01367-d7efc68f.era1"; "era_mainnet_1367")]
|
||||
#[test_case::test_case("mainnet-01895-3f81607c.era1"; "era_mainnet_1895")]
|
||||
#[test_case::test_case("mainnet-00000-5ec1ffb8.era1"; "era1_roundtrip_mainnet_0")]
|
||||
#[test_case::test_case("mainnet-00151-e322efe1.era1"; "era1_roundtrip_mainnet_151")]
|
||||
#[test_case::test_case("mainnet-01367-d7efc68f.era1"; "era1_roundtrip_mainnet_1367")]
|
||||
#[test_case::test_case("mainnet-01895-3f81607c.era1"; "era1_roundtrip_mainnet_1895")]
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore = "download intensive"]
|
||||
async fn test_roundtrip_compression_encoding_mainnet(filename: &str) -> eyre::Result<()> {
|
||||
let downloader = EraTestDownloader::new().await?;
|
||||
test_file_roundtrip(&downloader, filename, MAINNET).await
|
||||
test_era1_file_roundtrip(&downloader, filename, MAINNET).await
|
||||
}
|
||||
|
||||
#[test_case::test_case("sepolia-00000-643a00f7.era1"; "era_sepolia_0")]
|
||||
#[test_case::test_case("sepolia-00074-0e81003c.era1"; "era_sepolia_74")]
|
||||
#[test_case::test_case("sepolia-00173-b6924da5.era1"; "era_sepolia_173")]
|
||||
#[test_case::test_case("sepolia-00182-a4f0a8a1.era1"; "era_sepolia_182")]
|
||||
#[test_case::test_case("sepolia-00000-643a00f7.era1"; "era1_roundtrip_sepolia_0")]
|
||||
#[test_case::test_case("sepolia-00074-0e81003c.era1"; "era1_roundtrip_sepolia_74")]
|
||||
#[test_case::test_case("sepolia-00173-b6924da5.era1"; "era1_roundtrip_sepolia_173")]
|
||||
#[test_case::test_case("sepolia-00182-a4f0a8a1.era1"; "era1_roundtrip_sepolia_182")]
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore = "download intensive"]
|
||||
async fn test_roundtrip_compression_encoding_sepolia(filename: &str) -> eyre::Result<()> {
|
||||
let downloader = EraTestDownloader::new().await?;
|
||||
|
||||
test_file_roundtrip(&downloader, filename, SEPOLIA).await?;
|
||||
test_era1_file_roundtrip(&downloader, filename, SEPOLIA).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -91,16 +91,19 @@ const ERA_MAINNET_URL: &str = "https://mainnet.era.nimbus.team/";
|
||||
/// Succinct list of mainnet files we want to download
|
||||
/// from <https://mainnet.era.nimbus.team/> //TODO: to replace with internal era files hosting url
|
||||
/// for testing purposes
|
||||
const ERA_MAINNET_FILES_NAMES: [&str; 4] = [
|
||||
const ERA_MAINNET_FILES_NAMES: [&str; 8] = [
|
||||
"mainnet-00000-4b363db9.era",
|
||||
"mainnet-00178-0d0a5290.era",
|
||||
"mainnet-00518-4e267a3a.era",
|
||||
"mainnet-01140-f70d4869.era",
|
||||
"mainnet-00780-bb546fec.era",
|
||||
"mainnet-01070-7616e3e2.era",
|
||||
"mainnet-01267-e3ddc749.era",
|
||||
"mainnet-01581-82073d28.era",
|
||||
"mainnet-01592-d4dc8b98.era",
|
||||
];
|
||||
|
||||
/// Utility for downloading `.era1` files for tests
|
||||
/// in a temporary directory
|
||||
/// and caching them in memory
|
||||
/// Utility for downloading `.era` and `.era1` files for tests
|
||||
/// in a temporary directory and caching them in memory
|
||||
#[derive(Debug)]
|
||||
struct EraTestDownloader {
|
||||
/// Temporary directory for storing downloaded files
|
||||
@@ -180,7 +183,7 @@ impl EraTestDownloader {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get network configuration, URL and supported files, based on network and file type
|
||||
/// Get network configuration, URL and supported files, based on network and file type
|
||||
fn get_network_config(
|
||||
&self,
|
||||
filename: &str,
|
||||
@@ -202,14 +205,13 @@ impl EraTestDownloader {
|
||||
}
|
||||
}
|
||||
|
||||
/// open .era1 file, downloading it if necessary
|
||||
/// Open `.era1` file, downloading it if necessary
|
||||
async fn open_era1_file(&self, filename: &str, network: &str) -> Result<Era1File> {
|
||||
let path = self.download_file(filename, network).await?;
|
||||
Era1Reader::open(&path, network).map_err(|e| eyre!("Failed to open Era1 file: {e}"))
|
||||
}
|
||||
|
||||
/// open .era file, downloading it if necessary
|
||||
#[allow(dead_code)]
|
||||
/// Open `.era` file, downloading it if necessary
|
||||
async fn open_era_file(&self, filename: &str, network: &str) -> Result<EraFile> {
|
||||
let path = self.download_file(filename, network).await?;
|
||||
EraReader::open(&path, network).map_err(|e| eyre!("Failed to open Era1 file: {e}"))
|
||||
|
||||
@@ -22,6 +22,7 @@ reth-consensus.workspace = true
|
||||
alloy-eips.workspace = true
|
||||
alloy-primitives.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
alloy-rlp.workspace = true
|
||||
|
||||
tracing.workspace = true
|
||||
|
||||
@@ -38,6 +39,7 @@ std = [
|
||||
"reth-execution-types/std",
|
||||
"reth-primitives-traits/std",
|
||||
"tracing/std",
|
||||
"alloy-rlp/std",
|
||||
]
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -75,7 +75,13 @@ where
|
||||
block: &RecoveredBlock<N::Block>,
|
||||
result: &BlockExecutionResult<N::Receipt>,
|
||||
) -> Result<(), ConsensusError> {
|
||||
validate_block_post_execution(block, &self.chain_spec, &result.receipts, &result.requests)
|
||||
validate_block_post_execution(
|
||||
block,
|
||||
&self.chain_spec,
|
||||
&result.receipts,
|
||||
&result.requests,
|
||||
&result.block_access_list,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +182,15 @@ where
|
||||
} else if header.requests_hash().is_some() {
|
||||
return Err(ConsensusError::RequestsHashUnexpected)
|
||||
}
|
||||
// if self.chain_spec.is_amsterdam_active_at_timestamp(header.timestamp()) &&
|
||||
// header.block_access_list_hash().is_none()
|
||||
// {
|
||||
// return Err(ConsensusError::BlockAccessListHashMissing)
|
||||
// } else if !self.chain_spec.is_amsterdam_active_at_timestamp(header.timestamp()) &&
|
||||
// header.block_access_list_hash().is_some()
|
||||
// {
|
||||
// return Err(ConsensusError::BlockAccessListHashUnexpected)
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use alloc::vec::Vec;
|
||||
use alloy_consensus::{proofs::calculate_receipt_root, BlockHeader, TxReceipt};
|
||||
use alloy_eips::{eip7685::Requests, Encodable2718};
|
||||
use alloy_eips::{eip7685::Requests, eip7928::BlockAccessList, Encodable2718};
|
||||
use alloy_primitives::{Bloom, Bytes, B256};
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_primitives_traits::{
|
||||
receipt::gas_spent_by_transactions, Block, GotExpected, Receipt, RecoveredBlock,
|
||||
receipt::gas_spent_by_transactions, Block, BlockBody, GotExpected, Receipt, RecoveredBlock,
|
||||
};
|
||||
|
||||
/// Validate a block with regard to execution results:
|
||||
@@ -17,6 +17,7 @@ pub fn validate_block_post_execution<B, R, ChainSpec>(
|
||||
chain_spec: &ChainSpec,
|
||||
receipts: &[R],
|
||||
requests: &Requests,
|
||||
block_access_list: &Option<BlockAccessList>,
|
||||
) -> Result<(), ConsensusError>
|
||||
where
|
||||
B: Block,
|
||||
@@ -65,6 +66,33 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// Validate bal hash matches the calculated hash
|
||||
if chain_spec.is_amsterdam_active_at_timestamp(block.header().timestamp()) {
|
||||
let Some(header_block_access_list_hash) = block.header().block_access_list_hash() else {
|
||||
return Err(ConsensusError::BlockAccessListHashMissing)
|
||||
};
|
||||
if let Some(bal) = block_access_list {
|
||||
let bal_hash = alloy_primitives::keccak256(alloy_rlp::encode(bal));
|
||||
let block_bal = block.body().block_access_list();
|
||||
tracing::debug!("Block Bal :{:?}", block_bal);
|
||||
if let Some(body_bal) = block_bal {
|
||||
if body_bal.len() == 0 {
|
||||
tracing::debug!("Hit Empty BAL : Block is {:?}", block);
|
||||
}
|
||||
verify_bal(body_bal, bal)?;
|
||||
}
|
||||
|
||||
if bal_hash != header_block_access_list_hash {
|
||||
tracing::debug!(
|
||||
?bal_hash,
|
||||
?header_block_access_list_hash,
|
||||
"block access list hash mismatch"
|
||||
);
|
||||
return Err(ConsensusError::InvalidBalHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -115,6 +143,47 @@ fn compare_receipts_root_and_logs_bloom(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates that the block access list in the body matches the expected block access list.
|
||||
fn verify_bal(
|
||||
body_bal: &BlockAccessList,
|
||||
expected_bal: &BlockAccessList,
|
||||
) -> Result<(), ConsensusError> {
|
||||
if body_bal == expected_bal {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Extract addresses
|
||||
let body_addrs: Vec<_> = body_bal.iter().map(|a| a.address).collect();
|
||||
let expected_addrs: Vec<_> = expected_bal.iter().map(|a| a.address).collect();
|
||||
|
||||
// Missing accounts (expected but not found in body)
|
||||
for addr in &expected_addrs {
|
||||
if !body_addrs.contains(addr) {
|
||||
tracing::debug!("Missing acc : computed bal {:?},body bal{:?}", expected_bal, body_bal);
|
||||
tracing::debug!("Missing Address: {:?}", addr);
|
||||
return Err(ConsensusError::InvalidBalMissingAccount);
|
||||
}
|
||||
}
|
||||
|
||||
// Extra accounts (body has accounts not in expected)
|
||||
for addr in &body_addrs {
|
||||
if !expected_addrs.contains(addr) {
|
||||
tracing::debug!("Extra acc : computed bal {:?},body bal{:?}", expected_bal, body_bal);
|
||||
tracing::debug!("Extra Address: {:?}", addr);
|
||||
return Err(ConsensusError::InvalidBalExtraAccount);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::debug!(
|
||||
?expected_bal,
|
||||
?body_bal,
|
||||
"block access list in body does not match the provided block access list"
|
||||
);
|
||||
|
||||
// Fallback: mismatched access lists
|
||||
Err(ConsensusError::InvalidBlockAccessList)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -17,7 +17,9 @@ pub use payload::{payload_id, BlobSidecars, EthBuiltPayload, EthPayloadBuilderAt
|
||||
mod error;
|
||||
pub use error::*;
|
||||
|
||||
use alloy_rpc_types_engine::{ExecutionData, ExecutionPayload, ExecutionPayloadEnvelopeV5};
|
||||
use alloy_rpc_types_engine::{
|
||||
ExecutionData, ExecutionPayload, ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6,
|
||||
};
|
||||
pub use alloy_rpc_types_engine::{
|
||||
ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4,
|
||||
ExecutionPayloadV1, PayloadAttributes as EthPayloadAttributes,
|
||||
@@ -66,13 +68,15 @@ where
|
||||
+ TryInto<ExecutionPayloadEnvelopeV2>
|
||||
+ TryInto<ExecutionPayloadEnvelopeV3>
|
||||
+ TryInto<ExecutionPayloadEnvelopeV4>
|
||||
+ TryInto<ExecutionPayloadEnvelopeV5>,
|
||||
+ TryInto<ExecutionPayloadEnvelopeV5>
|
||||
+ TryInto<ExecutionPayloadEnvelopeV6>,
|
||||
{
|
||||
type ExecutionPayloadEnvelopeV1 = ExecutionPayloadV1;
|
||||
type ExecutionPayloadEnvelopeV2 = ExecutionPayloadEnvelopeV2;
|
||||
type ExecutionPayloadEnvelopeV3 = ExecutionPayloadEnvelopeV3;
|
||||
type ExecutionPayloadEnvelopeV4 = ExecutionPayloadEnvelopeV4;
|
||||
type ExecutionPayloadEnvelopeV5 = ExecutionPayloadEnvelopeV5;
|
||||
type ExecutionPayloadEnvelopeV6 = ExecutionPayloadEnvelopeV6;
|
||||
}
|
||||
|
||||
/// A default payload type for [`EthEngineTypes`]
|
||||
|
||||
@@ -11,8 +11,9 @@ use alloy_primitives::{Address, B256, U256};
|
||||
use alloy_rlp::Encodable;
|
||||
use alloy_rpc_types_engine::{
|
||||
BlobsBundleV1, BlobsBundleV2, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3,
|
||||
ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadFieldV2,
|
||||
ExecutionPayloadV1, ExecutionPayloadV3, PayloadAttributes, PayloadId,
|
||||
ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6,
|
||||
ExecutionPayloadFieldV2, ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4,
|
||||
PayloadAttributes, PayloadId,
|
||||
};
|
||||
use core::convert::Infallible;
|
||||
use reth_ethereum_primitives::EthPrimitives;
|
||||
@@ -158,6 +159,38 @@ impl EthBuiltPayload {
|
||||
execution_requests: requests.unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Try converting built payload into [`ExecutionPayloadEnvelopeV6`].
|
||||
pub fn try_into_v6(self) -> Result<ExecutionPayloadEnvelopeV6, BuiltPayloadConversionError> {
|
||||
let Self { block, fees, sidecars, requests, .. } = self;
|
||||
|
||||
let blobs_bundle = match sidecars {
|
||||
BlobSidecars::Empty => BlobsBundleV2::empty(),
|
||||
BlobSidecars::Eip7594(sidecars) => BlobsBundleV2::from(sidecars),
|
||||
BlobSidecars::Eip4844(_) => {
|
||||
return Err(BuiltPayloadConversionError::UnexpectedEip4844Sidecars)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ExecutionPayloadEnvelopeV6 {
|
||||
execution_payload: ExecutionPayloadV4::from_block_unchecked(
|
||||
block.hash(),
|
||||
&Arc::unwrap_or_clone(block).into_block(),
|
||||
),
|
||||
block_value: fees,
|
||||
// From the engine API spec:
|
||||
//
|
||||
// > Client software **MAY** use any heuristics to decide whether to set
|
||||
// `shouldOverrideBuilder` flag or not. If client software does not implement any
|
||||
// heuristic this flag **SHOULD** be set to `false`.
|
||||
//
|
||||
// Spec:
|
||||
// <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#specification-2>
|
||||
should_override_builder: false,
|
||||
blobs_bundle,
|
||||
execution_requests: requests.unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NodePrimitives> BuiltPayload for EthBuiltPayload<N> {
|
||||
@@ -225,6 +258,14 @@ impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV5 {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV6 {
|
||||
type Error = BuiltPayloadConversionError;
|
||||
|
||||
fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
|
||||
value.try_into_v6()
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum representing blob transaction sidecars belonging to [`EthBuiltPayload`].
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub enum BlobSidecars {
|
||||
|
||||
@@ -27,6 +27,7 @@ alloy-eips.workspace = true
|
||||
alloy-evm.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
alloy-rpc-types-engine.workspace = true
|
||||
alloy-rlp.workspace = true
|
||||
|
||||
# Misc
|
||||
parking_lot = { workspace = true, optional = true }
|
||||
@@ -57,6 +58,7 @@ std = [
|
||||
"derive_more?/std",
|
||||
"alloy-rpc-types-engine/std",
|
||||
"reth-storage-errors/std",
|
||||
"alloy-rlp/std",
|
||||
]
|
||||
test-utils = [
|
||||
"dep:parking_lot",
|
||||
|
||||
@@ -48,7 +48,8 @@ where
|
||||
execution_ctx: ctx,
|
||||
parent,
|
||||
transactions,
|
||||
output: BlockExecutionResult { receipts, requests, gas_used, blob_gas_used },
|
||||
output:
|
||||
BlockExecutionResult { receipts, requests, gas_used, blob_gas_used, block_access_list },
|
||||
state_root,
|
||||
..
|
||||
} = input;
|
||||
@@ -93,6 +94,18 @@ where
|
||||
};
|
||||
}
|
||||
|
||||
let (built_block_access_list, block_access_list_hash) =
|
||||
if self.chain_spec.is_amsterdam_active_at_timestamp(timestamp) {
|
||||
if let Some(bal) = block_access_list {
|
||||
let hash = alloy_primitives::keccak256(alloy_rlp::encode(bal));
|
||||
(Some(bal), Some(hash))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let header = Header {
|
||||
parent_hash: ctx.parent_hash,
|
||||
ommers_hash: EMPTY_OMMER_ROOT_HASH,
|
||||
@@ -115,11 +128,17 @@ where
|
||||
blob_gas_used: block_blob_gas_used,
|
||||
excess_blob_gas,
|
||||
requests_hash,
|
||||
block_access_list_hash,
|
||||
};
|
||||
|
||||
Ok(Block {
|
||||
header,
|
||||
body: BlockBody { transactions, ommers: Default::default(), withdrawals },
|
||||
body: BlockBody {
|
||||
transactions,
|
||||
ommers: Default::default(),
|
||||
withdrawals,
|
||||
block_access_list: built_block_access_list.cloned(),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,12 +289,15 @@ where
|
||||
&self,
|
||||
payload: &ExecutionData,
|
||||
) -> Result<impl ExecutableTxIterator<Self>, Self::Error> {
|
||||
Ok(payload.payload.transactions().clone().into_iter().map(|tx| {
|
||||
let txs = payload.payload.transactions().clone().into_iter();
|
||||
let convert = |tx: Bytes| {
|
||||
let tx =
|
||||
TxTy::<Self::Primitives>::decode_2718_exact(tx.as_ref()).map_err(AnyError::new)?;
|
||||
let signer = tx.try_recover().map_err(AnyError::new)?;
|
||||
Ok::<_, AnyError>(tx.with_signer(signer))
|
||||
}))
|
||||
};
|
||||
|
||||
Ok((txs, convert))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::EthEvmConfig;
|
||||
use alloc::{boxed::Box, sync::Arc, vec, vec::Vec};
|
||||
use alloy_consensus::Header;
|
||||
use alloy_eips::eip7685::Requests;
|
||||
use alloy_evm::precompiles::PrecompilesMap;
|
||||
use alloy_evm::{block::StateDB, precompiles::PrecompilesMap};
|
||||
use alloy_primitives::Bytes;
|
||||
use alloy_rpc_types_engine::ExecutionData;
|
||||
use parking_lot::Mutex;
|
||||
@@ -19,7 +19,6 @@ use reth_execution_types::{BlockExecutionResult, ExecutionOutcome};
|
||||
use reth_primitives_traits::{BlockTy, SealedBlock, SealedHeader};
|
||||
use revm::{
|
||||
context::result::{ExecutionResult, Output, ResultAndState, SuccessReason},
|
||||
database::State,
|
||||
Inspector,
|
||||
};
|
||||
|
||||
@@ -58,12 +57,12 @@ impl BlockExecutorFactory for MockEvmConfig {
|
||||
|
||||
fn create_executor<'a, DB, I>(
|
||||
&'a self,
|
||||
evm: EthEvm<&'a mut State<DB>, I, PrecompilesMap>,
|
||||
evm: EthEvm<DB, I, PrecompilesMap>,
|
||||
_ctx: Self::ExecutionCtx<'a>,
|
||||
) -> impl BlockExecutorFor<'a, Self, DB, I>
|
||||
where
|
||||
DB: Database + 'a,
|
||||
I: Inspector<<Self::EvmFactory as EvmFactory>::Context<&'a mut State<DB>>> + 'a,
|
||||
DB: StateDB + Database + 'a,
|
||||
I: Inspector<<Self::EvmFactory as EvmFactory>::Context<DB>> + 'a,
|
||||
{
|
||||
MockExecutor { result: self.exec_results.lock().pop().unwrap(), evm, hook: None }
|
||||
}
|
||||
@@ -71,17 +70,17 @@ impl BlockExecutorFactory for MockEvmConfig {
|
||||
|
||||
/// Mock executor that returns a fixed execution result.
|
||||
#[derive(derive_more::Debug)]
|
||||
pub struct MockExecutor<'a, DB: Database, I> {
|
||||
pub struct MockExecutor<DB: Database, I> {
|
||||
result: ExecutionOutcome,
|
||||
evm: EthEvm<&'a mut State<DB>, I, PrecompilesMap>,
|
||||
evm: EthEvm<DB, I, PrecompilesMap>,
|
||||
#[debug(skip)]
|
||||
hook: Option<Box<dyn reth_evm::OnStateHook>>,
|
||||
}
|
||||
|
||||
impl<'a, DB: Database, I: Inspector<EthEvmContext<&'a mut State<DB>>>> BlockExecutor
|
||||
for MockExecutor<'a, DB, I>
|
||||
impl<DB: StateDB + Database, I: Inspector<EthEvmContext<DB>>> BlockExecutor
|
||||
for MockExecutor<DB, I>
|
||||
{
|
||||
type Evm = EthEvm<&'a mut State<DB>, I, PrecompilesMap>;
|
||||
type Evm = EthEvm<DB, I, PrecompilesMap>;
|
||||
type Transaction = TransactionSigned;
|
||||
type Receipt = Receipt;
|
||||
|
||||
@@ -125,10 +124,11 @@ impl<'a, DB: Database, I: Inspector<EthEvmContext<&'a mut State<DB>>>> BlockExec
|
||||
reqs
|
||||
}),
|
||||
gas_used: 0,
|
||||
block_access_list: None,
|
||||
blob_gas_used: 0,
|
||||
};
|
||||
|
||||
evm.db_mut().bundle_state = bundle;
|
||||
*evm.db_mut().bundle_state_mut() = bundle;
|
||||
|
||||
Ok((evm, result))
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ fn create_database_with_beacon_root_contract() -> CacheDB<EmptyDB> {
|
||||
code_hash: keccak256(BEACON_ROOTS_CODE.clone()),
|
||||
nonce: 1,
|
||||
code: Some(Bytecode::new_raw(BEACON_ROOTS_CODE.clone())),
|
||||
storage_id: None,
|
||||
};
|
||||
|
||||
db.insert_account_info(BEACON_ROOTS_ADDRESS, beacon_root_contract_account);
|
||||
@@ -53,6 +54,7 @@ fn create_database_with_withdrawal_requests_contract() -> CacheDB<EmptyDB> {
|
||||
balance: U256::ZERO,
|
||||
code_hash: keccak256(WITHDRAWAL_REQUEST_PREDEPLOY_CODE.clone()),
|
||||
code: Some(Bytecode::new_raw(WITHDRAWAL_REQUEST_PREDEPLOY_CODE.clone())),
|
||||
storage_id: None,
|
||||
};
|
||||
|
||||
db.insert_account_info(
|
||||
@@ -86,7 +88,12 @@ fn eip_4788_non_genesis_call() {
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header: header.clone(),
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
body: BlockBody {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: None,
|
||||
block_access_list: None,
|
||||
},
|
||||
},
|
||||
vec![],
|
||||
))
|
||||
@@ -105,7 +112,12 @@ fn eip_4788_non_genesis_call() {
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header: header.clone(),
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
body: BlockBody {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: None,
|
||||
block_access_list: None,
|
||||
},
|
||||
},
|
||||
vec![],
|
||||
))
|
||||
@@ -165,7 +177,12 @@ fn eip_4788_no_code_cancun() {
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header,
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
body: BlockBody {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: None,
|
||||
block_access_list: None,
|
||||
},
|
||||
},
|
||||
vec![],
|
||||
))
|
||||
@@ -207,7 +224,12 @@ fn eip_4788_empty_account_call() {
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header,
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
body: BlockBody {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: None,
|
||||
block_access_list: None,
|
||||
},
|
||||
},
|
||||
vec![],
|
||||
))
|
||||
@@ -339,6 +361,7 @@ fn create_database_with_block_hashes(latest_block: u64) -> CacheDB<EmptyDB> {
|
||||
code_hash: keccak256(HISTORY_STORAGE_CODE.clone()),
|
||||
code: Some(Bytecode::new_raw(HISTORY_STORAGE_CODE.clone())),
|
||||
nonce: 1,
|
||||
storage_id: None,
|
||||
};
|
||||
|
||||
db.insert_account_info(HISTORY_STORAGE_ADDRESS, blockhashes_contract_account);
|
||||
@@ -796,6 +819,7 @@ fn test_balance_increment_not_duplicated() {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(vec![withdrawal].into()),
|
||||
block_access_list: None,
|
||||
},
|
||||
},
|
||||
vec![],
|
||||
|
||||
@@ -154,9 +154,13 @@ where
|
||||
|
||||
let state_provider = client.state_by_block_hash(parent_header.hash())?;
|
||||
let state = StateProviderDatabase::new(&state_provider);
|
||||
let mut db =
|
||||
State::builder().with_database(cached_reads.as_db_mut(state)).with_bundle_update().build();
|
||||
|
||||
let mut db = State::builder()
|
||||
.with_database(cached_reads.as_db_mut(state))
|
||||
.with_bundle_update()
|
||||
.with_bal_builder()
|
||||
.build();
|
||||
db.bal_state.bal_index = 0;
|
||||
db.bal_state.bal_builder = Some(revm::state::bal::Bal::new());
|
||||
let mut builder = evm_config
|
||||
.builder_for_next_block(
|
||||
&mut db,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use alloy_consensus::Block;
|
||||
use alloy_rpc_types_engine::{ExecutionData, PayloadError};
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_payload_validator::{cancun, prague, shanghai};
|
||||
use reth_payload_validator::{amsterdam, cancun, prague, shanghai};
|
||||
use reth_primitives_traits::{Block as _, SealedBlock, SignedTransaction};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -103,5 +103,10 @@ where
|
||||
chain_spec.is_prague_active_at_timestamp(sealed_block.timestamp),
|
||||
)?;
|
||||
|
||||
amsterdam::ensure_well_formed_fields(
|
||||
sealed_block.body(),
|
||||
chain_spec.is_amsterdam_active_at_timestamp(sealed_block.timestamp),
|
||||
)?;
|
||||
|
||||
Ok(sealed_block)
|
||||
}
|
||||
|
||||
@@ -18,22 +18,51 @@ pub trait ConfigureEngineEvm<ExecutionData>: ConfigureEvm {
|
||||
) -> Result<impl ExecutableTxIterator<Self>, Self::Error>;
|
||||
}
|
||||
|
||||
/// Iterator over executable transactions.
|
||||
pub trait ExecutableTxIterator<Evm: ConfigureEvm>:
|
||||
Iterator<Item = Result<Self::Tx, Self::Error>> + Send + 'static
|
||||
{
|
||||
/// A helper trait representing a pair of a "raw" transactions iterator and a closure that can be
|
||||
/// used to convert them to an executable transaction. This tuple is used in the engine to
|
||||
/// parallelize heavy work like decoding or recovery.
|
||||
pub trait ExecutableTxTuple: Into<(Self::Iter, Self::Convert)> + Send + 'static {
|
||||
/// Raw transaction that can be converted to an [`ExecutableTxTuple::Tx`]
|
||||
///
|
||||
/// This can be any type that can be converted to an [`ExecutableTxTuple::Tx`]. For example,
|
||||
/// an unrecovered transaction or just the transaction bytes.
|
||||
type RawTx: Send + Sync + 'static;
|
||||
/// The executable transaction type iterator yields.
|
||||
type Tx: ExecutableTxFor<Evm> + Clone + Send + Sync + 'static;
|
||||
type Tx: Clone + Send + Sync + 'static;
|
||||
/// Errors that may occur while recovering or decoding transactions.
|
||||
type Error: core::error::Error + Send + Sync + 'static;
|
||||
|
||||
/// Iterator over [`ExecutableTxTuple::Tx`]
|
||||
type Iter: Iterator<Item = Self::RawTx> + Send + 'static;
|
||||
/// Closure that can be used to convert a [`ExecutableTxTuple::RawTx`] to a
|
||||
/// [`ExecutableTxTuple::Tx`]. This might involve heavy work like decoding or recovery
|
||||
/// and will be parallelized in the engine.
|
||||
type Convert: Fn(Self::RawTx) -> Result<Self::Tx, Self::Error> + Send + Sync + 'static;
|
||||
}
|
||||
|
||||
impl<Evm: ConfigureEvm, Tx, Err, T> ExecutableTxIterator<Evm> for T
|
||||
impl<RawTx, Tx, Err, I, F> ExecutableTxTuple for (I, F)
|
||||
where
|
||||
Tx: ExecutableTxFor<Evm> + Clone + Send + Sync + 'static,
|
||||
RawTx: Send + Sync + 'static,
|
||||
Tx: Clone + Send + Sync + 'static,
|
||||
Err: core::error::Error + Send + Sync + 'static,
|
||||
T: Iterator<Item = Result<Tx, Err>> + Send + 'static,
|
||||
I: Iterator<Item = RawTx> + Send + 'static,
|
||||
F: Fn(RawTx) -> Result<Tx, Err> + Send + Sync + 'static,
|
||||
{
|
||||
type RawTx = RawTx;
|
||||
type Tx = Tx;
|
||||
type Error = Err;
|
||||
|
||||
type Iter = I;
|
||||
type Convert = F;
|
||||
}
|
||||
|
||||
/// Iterator over executable transactions.
|
||||
pub trait ExecutableTxIterator<Evm: ConfigureEvm>:
|
||||
ExecutableTxTuple<Tx: ExecutableTxFor<Evm>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, Evm: ConfigureEvm> ExecutableTxIterator<Evm> for T where
|
||||
T: ExecutableTxTuple<Tx: ExecutableTxFor<Evm>>
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//! Traits for execution.
|
||||
|
||||
use crate::{ConfigureEvm, Database, OnStateHook, TxEnvFor};
|
||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloy_consensus::{BlockHeader, Header};
|
||||
use alloy_eips::eip2718::WithEncoded;
|
||||
pub use alloy_evm::block::{BlockExecutor, BlockExecutorFactory};
|
||||
use alloy_evm::{
|
||||
block::{CommitChanges, ExecutableTx},
|
||||
block::{CommitChanges, ExecutableTx, StateDB},
|
||||
Evm, EvmEnv, EvmFactory, RecoveredTx, ToTxEnv,
|
||||
};
|
||||
use alloy_primitives::{Address, B256};
|
||||
@@ -214,7 +214,7 @@ pub struct BlockAssemblerInput<'a, 'b, F: BlockExecutorFactory, H = Header> {
|
||||
/// Output of block execution.
|
||||
pub output: &'b BlockExecutionResult<F::Receipt>,
|
||||
/// [`BundleState`] after the block execution.
|
||||
pub bundle_state: &'a BundleState,
|
||||
pub bundle_state: Cow<'a, BundleState>,
|
||||
/// Provider with access to state.
|
||||
#[debug(skip)]
|
||||
pub state_provider: &'b dyn StateProvider,
|
||||
@@ -234,7 +234,7 @@ impl<'a, 'b, F: BlockExecutorFactory, H> BlockAssemblerInput<'a, 'b, F, H> {
|
||||
parent: &'a SealedHeader<H>,
|
||||
transactions: Vec<F::Transaction>,
|
||||
output: &'b BlockExecutionResult<F::Receipt>,
|
||||
bundle_state: &'a BundleState,
|
||||
bundle_state: impl Into<Cow<'a, BundleState>>,
|
||||
state_provider: &'b dyn StateProvider,
|
||||
state_root: B256,
|
||||
) -> Self {
|
||||
@@ -244,7 +244,7 @@ impl<'a, 'b, F: BlockExecutorFactory, H> BlockAssemblerInput<'a, 'b, F, H> {
|
||||
parent,
|
||||
transactions,
|
||||
output,
|
||||
bundle_state,
|
||||
bundle_state: bundle_state.into(),
|
||||
state_provider,
|
||||
state_root,
|
||||
}
|
||||
@@ -461,8 +461,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F, DB, Executor, Builder, N> BlockBuilder
|
||||
for BasicBlockBuilder<'a, F, Executor, Builder, N>
|
||||
impl<'a, F, Executor, Builder, N> BlockBuilder for BasicBlockBuilder<'a, F, Executor, Builder, N>
|
||||
where
|
||||
F: BlockExecutorFactory<Transaction = N::SignedTx, Receipt = N::Receipt>,
|
||||
Executor: BlockExecutor<
|
||||
@@ -470,12 +469,11 @@ where
|
||||
Spec = <F::EvmFactory as EvmFactory>::Spec,
|
||||
HaltReason = <F::EvmFactory as EvmFactory>::HaltReason,
|
||||
BlockEnv = <F::EvmFactory as EvmFactory>::BlockEnv,
|
||||
DB = &'a mut State<DB>,
|
||||
DB: StateDB + 'a,
|
||||
>,
|
||||
Transaction = N::SignedTx,
|
||||
Receipt = N::Receipt,
|
||||
>,
|
||||
DB: Database + 'a,
|
||||
Builder: BlockAssembler<F, Block = N::Block>,
|
||||
N: NodePrimitives,
|
||||
{
|
||||
@@ -508,13 +506,13 @@ where
|
||||
state: impl StateProvider,
|
||||
) -> Result<BlockBuilderOutcome<N>, BlockExecutionError> {
|
||||
let (evm, result) = self.executor.finish()?;
|
||||
let (db, evm_env) = evm.finish();
|
||||
let (mut db, evm_env) = evm.finish();
|
||||
|
||||
// merge all transitions into bundle state
|
||||
db.merge_transitions(BundleRetention::Reverts);
|
||||
|
||||
// calculate the state root
|
||||
let hashed_state = state.hashed_post_state(&db.bundle_state);
|
||||
let hashed_state = state.hashed_post_state(db.bundle_state());
|
||||
let (state_root, trie_updates) = state
|
||||
.state_root_with_updates(hashed_state.clone())
|
||||
.map_err(BlockExecutionError::other)?;
|
||||
@@ -528,7 +526,7 @@ where
|
||||
parent: self.parent,
|
||||
transactions,
|
||||
output: &result,
|
||||
bundle_state: &db.bundle_state,
|
||||
bundle_state: Cow::Owned(db.take_bundle()),
|
||||
state_provider: &state,
|
||||
state_root,
|
||||
})?;
|
||||
@@ -564,8 +562,14 @@ pub struct BasicBlockExecutor<F, DB> {
|
||||
impl<F, DB: Database> BasicBlockExecutor<F, DB> {
|
||||
/// Creates a new `BasicBlockExecutor` with the given strategy.
|
||||
pub fn new(strategy_factory: F, db: DB) -> Self {
|
||||
let db =
|
||||
State::builder().with_database(db).with_bundle_update().without_state_clear().build();
|
||||
let mut db = State::builder()
|
||||
.with_database(db)
|
||||
.with_bundle_update()
|
||||
.with_bal_builder()
|
||||
.without_state_clear()
|
||||
.build();
|
||||
db.bal_state.bal_index = 0;
|
||||
db.bal_state.bal_builder = Some(revm::state::bal::Bal::new());
|
||||
Self { strategy_factory, db }
|
||||
}
|
||||
}
|
||||
@@ -741,6 +745,7 @@ mod tests {
|
||||
nonce,
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code: None,
|
||||
storage_id: None,
|
||||
};
|
||||
state.insert_account(addr, account_info);
|
||||
state
|
||||
@@ -777,8 +782,13 @@ mod tests {
|
||||
|
||||
let mut state = setup_state_with_account(addr1, 100, 1);
|
||||
|
||||
let account2 =
|
||||
AccountInfo { balance: U256::from(200), nonce: 1, code_hash: KECCAK_EMPTY, code: None };
|
||||
let account2 = AccountInfo {
|
||||
balance: U256::from(200),
|
||||
nonce: 1,
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code: None,
|
||||
storage_id: None,
|
||||
};
|
||||
state.insert_account(addr2, account2);
|
||||
|
||||
let mut increments = HashMap::default();
|
||||
@@ -799,8 +809,13 @@ mod tests {
|
||||
|
||||
let mut state = setup_state_with_account(addr1, 100, 1);
|
||||
|
||||
let account2 =
|
||||
AccountInfo { balance: U256::from(200), nonce: 1, code_hash: KECCAK_EMPTY, code: None };
|
||||
let account2 = AccountInfo {
|
||||
balance: U256::from(200),
|
||||
nonce: 1,
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code: None,
|
||||
storage_id: None,
|
||||
};
|
||||
state.insert_account(addr2, account2);
|
||||
|
||||
let mut increments = HashMap::default();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
extern crate alloc;
|
||||
|
||||
use crate::execute::{BasicBlockBuilder, Executor};
|
||||
use ::revm::context::TxEnv;
|
||||
use alloc::vec::Vec;
|
||||
use alloy_eips::{
|
||||
eip2718::{EIP2930_TX_TYPE_ID, LEGACY_TX_TYPE_ID},
|
||||
@@ -25,7 +26,7 @@ use alloy_eips::{
|
||||
eip4895::Withdrawals,
|
||||
};
|
||||
use alloy_evm::{
|
||||
block::{BlockExecutorFactory, BlockExecutorFor},
|
||||
block::{BlockExecutorFactory, BlockExecutorFor, StateDB},
|
||||
precompiles::PrecompilesMap,
|
||||
};
|
||||
use alloy_primitives::{Address, B256};
|
||||
@@ -35,7 +36,7 @@ use reth_execution_errors::BlockExecutionError;
|
||||
use reth_primitives_traits::{
|
||||
BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
|
||||
};
|
||||
use revm::{context::TxEnv, database::State};
|
||||
use revm::DatabaseCommit;
|
||||
|
||||
pub mod either;
|
||||
/// EVM environment configuration.
|
||||
@@ -312,20 +313,20 @@ pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
|
||||
/// Creates a strategy with given EVM and execution context.
|
||||
fn create_executor<'a, DB, I>(
|
||||
&'a self,
|
||||
evm: EvmFor<Self, &'a mut State<DB>, I>,
|
||||
evm: EvmFor<Self, DB, I>,
|
||||
ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
|
||||
) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
|
||||
where
|
||||
DB: Database,
|
||||
I: InspectorFor<Self, &'a mut State<DB>> + 'a,
|
||||
DB: StateDB + DatabaseCommit + Database + 'a,
|
||||
I: InspectorFor<Self, DB> + 'a,
|
||||
{
|
||||
self.block_executor_factory().create_executor(evm, ctx)
|
||||
}
|
||||
|
||||
/// Creates a strategy for execution of a given block.
|
||||
fn executor_for_block<'a, DB: Database>(
|
||||
fn executor_for_block<'a, DB: StateDB + DatabaseCommit + Database + 'a>(
|
||||
&'a self,
|
||||
db: &'a mut State<DB>,
|
||||
db: DB,
|
||||
block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
|
||||
) -> Result<impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>, Self::Error> {
|
||||
let evm = self.evm_for_block(db, block.header())?;
|
||||
@@ -350,7 +351,7 @@ pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
|
||||
/// ```
|
||||
fn create_block_builder<'a, DB, I>(
|
||||
&'a self,
|
||||
evm: EvmFor<Self, &'a mut State<DB>, I>,
|
||||
evm: EvmFor<Self, DB, I>,
|
||||
parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
|
||||
ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
|
||||
) -> impl BlockBuilder<
|
||||
@@ -358,8 +359,8 @@ pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
|
||||
Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>,
|
||||
>
|
||||
where
|
||||
DB: Database,
|
||||
I: InspectorFor<Self, &'a mut State<DB>> + 'a,
|
||||
DB: StateDB + DatabaseCommit + Database + 'a,
|
||||
I: InspectorFor<Self, DB> + 'a,
|
||||
{
|
||||
BasicBlockBuilder {
|
||||
executor: self.create_executor(evm, ctx.clone()),
|
||||
@@ -399,9 +400,9 @@ pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
|
||||
/// // Complete block building
|
||||
/// let outcome = builder.finish(state_provider)?;
|
||||
/// ```
|
||||
fn builder_for_next_block<'a, DB: Database>(
|
||||
fn builder_for_next_block<'a, DB: StateDB + DatabaseCommit + Database + 'a>(
|
||||
&'a self,
|
||||
db: &'a mut State<DB>,
|
||||
db: DB,
|
||||
parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
|
||||
attributes: Self::NextBlockEnvCtx,
|
||||
) -> Result<
|
||||
|
||||
@@ -17,6 +17,14 @@ pub struct ExecutorMetrics {
|
||||
/// The Histogram for amount of gas used.
|
||||
pub gas_used_histogram: Histogram,
|
||||
|
||||
/// The Histogram for amount of time taken to execute the pre-execution changes.
|
||||
pub pre_execution_histogram: Histogram,
|
||||
/// The Histogram for amount of time taken to wait for one transaction to be available.
|
||||
pub transaction_wait_histogram: Histogram,
|
||||
/// The Histogram for amount of time taken to execute one transaction.
|
||||
pub transaction_execution_histogram: Histogram,
|
||||
/// The Histogram for amount of time taken to execute the post-execution changes.
|
||||
pub post_execution_histogram: Histogram,
|
||||
/// The Histogram for amount of time taken to execute blocks.
|
||||
pub execution_histogram: Histogram,
|
||||
/// The total amount of time it took to execute the latest block.
|
||||
|
||||
@@ -929,10 +929,20 @@ mod tests {
|
||||
let address3 = Address::random();
|
||||
|
||||
// Set up account info with some changes
|
||||
let account_info1 =
|
||||
AccountInfo { nonce: 1, balance: U256::from(100), code_hash: B256::ZERO, code: None };
|
||||
let account_info2 =
|
||||
AccountInfo { nonce: 2, balance: U256::from(200), code_hash: B256::ZERO, code: None };
|
||||
let account_info1 = AccountInfo {
|
||||
nonce: 1,
|
||||
balance: U256::from(100),
|
||||
code_hash: B256::ZERO,
|
||||
code: None,
|
||||
storage_id: None,
|
||||
};
|
||||
let account_info2 = AccountInfo {
|
||||
nonce: 2,
|
||||
balance: U256::from(200),
|
||||
code_hash: B256::ZERO,
|
||||
code: None,
|
||||
storage_id: None,
|
||||
};
|
||||
|
||||
// Set up the bundle state with these accounts
|
||||
let mut bundle_state = BundleState::default();
|
||||
|
||||
@@ -185,22 +185,22 @@ mod tests {
|
||||
|
||||
// wal with 1 block and tx
|
||||
// <https://github.com/paradigmxyz/reth/issues/15012>
|
||||
#[test]
|
||||
fn decode_notification_wal() {
|
||||
let wal = include_bytes!("../../test-data/28.wal");
|
||||
let notification: reth_exex_types::serde_bincode_compat::ExExNotification<
|
||||
'_,
|
||||
reth_ethereum_primitives::EthPrimitives,
|
||||
> = rmp_serde::decode::from_slice(wal.as_slice()).unwrap();
|
||||
let notification: ExExNotification = notification.into();
|
||||
match notification {
|
||||
ExExNotification::ChainCommitted { new } => {
|
||||
assert_eq!(new.blocks().len(), 1);
|
||||
assert_eq!(new.tip().transaction_count(), 1);
|
||||
}
|
||||
_ => panic!("unexpected notification"),
|
||||
}
|
||||
}
|
||||
// #[test]
|
||||
// fn decode_notification_wal() {
|
||||
// let wal = include_bytes!("../../test-data/28.wal");
|
||||
// let notification: reth_exex_types::serde_bincode_compat::ExExNotification<
|
||||
// '_,
|
||||
// reth_ethereum_primitives::EthPrimitives,
|
||||
// > = rmp_serde::decode::from_slice(wal.as_slice()).unwrap();
|
||||
// let notification: ExExNotification = notification.into();
|
||||
// match notification {
|
||||
// ExExNotification::ChainCommitted { new } => {
|
||||
// assert_eq!(new.blocks().len(), 1);
|
||||
// assert_eq!(new.tip().transaction_count(), 1);
|
||||
// }
|
||||
// _ => panic!("unexpected notification"),
|
||||
// }
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_roundtrip() -> eyre::Result<()> {
|
||||
|
||||
@@ -95,17 +95,33 @@ pub(super) mod serde_bincode_compat {
|
||||
/// notification: ExExNotification<N>,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This enum mirrors [`super::ExExNotification`] but uses borrowed [`Chain`] types
|
||||
/// instead of `Arc<Chain>` for bincode compatibility.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[expect(missing_docs)]
|
||||
#[serde(bound = "")]
|
||||
#[expect(clippy::large_enum_variant)]
|
||||
pub enum ExExNotification<'a, N>
|
||||
where
|
||||
N: NodePrimitives,
|
||||
{
|
||||
ChainCommitted { new: Chain<'a, N> },
|
||||
ChainReorged { old: Chain<'a, N>, new: Chain<'a, N> },
|
||||
ChainReverted { old: Chain<'a, N> },
|
||||
/// Chain got committed without a reorg, and only the new chain is returned.
|
||||
ChainCommitted {
|
||||
/// The new chain after commit.
|
||||
new: Chain<'a, N>,
|
||||
},
|
||||
/// Chain got reorged, and both the old and the new chains are returned.
|
||||
ChainReorged {
|
||||
/// The old chain before reorg.
|
||||
old: Chain<'a, N>,
|
||||
/// The new chain after reorg.
|
||||
new: Chain<'a, N>,
|
||||
},
|
||||
/// Chain got reverted, and only the old chain is returned.
|
||||
ChainReverted {
|
||||
/// The old chain before reversion.
|
||||
old: Chain<'a, N>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, N> From<&'a super::ExExNotification<N>> for ExExNotification<'a, N>
|
||||
|
||||
@@ -256,6 +256,10 @@ impl<B: FullBlock<Header: reth_primitives_traits::BlockHeader>> FromReader
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
tracing::debug!(target: "downloaders::file",
|
||||
block=?block,
|
||||
"decoded block from file chunk"
|
||||
);
|
||||
let block = SealedBlock::seal_slow(block);
|
||||
|
||||
// Validate standalone header
|
||||
@@ -272,6 +276,11 @@ impl<B: FullBlock<Header: reth_primitives_traits::BlockHeader>> FromReader
|
||||
let block_hash = block.hash();
|
||||
let block_number = block.number();
|
||||
let (header, body) = block.split_sealed_header_body();
|
||||
tracing::debug!(target: "downloaders::file",
|
||||
header=?header,
|
||||
body=?body,
|
||||
"adding block to file client buffers"
|
||||
);
|
||||
headers.insert(block_number, header.unseal());
|
||||
hash_to_number.insert(block_hash, block_number);
|
||||
bodies.insert(block_hash, body);
|
||||
|
||||
@@ -265,6 +265,7 @@ mod tests {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash:None
|
||||
},
|
||||
]),
|
||||
}.encode(&mut data);
|
||||
@@ -302,6 +303,7 @@ mod tests {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash: None
|
||||
},
|
||||
]),
|
||||
};
|
||||
@@ -408,9 +410,11 @@ mod tests {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash:None
|
||||
},
|
||||
],
|
||||
withdrawals: None,
|
||||
block_access_list:None
|
||||
}
|
||||
]),
|
||||
};
|
||||
@@ -485,9 +489,11 @@ mod tests {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash:None
|
||||
},
|
||||
],
|
||||
withdrawals: None,
|
||||
block_access_list:None
|
||||
}
|
||||
]),
|
||||
};
|
||||
|
||||
@@ -152,6 +152,7 @@ mod tests {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash:None
|
||||
};
|
||||
assert_eq!(header.hash_slow(), expected_hash);
|
||||
}
|
||||
@@ -268,6 +269,7 @@ mod tests {
|
||||
excess_blob_gas: Some(0),
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash: None,
|
||||
};
|
||||
|
||||
let header = Header::decode(&mut data.as_slice()).unwrap();
|
||||
@@ -310,6 +312,7 @@ mod tests {
|
||||
blob_gas_used: Some(0),
|
||||
excess_blob_gas: Some(0x1600000),
|
||||
requests_hash: None,
|
||||
block_access_list_hash: None,
|
||||
};
|
||||
|
||||
let header = Header::decode(&mut data.as_slice()).unwrap();
|
||||
|
||||
@@ -755,6 +755,7 @@ mod tests {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Default::default()),
|
||||
block_access_list: None,
|
||||
}]
|
||||
.into(),
|
||||
}));
|
||||
|
||||
@@ -131,6 +131,8 @@ pub struct TransactionsManagerMetrics {
|
||||
/// capacity. Note, this is not a limit to the number of inflight requests, but a health
|
||||
/// measure.
|
||||
pub(crate) capacity_pending_pool_imports: Counter,
|
||||
/// The time it took to prepare transactions for import. This is mostly sender recovery.
|
||||
pub(crate) pool_import_prepare_duration: Histogram,
|
||||
|
||||
/* ================ POLL DURATION ================ */
|
||||
|
||||
|
||||
@@ -1338,6 +1338,8 @@ where
|
||||
let Some(peer) = self.peers.get_mut(&peer_id) else { return };
|
||||
let mut transactions = transactions.0;
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
// mark the transactions as received
|
||||
self.transaction_fetcher
|
||||
.remove_hashes_from_transaction_fetcher(transactions.iter().map(|tx| tx.tx_hash()));
|
||||
@@ -1459,6 +1461,8 @@ where
|
||||
if num_already_seen_by_peer > 0 {
|
||||
self.report_already_seen(peer_id);
|
||||
}
|
||||
|
||||
self.metrics.pool_import_prepare_duration.record(start.elapsed());
|
||||
}
|
||||
|
||||
/// Processes a [`FetchEvent`].
|
||||
|
||||
@@ -281,6 +281,7 @@ impl EngineNodeLauncher {
|
||||
let startup_sync_state_idle = ctx.node_config().debug.startup_sync_state_idle;
|
||||
|
||||
info!(target: "reth::cli", "Starting consensus engine");
|
||||
info!(target: "reth::cli", "built payloads ready: {:#?}", built_payloads);
|
||||
ctx.task_executor().spawn_critical("consensus engine", Box::pin(async move {
|
||||
if let Some(initial_target) = initial_target {
|
||||
debug!(target: "reth::cli", %initial_target, "start backfill sync");
|
||||
|
||||
@@ -300,6 +300,7 @@ mod tests {
|
||||
transactions: vec![transaction],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Withdrawals::default()),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
let block = SealedBlock::seal_slow(alloy_consensus::Block { header, body });
|
||||
@@ -337,6 +338,7 @@ mod tests {
|
||||
transactions: vec![transaction],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Withdrawals::default()),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
let block = SealedBlock::seal_slow(alloy_consensus::Block { header, body });
|
||||
@@ -392,6 +394,7 @@ mod tests {
|
||||
transactions: vec![transaction],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Withdrawals::default()),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
let block = SealedBlock::seal_slow(alloy_consensus::Block { header, body });
|
||||
@@ -401,6 +404,7 @@ mod tests {
|
||||
receipts: vec![receipt],
|
||||
requests: Requests::default(),
|
||||
gas_used: GAS_USED,
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
// validate blob, it should pass blob gas used validation
|
||||
@@ -459,6 +463,7 @@ mod tests {
|
||||
transactions: vec![transaction],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Withdrawals::default()),
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
let block = SealedBlock::seal_slow(alloy_consensus::Block { header, body });
|
||||
@@ -468,6 +473,7 @@ mod tests {
|
||||
receipts: vec![receipt],
|
||||
requests: Requests::default(),
|
||||
gas_used: GAS_USED,
|
||||
block_access_list: None,
|
||||
};
|
||||
|
||||
// validate blob, it should pass blob gas used validation
|
||||
|
||||
@@ -518,6 +518,7 @@ mod tests {
|
||||
transactions: vec![],
|
||||
ommers: vec![],
|
||||
withdrawals: Some(Default::default()),
|
||||
..Default::default()
|
||||
};
|
||||
validate_body_against_header_op(&chainspec, &body, &header).unwrap();
|
||||
|
||||
@@ -542,6 +543,7 @@ mod tests {
|
||||
receipts: vec![],
|
||||
requests: Requests::default(),
|
||||
gas_used: GAS_USED,
|
||||
block_access_list: None,
|
||||
};
|
||||
validate_block_post_execution(&header, &chainspec, &result).unwrap();
|
||||
}
|
||||
@@ -563,6 +565,7 @@ mod tests {
|
||||
receipts: vec![],
|
||||
requests: Requests::default(),
|
||||
gas_used: GAS_USED,
|
||||
block_access_list: None,
|
||||
};
|
||||
assert_eq!(
|
||||
validate_block_post_execution(&header, &chainspec, &result),
|
||||
|
||||
@@ -46,7 +46,14 @@ impl<ChainSpec: OpHardforks> OpBlockAssembler<ChainSpec> {
|
||||
evm_env,
|
||||
execution_ctx: ctx,
|
||||
transactions,
|
||||
output: BlockExecutionResult { receipts, gas_used, blob_gas_used, requests: _ },
|
||||
output:
|
||||
BlockExecutionResult {
|
||||
receipts,
|
||||
gas_used,
|
||||
blob_gas_used,
|
||||
requests: _,
|
||||
block_access_list: _,
|
||||
},
|
||||
bundle_state,
|
||||
state_root,
|
||||
state_provider,
|
||||
@@ -70,7 +77,7 @@ impl<ChainSpec: OpHardforks> OpBlockAssembler<ChainSpec> {
|
||||
// withdrawals root field in block header is used for storage root of L2 predeploy
|
||||
// `l2tol1-message-passer`
|
||||
Some(
|
||||
isthmus::withdrawals_root(bundle_state, state_provider)
|
||||
isthmus::withdrawals_root(&bundle_state, state_provider)
|
||||
.map_err(BlockExecutionError::other)?,
|
||||
)
|
||||
} else if self.chain_spec.is_canyon_active_at_timestamp(timestamp) {
|
||||
@@ -112,6 +119,7 @@ impl<ChainSpec: OpHardforks> OpBlockAssembler<ChainSpec> {
|
||||
blob_gas_used,
|
||||
excess_blob_gas,
|
||||
requests_hash,
|
||||
block_access_list_hash: None,
|
||||
};
|
||||
|
||||
Ok(Block::new(
|
||||
@@ -123,6 +131,7 @@ impl<ChainSpec: OpHardforks> OpBlockAssembler<ChainSpec> {
|
||||
.chain_spec
|
||||
.is_canyon_active_at_timestamp(timestamp)
|
||||
.then(Default::default),
|
||||
block_access_list: None,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use alloy_consensus::{BlockHeader, Header};
|
||||
use alloy_eips::Decodable2718;
|
||||
use alloy_evm::{EvmFactory, FromRecoveredTx, FromTxWithEncoded};
|
||||
use alloy_op_evm::block::{receipt_builder::OpReceiptBuilder, OpTxEnv};
|
||||
use alloy_primitives::U256;
|
||||
use alloy_primitives::{Bytes, U256};
|
||||
use core::fmt::Debug;
|
||||
use op_alloy_consensus::EIP1559ParamError;
|
||||
use op_alloy_rpc_types_engine::OpExecutionData;
|
||||
@@ -265,12 +265,15 @@ where
|
||||
&self,
|
||||
payload: &OpExecutionData,
|
||||
) -> Result<impl ExecutableTxIterator<Self>, Self::Error> {
|
||||
Ok(payload.payload.transactions().clone().into_iter().map(|encoded| {
|
||||
let transactions = payload.payload.transactions().clone().into_iter();
|
||||
let convert = |encoded: Bytes| {
|
||||
let tx = TxTy::<Self::Primitives>::decode_2718_exact(encoded.as_ref())
|
||||
.map_err(AnyError::new)?;
|
||||
let signer = tx.try_recover().map_err(AnyError::new)?;
|
||||
Ok::<_, AnyError>(WithEncoded::new(encoded, tx.with_signer(signer)))
|
||||
}))
|
||||
};
|
||||
|
||||
Ok((transactions, convert))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use alloy_consensus::{Eip658Value, Receipt};
|
||||
use alloy_evm::eth::receipt_builder::ReceiptBuilderCtx;
|
||||
use alloy_op_evm::block::receipt_builder::OpReceiptBuilder;
|
||||
use op_alloy_consensus::{OpDepositReceipt, OpTxType};
|
||||
use op_alloy_consensus::OpTxType;
|
||||
use reth_evm::Evm;
|
||||
use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
|
||||
|
||||
@@ -41,7 +41,7 @@ impl OpReceiptBuilder for OpRethReceiptBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_deposit_receipt(&self, inner: OpDepositReceipt) -> Self::Receipt {
|
||||
fn build_deposit_receipt(&self, inner: op_alloy_consensus::OpDepositReceipt) -> Self::Receipt {
|
||||
OpReceipt::Deposit(inner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ where
|
||||
type ExecutionPayloadEnvelopeV3 = OpExecutionPayloadEnvelopeV3;
|
||||
type ExecutionPayloadEnvelopeV4 = OpExecutionPayloadEnvelopeV4;
|
||||
type ExecutionPayloadEnvelopeV5 = OpExecutionPayloadEnvelopeV4;
|
||||
type ExecutionPayloadEnvelopeV6 = OpExecutionPayloadEnvelopeV4;
|
||||
}
|
||||
|
||||
/// Validator for Optimism engine API.
|
||||
@@ -279,7 +280,8 @@ pub fn validate_withdrawals_presence(
|
||||
EngineApiMessageVersion::V2 |
|
||||
EngineApiMessageVersion::V3 |
|
||||
EngineApiMessageVersion::V4 |
|
||||
EngineApiMessageVersion::V5 => {
|
||||
EngineApiMessageVersion::V5 |
|
||||
EngineApiMessageVersion::V6 => {
|
||||
if is_shanghai && !has_withdrawals {
|
||||
return Err(message_validation_kind
|
||||
.to_error(VersionSpecificValidationError::NoWithdrawalsPostShanghai));
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
OpPayloadBuilderAttributes, OpPayloadPrimitives,
|
||||
};
|
||||
use alloy_consensus::{BlockHeader, Transaction, Typed2718};
|
||||
use alloy_evm::Evm as AlloyEvm;
|
||||
use alloy_evm::{block::StateDB, Evm as AlloyEvm};
|
||||
use alloy_primitives::{B256, U256};
|
||||
use alloy_rpc_types_debug::ExecutionWitness;
|
||||
use alloy_rpc_types_engine::PayloadId;
|
||||
@@ -38,7 +38,10 @@ use reth_revm::{
|
||||
};
|
||||
use reth_storage_api::{errors::ProviderError, StateProvider, StateProviderFactory};
|
||||
use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction, TransactionPool};
|
||||
use revm::context::{Block, BlockEnv};
|
||||
use revm::{
|
||||
context::{Block, BlockEnv},
|
||||
DatabaseCommit,
|
||||
};
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
@@ -598,9 +601,9 @@ where
|
||||
}
|
||||
|
||||
/// Prepares a [`BlockBuilder`] for the next block.
|
||||
pub fn block_builder<'a, DB: Database>(
|
||||
pub fn block_builder<'a, DB: StateDB + DatabaseCommit + Database + 'a>(
|
||||
&'a self,
|
||||
db: &'a mut State<DB>,
|
||||
db: DB,
|
||||
) -> Result<
|
||||
impl BlockBuilder<
|
||||
Primitives = Evm::Primitives,
|
||||
|
||||
@@ -91,6 +91,7 @@ pub const BEDROCK_HEADER: Header = Header {
|
||||
excess_blob_gas: None,
|
||||
parent_beacon_block_root: None,
|
||||
requests_hash: None,
|
||||
block_access_list_hash:None
|
||||
};
|
||||
|
||||
/// Bedrock total difficulty on Optimism Mainnet.
|
||||
|
||||
@@ -116,6 +116,17 @@ pub enum VersionSpecificValidationError {
|
||||
/// Shanghai
|
||||
#[error("withdrawals pre-Shanghai")]
|
||||
HasWithdrawalsPreShanghai,
|
||||
/// Thrown if the pre-V6 `PayloadAttributes` or `ExecutionPayload` contains a block access list
|
||||
#[error("block access list not before V6")]
|
||||
BlockAccessListNotSupportedBeforeV6,
|
||||
/// Thrown if `engine_newPayload` contains no block access list
|
||||
/// after Amsterdam
|
||||
#[error("no block access list post-Amsterdam")]
|
||||
NoBlockAccessListPostAmsterdam,
|
||||
/// Thrown if `engine_newPayload` contains block access list
|
||||
/// before Amsterdam
|
||||
#[error("block access list pre-Amsterdam")]
|
||||
HasBlockAccessListPreAmsterdam,
|
||||
/// Thrown if the `PayloadAttributes` or `ExecutionPayload` contains no parent beacon block
|
||||
/// root after Cancun
|
||||
#[error("no parent beacon block root post-cancun")]
|
||||
|
||||
@@ -159,12 +159,23 @@ pub fn validate_payload_timestamp(
|
||||
// built payload does not fall within the time frame of the Osaka fork.
|
||||
return Err(EngineObjectValidationError::UnsupportedFork)
|
||||
}
|
||||
|
||||
// `engine_getPayloadV4` MUST reject payloads with a timestamp >= Osaka.
|
||||
if version.is_v4() && kind == MessageValidationKind::GetPayload && is_osaka {
|
||||
return Err(EngineObjectValidationError::UnsupportedFork)
|
||||
}
|
||||
|
||||
let is_amsterdam = chain_spec.is_amsterdam_active_at_timestamp(timestamp);
|
||||
if version.is_v6() && !is_amsterdam {
|
||||
// From the Engine API spec:
|
||||
// <https://github.com/ethereum/execution-apis/blob/15399c2e2f16a5f800bf3f285640357e2c245ad9/src/engine/osaka.md#specification>
|
||||
//
|
||||
// For `engine_getPayloadV6`
|
||||
//
|
||||
// 1. Client software MUST return -38005: Unsupported fork error if the timestamp of the
|
||||
// built payload does not fall within the time frame of the Amsterdam fork.
|
||||
|
||||
return Err(EngineObjectValidationError::UnsupportedFork)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -190,7 +201,8 @@ pub fn validate_withdrawals_presence<T: EthereumHardforks>(
|
||||
EngineApiMessageVersion::V2 |
|
||||
EngineApiMessageVersion::V3 |
|
||||
EngineApiMessageVersion::V4 |
|
||||
EngineApiMessageVersion::V5 => {
|
||||
EngineApiMessageVersion::V5 |
|
||||
EngineApiMessageVersion::V6 => {
|
||||
if is_shanghai_active && !has_withdrawals {
|
||||
return Err(message_validation_kind
|
||||
.to_error(VersionSpecificValidationError::NoWithdrawalsPostShanghai))
|
||||
@@ -205,6 +217,45 @@ pub fn validate_withdrawals_presence<T: EthereumHardforks>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates the presence of the `block access lists` field according to the payload timestamp.
|
||||
/// After Amsterdam, block access list field must be [Some].
|
||||
/// Before Amsterdam, block access list field must be [None];
|
||||
pub fn validate_block_access_list_presence<T: EthereumHardforks>(
|
||||
chain_spec: &T,
|
||||
version: EngineApiMessageVersion,
|
||||
message_validation_kind: MessageValidationKind,
|
||||
timestamp: u64,
|
||||
has_block_access_list: bool,
|
||||
) -> Result<(), EngineObjectValidationError> {
|
||||
let is_amsterdam_active = chain_spec.is_amsterdam_active_at_timestamp(timestamp);
|
||||
|
||||
match version {
|
||||
EngineApiMessageVersion::V1 |
|
||||
EngineApiMessageVersion::V2 |
|
||||
EngineApiMessageVersion::V3 |
|
||||
EngineApiMessageVersion::V4 |
|
||||
EngineApiMessageVersion::V5 => {
|
||||
if has_block_access_list {
|
||||
return Err(message_validation_kind
|
||||
.to_error(VersionSpecificValidationError::BlockAccessListNotSupportedBeforeV6))
|
||||
}
|
||||
}
|
||||
|
||||
EngineApiMessageVersion::V6 => {
|
||||
if is_amsterdam_active && !has_block_access_list {
|
||||
return Err(message_validation_kind
|
||||
.to_error(VersionSpecificValidationError::NoBlockAccessListPostAmsterdam))
|
||||
}
|
||||
if !is_amsterdam_active && has_block_access_list {
|
||||
return Err(message_validation_kind
|
||||
.to_error(VersionSpecificValidationError::HasBlockAccessListPreAmsterdam))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate the presence of the `parentBeaconBlockRoot` field according to the given timestamp.
|
||||
/// This method is meant to be used with either a `payloadAttributes` field or a full payload, with
|
||||
/// the `engine_forkchoiceUpdated` and `engine_newPayload` methods respectively.
|
||||
@@ -291,7 +342,10 @@ pub fn validate_parent_beacon_block_root_presence<T: EthereumHardforks>(
|
||||
))
|
||||
}
|
||||
}
|
||||
EngineApiMessageVersion::V3 | EngineApiMessageVersion::V4 | EngineApiMessageVersion::V5 => {
|
||||
EngineApiMessageVersion::V3 |
|
||||
EngineApiMessageVersion::V4 |
|
||||
EngineApiMessageVersion::V5 |
|
||||
EngineApiMessageVersion::V6 => {
|
||||
if !has_parent_beacon_block_root {
|
||||
return Err(validation_kind
|
||||
.to_error(VersionSpecificValidationError::NoParentBeaconBlockRootPostCancun))
|
||||
@@ -364,6 +418,14 @@ where
|
||||
Type: PayloadAttributes,
|
||||
T: EthereumHardforks,
|
||||
{
|
||||
validate_block_access_list_presence(
|
||||
chain_spec,
|
||||
version,
|
||||
payload_or_attrs.message_validation_kind(),
|
||||
payload_or_attrs.timestamp(),
|
||||
payload_or_attrs.block_access_list().is_some(),
|
||||
)?;
|
||||
|
||||
validate_withdrawals_presence(
|
||||
chain_spec,
|
||||
version,
|
||||
@@ -402,6 +464,10 @@ pub enum EngineApiMessageVersion {
|
||||
///
|
||||
/// Added in the Osaka hardfork.
|
||||
V5 = 5,
|
||||
/// Version 6
|
||||
///
|
||||
/// Added in the Amsterdam hardfork
|
||||
V6 = 6,
|
||||
}
|
||||
|
||||
impl EngineApiMessageVersion {
|
||||
@@ -430,6 +496,11 @@ impl EngineApiMessageVersion {
|
||||
matches!(self, Self::V5)
|
||||
}
|
||||
|
||||
/// Returns true if version is V6
|
||||
pub const fn is_v6(&self) -> bool {
|
||||
matches!(self, Self::V6)
|
||||
}
|
||||
|
||||
/// Returns the method name for the given version.
|
||||
pub const fn method_name(&self) -> &'static str {
|
||||
match self {
|
||||
@@ -437,7 +508,7 @@ impl EngineApiMessageVersion {
|
||||
Self::V2 => "engine_newPayloadV2",
|
||||
Self::V3 => "engine_newPayloadV3",
|
||||
Self::V4 => "engine_newPayloadV4",
|
||||
Self::V5 => "engine_newPayloadV5",
|
||||
Self::V5 | Self::V6 => "engine_newPayloadV5",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user