Conversation
littidx stores receipt bodies in LittDB — point lookup by tx hash, where litt's keymap IS the tx-hash index (eth_getTransactionReceipt is one lookup, no separate index) — and supports eth_getLogs via a small pebble tag index: one empty-valued key per log tag (address + each topic position), queried by seeking the matching (block, tag) entries, intersecting across criteria dimensions, and point-reading only the matching receipts from litt. getLogs never decodes non-matching receipts, and receipt bytes are never duplicated. - Bodies live in litt immutable segments, so large values never enter LSM compaction and expiry reclaims whole segments. - Tag key: 't'+block+kind+tag+txIndex+firstLogIndex+txHash -> nil. Pruning a block range is a single pebble range tombstone (adds DeleteRange to the pebbledb wrapper). - Retention: litt TTL reclaims bodies; a read-time floor bounds visibility to KeepRecent regardless of GC timing. Wired as receipt backend "littidx", reusing existing helpers (matchLog, getLogsForTx, key consts). Tests cover read/write, getLogs semantics (address/topic AND/OR/wildcard, range bounds), multi-log numbering, reopen persistence, and prune. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR SummaryMedium Risk Overview Receipt payloads are stored in LittDB with tx-hash secondary keys for single-lookup Factory wiring in Reviewed by Cursor Bugbot for commit 0771fd0. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).
|
| } | ||
| } | ||
| } | ||
| firstLogIndex += uint32(len(record.Receipt.Logs)) //nolint:gosec // log counts fit within uint32 |
There was a problem hiding this comment.
Multi-part block log index
High Severity
When the same block is written in multiple SetReceipts calls (extra litt parts), stageTagKeys always starts firstLogIndex at zero for that batch. Tag keys and getLogsForTx then use wrong block-wide log indices for later parts, so eth_getLogs can return incorrect or colliding log.Index values even when filtering matches.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7383fb0. Configure here.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3620 +/- ##
==========================================
- Coverage 59.01% 58.17% -0.85%
==========================================
Files 2224 2152 -72
Lines 182699 174544 -8155
==========================================
- Hits 107823 101536 -6287
+ Misses 65197 63978 -1219
+ Partials 9679 9030 -649
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Review cleanups for the littidx backend — no behavior change: - Drop the dead u32-length framing in writeBlock. Every read fetches a receipt via its tx-hash secondary key (a value sub-range alias), and the part value is never read whole, so the per-receipt length prefixes were unused. Saves 4 bytes/receipt and clarifies the format. - Remove the redundant Exists check in writeBlock: nextPartIndex already returns the first free part slot, so the check was always false. - Replace deleteIndexRange's iterate-and-point-delete fallback (dead code — the index is always pebble) with a required rangeDeleter assertion that errors loudly if a future backend lacks range delete. - Rename the orphaned ledgerTxIndexLen to littTxIndexLen and name the log index width (littLogIndexLen) so the tag-key suffix layout is explicit. - Document that firstLogIndex restarts per part for a block split across SetReceipts calls (legacy migration only) — harmless, the RPC layer recomputes log indices from canonical block data. - Add TestLittIdxBlockWideLogIndex covering firstLogIndex accumulation across transactions (previously only single-tx numbering was tested). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| for { | ||
| pruneBefore := s.latestVersion.Load() - s.keepRecent | ||
| if pruneBefore > 0 { | ||
| if err := s.pruneBlocksBelow(uint64(pruneBefore)); err != nil { |
There was a problem hiding this comment.
Background prune retains extra block
Medium Severity
Background pruning passes latestVersion - keepRecent directly into pruneBlocksBelow, which treats that value as the first visible block. The pebble receipt pruner removes versions through that same difference inclusive, so one additional block stays queryable via GetReceipt and FilterLogs than KeepRecent intends.
Reviewed by Cursor Bugbot for commit 6531f47. Configure here.
| } | ||
| } | ||
| if err := batch.Commit(dbtypes.WriteOptions{}); err != nil { | ||
| return err |
There was a problem hiding this comment.
Index commit failure leaves orphan receipts
Medium Severity
SetReceipts writes receipt bodies to LittDB inside writeBlock before the pebble tag batch commits. If batch.Commit fails after one or more blocks were persisted, those receipts remain hash-addressable while their log tags were never indexed, so GetReceipt can succeed while FilterLogs omits the same transactions.
Reviewed by Cursor Bugbot for commit 6531f47. Configure here.
| // and stall throughput, so raise the key-count and key-file caps past a | ||
| // retention window and let only the value-file size bind segment seals. | ||
| littConfig.MaxSegmentKeyCount = 100_000_000 | ||
| littConfig.TargetSegmentFileSize = 512 << 20 |
There was a problem hiding this comment.
Bit-shift segment size literal
Low Severity
TargetSegmentFileSize is set with 512 << 20 even though this file already imports unit and uses unit.GB nearby. sei-db convention is byte sizes via unit.MB / unit.GB, not bit-shift literals.
Triggered by learned rule: sei-db: use unit.MB/GB constants for byte sizes, not bit-shift literals
Reviewed by Cursor Bugbot for commit 6531f47. Configure here.
…iest Address independent review findings: - Make SetEarliestVersion monotonic (only move the retention floor forward), matching SetLatestVersion in the same file so the floor can never move backward and re-expose pruned blocks. - Add TestLittIdxMultiPart: a block written across two SetReceipts calls exercises nextPartIndex and multi-part read/filter (previously untested). - Add TestLittIdxLegacyFallback: GetReceipt falling back to the legacy KV store for a receipt absent from litt (the one untested behavioral branch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
There are 5 total unresolved issues (including 4 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0771fd0. Configure here.
| } | ||
| } | ||
| if err := batch.Commit(dbtypes.WriteOptions{}); err != nil { | ||
| return err |
There was a problem hiding this comment.
Failed flush appends duplicate parts
High Severity
SetReceipts writes each block to LittDB via receipts.Put before the pebble index batch commits. If writeBlock or batch.Commit fails after a successful Put, a retry uses nextPartIndex and appends another part for the same block instead of replacing the failed write, duplicating receipt data and secondary tx-hash keys.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0771fd0. Configure here.


No description provided.