github paradigmxyz/reth v2.8.0
Reth v2.8.0

3 hours ago

image

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 pull eth_maxPriorityFeePerGas down to 0. Set --gpo.ignoreprice 0 to restore the previous behavior (#27895).
  • Enforced --ws.origins on WebSocket handshakes. Disallowed or duplicate Origin headers 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-fee to 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-count and --engine.account-worker-count values now apply to every block and bypass the new per-block proof-worker sizing, and 0 now 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_seconds and trie.hashed_cursor.overall_duration_seconds, and moved hashed-cursor spans to the trie::hashed_cursor tracing target. Update dashboards, alerts and log filters that use the old names (#27771, #27772).
  • Offline commands such as prune, stage drop and db clear now fail on a config file that exists but cannot be loaded, instead of falling back to defaults. reth p2p enode no longer creates a missing key file (#27982).

RPC

  • engine_forkchoiceUpdated now returns -32603 with 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 empty stateDiff storage, vmTrace ops and subs reflect only what executed, and reverted CREATEs return {gasUsed, output} without an address (#27668).
  • testing_buildBlockV1 now returns an ExecutionPayloadEnvelopeV6 with blockAccessList and slotNumber for Amsterdam blocks. Pre-Amsterdam responses are unchanged (#27883).

SDK

  • Added a required cause: Span field to BeaconEngineMessage::{NewPayload, RethNewPayload, ForkchoiceUpdated}, so tracing context follows Engine API requests into the engine and its workers. Pass Span::current(), or Span::none() when there is no context (#27529).
  • Changed OnForkChoiceUpdated::Output to Result<ForkchoiceUpdated, BeaconForkChoiceUpdateError>. Custom payload builders that reject attributes should return the new PayloadBuilderError::InvalidAttributes to keep answering -38003 (#28015).
  • Changed StorageRootMerkleCheckpoint::new to take an Account instead of separate nonce, balance and bytecode-hash arguments (#27501).
  • Narrowed the trie APIs. Removed ComputedTrieData in favor of SortedTrieData, removed unused sparse-trie types and the rayon re-export from reth_trie_common, renamed the borrowing into_sorted_ref conversions to to_sorted_ref, made RangeProofError opaque, made several reth-trie-parallel internals private, removed Proof::multiproof_v2 and DbProof::overlay_multiproof_v2, and changed StateProofProvider::multiproof_v2 to take the targets and a requires_masks flag (#27794, #27793, #27792, #27769, #27789, #27785, #27791, #27770, #27790, #27788, #27945).
  • Keyed PreservedSparseTrie by block hash. state_root() became block_hash(), pending() changed signature, and PreservedSparseTrieCompleter was removed (#27270).
  • Custom BackfillSync implementations must handle the new BackfillAction::UpdateTarget variant (#27541).
  • Reworked the test utilities. The reth-network test-utils testnet helpers are rebuilt around a PeerConfig builder, and the reth-e2e-test-utils payload 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-prewarming also 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 newPayload latency on regular mainnet blocks by 3.54% and trie prune duration by 34%, and reducing P90 newPayload latency 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_callMany and block traces (#27462).
  • Made resumed reth download runs 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 1793036568 and 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.v2 flag 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.v2 is 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 --bootnodes now accepts enode URLs or signed ENRs across both address families (#26402).
  • Dialed peers added through admin_addPeer as 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-reuse and --db.sync-mode to the RETH_ENGINE_PREWARM_REUSE and RETH_DB_SYNC_MODE environment variables (#27917, #27938).

SDK

  • Added the opt-in account-ext feature for chains with account extensions. Extensions are carried through merkle checkpoints, proofs and EIP-1186 recovery, and returned by eth_getAccountInfo and debug_accountInfoAt. The reth binary refuses to start if built with it (#27501, #27454, #27524, #27574).
  • Made engine backfill pluggable through BackfillSyncBuilder and EngineNodeLauncher::with_backfill, keeping the staged pipeline as the default (#27542, #27541).
  • Added ConfigureEvm::create_block_builder_with, plus ConfigureEvm hooks that custom EVMs implement to support prewarm reuse (#28011, #27894, #27904).
  • CLI parsing now honors defaults registered through DefaultRpcServerArgs for 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-cache so payload builders can use it without the engine tree. The reth_engine_tree path remains as a re-export (#27604).
  • Added Pipeline::run_until, and a DownloadDefaults opt-in to download a snapshot's RocksDB history indices instead of rebuilding them (#27537, #27940).
  • Expanded reth-e2e-test-utils with 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 Status handshake, with pre-Status traffic 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_removeTrustedPeer and restarts.

    (#27898, #27951, #27842, #27843, #27946, #27950, #27947, #27948, #27949)

  • Bound discv4 PONG and Neighbours replies 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 rustls to 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_getMultiProof took 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 found after 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-v2 writing empty changesets and clearing the source tables after a changeset read error (#27978).
  • Rejected unwinds below already-pruned account or storage history (#27677).
  • Fixed --full nodes 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 download issues (#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 manifest and p2p enode reject 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-inspectors to 0.44.3 (#27903, #28034):
    • callTracer and muxTracer now report the correct root frame (recipient, value and out of gas error) for transactions that run out of gas before entering their first call frame under Amsterdam.
    • 4byteTracer skips precompile calls.
    • Prestate traces omit empty accounts.
    • JS tracers report create-frame errors.
  • Made debug_traceTransaction and debug_traceCall honor the JS tracer timeout option, 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 gas within --rpc.gascap, and enforced the EIP-7825 execution gas cap under Amsterdam in eth_call, eth_createAccessList, debug_traceCall, debug_traceCallMany and trace_call (#27586, #27633).
  • Aligned eth_simulateV1 with 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_getTransactionByHash and eth_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 -

Don't miss a new reth release

NewReleases is sending notifications on new releases.