Reth v2.6.0 expands Amsterdam and Hegotá protocol support, installs the REST-SSZ Engine API by default, advances EIP-8189 snap-sync infrastructure, and moves partial persistence further into production paths.
The release also improves performance across block processing, historical-state RPC, pruning, transaction-pool updates, and peer discovery. On a 300M-gas BAL workload, storage-trie job parallelism reduced mean newPayload latency by 8.6% and state-root wait time by 39%.
Action Required
Operators with explicit engine persistence thresholds should review their configuration. The defaults are now 50 persisted blocks, 30 state-masking blocks, and 100 blocks of backpressure. A nonzero masking window must satisfy num-state-masking-blocks + memory-block-buffer-target < persistence-threshold (#27220).
- Set
--engine.num-state-masking-blocks 0to disable state masking (partial persistence). - Set
--engine.persistence-threshold 0to preserve immediate persistence and disable state masking (partial persistence).
Operators which read the Reth database out-of-process should disable partial persistence by setting --engine.num-state-masking-blocks 0.
Update Priority
| User Class | Priority |
|---|---|
| Payload Builders | Low |
| Non-Payload Builders | Low |
Breaking Changes
Runtime and Configuration
- Raised the default persistence threshold from 7 to 50 blocks, enabled 30 blocks of state masking by default, and raised the backpressure threshold from 16 to 100 blocks. Partial persistence is now compiled unconditionally (#26800, #27220).
- Installed REST-SSZ routes on the authenticated Engine API server by default. Custom Engine API implementations must implement
EngineSszApi(#26254).
SDK and RPC APIs
- Changed
EthApiInner::newto accept a singleEthApiSettingsvalue instead of individual settings arguments. Custom RPC builders must update construction; existing builder setters and defaults remain available (#27251, #27268). - Added the required
in_memory_sizecache field to the publicEthPooledTransactionstruct. Downstream users constructing it with struct literals must initialize the field; constructor users are unaffected (#27061). - Replaced the layered transaction-announcement wrapper types with ordered
TransactionAnnouncement,AnnouncedTransaction, andTransactionMetadatatypes. Downstream networking users of the previous public internals must migrate (#27021). - Made
eth_getMultiProofalways return V2 proofs, including child branch nodes after extensions. The RPC method keeps its existing two-argument signature (#26851).
Features
Performance
- Ran storage-trie updates inside checked-out jobs, reducing mean
newPayloadlatency and state-root wait time (#27156). - Added opt-in caching and prewarming of RPC-computed BALs with
--rpc-cache.cache-computed-balsand--rpc-cache.prewarm-bals[=BLOCKS]. (#24097). - Reused RocksDB snapshots and iterators for historical-state lookups, reducing mean trace RPC latency, and CPU per request while increasing throughput (#27210).
- Skipped history shards that pruning cannot affect, improving mean pruning time (#26900).
- Limited transaction-pool fee updates to changed senders when possible, reducing a 0.25% sender update from 93 µs to 0.9 µs in a saturated-pool benchmark (#26956).
- Removed the one-second startup wait for discv5 boot-node ENR requests by moving them into the background (#26929).
- Reduced RPC memory and CPU overhead by windowing
eth_getLogsscans, bloom-filtering log paths, lazily convertingtrace_getresults, and sharing fee-history entries (#26946, #27000, #27031, #26942).
Partial Persistence
Reth now enables partial persistence by default. In this mode state/trie database keys are not updated in the database if later blocks contain updates to those same keys. Those later blocks are referred to as "state masking" blocks.
The new behavior, given default persistence parameters, is:
--engine.persistence-threshold 50: Persistence is triggered once there are 50 blocks in-memory.--engine.memory-block-buffer-target 5: Of those 50, 5 will not be persisted at all but will be retained in-memory.--engine.num-state-masking-blocks 30: Of the remaining 45 blocks, 30 will not have their state/trie updates persisted yet. All other block data (headers, transactions, changesets, indexes, etc..) will still be persisted.- The remaining 15 blocks will have their state/trie updates persisted, but only those keys not overwritten by the 30 masking blocks.
Consistency is guaranteed on startup after a crash by using the changesets of the masking blocks to revert all state which was not written due to masking by those blocks.
Engine, Payload Building and Protocol Support
- Added Bogota chainspec and Engine API support for
engine_newPayloadV6andengine_forkchoiceUpdatedV5, including fork-time validation (#26686, #26691, #26706, #26711). - Added foundational FOCIL support with
engine_getInclusionListV1and bounded inclusion-list construction from non-blob pool transactions (#26682, #26737). - Validated Amsterdam payload fields and imported EIP-7928 block access lists against their header commitments, and advertised the Amsterdam system contracts through
eth_config(#27173, #26696, #26705). - Installed the REST-SSZ Engine API transport by default, including payload-body retrieval by hash and range and the experimental Amsterdam payload-witness endpoint (#26254, #26394, #26406, #27028).
- Fetched authenticated BALs for downloaded Amsterdam blocks and used them on the parallel BAL execution path (#26823, #26885).
Networking
- Advertised eth/70 and eth/71 by default, added an outbound
GetCellsclient, and bounded inbound RLPx subprotocol queues by message count and memory (#26824, #26673, #26660).
RPC and CLI
- Added the Geth-compatible
debug_traceChainsubscription with sequential, bounded tracing (#26582). - Added HTTP request decompression and a
--http.compressionallowlist for response compression algorithms (#20277, #26668). - Exposed raw block transaction lookup methods on the authenticated Engine API server (#26760).
- Added EIP-8037 state-gas tracing while preserving pre-Amsterdam trace output (#26804).
- Added
--authrpc.jwtsecret-hexas an inline alternative to a JWT-secret file (#27034). - Added downstream hooks for custom transaction replacement pricing and nonce-bound validation while preserving Ethereum defaults (#27201, #27185).
Execution Overlays and Storage
- Ground-up rewrite of execution/trie state overlay management. Execution state overlays are now flattened for better performance with high in-memory block counts (#26834, #26838, #26862, #26616, #27056, #27219).
Bug Fixes
Security and Networking
- Kept the engine tree alive when downloaded or buffered blocks contain unrecoverable transactions, preventing malformed peer-served blocks from stopping the task (#26901).
- Updated
h2to 0.4.16 for the fix to RUSTSEC-2026-0258 (#26753). - Made eth/72 transaction announcements interoperable with Geth's cell-mask encoding instead of disconnecting compliant peers (#26670).
Engine, Trie and Payload
- Flushed retained state and trie data before pipeline backfill so staged execution cannot read masked state without its in-memory overlay (#26911).
- Fixed proof V2 dirty-range processing and branch collapse around cached trie branches (#26842, #26843).
- Preserved storage wipes in execution overlays so pre-Dencun
SELFDESTRUCTreads do not fall back to durable state (#26872). - Prevented an engine panic when the payload stream terminates and adjudicated speculative BAL worker failures in transaction order (#27218, #26721).
- Applied persistence backpressure to the retained state-trie frontier and fixed cache handoff races during persistence (#27269, #27230, #27234).
RPC and Txpool
- Rejected a caller-supplied
chainIdthat does not match the node instead of silently re-signing and submitting the transaction on another chain (#26782). - Returned an error for
eth_getLogsqueries whose matching receipts were pruned instead of returning incomplete results (#27002). - Returned actual used gas from the basic-transfer
eth_estimateGasshortcut, fixing post-Amsterdam overestimation of up to 75% (#26875). - Derived the next-block base fee for
eth_callBundle, simulatedmev_simBundlein the block afterparentBlock, and returnednullfor sender-nonce gaps consumed by EIP-7702 authorization (#27265, #27266, #27275). - Parked pending blob transactions when the blob fee rises while the base fee falls, enforced the configured minimum priority fee for local transactions, and rejected transactions below the tracked sender nonce when enabled (#26962, #26861, #26981).
