Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,10 @@ cargo test -p ethlambda-blockchain --test forkchoice_spectests -- --test-threads
- Blocks are split into three tables: `BlockHeaders`, `BlockBodies`, `BlockSignatures`
- Genesis/anchor blocks have empty bodies (detected via `EMPTY_BODY_ROOT`) — no entry in `BlockBodies`
- Genesis block has no signatures — no entry in `BlockSignatures`
- All other blocks must have entries in all three tables
- Non-genesis blocks have a `BlockSignatures` entry until finalized: once below the
finalized boundary, signatures are pruned (`prune_old_block_signatures`) while
headers and bodies are kept forever. `get_signed_block` returns `None` for a
pruned finalized block
- `LiveChain` table provides fast `(slot||root) → parent_root` index for fork choice
- Storage uses trait-based API: `StorageBackend` → `StorageReadView` (reads) + `StorageWriteBatch` (atomic writes)

Expand Down
16 changes: 12 additions & 4 deletions crates/storage/src/backend/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,20 @@ impl StorageReadView for InMemoryReadView<'_> {
prefix: &[u8],
) -> Result<Box<dyn Iterator<Item = PrefixResult> + '_>, Error> {
let table_data = self.guard.get(&table).expect("table exists");
let prefix_owned = prefix.to_vec();

let iter = table_data
// Collect and sort by key so iteration order matches the RocksDB backend
// (lexicographic). Callers rely on this for early-stop range scans over
// slot||root keys (e.g. signature/live-chain pruning).
let mut items: Vec<(Vec<u8>, Vec<u8>)> = table_data
.iter()
.filter(move |(k, _)| k.starts_with(&prefix_owned))
.map(|(k, v)| Ok((k.clone().into_boxed_slice(), v.clone().into_boxed_slice())));
.filter(|(k, _)| k.starts_with(prefix))
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
items.sort_by(|a, b| a.0.cmp(&b.0));

let iter = items
.into_iter()
.map(|(k, v)| Ok((k.into_boxed_slice(), v.into_boxed_slice())));

Ok(Box::new(iter))
}
Expand Down
Loading