Skip to content

Conversation

@prestwich
Copy link
Member

Summary

  • Adds ColdStorage::get_logs(LogFilter) with eth_getLogs semantics — filter by block range, address, and topics (OR within position, AND between positions)
  • Introduces RichLog return type with block_log_index (absolute position in block) and tx_log_index for RPC response construction
  • Adds first_log_index to ReceiptContext (subsumes feat(cold): add first_log_index to ReceiptContext #23) for computing per-log logIndex without refetching prior receipts
  • Replaces single-column idx_logs_address with composite idx_logs_address_block(address, block_number) for efficient filtered range scans
  • Factors out row_to_log_row helper in the SQL backend
  • Implements for all three backends: in-memory, SQLite, PostgreSQL
  • SQL backend uses a correlated subquery on the PK index to compute block_log_index

Test plan

  • In-memory conformance passes (cargo t -p signet-cold)
  • SQLite conformance passes (cargo t -p signet-cold-sql --features test-utils)
  • PostgreSQL conformance passes (./scripts/test-postgres.sh)
  • Clippy clean with --all-features and --no-default-features for both crates
  • Conformance covers: empty ranges, block range filtering, single/multi address, single/multi topic0, multi-position AND, wildcard positions, combined filters, ordering, block_log_index correctness, metadata correctness

Closes #23

🤖 Generated with Claude Code

prestwich and others added 3 commits February 12, 2026 10:08
Adds the index of a receipt's first log among all logs in its block,
enabling callers to compute per-log logIndex for RPC responses without
refetching prior receipts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…text

Add log filtering to cold storage following eth_getLogs semantics, and
include block-level log indexing for RPC response construction.

- Add `LogFilter` type with block range, address, and topic filters
- Add `RichLog` type with full block/tx context and block_log_index
- Add `ColdStorage::get_logs` with implementations for in-memory, SQLite,
  and PostgreSQL backends
- Add `first_log_index` to `ReceiptContext` (cherry-picked from #23)
- Replace `idx_logs_address` with composite `idx_logs_address_block`
- Factor out `row_to_log_row` helper in SQL backend
- Wire through task channel plumbing (request, handle, runner)
- Comprehensive conformance tests covering all filter combinations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
prestwich and others added 3 commits February 12, 2026 15:00
…ackend

iter_k2 had two bugs: (1) next_dual_above positioned the cursor at the
first entry and returned it, but the iterator discarded that result and
called next_k2() which advanced past it — so the first entry was never
yielded. Fix: capture the first entry in the iterator struct and yield
it before advancing. (2) The in-memory backend's next_k2 used
next_dual_above(current_k1, current_k2) which is "at or above",
returning the same entry forever. Fix: use read_next() (strictly above)
and verify k1 still matches.

Adds iter_k2 regression tests to the conformance suite.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tches_log

Move log-matching logic from a private function in mem.rs to a public
LogFilter::matches_log method for cross-backend reuse. Implement
get_logs on MdbxColdBackend using per-index exact_dual lookups. Remove
unused SQL helper methods left over from a prior refactor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…aits

The default iter() and iter_from() implementations on KvTraverse and
DualKeyTraverse discarded the entry returned by the initial positioning
call (first()/lower_bound()/next_dual_above()), causing the first entry
to be skipped. The typed iter_from() on TableTraverse and
DualTableTraverse had a second bug: they positioned the cursor then
called iter() which reset it via first().

Fix by capturing the first entry as owned data in the iterator structs
(RawKvIter, RawDualKeyIter) and yielding it before calling read_next().
Also override iter()/iter_from() on the MDBX cursor to use native
libmdbx iterators which handle first-entry capture natively.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace manual exact_dual index probing with iter_k2 in
MdbxColdBackend::get_logs_inner, matching the convention used by all
other dual-table iterations in this file. Replace inner for/if/push
loops with filter/map/extend in both MDBX and in-memory backends.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant