Reth v2.8.0 schedules the Amsterdam hardfork on Hoodi, adds opt-in snap/2 sync and prewarm result reuse, and hardens peer-to-peer networking and RPC.
With the opt-in --engine.prewarm-reuse, reth commits prewarmed transaction results instead of re-executing them. This reduced mean latency by 12.35% and raised Mgas/s by 18.58% over 500 replayed blocks (#27894). Per-block proof-worker sizing reduced mean execution time on 300M-gas BAL blocks by 8.41% (#27196). RPC response compression no longer cuts throughput by up to 22x (#27863).
Action Required
Hoodi operators must upgrade before 26 October 2026 at 17:42:48 UTC. This release schedules Amsterdam on Hoodi at timestamp 1793036568 (epoch 132352) and extends the Hoodi fork IDs through Amsterdam. (Reth change, Hoodi schedule)
All operators should review the default and behavior changes under Breaking Changes, especially those affecting the gas price oracle, WebSocket origins and the minimum priority fee.
Update Priority
| User Class | Priority |
|---|---|
| Payload Builders | Medium |
| Non-Payload Builders | Medium |
Breaking Changes
Runtime and Configuration
- Changed the default gas price oracle ignore threshold (
--gpo.ignoreprice) from 0 to 2 wei to match Geth, so zero-tip transactions no longer pulleth_maxPriorityFeePerGasdown to 0. Set--gpo.ignoreprice 0to restore the previous behavior (#27895). - Enforced
--ws.originson WebSocket handshakes. Disallowed or duplicateOriginheaders are now rejected with HTTP 403 on both separate and shared HTTP/WS listeners, so make sure every browser origin that connects over WebSocket is listed (#27952). - Applied
--txpool.minimum-priority-feeto legacy and EIP-2930 transactions by comparing their gas price against the floor, matching Geth. Previously only dynamic-fee transactions were checked (#27720). - Pinned
--engine.storage-worker-countand--engine.account-worker-countvalues now apply to every block and bypass the new per-block proof-worker sizing, and0now means unset. Unset them to use automatic sizing (#27196, #27660). - Stopped compressing HTTP RPC responses on servers bound to a loopback address, including the default
127.0.0.1, even when clients request compression. If you rely on compression behind a local reverse proxy, enable it at the proxy (#27865). - The metrics endpoint now serves at most four concurrent requests and returns HTTP 503 to the rest. It also gzips responses for clients that send
Accept-Encoding: gzip(#27766). - Renamed the trie cursor duration histograms to
trie.cursor.overall_duration_secondsandtrie.hashed_cursor.overall_duration_seconds, and moved hashed-cursor spans to thetrie::hashed_cursortracing target. Update dashboards, alerts and log filters that use the old names (#27771, #27772). - Offline commands such as
prune,stage dropanddb clearnow fail on a config file that exists but cannot be loaded, instead of falling back to defaults.reth p2p enodeno longer creates a missing key file (#27982).
RPC
engine_forkchoiceUpdatednow returns-32603with the builder's error when a payload job fails to start, instead of always returning-38003. Only invalid payload attributes still map to-38003(#28015).- Changed Parity
trace_*output to match other clients. Deleted accounts report emptystateDiffstorage,vmTraceops and subs reflect only what executed, and reverted CREATEs return{gasUsed, output}without an address (#27668). testing_buildBlockV1now returns anExecutionPayloadEnvelopeV6withblockAccessListandslotNumberfor Amsterdam blocks. Pre-Amsterdam responses are unchanged (#27883).
SDK
- Added a required
cause: Spanfield toBeaconEngineMessage::{NewPayload, RethNewPayload, ForkchoiceUpdated}, so tracing context follows Engine API requests into the engine and its workers. PassSpan::current(), orSpan::none()when there is no context (#27529). - Changed
OnForkChoiceUpdated::OutputtoResult<ForkchoiceUpdated, BeaconForkChoiceUpdateError>. Custom payload builders that reject attributes should return the newPayloadBuilderError::InvalidAttributesto keep answering-38003(#28015). - Changed
StorageRootMerkleCheckpoint::newto take anAccountinstead of separate nonce, balance and bytecode-hash arguments (#27501). - Narrowed the trie APIs. Removed
ComputedTrieDatain favor ofSortedTrieData, removed unused sparse-trie types and therayonre-export fromreth_trie_common, renamed the borrowinginto_sorted_refconversions toto_sorted_ref, madeRangeProofErroropaque, made severalreth-trie-parallelinternals private, removedProof::multiproof_v2andDbProof::overlay_multiproof_v2, and changedStateProofProvider::multiproof_v2to take the targets and arequires_masksflag (#27794, #27793, #27792, #27769, #27789, #27785, #27791, #27770, #27790, #27788, #27945). - Keyed
PreservedSparseTrieby block hash.state_root()becameblock_hash(),pending()changed signature, andPreservedSparseTrieCompleterwas removed (#27270). - Custom
BackfillSyncimplementations must handle the newBackfillAction::UpdateTargetvariant (#27541). - Reworked the test utilities. The
reth-networktest-utilstestnet helpers are rebuilt around aPeerConfigbuilder, and thereth-e2e-test-utilspayload submission helpers now fail on INVALID payloads (#27453, #27713).
Features
Performance
- Added opt-in reuse of transaction prewarming results with
--engine.prewarm-reuse. Prewarmed results whose recorded reads are still valid are committed instead of re-executed, which reduced mean latency by 12.35% and raised Mgas/s by 18.58% over 500 replayed blocks. With--engine.txpool-prewarmingalso enabled, pending pool transactions are executed ahead of the block, cutting p99 execution latency by 37.09%. Blocks with access lists or EIP-8037 state gas keep the existing path (#27894, #27904). - Sized storage and account proof worker pools per block from its gas and transaction count. This reduced mean execution time on 300M-gas BAL blocks by 8.41%, with regular blocks neutral (#27196, #27660, #27661, #27674).
- Compacted sparse-trie nodes from 248 to 168 bytes, improving P50
newPayloadlatency on regular mainnet blocks by 3.54% and trie prune duration by 34%, and reducing P90newPayloadlatency on 300M-gas BAL blocks by 15.0% (#27157, #27155). - Made RPC response compression use the fastest level and apply only to responses of at least 1 KiB. Compression had cut throughput by up to 22x; brotli-encoded 1.7 KB block responses went from 21,101 to 462,216 requests per second (#27863).
- Reused storage roots from the preserved sparse trie when building account proofs, prefetched large bytecode pages on Linux, and recovered senders for the earliest transactions first so ordered BAL execution can start sooner (#28016, #27919, #27544).
- Stopped long-running blocking RPC work once the client disconnects or the request times out, including
eth_estimateGas,eth_callMany,debug_traceCallMany,trace_callManyand block traces (#27462). - Made resumed
reth downloadruns verify existing files once and in parallel, cutting the reuse check on a 9.2 GB snapshot from 6.55–6.83 s to 0.80 s, and cached ERA file-list metadata (#27665, #28004).
Engine and Protocol Support
- Scheduled Amsterdam on Hoodi at timestamp
1793036568and extended the Hoodi fork IDs through Amsterdam (#27811). - Carried tracing context from Engine API requests through the engine, payload building and transaction conversion workers, so OTLP traces stay connected end to end (#27529).
Snap Sync (Experimental)
- Added the opt-in
--snap.v2flag for EIP-8189 snap/2 sync. On chains with Amsterdam active, it bootstraps a fresh database by following forkchoice to a recent pivot. It then rebuilds and verifies the trie, recovers from reorgs that cross the pivot, and resumes interrupted runs. Public state reads reject unverified snap state, so a partial bootstrap is not exposed over RPC (#27712, #27708, #27706, #27704, #27539, #27538, #27698, #27482, #27730, #27457, #27985, #27986, #27987). - Snap sync requires the hashed-state (v2) storage layout and refuses older databases (#27540).
- Advertised snap/2 in discv4 and discv5 ENRs when
--snap.v2is enabled, so DNS discovery lists can select reth snap servers (#27861).
Networking
- Served discv4 over both IPv4 and IPv6 on dual-stack sockets.
reth p2p bootnode --bootnodesnow accepts enode URLs or signed ENRs across both address families (#26402). - Dialed peers added through
admin_addPeeras soon as outbound slots are free, instead of after up to 5 seconds (#27499).
RPC and CLI
- Added
--cpu-cores <COUNT>to override the CPU count used to size Tokio workers, Rayon pools and parallel state-root work, without changing CPU affinity (#27765). - Added
reth download --prune-unlisted, which removes files the selected snapshot does not list while reusing verified files (#27669). - Bound
--engine.prewarm-reuseand--db.sync-modeto theRETH_ENGINE_PREWARM_REUSEandRETH_DB_SYNC_MODEenvironment variables (#27917, #27938).
SDK
- Added the opt-in
account-extfeature for chains with account extensions. Extensions are carried through merkle checkpoints, proofs and EIP-1186 recovery, and returned byeth_getAccountInfoanddebug_accountInfoAt. Therethbinary refuses to start if built with it (#27501, #27454, #27524, #27574). - Made engine backfill pluggable through
BackfillSyncBuilderandEngineNodeLauncher::with_backfill, keeping the staged pipeline as the default (#27542, #27541). - Added
ConfigureEvm::create_block_builder_with, plusConfigureEvmhooks that custom EVMs implement to support prewarm reuse (#28011, #27894, #27904). - CLI parsing now honors defaults registered through
DefaultRpcServerArgsfor the transaction fee cap, gas price oracle, pending block, forwarding, synchronous send timeout and RPC cache flags (#27926, #27954, #27975). - Moved the precompile cache into
reth-execution-cacheso payload builders can use it without the engine tree. Thereth_engine_treepath remains as a re-export (#27604). - Added
Pipeline::run_until, and aDownloadDefaultsopt-in to download a snapshot's RocksDB history indices instead of rebuilding them (#27537, #27940). - Expanded
reth-e2e-test-utilswith helpers for chain control, transactions and node lifecycle (#27713, #27656).
Bug Fixes
Security and Networking
-
Hardened peer management:
- Custom RLPx subprotocols start only after a successful eth
Statushandshake, with pre-Statustraffic capped. - Outbound ECIES, transport and Hello-timeout failures no longer ban unproven peer IDs.
- Pending inbound connections are rate-limited per IP even when slots are full.
- Outbound dial accounting no longer overshoots
max_outbound, and trusted peers can connect above it. - Bans are extend-only, and trusted-peer state stays consistent across
admin_removeTrustedPeerand restarts.
(#27898, #27951, #27842, #27843, #27946, #27950, #27947, #27948, #27949)
- Custom RLPx subprotocols start only after a successful eth
-
Bound discv4 PONG and
Neighboursreplies to the queried IP, preventing reflected FINDNODE replies and replayed responses. Timed-out ENR requests are now retried so fork-ID discovery is not blocked (#27868, #27722, #27630). -
Capped IPC request buffering at
max_request_body_size, timed out compressed HTTP request bodies after 30 seconds, and made the Otterscan tracing methods take tracing permits (#27864, #27866, #27530, #27465). -
Rejected Amsterdam transactions whose intrinsic gas or calldata floor exceeds the EIP-7825 cap. The pool previously admitted and gossiped these never-includable transactions, which could evict valid pending transactions (#27587).
-
Skipped EIP-7702 authorizations with a foreign chain ID during pool validation, so they can no longer make an unrelated account appear delegated and get its transactions rejected (#27869).
-
Rejected withdrawals in pre-Shanghai block bodies served by peers, and fixed eth/70 receipt responses that peers rejected (#27715, #27717).
-
Fixed parsing of enodes on port 80. discv5 peers are now dialed on the TCP port matching the session's address family; the old behavior also panicked in dual-stack mode (#27764, #27735).
-
Updated
rustlsto 0.23.46 for RUSTSEC-2026-0346 through RUSTSEC-2026-0349 (#27916).
Engine, Trie and Proofs
- Fixed a v2.7.0 regression where historical proof, multiproof and witness requests recomputed most of the state. A depth-147
eth_getMultiProoftook 382 s and could hit the MDBX read-transaction timeout, compared with 387 ms before the regression (#27634, #27651). - Fixed multi-block trie reverts that could leave stale trie nodes on disk when trie persistence lagged behind. Cached keys are now also invalidated when an overlay reverts below a fork (#27615, #27614).
- Deleted orphaned trie branches during crash recovery, which could otherwise lead to an incorrect state root (#27832).
- Tied preserved sparse-trie reuse to the parent block hash, so a cached trie can no longer be reused across forks with identical state (#27270).
- Fixed shutdown crashes while RocksDB closes and when proof worker pools drop their last runtime handle. Also fixed a stack overflow when dropping long unpersisted chains (#27909, #27805, #27818).
- Fixed forkchoice updates that unwind the canonical chain to genesis with
--engine.allow-unwind-canonical-header(#27622). - Returned trie walker errors instead of panicking when historical proof transactions time out, and hardened trie cursors and chunking for downstream callers (#27737, #27782, #27784, #27786).
- Resolved an unset transaction gas cap to the spec default in the BAL executor and
eth_simulateV1, fixing rejections on nodes with custom EVM configs (#27644, #27659). - Stopped logging full blocks and payloads in invalid-block errors and debug output (#27988, #27989, #27990, #27991).
Storage and Sync
- Fixed static-file reads and row pruning around uncommitted rows, which could reject valid payloads with
no header foundafter the pruner deleted static files (#27678, #27719). - Fixed consistency recovery leaving transaction static files ahead of the database after interrupted body writes (#27676, #27680, #27229).
- Fixed
reth db migrate-v2writing empty changesets and clearing the source tables after a changeset read error (#27978). - Rejected unwinds below already-pruned account or storage history (#27677).
- Fixed
--fullnodes on Holesky and Hoodi pruning bodies down to genesis (#27603). - Rebuilt history indexes with the append-only loader on pruned storage-v2 restores, avoiding about 3.9M missed shard reads (~473 s) on Base Sepolia (#27602).
- Detected sync targets that do not attach to the local head, and let the pipeline unwind detached heads down to genesis (#27888, #27937).
- Fixed execution outcome reconstruction attaching the first receipt to empty blocks, which affected reorg and unwind handling (#27966).
- Fixed several
reth downloadissues (#27939, #27933, #27935, #27756, #27498):- Pruned snapshots now get correct prune checkpoints.
- A failed piece is retried on its own, and all 5xx responses are retryable.
- The chain ID is checked only when the chain selects the source.
- The command exits as soon as it finishes.
- Made
reth db,stage,re-execute,init-state,download manifestandp2p enodereject invalid arguments and surface read errors instead of panicking (#27979, #27980, #27981, #27983, #27984). - Rejected ERA1 records with trailing bytes after the RLP value (#27997).
RPC, Tracing and Txpool
- Updated
revm-inspectorsto 0.44.3 (#27903, #28034):callTracerandmuxTracernow report the correct root frame (recipient, value andout of gaserror) for transactions that run out of gas before entering their first call frame under Amsterdam.4byteTracerskips precompile calls.- Prestate traces omit empty accounts.
- JS tracers report create-frame errors.
- Made
debug_traceTransactionanddebug_traceCallhonor the JS tracertimeoutoption, with Geth's 5 s default, and stop JS traces when the request is dropped. Abandoned traces no longer run until the node runs out of memory (#27903). - Kept calls with an omitted
gaswithin--rpc.gascap, and enforced the EIP-7825 execution gas cap under Amsterdam ineth_call,eth_createAccessList,debug_traceCall,debug_traceCallManyandtrace_call(#27586, #27633). - Aligned
eth_simulateV1with the spec and Geth. Max-nonce senders now return-32603, Amsterdam gas defaults account for state gas, and simulations run on the state of the block they resolve (#27881, #27882, #27714). - Seeded the transaction validator's block gas limit from the latest header at startup, so Amsterdam chains no longer reject transactions above 30M gas until the next block arrives (#27682).
- Returned mined transactions with impersonated senders from
eth_getTransactionByHashandeth_getTransactionReceipt(#27816).
Full changelog: v2.7.0...v2.8.0
Binaries
See pre-built binaries documentation.
The binaries are signed with the PGP key: 50FB 7CC5 5B2E 8AFA 59FE 03B7 AA5E D56A 7FBF 253E
Reth
| System | Architecture | Binary | PGP Signature |
|---|---|---|---|
| x86_64 | reth-v2.8.0-x86_64-unknown-linux-gnu.tar.gz | PGP Signature | |
| aarch64 | reth-v2.8.0-aarch64-unknown-linux-gnu.tar.gz | PGP Signature | |
| aarch64 | reth-v2.8.0-aarch64-apple-darwin.tar.gz | PGP Signature | |
| Docker | paradigmxyz/reth | - |
