Skip to content

feat(storage): add EitherReader for routing history queries to MDBX or RocksDB#21063

Merged
yongkangc merged 30 commits intomainfrom
yk/rocksdb-either-reader
Jan 16, 2026
Merged

feat(storage): add EitherReader for routing history queries to MDBX or RocksDB#21063
yongkangc merged 30 commits intomainfrom
yk/rocksdb-either-reader

Conversation

@yongkangc
Copy link
Member

@yongkangc yongkangc commented Jan 14, 2026

Summary

Adds EitherReader abstraction to route historical state queries (account history, storage history) to either MDBX or RocksDB based on storage settings. This is the foundation for using RocksDB as an alternative backend for history indices.

Changes

EitherReader Abstraction

  • Add EitherReader enum with Database and RocksDB variants in either_writer.rs
  • Implement account_history_info() and storage_history_info() methods that handle shard lookups
  • Extract shared compute_history_rank() and needs_prev_shard_check() helpers to reduce duplication between backends

Historical State Provider Integration

  • Wire EitherReader into HistoricalStateProviderRef for account and storage lookups
  • Add with_rocksdb_tx() helper to RocksDBProviderFactory trait for scoped RocksDB transactions

RocksDB Provider Enhancements

  • Add history_info() method to RocksTx for efficient shard lookups using raw iterators
  • Implement proper shard logic for history indices in write_blocks_data
  • Handle sentinel-only entries and empty tables in consistency checks

PR Stack

main
  ↑
#21063 (rocksdb-either-reader) ◀ you are here
  ↑
#21124 (rocksdb-index-account-history)
  ↑
#21125 (rocksdb-index-storage-history)

@yongkangc yongkangc added the A-rocksdb Related to rocksdb integration label Jan 14, 2026
@github-project-automation github-project-automation bot moved this to Backlog in Reth Tracker Jan 14, 2026
@joshieDo joshieDo force-pushed the joshie/par-save-blocks-rocksdb branch 2 times, most recently from fff917c to d8a600c Compare January 14, 2026 21:38
@yongkangc yongkangc force-pushed the yk/rocksdb-either-reader branch from 49154c0 to f8a98e7 Compare January 15, 2026 10:12
@yongkangc yongkangc self-assigned this Jan 15, 2026
@yongkangc yongkangc force-pushed the yk/rocksdb-either-reader branch from f8a98e7 to 7dcc5e3 Compare January 15, 2026 12:13
@joshieDo joshieDo force-pushed the joshie/par-save-blocks-rocksdb branch from a795126 to 8e8e6b7 Compare January 15, 2026 12:31
Base automatically changed from joshie/par-save-blocks-rocksdb to main January 15, 2026 18:44
@yongkangc yongkangc force-pushed the yk/rocksdb-either-reader branch from feb3c69 to 585bcc1 Compare January 15, 2026 19:08
Copy link
Member

@gakonst gakonst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #21063 (Base of RocksDB stack)

CI Status

  • clippy failure
  • udeps failure
  • test / ethereum / edge failure

Changes Summary

Adds EitherReader abstraction to route history lookups to MDBX or RocksDB based on storage settings. Good design pattern.

Review Notes

✅ Good

  • Clean abstraction with EitherReader enum variants
  • with_rocksdb_tx helper nicely encapsulates cfg-gated code
  • Proper rank/select logic for history lookups
  • needs_prev_shard_check reused correctly

🟡 Suggestions

  1. Duplicated rank/select logic: The rank adjustment code is duplicated in both account_history_info and storage_history_info:

    let mut rank = chunk.rank(block_number);
    if rank.checked_sub(1).and_then(|r| chunk.select(r)) == Some(block_number) {
        rank -= 1;
    }
    let found_block = chunk.select(rank);

    Consider extracting to a helper function (I see #21064 adds compute_history_rank - good).

  2. Test pattern match update: Line 1032 updates to EitherReader::Database(_) but line 1027 still has EitherReader::StaticFile(_, _) - inconsistent pattern. Should be StaticFile(..) for consistency with other changes.

  3. PhantomData inconsistency: StaticFile variant keeps PhantomData<&'a ()> but comment says it's for lifetime when rocksdb feature is disabled. The Database variant no longer has it - verify this compiles correctly with all feature combinations.

Blocking Issues

Fix CI failures before this can be merged - likely clippy warnings and unused deps.


Review by @tempo_ai

@yongkangc yongkangc changed the title feat(storage): EitherReader abstraction for routing history queries to MDBX or RocksDB feat(storage): add EitherReader for routing history queries to MDBX or RocksDB Jan 16, 2026
This wires RocksDB into the history lookup paths:

- Adds account_history_info and storage_history_info methods to EitherReader
- Updates HistoricalStateProviderRef to use EitherReader for lookups
- Adds RocksDBProviderFactory trait bounds to provider impls
- Uses the rank/select pattern for efficient binary search in shards
**Problem**
- EitherReader had unnecessary PhantomData markers
- RocksDB transaction setup was duplicated in historical.rs with cfg-gated blocks
- Addressed joshieDo's feedback about RocksDB logic leaking into historical provider

**Solution**
- Remove PhantomData from EitherReader enum variants (lifetime already captured by RocksDB reference)
- Add with_rocksdb_tx helper method to RocksDBProviderFactory trait
- Refactor historical.rs to use trait method instead of duplicated cfg-gated blocks

**Changes**
- Remove PhantomData from EitherReader enum and all constructors/match arms
- Add with_rocksdb_tx to RocksDBProviderFactory trait with default implementation
- Refactor account_history_lookup and storage_history_lookup to use with_rocksdb_tx helper
- Make RocksTxRefArg type alias public for trait method

**Expected Impact**
- Cleaner EitherReader API without unnecessary PhantomData
- RocksDB transaction setup encapsulated in trait method
- Reduced cfg-gated block duplication in historical.rs
- No behavioral changes, all existing tests pass (96/97)
When rocksdb feature is disabled, the RocksDB variant is compiled out,
leaving the lifetime 'a unused and causing E0392 error.

Add PhantomData<&'a ()> to StaticFile variant to ensure the lifetime
is always used regardless of feature flags.
…lication

- Add compute_history_rank() function for shared rank/select logic
- Simplify EitherReader::storage_history_info and account_history_info
- Simplify RocksTx::history_info by using the shared helper
- Fix clippy doc_markdown warning for RocksDB

Reduces duplicated rank/select code across 3 locations while preserving comments.
Previously, when RocksDB tables were empty but MDBX had checkpoints > 0,
the consistency check would return Some(0), triggering an assertion
failure because unwinding to block 0 is considered destructive.

This is the expected state when RocksDB is enabled for the first time
alongside existing MDBX data. The fix treats empty RocksDB tables as a
first-run/migration scenario, logging a warning instead of requesting
an unwind. The pipeline will naturally populate the tables during sync.
- Use edge feature instead of separate rocksdb feature for enabling RocksDB
- Remove 'expected on first run' warning logs from invariants.rs
- Keep Debug impl in historical.rs (required by lint)
RocksDB already propagates through existing edge feature chain:
reth-ethereum-cli/edge → reth-cli-commands/edge → reth-db-common/edge → reth-provider/rocksdb
@yongkangc yongkangc force-pushed the yk/rocksdb-either-reader branch from bbbe927 to 280f62c Compare January 16, 2026 16:40
@yongkangc yongkangc force-pushed the yk/rocksdb-either-reader branch from 2e064e0 to bea16c0 Compare January 16, 2026 16:45
yongkangc and others added 4 commits January 17, 2026 01:17
Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
@github-project-automation github-project-automation bot moved this from Backlog to In Progress in Reth Tracker Jan 16, 2026
@yongkangc yongkangc added this pull request to the merge queue Jan 16, 2026
|key| key.key == address,
self.lowest_available_blocks.account_history_block_number,
)
self.provider.with_rocksdb_tx(|rocks_tx_ref| {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but i think we have to turn the with_rocksdb_tx/batch and the batch we pass to the eihereader an option, otherwise we'll always be creating it even for legacy nodes

Merged via the queue into main with commit 13c3262 Jan 16, 2026
44 checks passed
@yongkangc yongkangc deleted the yk/rocksdb-either-reader branch January 16, 2026 17:53
@github-project-automation github-project-automation bot moved this from In Progress to Done in Reth Tracker Jan 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-rocksdb Related to rocksdb integration

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants