Compare commits

..

115 Commits

Author SHA1 Message Date
rakita
d3771d341a add reth-core t4 patch (6b12498) 2026-04-16 10:58:25 +02:00
rakita
9936061e5f bump revm, revm-inspectors, and alloy-evm to t4 branches
revm: 89ecb25dbe49e1c3a10d99529e42f027d0bd2386
revm-inspectors: c6f88bbe7186d863f4667dd43c42608eb7a8ba5c
alloy-evm: ff0bbec9ccaa818155e25003a77f4d73d350bbd7
2026-04-16 10:26:28 +02:00
Alexey Shekhirin
199b7460a9 refactor: decouple CachedStateMetrics from SavedCache (#23552) 2026-04-15 21:30:15 +00:00
Derek Cofausper
41592ef1f8 fix(download): respect --datadir.static-files during extraction (#23445)
Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
Co-authored-by: Emma Jamieson-Hoare <21029500+emmajam@users.noreply.github.com>
Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
2026-04-15 21:19:42 +00:00
Arsenii Kulikov
bdbb8df17e fix: validate against executor output gas used (#23569) 2026-04-15 20:37:14 +00:00
Dan Cline
f451ad5380 feat(cli): add reth download config options (#23513) 2026-04-15 20:23:08 +00:00
AJStonewee
6e4009eed4 fix(rpc): prevent panic in log subscription on broadcast lag (#23561) 2026-04-15 19:23:33 +00:00
Brian Picciano
cf29b3fffe perf(engine): include backpressure in newPayload latency metric (#23541)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-15 17:14:35 +00:00
Matthias Seitz
7fe76a83d1 fix(net): encode block access lists as raw BAL RLP (#23536)
Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
2026-04-15 12:42:16 +00:00
Ishika Choudhury
b1cff500ad chore(BAL): remove debug_get_block_access_list (#23534) 2026-04-15 12:33:37 +00:00
figtracer
0b33057414 fix(init-state): write accounts directly with chunked commits (#23469) 2026-04-15 10:52:53 +00:00
Soubhik Singha Mahapatra
3891092ee9 chore: add amsterdam time to chainspec (#23526) 2026-04-15 10:29:14 +00:00
Emma Jamieson-Hoare
8784aa45fc chore: bump revm to v37 (EIP-8037 state gas) (#23191)
Co-authored-by: Federico Gimenez <federico.gimenez@gmail.com>
Co-authored-by: Federico Gimenez <fgimenez@users.noreply.github.com>
Co-authored-by: klkvr <klkvrr@gmail.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-15 10:08:12 +00:00
Brian Picciano
f1d90612e3 feat(ci): add slack=on-win mode to bench workflows (#23522)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-15 09:45:37 +00:00
Derek Cofausper
03d69f59a5 chore(ci): add @ai investigate to bench failure alerts (#23520)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
2026-04-15 09:19:14 +00:00
Ishika Choudhury
d372c8f5a9 chore(BAL): added gas limit fn to ExecutionPayload (#23518) 2026-04-15 09:01:35 +00:00
Arsenii Kulikov
dbb8495be1 fix: allow adding peers without overriding kind (#23516) 2026-04-14 21:00:39 +00:00
Ishika Choudhury
044db3ec95 feat: implement try into v6 (#23497)
Co-authored-by: Soubhik Singha Mahapatra <soubhiksmp2004@gmail.com>
Co-authored-by: Soubhik Singha Mahapatra <160333583+Soubhik-10@users.noreply.github.com>
2026-04-14 20:04:21 +00:00
Matthias Seitz
13217d5517 feat(discv4): add AddBootNode command (#23515) 2026-04-14 19:32:38 +00:00
Matthias Seitz
0165569bc1 feat(net): add discv4/discv5 getters to NetworkHandle (#23514) 2026-04-14 19:25:54 +00:00
Brian Picciano
84c14fe0a8 ci(bench): replace no_slack boolean with slack dropdown (always/on-error/never) (#23501)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-14 15:57:20 +00:00
Tim
5b4af55017 feat: add reqwest-rustls to support otlp endpoints with https (#23495) 2026-04-14 14:09:09 +00:00
Dan Cline
b8ab2c628e chore(cli): add binary name and chain detection in tempo download log (#23356)
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
Co-authored-by: Emma Jamieson-Hoare <21029500+emmajam@users.noreply.github.com>
2026-04-14 13:23:29 +00:00
Brian Picciano
766f4317a6 chore(bench): reduce default blocks to 200, warmup to 20 for big-blocks (#23494)
Co-authored-by: mediocregopher <mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-14 13:13:21 +00:00
Derek Cofausper
c20d897efe fix(node): downgrade prune config log from warn to info (#23493)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
2026-04-14 11:43:43 +00:00
Brian Picciano
ad1e8f2cea feat(bench): BAL capture, replay, and inline payload decoding (#23434)
Co-authored-by: Soubhik Singha Mahapatra <soubhiksmp2004@gmail.com>
Co-authored-by: Soubhik Singha Mahapatra <160333583+Soubhik-10@users.noreply.github.com>
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: steven <corderosteven6@gmail.com>
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
2026-04-14 11:23:13 +00:00
Derek Cofausper
51309ff55c fix(bench): retry on all transport errors (#23491)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
Co-authored-by: Alexey Shekhirin <github@shekhirin.com>
2026-04-14 10:42:05 +00:00
Soubhik Singha Mahapatra
e0aac5015f chore(BAL): added newPayloadV5 and getPayloadV6 (#23486)
Co-authored-by: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com>
2026-04-14 08:57:42 +00:00
Ishika Choudhury
3b8290439a chore(BAL): added helper functions for building (#23490) 2026-04-14 08:49:49 +00:00
yottaes
1a2836ff53 feat(rpc): support transactionReceipts subscription in eth_subscribe (#23485)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-14 08:42:01 +00:00
MagicJoshh
bce7368a82 fix(engine): use IndexSet for deterministic block buffer child ordering (#22676) 2026-04-13 19:18:23 +00:00
MagicJoshh
1e461ef281 fix(trie): terminate depth-first iterator on database error (#22709) 2026-04-13 17:48:07 +00:00
Ishika Choudhury
a5113622fd chore(BAL): added fcuv4 and EngineApiMessageVersion6 (#23480)
Co-authored-by: Soubhik Singha Mahapatra <soubhiksmp2004@gmail.com>
2026-04-13 14:47:28 +00:00
stevencartavia
bfb7ab72f7 chore: bump alloy to 2.0.0 (#23407)
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-13 13:51:19 +00:00
Matthias Seitz
3d5c29c179 feat(net): add enforce_enr_fork_id to DefaultNetworkArgs (#23477) 2026-04-13 13:00:59 +00:00
Ignacio Hagopian
a05960ab07 feat(stateless): make witness generation conform to the draft specs (#22289)
Signed-off-by: jsign <jsign.uy@gmail.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
Co-authored-by: Brian Picciano <me@mediocregopher.com>
2026-04-13 13:34:00 +02:00
John Chase
6b499151d8 perf(txpool): use FxHashMap/FxHashSet for TxHash-heavy containers (#23037) 2026-04-13 11:22:21 +02:00
Matthias Seitz
a9bd38a43e perf(trie): parallelize merge_ancestors_into_overlay (#21473)
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com>
2026-04-12 15:27:30 +02:00
github-actions[bot]
a544d244d8 chore(deps): weekly cargo update (#23464)
Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com>
2026-04-12 12:25:36 +02:00
Derek Cofausper
a550b7a7d3 perf(tracing): also disable target attribute in OTLP spans (#23462)
Co-authored-by: Arsenii Kulikov <62447812+klkvr@users.noreply.github.com>
Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
2026-04-11 16:54:06 +00:00
Derek Cofausper
7035bbcf3a refactor(examples): replace mev-share-sse with reqwest bytes_stream in beacon-api-sse (#23458)
Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
2026-04-11 10:33:34 +00:00
Tamjid Ahmed
0c278f5fab feat(eth-wire): introduce configurable maximum ETH message size acros… (#22668)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-11 06:23:12 +00:00
Arsh
03dd1c3ae2 fix(txpool): do not mark ExceedsFeeCap as a bad transaction (#23450) 2026-04-11 05:13:05 +00:00
Dan Cline
6aa2234d9a chore(cli): make --resumable default (#23451) 2026-04-11 04:49:16 +00:00
Derek Cofausper
5ae8f0bc54 perf(engine): downgrade sparse trie spans to trace (#23448)
Co-authored-by: Arsenii Kulikov <62447812+klkvr@users.noreply.github.com>
2026-04-11 00:24:25 +00:00
Derek Cofausper
e3536f768e perf(tracing): disable location and inactivity tracking in OTLP span export (#23447)
Co-authored-by: Arsenii Kulikov <62447812+klkvr@users.noreply.github.com>
2026-04-10 19:23:34 +00:00
Derek Cofausper
ff1a78e1ce ci: remove PGO from CI workflows (#23405)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
2026-04-10 19:17:42 +00:00
Matthias Seitz
fc3f465321 fix(net): seed peer range from handshake status (#23446)
Co-authored-by: Weixie Cui <cuiweixie@gmail.com>
2026-04-10 14:06:10 +00:00
cui
b0956b12ae fix(rpc): paginate ots_getBlockTransactions in block order (#23442)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-10 13:32:28 +00:00
cui
a774920b78 fix(provider): size block_range buffer for inclusive span (#23443) 2026-04-10 13:07:59 +00:00
cui
77d5f86b42 fix(consensus): always validate minimum gas limit (#23441) 2026-04-10 12:55:11 +00:00
Hwangjae Lee
e118963b8f fix(rpc): preserve nested bundle structure in mev_simBundle logs (#20565)
Signed-off-by: Hwangjae Lee <meetrick@gmail.com>
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-10 12:54:27 +00:00
Derek Cofausper
64f6117dc0 docs(trie): replace stale MultiProofTask references with SparseTrieCacheTask (#22780)
Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-10 11:30:42 +00:00
Emma Jamieson-Hoare
53fe0a077a bench: add release regression mode (#23416)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-10 11:13:24 +00:00
Brian Picciano
828965c39d perf(engine): improve BAL prewarm sparse-trie streaming (#23423)
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-10 10:11:16 +00:00
Emma Jamieson-Hoare
53e1ec81b3 docs: update README for Reth 2.0 (#23424)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-10 09:25:31 +00:00
dependabot[bot]
608c96791f chore(deps): bump tokio from 1.51.0 to 1.51.1 in the cargo-weekly group (#23410)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 07:22:23 +00:00
Derek Cofausper
13ae241a0d ci: bump MSRV job runner to depot-ubuntu-latest-8 (#23432)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
2026-04-10 06:45:30 +00:00
Alexey Shekhirin
cecbb4cc8c fix(cli): use recent speed instead of all-time average for download ETA (#23425) 2026-04-10 00:29:54 +00:00
Alexey Shekhirin
0ed4739482 fix(download): show error on retry and reset counter on progress (#23426) 2026-04-10 00:29:45 +00:00
Emma Jamieson-Hoare
76bdfb30ff chore: update README logo to Reth v2.0 branding (#23421)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-09 14:10:24 +00:00
Tim
d68dc8306b fix: add no-list in order to avoid prefix matching (#23420) 2026-04-09 13:44:39 +00:00
Derek Cofausper
3b5045021d chore(engine): rename to_multi_proof to to_sparse_trie_task in prewarm (#23418)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
2026-04-09 13:17:45 +00:00
dependabot[bot]
20c75ab0e5 chore(deps): bump actions/deploy-pages from 4 to 5 (#23408)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 11:08:59 +00:00
Derek Cofausper
44bcf5e9d4 chore: remove migrate-trie-to-packed example (#23385)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
Co-authored-by: Sergei Shulepov <s.pepyakin@gmail.com>
2026-04-09 13:12:52 +02:00
Arsenii Kulikov
ac3120703a fix: properly validate authorities in the pool (#23406) 2026-04-09 10:55:55 +00:00
Matthias Seitz
c9866e2c85 fix(pruning): avoid unused import warning in checkpoint (#23412) 2026-04-09 12:54:57 +02:00
Soubhik Singha Mahapatra
5f2f4908ae feat: implement Bal Client for eth 71 (#22605)
Co-authored-by: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-09 10:12:45 +00:00
Derek Cofausper
f29c83dee9 chore(ci): add set -x to all GHA bash scripts (#23413)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-09 10:04:32 +00:00
Derek Cofausper
d56b1be103 ci(bench): always send Slack notification for nightly bench runs (#23417)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
2026-04-09 09:56:03 +00:00
Derek Cofausper
346f0e5851 fix(ci): handle stale minio cache in bench build script (#23415)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
2026-04-09 09:55:54 +00:00
Matthias Seitz
91b8e1a8ae perf(storage): use sort_unstable in safe paths (#23386) 2026-04-09 07:48:35 +00:00
Arsenii Kulikov
3d5057b97a refactor: support modifying next_available_nonce_for (#23409) 2026-04-09 04:22:48 +00:00
Brian Picciano
b27b3e0e2c fix(reth-bb): use noop consensus (#23399)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-09 02:37:40 +00:00
Alexey Shekhirin
5bfe2c8b13 chore: add reth 2.0 banner image (#23402) 2026-04-08 18:29:42 +02:00
Tim
e4cf0ab09b fix: add full recover fallback (#23390) 2026-04-08 14:37:55 +00:00
Brian Picciano
3248af34a9 fix(engine): disable payload state hook when BAL is present (#23393)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-08 14:27:57 +00:00
Derek Cofausper
e6f1c2c6b9 fix: add --kill to all schelk recover calls (#23384)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-08 10:45:03 +00:00
Derek Cofausper
83e6677078 refactor(engine): use Mutex instead of RwLock in PayloadExecutionCache (#23387)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-08 09:28:41 +00:00
Kenil shah
390def905d perf: use sort_unstable in CLI, networking, and RPC hot paths (#23364)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-08 08:09:09 +00:00
Crypto Nomad
c924902b89 perf(provider): avoid full receipt clone in tx-range query (#23187)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-08 07:48:06 +00:00
Derek Cofausper
ed8bfca9ac fix: use named systemd scope for reliable reth cleanup in benchmarks (#23374)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-07 16:57:56 +00:00
Derek Cofausper
4178e63011 fix(ci): pin CPU frequency to nominal clock in bench workflow (#23370)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-07 13:00:29 +00:00
Derek Cofausper
eb4c15e5e3 chore: remove changelog workflow and .changelog directory (#23376)
Co-authored-by: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com>
2026-04-07 12:27:32 +00:00
Emma Jamieson-Hoare
9320216ff2 chore: 2.0 release branch (#23372) 2026-04-07 11:57:37 +00:00
Tim
01d851ce4a fix: unmount schelk volume before recover in snapshot script (#23371) 2026-04-07 10:42:07 +00:00
Ishika Choudhury
2155fb7223 chore: added block_access_list_raw rpc (#23363) 2026-04-07 12:45:55 +02:00
figtracer
a539daf0d0 feat(trie): add DecodedMultiProofV2::from_witness constructor (#23362) 2026-04-07 10:19:31 +00:00
Arsenii Kulikov
6b176abc5d feat: expose EVM config on EthTransactionValidator (#23369) 2026-04-07 10:18:03 +00:00
Arsenii Kulikov
0e4f143172 feat: catch-up for read-only ProviderFactorys (#23357) 2026-04-06 19:47:00 +00:00
github-actions[bot]
1a7288373e chore(deps): weekly cargo update (#23359)
Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com>
2026-04-05 06:35:25 +00:00
Arsenii Kulikov
adc960162f refactor(rocksdb): use secondary instances for read only providers (#23346) 2026-04-03 17:48:56 +00:00
Derek Cofausper
f3e813cfea fix(ci): fix Grafana URL year-2082 when ABBA disabled (#23348)
Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
2026-04-03 17:20:00 +00:00
figtracer
86faf54ac5 feat(revm): add ExecutionWitnessRecord::into_execution_witness helper (#23345) 2026-04-03 11:04:07 +00:00
Emma Jamieson-Hoare
c82d43594e feat(bench): upload nightly regression results to ClickHouse (#23344)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-02 12:26:36 +00:00
joshieDo
4a6f9cd5c9 fix(provider): cap storage_v2 unwind history by MDBX tip (#23335)
Co-authored-by: Amp <amp@ampcode.com>
2026-04-02 11:19:41 +00:00
Soubhik Singha Mahapatra
7ecbea5847 feat: add bal rpc methods (#23330)
Co-authored-by: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com>
2026-04-02 11:07:37 +00:00
AKABABA-ETH
aa5effbffe perf(rpc): pre-allocate vectors in eth_feeHistory (#23334)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-02 10:41:50 +00:00
Satoshi Nakamoto
abab6781b2 fix(rpc): apply count only after after is consumed (#23338)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2026-04-02 10:39:02 +00:00
dependabot[bot]
079d496c8a chore(deps): bump actions/configure-pages from 5 to 6 (#23336)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 10:28:39 +00:00
dependabot[bot]
00336b3e2a chore(deps): bump the cargo-weekly group with 3 updates (#23337)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 10:28:39 +00:00
AlexYue
8b8430ac41 docs(libmdbx): fix typo writeable -> writable (#23339) 2026-04-02 10:02:33 +00:00
Brian Picciano
8c223dbe99 chore(nix): update nixpkgs to 25.11 and refresh all flake inputs (#23342)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
2026-04-02 09:33:01 +00:00
Derek Cofausper
abdba93fc6 chore: remove unused return value from dispatch_with_chunking (#23341)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-02 09:08:15 +00:00
Derek Cofausper
08a33da36e chore: migrate allow(clippy:: to expect(clippy:: (#23340)
Co-authored-by: Sergei Shulepov <2205845+pepyakin@users.noreply.github.com>
2026-04-02 08:34:48 +00:00
Matthias Seitz
1f84158137 chore: move alloy-rlp to dev-dependencies in reth-execution-types (#23333) 2026-04-01 18:01:34 +02:00
Matthias Seitz
357188f918 fix(net): avoid itertools Format panic in tracing log (#23331) 2026-04-01 17:32:45 +02:00
Matthias Seitz
082c36ebee chore: allow "writeable" in typos config (#23332) 2026-04-01 17:26:25 +02:00
Brian Picciano
0031445779 feat(engine): include backpressure in reported persistence_wait, make wait-time mimic CL slot time (#23308)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-01 13:35:10 +00:00
Tim
3661c96c70 Fix: Use repository to track hourly reth-bench runs instead of github actions cache (#23306) 2026-04-01 13:28:59 +00:00
Matthias Seitz
90dfaac5e2 refactor(reth-bench): make payload handling ethereum-only (#23324)
Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com>
Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
2026-04-01 12:02:42 +00:00
Brian Picciano
17544f847b fix(bench): add warmup step for big blocks mode (#23323)
Co-authored-by: Brian Picciano <933154+mediocregopher@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-01 11:22:00 +00:00
Ivan Wang
1bdc577f19 fix(rpc): admin_nodeInfo.id now returns keccak256 node ID matching go-ethereum format (#23319) 2026-04-01 10:19:51 +00:00
Sergei Shulepov
b58827ec2d perf: reduce cacheline ping pong in workers availability (#23321) 2026-04-01 10:04:16 +00:00
Ivan Wang
239c2625a4 fix(rpc): remove 0x prefix from admin_peers id to match go-ethereum format (#23318) 2026-04-01 07:53:21 +00:00
352 changed files with 7085 additions and 5827 deletions

View File

@@ -1,4 +0,0 @@
---
---
Added site-level meta description for SEO.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: patch
---
Renamed and documented validation methods for clarity. `validate_one_no_state` and `validate_one_against_state` are now public methods `validate_stateless` and `validate_stateful` with improved documentation explaining their respective validation phases.

View File

@@ -1,10 +0,0 @@
---
reth-engine-primitives: patch
reth-engine-tree: patch
reth-node-core: patch
reth-trie-parallel: minor
---
Removed legacy proof calculation system and V2-specific configuration flags.
Removed the legacy (non-V2) proof calculation code paths, simplified multiproof task architecture by removing the dual-mode system, and cleaned up V2-specific CLI flags (`--engine.disable-proof-v2`, `--engine.disable-trie-cache`) that are no longer needed. The codebase now exclusively uses V2 proofs with the sparse trie cache.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Refactored sparse trie node state tracking to use RLP nodes instead of hashes. Replaced `Option<B256>` hash fields with `SparseNodeState` enum that tracks either dirty nodes or cached RLP nodes with optional database storage flags. Added debug assertions to validate leaf path lengths and improved pruning logic to use node paths directly instead of path-hash tuples.

View File

@@ -1,20 +0,0 @@
# Changelogs configuration for reth
# https://github.com/wevm/changelogs
# How to bump packages that depend on changed packages
dependent_bump = "patch"
[changelog]
# Generate per-crate changelogs (vs single root changelog)
format = "per-crate"
# Fixed groups: all always share the same version
# reth binaries share version
[[fixed]]
members = ["reth"]
# Packages to ignore (internal/test-only crates)
ignore = [
"reth-testing-utils",
"reth-bench",
]

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Fixed a bug in `merge_subtrie_updates` where source insertions did not cancel destination removals (and vice versa), causing inconsistent trie updates accumulated across multiple `root()` calls without intermediate `take_updates()`. Added a test covering the cross-cancellation behavior.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: minor
---
Added support for optional custom stateless and stateful validation hooks in `EthTransactionValidator` via `set_additional_stateless_validation` and `set_additional_stateful_validation` methods. Also implemented a manual `Debug` impl to handle the non-`Debug` function pointer fields.

View File

@@ -1,17 +0,0 @@
---
reth: minor
reth-cli-commands: minor
reth-e2e-test-utils: minor
reth-ethereum-cli: minor
reth-node-core: minor
reth-optimism-bin: minor
reth-optimism-cli: minor
reth-prune: patch
reth-stages: patch
reth-storage-api: minor
reth-storage-db-api: minor
reth-storage-db-common: patch
reth-storage-provider: patch
---
Introduced `--storage.v2` flag to control storage mode defaults, replacing the `edge` feature flag with `rocksdb` feature. The new flag enables v2 storage settings (static files + RocksDB routing) while individual `--static-files.*` and `--rocksdb.*` flags can still override defaults. Updated feature gates from `edge` to `rocksdb` across all affected crates.

View File

@@ -1,5 +0,0 @@
---
reth-tasks: patch
---
Added panic handler to all rayon thread pools that logs panics via `tracing::error` instead of aborting the process.

View File

@@ -1,5 +0,0 @@
---
reth: patch
---
Removed Windows platform support from the codebase, including the Windows cross-compilation Dockerfile, build targets in Cross.toml and Makefile, and Windows-specific options in the bug report template.

View File

@@ -1,5 +0,0 @@
---
reth-network: minor
---
Added reason label to backed_off_peers metric. The metric now tracks backed off peers by reason (too_many_peers, graceful_close, connection_error) to improve observability.

View File

@@ -1,5 +0,0 @@
---
reth-network-types: patch
---
Increased default maximum concurrent outbound dials from 15 to 30.

View File

@@ -1,6 +0,0 @@
---
reth-trie-common: minor
reth-trie: minor
---
Added `contains_range` method to `PrefixSet` for checking if any key falls within a half-open range. Added prefix set support to `ProofCalculator` via `with_prefix_set`, enabling stale cached hash invalidation and branch collapse detection when keys are inserted or removed; propagated storage prefix sets through `SyncAccountValueEncoder`.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Refactored arena trie internals by adding a `BranchChildIdx::sibling()` helper, deduplicating `Index`/`NodeArena` type aliases, and replacing `is_empty()` with a `drop_root()` method. Fixed a bug where `cursor.pop()` was called before checking if the leaf was the root node, which could cause incorrect dirty-state propagation.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Added recording of `SetRoot` operation in `ParallelSparseTrie::set_root` when the `trie-debug` feature is enabled.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: minor
---
Fixed a bug in `ArenaParallelSparseTrie` where subtrie updates that would completely empty a subtrie were incorrectly dispatched to parallel workers instead of being processed inline, preventing correct branch collapse detection when blinded siblings are present. Refactored the `SparseTrie` test suite to accept a `fn() -> T` factory instead of requiring `T: Default`, enabling a new `arena_parallel_sparse_trie_always_parallel` test variant that exercises all tests with parallelism thresholds set to 1. Added `test_branch_collapse_multi_empty_subtries_blinded_remaining` to cover the case where removing multiple revealed leaves empties their subtries and leaves a single blinded sibling requiring a proof.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse-parallel: patch
---
Fixed parallel sparse trie to skip revealing disconnected leaves by checking parent branch reachability before inserting leaf nodes.

View File

@@ -1,5 +0,0 @@
---
ef-tests: patch
---
Removed reth-stateless crate and stateless validation from ef-tests.

View File

@@ -1,6 +0,0 @@
---
reth-rpc-convert: minor
reth-storage-rpc-provider: minor
---
Replaced the separate `TryFromBlockResponse`, `TryFromReceiptResponse`, and `TryFromTransactionResponse` traits with a unified `RpcResponseConverter` trait and default `EthRpcConverter` implementation. Removed the `op-alloy-network` dependency and refactored `RpcBlockchainProvider` to store a dynamic converter instance instead of relying on per-type trait bounds.

View File

@@ -1,6 +0,0 @@
---
reth-engine-tree: patch
reth-trie-sparse-parallel: patch
---
Added tracing spans and debug logs to sparse trie operations for better observability during parallel state root computation.

View File

@@ -1,6 +0,0 @@
---
reth-exex: patch
reth-exex-types: patch
---
Added configurable backfill thresholds to ExEx notifications stream and added regression tests for state provider parity between pipeline and backfill execution paths.

View File

@@ -1,5 +0,0 @@
---
reth-payload-builder: minor
---
Added observability metrics for payload resolve latency and new payload job creation latency to the payload builder service.

View File

@@ -1,4 +0,0 @@
---
---
Added WebSocket subscription integration tests for eth_subscribe.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: minor
---
Added `consensus_ref` method to `PoolTransaction` trait for borrowing consensus transactions without cloning.

View File

@@ -1,4 +0,0 @@
---
---
Improved nightly Docker build failure Slack notification with more detailed formatting and context.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Fixed another branch collapse edge case where `check_subtrie_collapse_needs_proof` incorrectly compared removal count against total update count (including `Touched` entries), causing it to skip proof requests for blinded siblings and panic when the subtrie emptied. Added a regression test covering the removals + `Touched` + blinded sibling scenario.

View File

@@ -1,10 +0,0 @@
---
reth-chain-state: minor
reth-engine-primitives: minor
reth-engine-tree: minor
reth-node-core: minor
reth-node-events: minor
reth: patch
---
Added configurable slow block logging (`--engine.slow-block-threshold`) that emits a structured `warn!` log with detailed timing, state-operation counts, and cache hit-rate metrics for blocks whose total processing time exceeds the threshold. Introduced `ExecutionTimingStats`, `CacheStats`, `StateProviderStats`, and `SlowBlockInfo` types to carry execution statistics from block validation through persistence, and refactored `PersistenceResult` to carry commit duration alongside the last persisted block.

View File

@@ -1,5 +0,0 @@
---
reth-cli-commands: patch
---
Added `snapshot_api_url` field to `DownloadDefaults` so downstream projects can override the snapshot discovery API endpoint. Previously, `discover_manifest_url`, `fetch_snapshot_api_entries`, and `print_snapshot_listing` used a hardcoded `snapshots.reth.rs` URL that bypassed the `DownloadDefaults` override mechanism.

View File

@@ -1,5 +0,0 @@
---
reth-rpc-eth-types: patch
---
Updated `eth_simulateV1` revert error code from `-32000` to `3` to be consistent with `eth_call`, per [execution-apis#748](https://github.com/ethereum/execution-apis/pull/748).

View File

@@ -1,5 +0,0 @@
---
reth-engine-tree: patch
---
Reordered cache size calculations in `ExecutionCache::new` to group related operations together.

View File

@@ -1,7 +0,0 @@
---
reth: patch
reth-cli-commands: patch
reth-node-core: patch
---
Removed experimental ress protocol support for stateless Ethereum nodes.

View File

@@ -1,6 +0,0 @@
---
reth-trie-db: minor
reth-engine-tree: minor
---
Added `PendingChangeset` and `PendingChangesetGuard` to `ChangesetCache` so concurrent readers wait for an in-progress computation instead of falling back to the expensive DB-based path. The guard automatically cancels the pending entry on drop (e.g. task panic), ensuring waiters always make progress.

View File

@@ -1,5 +0,0 @@
---
reth-engine-tree: patch
---
Added sub-phase timing histograms to the sparse trie event loop, tracking channel wait, proof coalescing, multiproof reveal, and trie update durations separately.

View File

@@ -1,6 +0,0 @@
---
reth-primitives-traits: major
reth-downloaders: patch
---
Removed the local `size` module from `reth-primitives-traits` and replaced it with `alloy_consensus::InMemorySize`. Simplified `SignedTransaction` to a blanket impl covering all types satisfying the required bounds, removing `is_system_tx`, `auto_impl` attributes, and explicit impls for `EthereumTxEnvelope` and OP types. Updated import paths in `reth-downloaders` accordingly.

View File

@@ -1,13 +0,0 @@
---
reth-primitives-traits: minor
reth-engine-local: patch
reth-evm: patch
reth-node-builder: patch
reth-payload-primitives: patch
reth-rpc-convert: patch
reth-rpc-eth-api: patch
reth-db-api: patch
reth-db: patch
---
Removed the unused `Extended` type and `op` feature (including `op-alloy-consensus` dependency) from `reth-primitives-traits`. Updated all dependent crates to remove the now-unnecessary `reth-primitives-traits/op` feature flag propagation.

View File

@@ -1,5 +0,0 @@
---
reth-node-builder: patch
---
Removed biased select in engine service loop to allow fair scheduling of shutdown requests alongside event processing.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: patch
---
Fixed swapped arguments in `blob_tx_priority` function calls, correcting the parameter order to match the function signature.

View File

@@ -1,4 +0,0 @@
---
---
Improved documentation overview page with better structure and clarity.

View File

@@ -1,5 +0,0 @@
---
reth: patch
---
Re-enabled changelog workflow to run automatically on pull requests.

View File

@@ -1,5 +0,0 @@
---
reth-node-events: patch
---
Updated consensus engine log message to be more accurate about received updates.

View File

@@ -1,8 +0,0 @@
---
reth-engine-primitives: minor
reth-engine-tree: minor
reth-node-core: minor
reth-trie-parallel: minor
---
Added `--engine.proof-jitter` CLI option behind the `trie-debug` feature flag. When set, each proof worker sleeps for a random duration up to the specified value before starting proof computation, useful for stress-testing timing-sensitive proof logic.

View File

@@ -1,6 +0,0 @@
---
reth-rpc-eth-api: minor
reth-rpc-server-types: minor
---
Added `eth_getStorageValues` RPC method for batch storage slot retrieval across multiple addresses.

View File

@@ -1,6 +0,0 @@
---
reth-chainspec: minor
reth-network-peers: minor
---
Removed OP stack bootnodes from default chain configurations and network peers module.

View File

@@ -1,5 +0,0 @@
---
reth-rpc-convert: patch
---
Updated `alloy-evm` dependency to git revision `9bc2dba` and adapted `TxEnvConverter` impl to the updated `TryIntoTxEnv` trait signature that now includes a `Spec` generic parameter.

View File

@@ -1,6 +0,0 @@
---
reth-trie: patch
reth-trie-sparse: patch
---
Refactored test harness for sparse trie tests by extracting `TrieTestHarness` into a shared `reth-trie` test utility, replacing duplicated inline harness code across multiple test modules. Updated `proof_v2` return type to include an optional root hash, and converted `original_root` and `storage` from public fields to accessor methods.

View File

@@ -1,5 +0,0 @@
---
reth-trie: patch
---
Removed the local `increment_and_strip_trailing_zeros` function and `PATH_ALL_ZEROS` static in `proof_v2`, replacing them with the equivalent `Nibbles::next_without_prefix` and `Nibbles::is_zeroes` builtins. Also replaced manual `.get()` calls on `state_mask`/`hash_mask` with direct field access and switched to `Nibbles::unpack_array` over the unsafe `unpack_unchecked`.

View File

@@ -1,9 +0,0 @@
---
reth-network-api: minor
reth-network-types: minor
reth-network: minor
reth-node-core: minor
reth: minor
---
Added optional ENR fork ID enforcement to filter out peers from incompatible networks during peer discovery, controlled by the `--enforce-enr-fork-id` CLI flag.

View File

@@ -1,5 +0,0 @@
---
reth-primitives: patch
---
Moved feature-referenced dependencies from dev-dependencies to optional dependencies to ensure they are available when their corresponding features are enabled.

View File

@@ -1,5 +0,0 @@
---
reth-engine-tree: patch
---
Added idle-time pre-computation of account trie upper hashes in the sparse trie payload processor when no pending proof results are available.

View File

@@ -1,6 +0,0 @@
---
reth-engine-local: patch
reth-node-builder: patch
---
Removed the `op` feature flag and `OpPayloadAttributes` `PayloadAttributesBuilder` implementation from `reth-engine-local`, along with the `op-alloy-rpc-types-engine` dependency. Updated `reth-node-builder` to no longer enable the removed `op` feature on `reth-engine-local`.

View File

@@ -1,5 +0,0 @@
---
reth-engine-tree: patch
---
Fixed `compare_trie_updates` to return `bool` indicating whether differences were found, and updated the caller to properly use the return value instead of treating all successful comparisons as having no differences.

View File

@@ -1,7 +0,0 @@
---
reth-cli-commands: minor
reth-node-core: minor
reth: patch
---
Made v2 storage the default for all new databases, deprecating the `--storage.v2` flag to a hidden no-op kept for backwards compatibility. Updated CLI reference docs to remove the now-hidden flag from all command help pages.

View File

@@ -1,5 +0,0 @@
---
reth-node-core: minor
---
Added `with_dev_block_time` helper method to `NodeConfig` for configuring dev miner block production interval.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: minor
---
Added `IntoIter: Send` bounds to `validate_transactions` and `validate_transactions_with_origin` in the `TransactionValidator` trait, avoiding unnecessary `Vec` collects. Simplified default `validate_transactions_with_origin` to delegate to `validate_transactions`.

View File

@@ -1,5 +0,0 @@
---
reth-db-api: patch
---
Changed `StoredNibblesSubKey` encoding to use a stack-allocated `[u8; 65]` array instead of a heap-allocated `Vec<u8>`, avoiding unnecessary heap allocation.

View File

@@ -1,7 +0,0 @@
---
reth-engine-tree: patch
reth-trie-sparse: patch
reth-tasks: patch
---
Offloaded deallocation of expensive proof node buffers to a persistent background thread (`Runtime::spawn_drop`) to avoid blocking state root computation or lock-holding code.

View File

@@ -1,5 +0,0 @@
---
reth-storage-api: patch
---
Added `Arc` to `auto_impl` derive for storage-api traits to support automatic `Arc` wrapper implementations.

View File

@@ -1,8 +0,0 @@
---
reth: patch
reth-engine-tree: patch
reth-node-builder: patch
reth-trie-sparse: minor
---
Added `trie-debug` feature for recording sparse trie mutations to aid in debugging state root mismatches.

View File

@@ -1,6 +0,0 @@
---
reth-static-file-types: patch
reth-provider: patch
---
Move changeset offsets from segment header to external `.csoff` sidecar file for incremental writes and crash recovery.

View File

@@ -1,5 +0,0 @@
---
reth-provider: patch
---
Removed unused staging types from ProviderFactoryBuilder.

View File

@@ -1,6 +0,0 @@
---
reth-trie-sparse: patch
reth-engine-tree: patch
---
Removed the `skip_proof_node_filtering` flag, `revealed_account_paths`/`revealed_paths` tracking, and the `filter_revealed_v2_proof_nodes` function from the sparse trie implementation. Also removed the corresponding skipped-nodes metrics, simplifying the proof node reveal path to always pass nodes directly to the sparse trie without pre-filtering.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: minor
---
Added a comprehensive generic `SparseTrie` test suite covering `set_root`, `reveal_nodes`, `update_leaves`, `root`, `take_updates`, `commit_updates`, `prune`, `wipe`/`clear`, `get_leaf_value`, `find_leaf`, `size_hint`, and integration lifecycle scenarios. Tests are stamped out for all concrete `SparseTrie` implementations via a macro.

View File

@@ -1,5 +0,0 @@
---
reth-provider: patch
---
Fixed sender pruning during block reorg to skip when sender_recovery is fully pruned, preventing a fatal crash when no sender data exists in static files.

View File

@@ -1,6 +0,0 @@
---
reth-payload-primitives: patch
reth-engine-local: patch
---
Removed the `op` feature and `op-alloy-rpc-types-engine` dependency from `reth-payload-primitives`, along with the `ExecutionPayload` impl for `OpExecutionData`. Updated `reth-engine-local` to drop the corresponding feature flag dependency.

View File

@@ -1,5 +0,0 @@
---
reth-engine-tree: patch
---
Downgraded per-transaction prewarm span from `debug_span!` to `trace_span!` to reduce noise in debug-level logging.

View File

@@ -1,7 +0,0 @@
---
reth-network-types: minor
reth-network: minor
reth-node-core: patch
---
Added `PersistedPeerInfo` struct to persist richer peer metadata (kind, fork ID, reputation) to disk. Updated `PeersConfig::with_basic_nodes_from_file` to support both the new `PersistedPeerInfo` format and the legacy `Vec<NodeRecord>` format with automatic conversion, and updated `write_peers_to_file` to exclude backed-off and banned peers.

View File

@@ -1,5 +0,0 @@
---
reth: patch
---
Added automated changelog generation infrastructure using wevm/changelogs-rs with Claude Code integration. Configured per-crate changelog format with fixed version groups for reth binaries and exclusions for internal test utilities.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: minor
---
Removed `SerialSparseTrie` from the workspace, consolidating on `ParallelSparseTrie` as the single sparse trie implementation in `reth-trie-sparse`.

View File

@@ -1,5 +0,0 @@
---
reth-cli-commands: minor
---
Added `reth_version` field to `SnapshotManifest` to record the Reth version that produced a snapshot. The field is optional and populated automatically during manifest generation.

View File

@@ -1,5 +0,0 @@
---
reth-network: minor
---
Added `fork_id` as a tiebreaker in peer selection when reputations are equal, preferring peers with a discovered `fork_id` as it indicates fork compatibility. Added a test to verify the tiebreaker behavior.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Fixed a panic in `ParallelSparseTrie::reveal_nodes` when a boundary node's upper parent is absent or non-branch (e.g. when an upper extension crosses the boundary). The code now skips gracefully instead of unwrapping. Added a regression test covering this case.

View File

@@ -1,5 +0,0 @@
---
reth-trie-sparse: patch
---
Fixed a bug where trie nodes could appear in both `updated_nodes` and `removed_nodes` simultaneously by removing entries from `removed_nodes` when a node is inserted as updated.

View File

@@ -1,8 +0,0 @@
---
reth-trie-common: minor
reth-trie: minor
reth-trie-parallel: minor
reth-engine-tree: patch
---
Moved `ProofV2Target`, `MultiProofTargetsV2`, and `ChunkedMultiProofTargetsV2` from `reth-trie-parallel::targets_v2` into a new `reth-trie-common::target_v2` module, making these types available at a lower level without pulling in the full parallel trie crate. Added a `multiproof_v2` method to `Proof` in `reth-trie` that generates a state multiproof using the V2 proof calculator with synchronous account value encoding.

View File

@@ -1,14 +0,0 @@
---
reth-engine-tree: patch
reth-evm-ethereum: patch
reth-evm: patch
reth-primitives-traits: patch
reth-revm: patch
reth-rpc-eth-api: patch
reth-rpc-eth-types: patch
reth-provider: patch
example-custom-evm: patch
example-precompile-cache: patch
---
Bumped revm to v35.0.0, revm-inspectors to 0.35.0, and alloy-evm to 0.29.0. Updated call sites throughout the codebase to align with the new APIs, including `ExecutionResult` field changes (`gas_used``gas.used()`/`gas.final_refunded()`), removal of `.without_state_clear()`, updated `EthPrecompiles::new(spec)` constructor, and updated `block_hashes.lowest()` access.

View File

@@ -1,9 +0,0 @@
---
reth-trie-sparse: minor
reth-engine-primitives: minor
reth-engine-tree: minor
reth-node-core: minor
reth-trie-common: patch
---
Added an arena-based sparse trie implementation (`ArenaParallelSparseTrie`) using `slotmap` arena allocation for node storage, enabling parallel subtrie mutation without per-node hashing overhead. Added `ConfigurableSparseTrie` enum to switch between the arena and hash-map implementations, and a `--engine.enable-arena-sparse-trie` CLI flag to opt in at runtime.

View File

@@ -1,5 +0,0 @@
---
reth: patch
---
Updated Alloy dependencies from 1.5.2 to 1.6.1.

View File

@@ -1,4 +0,0 @@
---
---
Expanded CLI integration tests with subcommand help coverage, config TOML validation, genesis JSON validation, and send transaction round-trip test for dev mode.

View File

@@ -1,6 +0,0 @@
---
reth-engine-local: minor
reth-node-builder: minor
---
Added trigger-based `MiningMode` variant that allows blocks to be built on-demand via custom streams, and exposed `with_mining_mode` method on `DebugNodeLauncherFuture` to override default mining configuration.

View File

@@ -1,5 +0,0 @@
---
reth-network: minor
---
Added direction labels to `closed_sessions` and `pending_session_failures` metrics. Operators can now distinguish session closures and failures by direction (`active`, `incoming_pending`, `outgoing_pending` for closed sessions; `inbound`, `outbound` for pending session failures).

View File

@@ -1,4 +0,0 @@
---
---
Moved Kurtosis CI failure notifications to the hive Slack channel.

View File

@@ -1,7 +0,0 @@
---
reth-rpc-api: minor
reth-rpc-builder: patch
reth-rpc: minor
---
Added `subscribeFinalizedChainNotifications` RPC endpoint that buffers committed chain notifications and emits them once a new finalized block is received.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: patch
---
Fixed a bug where transactions from the same sender were added to the pending subpool out of nonce order. Ensured `process_updates` runs before `add_new_transaction` so that lower-nonce promotions are enqueued before the newly inserted higher-nonce transaction, preserving correct ordering for live `BestTransactions` iterators.

View File

@@ -1,5 +0,0 @@
---
reth-transaction-pool: minor
---
Added `TransactionValidationTaskExecutor::spawn` as a dedicated constructor that encapsulates spawning validation tasks on a runtime, and refactored `EthTransactionValidatorBuilder::build_with_tasks` to use it.

View File

@@ -1,7 +0,0 @@
---
reth-engine-primitives: patch
reth-engine-tree: patch
reth-node-core: patch
---
Removed `--engine.enable-arena-sparse-trie` CLI flag and made the arena-based sparse trie the default implementation. The hash-map-based `ParallelSparseTrie` variant is no longer selectable.

View File

@@ -1,7 +0,0 @@
---
reth-trie: major
reth-trie-db: major
reth-provider: minor
---
Added `MaskedTrieCursorFactory` and `MaskedTrieCursor` to handle prefix-set-based hash invalidation at the cursor layer, replacing the `DatabaseTrieWitness` trait abstraction. Removed `with_prefix_sets_mut` from `TrieWitness` and deleted `DatabaseTrieWitness` — callers should now wrap their cursor factory with `MaskedTrieCursorFactory` to apply prefix sets during witness/proof computation.

View File

@@ -1,8 +0,0 @@
---
reth-engine-primitives: minor
reth-engine-tree: major
reth-node-core: minor
reth-cli-commands: minor
---
Added persistence backpressure to the engine tree: when the canonical-minus-persisted block gap exceeds a configurable threshold (`--engine.persistence-backpressure-threshold`, default 16), the engine loop stalls on the persistence receiver instead of processing new incoming messages. Added CLI argument, cross-field validation, metrics (`backpressure_active`, `backpressure_stall_duration`), and tests.

View File

@@ -1,6 +0,0 @@
---
reth-trie: minor
reth-trie-parallel: minor
---
Added `root_node` and `storage_root_node` methods to proof calculators for efficient root-only calculations. These methods directly return the root node without requiring dummy targets, replacing the previous workaround of passing fake targets to proof generation.

View File

@@ -1,5 +0,0 @@
---
reth-trie: patch
---
Fixed a potential panic in `ProofCalculator` by clearing internal computation state (`branch_stack`, `child_stack`, `branch_path`, etc.) after errors, preventing stale state from causing `usize` underflow panics when the calculator is reused. Added a test verifying correct behavior after simulated mid-computation errors.

View File

@@ -20,11 +20,6 @@
# include dist directory, where the reth binary is located after compilation
!/dist
# include PGO build helper used by Dockerfile.depot
!/.github
!/.github/scripts
!/.github/scripts/build_pgo_bolt.sh
# include licenses
!LICENSE-*

View File

@@ -16,7 +16,7 @@
#
# Required: mc (MinIO client) with a configured alias
# Optional env: BENCH_BIG_BLOCKS (true/false) — build reth-bb instead of reth
set -euo pipefail
set -euxo pipefail
MC="mc"
MODE="$1"
@@ -73,14 +73,14 @@ case "$MODE" in
mkdir -p "${SOURCE_DIR}/target/profiling"
CACHE_VALID=false
if $MC stat "${BUCKET}/${NODE_BIN}" &>/dev/null; then
if $MC stat --no-list "${BUCKET}/${NODE_BIN}" &>/dev/null; then
echo "Cache hit for baseline (${COMMIT}), downloading ${NODE_BIN}..."
$MC cp "${BUCKET}/${NODE_BIN}" "${SOURCE_DIR}/target/profiling/${NODE_BIN}"
chmod +x "${SOURCE_DIR}/target/profiling/${NODE_BIN}"
if verify_binary "${SOURCE_DIR}/target/profiling/${NODE_BIN}" "${COMMIT}"; then
if $MC cp "${BUCKET}/${NODE_BIN}" "${SOURCE_DIR}/target/profiling/${NODE_BIN}" && \
chmod +x "${SOURCE_DIR}/target/profiling/${NODE_BIN}" && \
verify_binary "${SOURCE_DIR}/target/profiling/${NODE_BIN}" "${COMMIT}"; then
CACHE_VALID=true
else
echo "Cached baseline binary is stale, rebuilding..."
echo "Cached baseline binary is stale or download failed, rebuilding..."
fi
fi
if [ "$CACHE_VALID" = false ]; then
@@ -105,16 +105,16 @@ case "$MODE" in
BUCKET="minio/reth-binaries/${BRANCH_SHA}${BUILD_SUFFIX}"
CACHE_VALID=false
if $MC stat "${BUCKET}/${NODE_BIN}" &>/dev/null && $MC stat "${BUCKET}/reth-bench" &>/dev/null; then
if $MC stat --no-list "${BUCKET}/${NODE_BIN}" &>/dev/null && $MC stat --no-list "${BUCKET}/reth-bench" &>/dev/null; then
echo "Cache hit for ${BRANCH_SHA}, downloading binaries..."
mkdir -p "${SOURCE_DIR}/target/profiling"
$MC cp "${BUCKET}/${NODE_BIN}" "${SOURCE_DIR}/target/profiling/${NODE_BIN}"
$MC cp "${BUCKET}/reth-bench" /home/ubuntu/.cargo/bin/reth-bench
chmod +x "${SOURCE_DIR}/target/profiling/${NODE_BIN}" /home/ubuntu/.cargo/bin/reth-bench
if verify_binary "${SOURCE_DIR}/target/profiling/${NODE_BIN}" "${COMMIT}"; then
if $MC cp "${BUCKET}/${NODE_BIN}" "${SOURCE_DIR}/target/profiling/${NODE_BIN}" && \
$MC cp "${BUCKET}/reth-bench" /home/ubuntu/.cargo/bin/reth-bench && \
chmod +x "${SOURCE_DIR}/target/profiling/${NODE_BIN}" /home/ubuntu/.cargo/bin/reth-bench && \
verify_binary "${SOURCE_DIR}/target/profiling/${NODE_BIN}" "${COMMIT}"; then
CACHE_VALID=true
else
echo "Cached feature binary is stale, rebuilding..."
echo "Cached feature binary is stale or download failed, rebuilding..."
fi
fi
if [ "$CACHE_VALID" = false ]; then

View File

@@ -26,7 +26,7 @@
#
# The script delegates to the existing bench-reth-*.sh scripts in the reth
# repo for the actual build, snapshot, and run steps.
set -euo pipefail
set -euxo pipefail
# ── PATH ──────────────────────────────────────────────────────────────
# Ensure cargo and user-local bins (mc, uv) are visible
@@ -399,12 +399,9 @@ upload_tracy() {
# ── Step 6: Pre-flight cleanup ───────────────────────────────────────
echo "▸ Pre-flight cleanup..."
pkill -f bench-metrics-proxy 2>/dev/null || true
sudo pkill -9 reth 2>/dev/null || true
sleep 1
if mountpoint -q "$SCHELK_MOUNT" 2>/dev/null; then
sudo umount -l "$SCHELK_MOUNT" 2>/dev/null || true
sudo schelk recover -y 2>/dev/null || true
fi
sudo systemctl stop "${RETH_SCOPE:-reth-bench.scope}" 2>/dev/null || true
sudo systemctl reset-failed "${RETH_SCOPE:-reth-bench.scope}" 2>/dev/null || true
sudo schelk recover -y --kill || sudo schelk full-recover -y || true
echo
# ── Step 7: Interleaved benchmark runs (B-F-F-B) ────────────────────

View File

@@ -7,13 +7,14 @@
#
# Required env: SCHELK_MOUNT, BENCH_RPC_URL, BENCH_BLOCKS, BENCH_WARMUP_BLOCKS
# Optional env: BENCH_BIG_BLOCKS (true/false), BENCH_WORK_DIR (for big blocks path)
# BENCH_RETH_NEW_PAYLOAD (true/false, default true)
# BENCH_BAL (false/true/feature/baseline; only used with big blocks)
# BENCH_WAIT_TIME (duration like 500ms, default empty)
# BENCH_BASELINE_ARGS (extra reth node args for baseline runs)
# BENCH_FEATURE_ARGS (extra reth node args for feature runs)
# BENCH_OTLP_TRACES_ENDPOINT (OTLP HTTP endpoint for traces, e.g. https://host/insert/opentelemetry/v1/traces)
# BENCH_OTLP_LOGS_ENDPOINT (OTLP HTTP endpoint for logs, e.g. https://host/insert/opentelemetry/v1/logs)
set -euo pipefail
# BENCH_OTLP_DISABLED (true to skip OTLP export even if endpoints are set)
set -euxo pipefail
LABEL="$1"
BINARY="$2"
@@ -26,6 +27,8 @@ DATADIR="$SCHELK_MOUNT/$DATADIR_NAME"
mkdir -p "$OUTPUT_DIR"
LOG="${OUTPUT_DIR}/node.log"
RETH_SCOPE="${RETH_SCOPE:-reth-bench.scope}"
cleanup() {
kill "$TAIL_PID" 2>/dev/null || true
# Stop tracy-capture first (SIGINT makes it disconnect and flush to disk)
@@ -46,7 +49,7 @@ cleanup() {
fi
wait "$TRACY_PID" 2>/dev/null || true
fi
if [ -n "${RETH_PID:-}" ] && sudo kill -0 "$RETH_PID" 2>/dev/null; then
if sudo systemctl is-active "$RETH_SCOPE" >/dev/null 2>&1; then
if [ "${BENCH_SAMPLY:-false}" = "true" ]; then
# Send SIGINT to the inner reth process by exact name (not -f which
# would also match samply's cmdline containing "reth"). Samply will
@@ -64,31 +67,28 @@ cleanup() {
echo "Samply still running after 120s, sending SIGTERM..."
sudo pkill -x samply 2>/dev/null || true
fi
else
sudo kill "$RETH_PID"
for i in $(seq 1 30); do
sudo kill -0 "$RETH_PID" 2>/dev/null || break
sleep 1
done
fi
sudo kill -9 "$RETH_PID" 2>/dev/null || true
# Stop the entire systemd scope — kills all processes in the cgroup.
# This is reliable regardless of process reparenting or PID wrapper issues.
sudo systemctl stop "$RETH_SCOPE" 2>/dev/null || true
sleep 1
fi
sudo systemctl reset-failed "$RETH_SCOPE" 2>/dev/null || true
# Fix ownership of reth-created files (reth runs as root)
sudo chown -R "$(id -un):$(id -gn)" "$OUTPUT_DIR" 2>/dev/null || true
if mountpoint -q "$SCHELK_MOUNT"; then
sudo umount -l "$SCHELK_MOUNT" || true
sudo schelk recover -y || true
fi
# Let schelk recover the mounted volume in place so dm-era can restore only
# the changed blocks and clean up its own state.
sudo schelk recover -y --kill || true
}
TAIL_PID=
TRACY_PID=
trap cleanup EXIT
# Clean up stale schelk state from a previous cancelled run.
# If schelk thinks it's still mounted (e.g. a cancelled run skipped cleanup),
# recover first to reset state.
sudo schelk recover -y -k || true
# Clean up stale state from a previous cancelled run.
# Stop any leftover reth process in the scope, then recover schelk state.
sudo systemctl stop "$RETH_SCOPE" 2>/dev/null || true
sudo systemctl reset-failed "$RETH_SCOPE" 2>/dev/null || true
sudo schelk recover -y --kill || true
# Mount
sudo schelk mount -y
@@ -149,11 +149,13 @@ if [ -n "${BENCH_METRICS_ADDR:-}" ]; then
fi
# OTLP traces and logs export
if [ -n "${BENCH_OTLP_TRACES_ENDPOINT:-}" ]; then
RETH_ARGS+=(--tracing-otlp="${BENCH_OTLP_TRACES_ENDPOINT}" --tracing-otlp.service-name=reth-bench)
fi
if [ -n "${BENCH_OTLP_LOGS_ENDPOINT:-}" ]; then
RETH_ARGS+=(--logs-otlp="${BENCH_OTLP_LOGS_ENDPOINT}" --logs-otlp.filter=debug)
if [ "${BENCH_OTLP_DISABLED:-false}" != "true" ]; then
if [ -n "${BENCH_OTLP_TRACES_ENDPOINT:-}" ]; then
RETH_ARGS+=(--tracing-otlp="${BENCH_OTLP_TRACES_ENDPOINT}" --tracing-otlp.service-name=reth-bench)
fi
if [ -n "${BENCH_OTLP_LOGS_ENDPOINT:-}" ]; then
RETH_ARGS+=(--logs-otlp="${BENCH_OTLP_LOGS_ENDPOINT}" --logs-otlp.filter=debug)
fi
fi
# Tracy profiling: add --log.tracy flags and set environment
@@ -180,19 +182,19 @@ echo "Memory limit: $(( MEM_LIMIT / 1024 / 1024 ))MB (95% of $(( TOTAL_MEM_KB /
if [ "${BENCH_SAMPLY:-false}" = "true" ]; then
RETH_ARGS+=(--log.samply)
SAMPLY="$(which samply)"
sudo systemd-run --scope -p MemoryMax="$MEM_LIMIT" -p AllowedCPUs="$RETH_CPUS" \
sudo systemd-run --quiet --scope --collect --unit="$RETH_SCOPE" \
-p MemoryMax="$MEM_LIMIT" -p AllowedCPUs="$RETH_CPUS" \
env "${SUDO_ENV[@]}" nice -n -20 \
"$SAMPLY" record --save-only --presymbolicate --rate 10000 \
--output "$OUTPUT_DIR/samply-profile.json.gz" \
-- "$BINARY" "${RETH_ARGS[@]}" \
> "$LOG" 2>&1 &
else
sudo systemd-run --scope -p MemoryMax="$MEM_LIMIT" -p AllowedCPUs="$RETH_CPUS" \
sudo systemd-run --quiet --scope --collect --unit="$RETH_SCOPE" \
-p MemoryMax="$MEM_LIMIT" -p AllowedCPUs="$RETH_CPUS" \
env "${SUDO_ENV[@]}" nice -n -20 "$BINARY" "${RETH_ARGS[@]}" \
> "$LOG" 2>&1 &
fi
RETH_PID=$!
stdbuf -oL tail -f "$LOG" | sed -u "s/^/[reth] /" &
TAIL_PID=$!
@@ -240,10 +242,7 @@ fi
BENCH_NICE="sudo nice -n -20 sudo -u $(id -un)"
# Build optional flags
EXTRA_BENCH_ARGS=()
if [ "${BENCH_RETH_NEW_PAYLOAD:-true}" != "false" ]; then
EXTRA_BENCH_ARGS+=(--reth-new-payload --wait-for-persistence)
fi
EXTRA_BENCH_ARGS=(--reth-new-payload)
if [ -n "${BENCH_WAIT_TIME:-}" ]; then
EXTRA_BENCH_ARGS+=(--wait-time "$BENCH_WAIT_TIME")
fi
@@ -251,8 +250,47 @@ fi
if [ "$BIG_BLOCKS" = "true" ]; then
# Big blocks mode: replay pre-generated payloads
BIG_BLOCKS_DIR="${BENCH_BIG_BLOCKS_DIR:-${BENCH_WORK_DIR}/big-blocks}"
BENCH_BAL_MODE="${BENCH_BAL:-false}"
# Start tracy-capture so profile only covers the benchmark
BB_BENCH_ARGS=(--reth-new-payload)
if [ -n "${BENCH_WAIT_TIME:-}" ]; then
BB_BENCH_ARGS+=(--wait-time "$BENCH_WAIT_TIME")
fi
case "$BENCH_BAL_MODE" in
false)
;;
true)
BB_BENCH_ARGS+=(--bal)
;;
baseline)
if [[ "$LABEL" == baseline* ]]; then
BB_BENCH_ARGS+=(--bal)
fi
;;
feature)
if [[ "$LABEL" == feature* ]]; then
BB_BENCH_ARGS+=(--bal)
fi
;;
*)
echo "::error::Unknown BENCH_BAL value: $BENCH_BAL_MODE"
exit 1
;;
esac
# Warmup
WARMUP="${BENCH_WARMUP_BLOCKS:-50}"
if [ "$WARMUP" -gt 0 ] 2>/dev/null; then
echo "Running big blocks warmup (${WARMUP} payloads)..."
$BENCH_NICE "$RETH_BENCH" replay-payloads \
"${BB_BENCH_ARGS[@]}" \
--count "$WARMUP" \
--payload-dir "$BIG_BLOCKS_DIR/payloads" \
--engine-rpc-url http://127.0.0.1:8551 \
--jwt-secret "$DATADIR/jwt.hex" 2>&1 | sed -u "s/^/[bench] /"
fi
# Start tracy-capture after warmup so profile only covers the benchmark
if [ "${BENCH_TRACY:-off}" != "off" ]; then
echo "Starting tracy-capture..."
tracy-capture -f -o "$OUTPUT_DIR/tracy-profile.tracy" &
@@ -260,18 +298,19 @@ if [ "$BIG_BLOCKS" = "true" ]; then
sleep 0.5 # give tracy-capture time to connect
fi
BB_BENCH_ARGS=(--reth-new-payload --wait-for-persistence)
if [ -n "${BENCH_WAIT_TIME:-}" ]; then
BB_BENCH_ARGS+=(--wait-time "$BENCH_WAIT_TIME")
# Benchmark — skip warmup payloads so they aren't measured
BB_SKIP=0
if [ "$WARMUP" -gt 0 ] 2>/dev/null; then
BB_SKIP="$WARMUP"
fi
# Limit number of payloads if blocks count is specified
if [ "${BENCH_BLOCKS:-0}" -gt 0 ] 2>/dev/null; then
BB_BENCH_ARGS+=(--count "$BENCH_BLOCKS")
fi
echo "Running big blocks benchmark (replay-payloads)..."
echo "Running big blocks benchmark (replay-payloads, skip=${BB_SKIP})..."
$BENCH_NICE "$RETH_BENCH" replay-payloads \
"${BB_BENCH_ARGS[@]}" \
--skip "$BB_SKIP" \
--payload-dir "$BIG_BLOCKS_DIR/payloads" \
--engine-rpc-url http://127.0.0.1:8551 \
--jwt-secret "$DATADIR/jwt.hex" \

View File

@@ -18,7 +18,7 @@
# BENCH_JOB_URL link to the Actions job
# BENCH_ACTOR user who triggered the benchmark
# BENCH_CONFIG config summary line
set -euo pipefail
set -euxo pipefail
MC="mc"
BUCKET="minio/reth-snapshots"
@@ -77,8 +77,8 @@ trap 'rm -f -- "$MANIFEST_TMP"' EXIT
echo "$MANIFEST_CONTENT" \
| jq --arg base "$BASE_URL" '.base_url = $base' > "$MANIFEST_TMP"
# Prepare mount
mountpoint -q "$SCHELK_MOUNT" && sudo schelk recover -y || true
# Prepare mount. If a previous run left the volume mounted, recover first.
sudo schelk recover -y --kill || true
sudo schelk mount -y
sudo rm -rf "$DATADIR"
sudo mkdir -p "$DATADIR"

View File

@@ -111,6 +111,14 @@ def compute_stats(combined: list[dict]) -> dict:
wall_clock_s = sum(total_latencies_ms) / 1_000
mean_total_lat_ms = sum(total_latencies_ms) / n
# Persistence wait mean (for main table)
persist_values_ms = []
for r in combined:
v = r.get("persistence_wait_us")
if v is not None:
persist_values_ms.append(v / 1_000)
mean_persist_ms = sum(persist_values_ms) / len(persist_values_ms) if persist_values_ms else 0.0
return {
"n": n,
"mean_ms": mean_lat,
@@ -121,6 +129,7 @@ def compute_stats(combined: list[dict]) -> dict:
"mean_mgas_s": mean_mgas_s,
"wall_clock_s": wall_clock_s,
"mean_total_lat_ms": mean_total_lat_ms,
"mean_persist_ms": mean_persist_ms,
}
@@ -145,7 +154,7 @@ def compute_wait_stats(combined: list[dict], field: str) -> dict:
def _paired_data(
baseline: list[dict], feature: list[dict]
) -> tuple[list[tuple[float, float]], list[float], list[float], list[float]]:
) -> tuple[list[tuple[float, float]], list[float], list[float], list[float], list[float]]:
"""Match blocks and return paired latencies and per-block diffs.
Returns:
@@ -153,6 +162,7 @@ def _paired_data(
lat_diffs_ms: list of feature baseline latency diffs in ms
mgas_diffs: list of feature baseline Mgas/s diffs
total_lat_diffs_ms: list of feature baseline total latency diffs in ms
persist_diffs_ms: list of feature baseline persistence wait diffs in ms
"""
baseline_by_block = {r["block_number"]: r for r in baseline}
feature_by_block = {r["block_number"]: r for r in feature}
@@ -162,6 +172,7 @@ def _paired_data(
lat_diffs_ms = []
mgas_diffs = []
total_lat_diffs_ms = []
persist_diffs_ms = []
for bn in common_blocks:
b = baseline_by_block[bn]
f = feature_by_block[bn]
@@ -179,7 +190,10 @@ def _paired_data(
total_lat_diffs_ms.append(
f["total_latency_us"] / 1_000 - b["total_latency_us"] / 1_000
)
return pairs, lat_diffs_ms, mgas_diffs, total_lat_diffs_ms
b_persist = (b.get("persistence_wait_us") or 0) / 1_000
f_persist = (f.get("persistence_wait_us") or 0) / 1_000
persist_diffs_ms.append(f_persist - b_persist)
return pairs, lat_diffs_ms, mgas_diffs, total_lat_diffs_ms, persist_diffs_ms
def compute_paired_stats(
@@ -195,13 +209,15 @@ def compute_paired_stats(
all_lat_diffs = []
all_mgas_diffs = []
all_total_lat_diffs = []
all_persist_diffs = []
blocks_per_pair = []
for baseline, feature in zip(baseline_runs, feature_runs):
pairs, lat_diffs, mgas_diffs, total_lat_diffs = _paired_data(baseline, feature)
pairs, lat_diffs, mgas_diffs, total_lat_diffs, persist_diffs = _paired_data(baseline, feature)
all_pairs.extend(pairs)
all_lat_diffs.extend(lat_diffs)
all_mgas_diffs.extend(mgas_diffs)
all_total_lat_diffs.extend(total_lat_diffs)
all_persist_diffs.extend(persist_diffs)
blocks_per_pair.append(len(pairs))
if not all_lat_diffs:
@@ -245,6 +261,11 @@ def compute_paired_stats(
total_se = std_total_diff / math.sqrt(len(all_total_lat_diffs)) if all_total_lat_diffs else 0.0
wall_clock_ci_ms = T_CRITICAL * total_se
mean_persist_diff = sum(all_persist_diffs) / len(all_persist_diffs) if all_persist_diffs else 0.0
std_persist_diff = stddev(all_persist_diffs, mean_persist_diff) if len(all_persist_diffs) > 1 else 0.0
persist_se = std_persist_diff / math.sqrt(len(all_persist_diffs)) if all_persist_diffs else 0.0
persist_ci_ms = T_CRITICAL * persist_se
return {
"n": n,
"mean_diff_ms": mean_diff,
@@ -258,6 +279,7 @@ def compute_paired_stats(
"mean_mgas_diff": mean_mgas_diff,
"mgas_ci": mgas_ci,
"wall_clock_ci_ms": wall_clock_ci_ms,
"persist_ci_ms": persist_ci_ms,
"blocks": max(blocks_per_pair),
}
@@ -290,6 +312,14 @@ def fmt_s(v: float) -> str:
return f"{v:.2f}s"
def display_bal_mode(bal_mode: str | None) -> str | None:
if not bal_mode or bal_mode == "false":
return None
if bal_mode == "both":
return "true"
return bal_mode
def significance(pct: float, ci_pct: float, lower_is_better: bool) -> str:
"""Return significance label: 'good', 'bad', or 'neutral'."""
significant = abs(pct) > ci_pct
@@ -328,6 +358,7 @@ def compute_changes(
("p99", "p99_ms", "p99_ci_ms", "p99_ms", True),
("mgas_s", "mean_mgas_s", "mgas_ci", "mean_mgas_s", False),
("wall_clock", "wall_clock_s", "wall_clock_ci_ms", "mean_total_lat_ms", True),
("persist_wait", "mean_persist_ms", "persist_ci_ms", "mean_persist_ms", True),
]
changes = {}
for name, stat_key, ci_key, base_key, lower_is_better in metrics:
@@ -351,6 +382,9 @@ def generate_comparison_table(
feature_name: str,
feature_sha: str,
big_blocks: bool = False,
warmup_blocks: str | None = None,
wait_time: str | None = None,
bal_mode: str | None = None,
) -> str:
"""Generate a markdown comparison table between baseline and feature."""
n = paired["blocks"]
@@ -366,6 +400,8 @@ def generate_comparison_table(
p90_pct = pct(run1["p90_ms"], run2["p90_ms"])
p99_pct = pct(run1["p99_ms"], run2["p99_ms"])
persist_pct = pct(run1["mean_persist_ms"], run2["mean_persist_ms"])
# Bootstrap CIs as % of baseline percentile
p50_ci_pct = paired["p50_ci_ms"] / run1["p50_ms"] * 100.0 if run1["p50_ms"] > 0 else 0.0
p90_ci_pct = paired["p90_ci_ms"] / run1["p90_ms"] * 100.0 if run1["p90_ms"] > 0 else 0.0
@@ -375,6 +411,7 @@ def generate_comparison_table(
lat_ci_pct = paired["ci_ms"] / run1["mean_ms"] * 100.0 if run1["mean_ms"] > 0 else 0.0
mgas_ci_pct = paired["mgas_ci"] / run1["mean_mgas_s"] * 100.0 if run1["mean_mgas_s"] > 0 else 0.0
wall_ci_pct = paired["wall_clock_ci_ms"] / run1["mean_total_lat_ms"] * 100.0 if run1["mean_total_lat_ms"] > 0 else 0.0
persist_ci_pct = paired["persist_ci_ms"] / run1["mean_persist_ms"] * 100.0 if run1["mean_persist_ms"] > 0 else 0.0
base_url = f"https://github.com/{repo}/commit"
baseline_label = f"[`{baseline_name}`]({base_url}/{baseline_ref})"
@@ -390,9 +427,18 @@ def generate_comparison_table(
f"| P99 | {fmt_ms(run1['p99_ms'])} | {fmt_ms(run2['p99_ms'])} | {change_str(p99_pct, p99_ci_pct, lower_is_better=True)} |",
f"| Mgas/s | {fmt_mgas(run1['mean_mgas_s'])} | {fmt_mgas(run2['mean_mgas_s'])} | {change_str(gas_pct, mgas_ci_pct, lower_is_better=False)} |",
f"| Wall Clock | {fmt_s(run1['wall_clock_s'])} | {fmt_s(run2['wall_clock_s'])} | {change_str(wall_pct, wall_ci_pct, lower_is_better=True)} |",
f"| Persist Wait | {fmt_ms(run1['mean_persist_ms'])} | {fmt_ms(run2['mean_persist_ms'])} | {change_str(persist_pct, persist_ci_pct, lower_is_better=True)} |",
"",
f"*{n} {'big blocks' if big_blocks else 'blocks'}*",
]
meta_parts = [f"{n} {'big blocks' if big_blocks else 'blocks'}"]
if warmup_blocks:
meta_parts.append(f"{warmup_blocks} warmup")
if wait_time:
meta_parts.append(f"wait time: {wait_time}")
display_mode = display_bal_mode(bal_mode)
if big_blocks and display_mode:
meta_parts.append(f"BAL: {display_mode}")
lines.append(f"*{', '.join(meta_parts)}*")
return "\n".join(lines)
@@ -472,6 +518,9 @@ def main():
parser.add_argument("--feature-ref", "--branch-sha", "--feature-sha", default=None, help="Feature commit SHA")
parser.add_argument("--behind-baseline", "--behind-main", type=int, default=0, help="Commits behind baseline")
parser.add_argument("--big-blocks", action="store_true", default=False, help="Big blocks mode")
parser.add_argument("--warmup-blocks", default=None, help="Number of warmup blocks")
parser.add_argument("--wait-time", default=None, help="Wait time interval used between blocks")
parser.add_argument("--bal-mode", default=None, help="BAL mode (true, feature, baseline)")
parser.add_argument("--grafana-url", default=None, help="Grafana dashboard URL for this benchmark run")
args = parser.parse_args()
@@ -511,6 +560,7 @@ def main():
baseline_name = args.baseline_name or "baseline"
feature_name = args.feature_name or "feature"
feature_sha = args.feature_ref or "unknown"
bal_mode = display_bal_mode(args.bal_mode)
comparison_table = generate_comparison_table(
baseline_stats,
@@ -522,6 +572,9 @@ def main():
feature_name=feature_name,
feature_sha=feature_sha,
big_blocks=args.big_blocks,
warmup_blocks=args.warmup_blocks,
wait_time=args.wait_time,
bal_mode=bal_mode,
)
print(f"Generated comparison ({paired_stats['n']} paired blocks, "
f"mean diff {paired_stats['mean_diff_ms']:+.3f}ms ± {paired_stats['ci_ms']:.3f}ms)")
@@ -553,6 +606,9 @@ def main():
summary = {
"blocks": paired_stats["blocks"],
"big_blocks": args.big_blocks,
"warmup_blocks": args.warmup_blocks,
"wait_time": args.wait_time,
"bal_mode": bal_mode,
"baseline": {
"name": baseline_name,
"ref": baseline_ref,

View File

@@ -2,17 +2,20 @@
#
# Resolves baseline and feature refs for scheduled benchmark runs.
#
# Supports two modes:
# Supports three modes:
# nightly — Queries the latest successful scheduled docker.yml run via
# GitHub API to find the nightly Docker image commit. Compares
# with the last successful feature ref to detect staleness.
# hourly — Compares origin/main HEAD against the last successfully
# benchmarked commit (falls back to HEAD~1 on first run).
# Checks for in-progress sibling runs to avoid overlap.
# release — Compares the latest GitHub release tag against the current
# nightly Docker build. Baseline is the release tag commit,
# feature is the nightly commit.
#
# Usage: bench-scheduled-refs.sh <force> <mode>
# force — "true" to run even if no new commit (bypass skip logic)
# mode — "nightly" or "hourly"
# mode — "nightly", "hourly", or "release"
#
# Outputs (via GITHUB_OUTPUT):
# baseline-ref — commit SHA for baseline
@@ -21,13 +24,15 @@
# is-stale — "true" if latest nightly build is >24h old (nightly only)
# stale-age-hours — age of the nightly build in hours (nightly only)
# nightly-created — ISO timestamp of the nightly build (nightly only)
# release-tag — release tag name (release mode only, e.g. "v2.0.0")
#
# Reads:
# .nightly-state/last-feature-ref (nightly, from GH Actions cache)
# .hourly-state/last-feature-ref (hourly, from GH Actions cache)
# state/nightly-last-feature-ref (nightly, from decofe/reth-bench-charts repo)
# state/hourly-last-feature-ref (hourly, from decofe/reth-bench-charts repo)
# state/release-last-feature-ref (release, from decofe/reth-bench-charts repo)
#
# Requires: gh (GitHub CLI), jq, date, git (hourly mode)
set -euo pipefail
# Requires: gh (GitHub CLI), jq, date, git (hourly mode), curl, DEREK_TOKEN env
set -euxo pipefail
FORCE="${1:-false}"
MODE="${2:-nightly}"
@@ -42,7 +47,7 @@ if [ "$MODE" = "hourly" ]; then
# --- Step 1: Resolve feature ref from git ---
echo "::group::Resolving hourly refs from git"
git fetch origin main --quiet
git fetch origin main --depth=2 --quiet
FEATURE_REF=$(git rev-parse origin/main)
echo "Feature (HEAD): $FEATURE_REF"
echo "::endgroup::"
@@ -69,15 +74,15 @@ if [ "$MODE" = "hourly" ]; then
fi
echo "::endgroup::"
# --- Step 3: Read last successful feature ref from cache ---
echo "::group::Reading cached state"
# --- Step 3: Read last successful feature ref from charts repo ---
echo "::group::Reading persisted state"
LAST_FEATURE_REF=""
STATE_FILE=".hourly-state/last-feature-ref"
if [ -f "$STATE_FILE" ]; then
LAST_FEATURE_REF=$(tr -d '[:space:]' < "$STATE_FILE")
STATE_URL="https://raw.githubusercontent.com/decofe/reth-bench-charts/state/state/hourly-last-feature-ref"
if RAW=$(curl -sfL -H "Authorization: token ${DEREK_TOKEN}" "$STATE_URL"); then
LAST_FEATURE_REF=$(echo "$RAW" | tr -d '[:space:]')
echo "Previous feature ref: $LAST_FEATURE_REF"
else
echo "No cached state found (first run)"
echo "No persisted state found (first run)"
fi
echo "::endgroup::"
@@ -121,6 +126,106 @@ if [ "$MODE" = "hourly" ]; then
exit 0
fi
# ==========================================================================
# Release mode: compare latest GitHub release tag vs current nightly build
# ==========================================================================
if [ "$MODE" = "release" ]; then
# --- Step 1: Resolve feature ref from latest nightly Docker build ---
echo "::group::Querying latest nightly docker build"
RUNS_JSON=$(gh run list \
-R "$REPO" \
--workflow=docker.yml \
--event=schedule \
--status=completed \
--limit 5 \
--json headSha,createdAt,conclusion)
LATEST=$(echo "$RUNS_JSON" | jq -r '[.[] | select(.conclusion == "success")] | first // empty')
if [ -z "$LATEST" ]; then
echo "::error::No successful scheduled docker.yml run found in the last 5 runs"
exit 1
fi
FEATURE_REF=$(echo "$LATEST" | jq -r '.headSha')
echo "Nightly commit (feature): $FEATURE_REF"
echo "::endgroup::"
# --- Step 2: Resolve baseline ref from latest GitHub release ---
echo "::group::Resolving latest release tag"
RELEASE_JSON=$(gh release view --repo "$REPO" --json tagName,targetCommitish,publishedAt 2>/dev/null || echo "{}")
RELEASE_TAG=$(echo "$RELEASE_JSON" | jq -r '.tagName // empty')
if [ -z "$RELEASE_TAG" ]; then
echo "::error::No release found on $REPO"
exit 1
fi
# Resolve the tag to a commit SHA
BASELINE_REF=$(gh api "repos/$REPO/git/ref/tags/$RELEASE_TAG" --jq '.object.sha' 2>/dev/null || true)
# If tag points to an annotated tag object, dereference to the commit
if [ -n "$BASELINE_REF" ]; then
OBJ_TYPE=$(gh api "repos/$REPO/git/tags/$BASELINE_REF" --jq '.object.type' 2>/dev/null || echo "commit")
if [ "$OBJ_TYPE" = "commit" ]; then
BASELINE_REF=$(gh api "repos/$REPO/git/tags/$BASELINE_REF" --jq '.object.sha' 2>/dev/null || echo "$BASELINE_REF")
fi
fi
if [ -z "$BASELINE_REF" ]; then
echo "::error::Could not resolve release tag $RELEASE_TAG to a commit"
exit 1
fi
echo "Release tag: $RELEASE_TAG"
echo "Release commit (baseline): $BASELINE_REF"
echo "::endgroup::"
# --- Step 3: Read last successful feature ref from charts repo ---
echo "::group::Reading persisted state"
LAST_FEATURE_REF=""
STATE_URL="https://raw.githubusercontent.com/decofe/reth-bench-charts/state/state/release-last-feature-ref"
if RAW=$(curl -sfL -H "Authorization: token ${DEREK_TOKEN}" "$STATE_URL"); then
LAST_FEATURE_REF=$(echo "$RAW" | tr -d '[:space:]')
echo "Previous feature ref: $LAST_FEATURE_REF"
else
echo "No persisted state found (first run)"
fi
echo "::endgroup::"
# --- Step 4: Skip logic ---
echo "::group::Resolving skip logic"
SHOULD_SKIP="false"
if [ -n "$LAST_FEATURE_REF" ] && [ "$LAST_FEATURE_REF" = "$FEATURE_REF" ]; then
if [ "$FORCE" = "true" ] || [ "$FORCE" = "--force" ]; then
echo "No new nightly, but force=true — running anyway"
else
SHOULD_SKIP="true"
echo "No new nightly since last release regression run — will skip"
fi
else
echo "New nightly detected or first run"
fi
echo "Baseline: $BASELINE_REF ($RELEASE_TAG)"
echo "Feature: $FEATURE_REF"
echo "Skip: $SHOULD_SKIP"
echo "::endgroup::"
# --- Step 5: Write outputs ---
{
echo "baseline-ref=$BASELINE_REF"
echo "feature-ref=$FEATURE_REF"
echo "should-skip=$SHOULD_SKIP"
echo "is-stale=false"
echo "stale-age-hours=0"
echo "nightly-created="
echo "long-running=false"
echo "release-tag=$RELEASE_TAG"
} >> "$GITHUB_OUTPUT"
exit 0
fi
# ==========================================================================
# Nightly mode: query latest Docker nightly build (original logic)
# ==========================================================================
@@ -173,15 +278,15 @@ else
fi
echo "::endgroup::"
# --- Step 3: Read last successful feature ref from cache ---
echo "::group::Reading cached state"
# --- Step 3: Read last successful feature ref from charts repo ---
echo "::group::Reading persisted state"
LAST_FEATURE_REF=""
STATE_FILE=".nightly-state/last-feature-ref"
if [ -f "$STATE_FILE" ]; then
LAST_FEATURE_REF=$(tr -d '[:space:]' < "$STATE_FILE")
STATE_URL="https://raw.githubusercontent.com/decofe/reth-bench-charts/state/state/nightly-last-feature-ref"
if RAW=$(curl -sfL -H "Authorization: token ${DEREK_TOKEN}" "$STATE_URL"); then
LAST_FEATURE_REF=$(echo "$RAW" | tr -d '[:space:]')
echo "Previous feature ref: $LAST_FEATURE_REF"
else
echo "No cached state found (first run)"
echo "No persisted state found (first run)"
fi
echo "::endgroup::"

View File

@@ -250,6 +250,8 @@ async function success({ core, context }) {
}
}
const slackMode = process.env.BENCH_SLACK || 'always';
// Post to public channel if any metric shows significant improvement or regression
const channel = process.env.SLACK_BENCH_CHANNEL;
let postedToChannel = false;
@@ -264,6 +266,14 @@ async function success({ core, context }) {
}
}
// In on-win mode, only notify on improvement — skip DM fallback entirely
if (slackMode === 'on-win') {
if (!postedToChannel) {
core.info('on-win mode: no improvement detected, skipping all notifications');
}
return;
}
// DM the actor only when results were not posted to the public channel
if (!postedToChannel) {
if (actorSlackId) {

150
.github/scripts/bench-upload-clickhouse.py vendored Executable file
View File

@@ -0,0 +1,150 @@
#!/usr/bin/env python3
"""Upload bench-scheduled summary.json results to ClickHouse.
Reads the summary JSON produced by bench-reth-summary.py and inserts a row
into the bench_dual_comparisons table so the PM dashboard can display results.
Usage:
bench-upload-clickhouse.py \
--summary <summary.json> \
--workflow-name <name> \
--chain <chain>
Environment variables:
CLICKHOUSE_HOST ClickHouse host URL
CLICKHOUSE_USER ClickHouse username
CLICKHOUSE_PASSWORD ClickHouse password
CLICKHOUSE_DATABASE ClickHouse database (default: "default")
"""
import argparse
import json
import os
import sys
import urllib.request
import urllib.error
def main():
parser = argparse.ArgumentParser(description="Upload benchmark results to ClickHouse")
parser.add_argument("--summary", required=True, help="Path to summary.json")
parser.add_argument("--workflow-name", required=True, help="Workflow name for ClickHouse")
parser.add_argument("--chain", default="mainnet", help="Chain name")
parser.add_argument("--grafana-url", default="", help="Grafana dashboard URL")
parser.add_argument("--github-diff-url", default="", help="GitHub diff URL")
parser.add_argument("--job-url", default="", help="CI job URL")
args = parser.parse_args()
ch_host = os.environ.get("CLICKHOUSE_HOST", "")
ch_user = os.environ.get("CLICKHOUSE_USER", "")
ch_password = os.environ.get("CLICKHOUSE_PASSWORD", "")
ch_database = os.environ.get("CLICKHOUSE_DATABASE", "default")
ch_table = "bench_dual_comparisons"
if not ch_host or not ch_user or not ch_password:
print("Missing ClickHouse credentials, skipping upload", file=sys.stderr)
sys.exit(0)
with open(args.summary) as f:
summary = json.load(f)
baseline = summary["baseline"]
feature = summary["feature"]
b_stats = baseline["stats"]
f_stats = feature["stats"]
changes = summary["changes"]
blocks = summary["blocks"]
# Extract wait time data
wait_times = summary.get("wait_times", {})
def wait_mean(field):
wt = wait_times.get(field, {})
b = wt.get("baseline", {}).get("mean_ms", 0.0)
f = wt.get("feature", {}).get("mean_ms", 0.0)
return b, f
b_persist, f_persist = wait_mean("persistence_wait_us")
b_exec_cache, f_exec_cache = wait_mean("execution_cache_wait_us")
b_sparse, f_sparse = wait_mean("sparse_trie_wait_us")
# gas_per_second: summary uses mean_mgas_s (Mgas/s), ClickHouse stores gas/s
b_gas_per_second = b_stats["mean_mgas_s"] * 1_000_000
f_gas_per_second = f_stats["mean_mgas_s"] * 1_000_000
mean_change = changes.get("mean", {}).get("pct", 0.0)
gas_change = changes.get("mgas_s", {}).get("pct", 0.0)
latency_improved = 1 if mean_change < 0 else 0
throughput_improved = 1 if gas_change > 0 else 0
big_blocks = "true" if summary.get("big_blocks", False) else "false"
warmup_blocks = summary.get("warmup_blocks", 0) or 0
def esc(s):
return str(s).replace("'", "\\'")
insert = f"""
INSERT INTO {ch_database}.{ch_table} (
workflow_name, chain,
baseline_ref, baseline_commit,
feature_ref, feature_commit,
blocks,
baseline_total_latency_ms, baseline_gas_per_second,
baseline_latency_mean_ms, baseline_latency_median_ms,
baseline_latency_p90_ms, baseline_latency_p99_ms,
feature_total_latency_ms, feature_gas_per_second,
feature_latency_mean_ms, feature_latency_median_ms,
feature_latency_p90_ms, feature_latency_p99_ms,
mean_latency_change_percent, gas_per_second_change_percent,
latency_improved, throughput_improved,
warmup_blocks, big_blocks,
grafana_benchmark_url, github_diff_url, argo_workflow_url,
baseline_persistence_wait_mean_ms, baseline_execution_cache_wait_mean_ms,
baseline_sparse_trie_wait_mean_ms,
feature_persistence_wait_mean_ms, feature_execution_cache_wait_mean_ms,
feature_sparse_trie_wait_mean_ms
) VALUES (
'{esc(args.workflow_name)}', '{esc(args.chain)}',
'{esc(baseline["ref"])}', '{esc(baseline["ref"])}',
'{esc(feature["ref"])}', '{esc(feature["ref"])}',
{blocks},
{b_stats.get("wall_clock_s", 0) * 1000}, {b_gas_per_second},
{b_stats["mean_ms"]}, {b_stats["p50_ms"]},
{b_stats["p90_ms"]}, {b_stats["p99_ms"]},
{f_stats.get("wall_clock_s", 0) * 1000}, {f_gas_per_second},
{f_stats["mean_ms"]}, {f_stats["p50_ms"]},
{f_stats["p90_ms"]}, {f_stats["p99_ms"]},
{mean_change}, {gas_change},
{latency_improved}, {throughput_improved},
{warmup_blocks}, '{big_blocks}',
'{esc(args.grafana_url)}', '{esc(args.github_diff_url)}', '{esc(args.job_url)}',
{b_persist}, {b_exec_cache}, {b_sparse},
{f_persist}, {f_exec_cache}, {f_sparse}
);
"""
# Build ClickHouse HTTP URL (credentials via headers, never in URL)
host = ch_host.rstrip("/")
if not host.startswith("http"):
host = f"https://{host}:8443"
url = f"{host}/?database={ch_database}"
req = urllib.request.Request(url, data=insert.encode("utf-8"), method="POST")
req.add_header("Content-Type", "text/plain")
req.add_header("X-ClickHouse-User", ch_user)
req.add_header("X-ClickHouse-Key", ch_password)
try:
with urllib.request.urlopen(req) as resp:
body = resp.read().decode("utf-8")
if body.strip():
print(f"ClickHouse response: {body}")
print(f"Successfully uploaded benchmark results to ClickHouse ({args.workflow_name})")
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8")
print(f"ClickHouse upload failed ({e.code}): {body}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -39,10 +39,25 @@ function loadSamplyUrls(workDir) {
return urls;
}
function balModeLabel(mode) {
switch (mode) {
case 'true':
case 'feature':
case 'baseline':
return mode;
case 'both':
return 'true';
default:
return '';
}
}
function blocksLabel(summary) {
const parts = [];
if (summary.big_blocks) {
parts.push({ key: 'Big Blocks', value: summary.blocks });
const balMode = balModeLabel(summary.bal_mode || summary.bal || process.env.BENCH_BAL || 'false');
if (balMode) parts.push({ key: 'BAL', value: balMode });
} else {
const warmup = summary.warmup_blocks || process.env.BENCH_WARMUP_BLOCKS || '';
if (warmup) parts.push({ key: 'Warmup', value: warmup });
@@ -50,6 +65,7 @@ function blocksLabel(summary) {
}
const cores = process.env.BENCH_CORES || '0';
if (cores !== '0') parts.push({ key: 'Cores', value: cores });
if (summary.wait_time) parts.push({ key: 'Wait time', value: summary.wait_time });
return parts;
}
@@ -67,6 +83,7 @@ function metricRows(summary) {
{ label: 'P99', baseline: fmtMs(b.p99_ms), feature: fmtMs(f.p99_ms), change: fmtChange(c.p99) },
{ label: 'Mgas/s', baseline: fmtMgas(b.mean_mgas_s), feature: fmtMgas(f.mean_mgas_s), change: fmtChange(c.mgas_s) },
{ label: 'Wall Clock', baseline: fmtS(b.wall_clock_s), feature: fmtS(f.wall_clock_s), change: fmtChange(c.wall_clock) },
{ label: 'Persist Wait', baseline: fmtMs(b.mean_persist_ms || 0), feature: fmtMs(f.mean_persist_ms || 0), change: fmtChange(c.persist_wait) },
];
}

View File

@@ -1,414 +0,0 @@
#!/usr/bin/env bash
#
# Full PGO+BOLT optimized build for reth using real reth-bench workloads.
#
# Phases:
# 1. Build PGO-instrumented reth, run reth-bench → collect PGO profiles
# 2. Build BOLT-instrumented reth (with PGO), run reth-bench → collect BOLT profiles
# 3. Build final PGO+BOLT optimized binary
#
# Required environment variables:
# DATADIR - Path to reth datadir (must already contain chain data)
# RPC_URL - Source RPC URL for reth-bench to fetch payloads from
#
# Optional environment variables:
# PGO_BLOCKS - Number of blocks for PGO profiling (default: 20)
# BOLT_BLOCKS - Number of blocks for BOLT profiling (default: 20)
# SKIP_BOLT - Temporarily skip BOLT phases (default: false)
# STRIP_SYMBOLS - Strip debug symbols from output binary (default: true)
# COLLECT_PGO_ONLY - Stop after producing merged.profdata (default: false)
# PGO_PROFDATA - Path to pre-collected merged.profdata (optional)
# PROFILE - Cargo profile (default: maxperf-symbols)
# FEATURES - Cargo features (default: jemalloc,asm-keccak,min-debug-logs)
# TARGET - Target triple (default: auto-detected)
# EXTRA_RUSTFLAGS - Additional RUSTFLAGS (e.g. -C target-cpu=x86-64-v3)
#
# Output:
# target/$PROFILE_DIR/reth — final optimized binary
set -euo pipefail
gha_section_start() {
local title="$1"
if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo "::group::$title"
else
echo ""
echo "=== $title ==="
fi
}
gha_section_end() {
if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo "::endgroup::"
fi
}
cd "$(dirname "$0")/../.."
# ── Configuration ──────────────────────────────────────────────────────────────
PGO_BLOCKS="${PGO_BLOCKS:-20}"
BOLT_BLOCKS="${BOLT_BLOCKS:-20}"
SKIP_BOLT="${SKIP_BOLT:-false}"
STRIP_SYMBOLS="${STRIP_SYMBOLS:-true}"
COLLECT_PGO_ONLY="${COLLECT_PGO_ONLY:-false}"
PROFILE="${PROFILE:-maxperf-symbols}"
FEATURES="${FEATURES:-jemalloc,asm-keccak,min-debug-logs}"
TARGET="${TARGET:-$(rustc -Vv | grep host | cut -d' ' -f2)}"
BASE_RUSTFLAGS="${RUSTFLAGS:-}"
EXTRA_RUSTFLAGS="${EXTRA_RUSTFLAGS:-}"
COMBINED_RUSTFLAGS="$BASE_RUSTFLAGS $EXTRA_RUSTFLAGS"
PGO_PROFDATA="${PGO_PROFDATA:-}"
DATADIR="${DATADIR:-}"
RPC_URL="${RPC_URL:-}"
SKIP_BOLT_BOOL=false
if [[ "${SKIP_BOLT,,}" == "true" || "$SKIP_BOLT" == "1" ]]; then
SKIP_BOLT_BOOL=true
fi
STRIP_SYMBOLS_BOOL=false
if [[ "${STRIP_SYMBOLS,,}" == "true" || "$STRIP_SYMBOLS" == "1" ]]; then
STRIP_SYMBOLS_BOOL=true
fi
COLLECT_PGO_ONLY_BOOL=false
if [[ "${COLLECT_PGO_ONLY,,}" == "true" || "$COLLECT_PGO_ONLY" == "1" ]]; then
COLLECT_PGO_ONLY_BOOL=true
fi
USE_PRECOLLECTED_PGO=false
if [ -n "$PGO_PROFDATA" ]; then
if [ ! -f "$PGO_PROFDATA" ]; then
echo "error: PGO_PROFDATA points to a missing file: $PGO_PROFDATA"
exit 1
fi
USE_PRECOLLECTED_PGO=true
fi
NEEDS_BENCH_WORKLOAD=true
if [ "$USE_PRECOLLECTED_PGO" = true ] && [ "$SKIP_BOLT_BOOL" = true ]; then
NEEDS_BENCH_WORKLOAD=false
fi
if [ "$NEEDS_BENCH_WORKLOAD" = true ]; then
: "${DATADIR:?DATADIR must be set to the reth data directory}"
: "${RPC_URL:?RPC_URL must be set}"
fi
if [[ "$PROFILE" == dev ]]; then
PROFILE_DIR=debug
else
PROFILE_DIR=$PROFILE
fi
MANIFEST_PATH="bin/reth"
LLVM_VERSION=$(rustc -Vv | grep -oP 'LLVM version: \K\d+')
PGO_DIR="$PWD/target/pgo-profiles"
BOLT_DIR="$PWD/target/bolt-profiles"
CARGO_ARGS=(--profile "$PROFILE" --features "$FEATURES" --manifest-path "$MANIFEST_PATH/Cargo.toml" --bin "reth" --locked)
# Enable debug symbols for BOLT (requires symbols to reorder code).
# Strip them at the end.
PROFILE_UPPER=$(echo "$PROFILE" | tr '[:lower:]-' '[:upper:]_')
export "CARGO_PROFILE_${PROFILE_UPPER}_STRIP=debuginfo"
gha_section_start "Full PGO+BOLT Build"
echo "Binary: reth"
echo "Manifest: $MANIFEST_PATH"
echo "Target: $TARGET"
echo "Profile: $PROFILE"
echo "Features: $FEATURES"
echo "LLVM: $LLVM_VERSION"
echo "PGO blocks: $PGO_BLOCKS"
echo "BOLT blocks: $BOLT_BLOCKS"
echo "Skip BOLT: $SKIP_BOLT"
echo "Strip symbols: $STRIP_SYMBOLS"
echo "Collect only: $COLLECT_PGO_ONLY"
echo "PGO profdata: ${PGO_PROFDATA:-<collect with reth-bench>}"
echo "RUSTFLAGS: ${BASE_RUSTFLAGS:-<unset>}"
echo "EXTRA_RUSTFLAGS: ${EXTRA_RUSTFLAGS:-<unset>}"
if [ "$NEEDS_BENCH_WORKLOAD" = true ]; then
echo "Datadir: $DATADIR"
echo "RPC URL: $RPC_URL"
else
echo "Datadir: <not required>"
echo "RPC URL: <not required>"
fi
gha_section_end
# ── Prerequisites ──────────────────────────────────────────────────────────────
gha_section_start "Installing prerequisites"
rustup component add llvm-tools-preview
LLVM_PROFDATA=$(find "$(rustc --print sysroot)" -name llvm-profdata -type f | head -1)
if [ -z "$LLVM_PROFDATA" ]; then
echo "error: llvm-profdata not found"
exit 1
fi
install_bolt() {
if command -v llvm-bolt &>/dev/null; then
echo "BOLT already installed"
return
fi
echo "Installing BOLT from apt.llvm.org..."
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc >/dev/null
CODENAME=$(lsb_release -cs)
echo "deb http://apt.llvm.org/$CODENAME/ llvm-toolchain-$CODENAME-$LLVM_VERSION main" | sudo tee /etc/apt/sources.list.d/llvm.list >/dev/null
sudo apt-get update -qq
sudo apt-get install -y -qq "bolt-$LLVM_VERSION"
sudo ln -sf "/usr/bin/llvm-bolt-$LLVM_VERSION" /usr/local/bin/llvm-bolt
sudo ln -sf "/usr/bin/merge-fdata-$LLVM_VERSION" /usr/local/bin/merge-fdata
}
if [ "$SKIP_BOLT_BOOL" = true ]; then
echo "Skipping BOLT installation (SKIP_BOLT=$SKIP_BOLT)"
else
install_bolt
fi
gha_section_end
if [ "$NEEDS_BENCH_WORKLOAD" = true ]; then
# Build reth-bench once (non-instrumented) — reused for both phases.
gha_section_start "Building reth-bench"
RUSTFLAGS="$COMBINED_RUSTFLAGS" \
cargo build --profile "$PROFILE" --features "$FEATURES" \
--manifest-path bin/reth-bench/Cargo.toml --bin reth-bench --locked
RETH_BENCH_BIN="$(find target -name reth-bench -type f -executable | head -1)"
echo "reth-bench: $RETH_BENCH_BIN"
gha_section_end
else
gha_section_start "Building reth-bench"
echo "Skipping reth-bench build (pre-collected PGO with SKIP_BOLT=true)"
gha_section_end
fi
# ── Helpers ────────────────────────────────────────────────────────────────────
RETH_PID=
cleanup() {
if [ -n "${RETH_PID:-}" ] && kill -0 "$RETH_PID" 2>/dev/null; then
echo "Stopping reth (pid $RETH_PID)..."
sudo kill "$RETH_PID" 2>/dev/null || true
for i in $(seq 1 60); do
sudo kill -0 "$RETH_PID" 2>/dev/null || break
if [ $((i % 10)) -eq 0 ]; then
echo " waiting... (${i}s)"
fi
sleep 1
done
sudo kill -9 "$RETH_PID" 2>/dev/null || true
fi
}
trap cleanup EXIT
# Start reth, wait for RPC, run reth-bench, then stop reth.
# Arguments: $1 = reth binary path, $2 = number of blocks, $3 = log label
run_bench_workload() {
local reth_bin="$1" blocks="$2" label="$3"
local http_port=8545 authrpc_port=8551
echo "--- Starting reth ($label) ---"
sudo "$reth_bin" node \
--datadir "$DATADIR" \
--log.file.directory "/tmp/reth-${label}-logs" \
--engine.accept-execution-requests-hash \
--http --http.port "$http_port" \
--authrpc.port "$authrpc_port" \
--disable-discovery --no-persist-peers \
> "/tmp/reth-${label}.log" 2>&1 &
RETH_PID=$!
echo "Waiting for reth RPC..."
for i in $(seq 1 120); do
if curl -sf "http://127.0.0.1:$http_port" -X POST \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
> /dev/null 2>&1; then
echo "reth is ready after ${i}s"
break
fi
if [ "$i" -eq 120 ]; then
echo "error: reth failed to start within 120s"
cat "/tmp/reth-${label}.log"
exit 1
fi
sleep 1
done
echo "Running reth-bench ($blocks blocks)..."
"$RETH_BENCH_BIN" new-payload-fcu \
--rpc-url "$RPC_URL" \
--engine-rpc-url "http://127.0.0.1:$authrpc_port" \
--jwt-secret "$DATADIR/jwt.hex" \
--advance "$blocks" \
--reth-new-payload 2>&1 | sed -u "s/^/[$label] /"
echo "Stopping reth ($label)..."
sudo kill "$RETH_PID" 2>/dev/null || true
for i in $(seq 1 60); do
sudo kill -0 "$RETH_PID" 2>/dev/null || break
sleep 1
done
sudo kill -9 "$RETH_PID" 2>/dev/null || true
RETH_PID=
}
publish_binary() {
local source_bin="$1"
for out in "target/$TARGET/$PROFILE_DIR" "target/$PROFILE_DIR"; do
local destination="$out/reth"
mkdir -p "$out"
# Skip copying when source and destination resolve to the same inode.
if [ -e "$destination" ] && [ "$source_bin" -ef "$destination" ]; then
continue
fi
cp "$source_bin" "$destination"
done
}
if [ "$USE_PRECOLLECTED_PGO" = true ]; then
gha_section_start "Phase 1: Using Pre-Collected PGO Profile"
rm -rf "$PGO_DIR"
mkdir -p "$PGO_DIR"
cp "$PGO_PROFDATA" "$PGO_DIR/merged.profdata"
echo "Using pre-collected profile: $PGO_PROFDATA"
echo "PGO profile: $PGO_DIR/merged.profdata ($(ls -lh "$PGO_DIR/merged.profdata" | awk '{print $5}'))"
gha_section_end
else
# ── Phase 1: PGO profile collection ───────────────────────────────────────
gha_section_start "Phase 1: PGO Profile Collection"
rm -rf "$PGO_DIR"
mkdir -p "$PGO_DIR"
echo "Building PGO-instrumented binary..."
RUSTFLAGS="-Cprofile-generate=$PGO_DIR -Crelocation-model=pic $COMBINED_RUSTFLAGS" \
cargo build "${CARGO_ARGS[@]}" --target "$TARGET"
PGO_RETH_BIN="$PWD/target/$TARGET/$PROFILE_DIR/reth"
echo "Instrumented binary: $PGO_RETH_BIN ($(ls -lh "$PGO_RETH_BIN" | awk '{print $5}'))"
run_bench_workload "$PGO_RETH_BIN" "$PGO_BLOCKS" "pgo"
# Fix ownership if reth ran as root.
sudo chown -R "$(id -un):$(id -gn)" "$PGO_DIR" 2>/dev/null || true
# Merge PGO profiles.
echo "Merging PGO profiles..."
PROFRAW_COUNT=$(find "$PGO_DIR" -name '*.profraw' | wc -l)
echo "Found $PROFRAW_COUNT .profraw files"
if [ "$PROFRAW_COUNT" -eq 0 ]; then
echo "error: no .profraw files — instrumented binary did not produce profiles"
exit 1
fi
"$LLVM_PROFDATA" merge -o "$PGO_DIR/merged.profdata" "$PGO_DIR"/*.profraw
echo "PGO profile: $PGO_DIR/merged.profdata ($(ls -lh "$PGO_DIR/merged.profdata" | awk '{print $5}'))"
gha_section_end
fi
if [ "$COLLECT_PGO_ONLY_BOOL" = true ]; then
gha_section_start "PGO Collection Complete"
echo "COLLECT_PGO_ONLY=true, skipping PGO/BOLT optimized binary build"
echo "Profile: $PGO_DIR/merged.profdata"
gha_section_end
exit 0
fi
if [ "$SKIP_BOLT_BOOL" = true ]; then
gha_section_start "BOLT Phase Skipped"
echo "SKIP_BOLT=$SKIP_BOLT, building PGO-only binary"
echo "Building PGO-optimized binary..."
RUSTFLAGS="-Cprofile-use=$PGO_DIR/merged.profdata $COMBINED_RUSTFLAGS" \
cargo build "${CARGO_ARGS[@]}" --target "$TARGET"
BUILT_BIN="$PWD/target/$TARGET/$PROFILE_DIR/reth"
if [ "$STRIP_SYMBOLS_BOOL" = true ]; then
echo "Stripping debug symbols..."
strip "$BUILT_BIN"
else
echo "Skipping strip (STRIP_SYMBOLS=$STRIP_SYMBOLS)"
fi
publish_binary "$BUILT_BIN"
gha_section_end
else
# ── Phase 2: BOLT profile collection (with PGO) ──────────────────────────
gha_section_start "Phase 2: BOLT Profile Collection (with PGO)"
rm -rf "$BOLT_DIR"
mkdir -p "$BOLT_DIR"
echo "Building BOLT-instrumented binary with PGO..."
# --emit-relocs preserves relocation entries in the binary, required by llvm-bolt -instrument
RUSTFLAGS="-Cprofile-use=$PGO_DIR/merged.profdata -Clink-arg=-Wl,--emit-relocs $COMBINED_RUSTFLAGS" \
cargo build "${CARGO_ARGS[@]}" --target "$TARGET"
# Instrument with BOLT
BUILT_BIN="$PWD/target/$TARGET/$PROFILE_DIR/reth"
BOLT_INSTRUMENTED_BIN="$BUILT_BIN-bolt-instrumented"
echo "Instrumenting binary with BOLT..."
# --skip-funcs: skip compiler-generated drop_in_place functions that BOLT can't handle
# as split functions in relocation mode (triggered by --emit-relocs)
llvm-bolt "$BUILT_BIN" \
-instrument \
--instrumentation-file-append-pid \
--instrumentation-file="$BOLT_DIR/prof" \
--skip-funcs='.*drop_in_place.*' \
-o "$BOLT_INSTRUMENTED_BIN"
echo "BOLT-instrumented binary: $BOLT_INSTRUMENTED_BIN ($(ls -lh "$BOLT_INSTRUMENTED_BIN" | awk '{print $5}'))"
run_bench_workload "$BOLT_INSTRUMENTED_BIN" "$BOLT_BLOCKS" "bolt"
# Fix ownership for BOLT profiles
sudo chown -R "$(id -un):$(id -gn)" "$BOLT_DIR" 2>/dev/null || true
# Merge BOLT profiles
echo "Merging BOLT profiles..."
FDATA_COUNT=$(find "$BOLT_DIR" -name '*.fdata' | wc -l)
echo "Found $FDATA_COUNT .fdata files"
if [ "$FDATA_COUNT" -eq 0 ]; then
echo "error: no .fdata files — BOLT-instrumented binary did not produce profiles"
exit 1
fi
merge-fdata "$BOLT_DIR"/*.fdata > "$BOLT_DIR/merged.fdata"
echo "BOLT profile: $BOLT_DIR/merged.fdata ($(ls -lh "$BOLT_DIR/merged.fdata" | awk '{print $5}'))"
gha_section_end
# ── Phase 3: Final optimized build ───────────────────────────────────────
gha_section_start "Phase 3: Final PGO+BOLT Optimized Build"
echo "Building PGO-optimized binary..."
# --emit-relocs preserves relocation entries in the binary, required by llvm-bolt for code reordering
RUSTFLAGS="-Cprofile-use=$PGO_DIR/merged.profdata -Clink-arg=-Wl,--emit-relocs $COMBINED_RUSTFLAGS" \
cargo build "${CARGO_ARGS[@]}" --target "$TARGET"
BUILT_BIN="$PWD/target/$TARGET/$PROFILE_DIR/reth"
OPTIMIZED_BIN="$BUILT_BIN-bolt-optimized"
echo "Optimizing with BOLT..."
llvm-bolt "$BUILT_BIN" \
-o "$OPTIMIZED_BIN" \
--data "$BOLT_DIR/merged.fdata" \
-reorder-blocks=ext-tsp \
-reorder-functions=cdsort \
-split-functions \
-split-all-cold \
-dyno-stats \
-icf=1 \
-use-gnu-stack \
--skip-funcs='.*drop_in_place.*'
if [ "$STRIP_SYMBOLS_BOOL" = true ]; then
echo "Stripping debug symbols..."
strip "$OPTIMIZED_BIN"
else
echo "Skipping strip (STRIP_SYMBOLS=$STRIP_SYMBOLS)"
fi
publish_binary "$OPTIMIZED_BIN"
gha_section_end
fi
gha_section_start "Build Complete"
ls -lh "target/$PROFILE_DIR/reth"
echo "Output: target/$PROFILE_DIR/reth"
gha_section_end

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash
set -uo pipefail
set -uxo pipefail
crates_to_check=(
reth-network-peers

Some files were not shown because too many files have changed in this diff Show More