OpenZeppelin / OpenZeppelin/Event-Scanner
Refactor reorg detection to use ring buffer parent hash verification
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19
- Forks
- 7
- Avg merge
- 2h 15m
- Merged PRs (30d)
- 4
Description
Summary
Replace the current reorg detection approach (checking if last streamed block hash exists on-chain) with a ring buffer approach that verifies incoming blocks against their parent hashes. This is cleaner to reason about and more performant in common scenarios.
Current Approach
Check whether the last streamed block's hash still exists on-chain. If not, walk back until we find a matching hash, then re-stream from that point.
Proposed Approach
Store block hashes and numbers in a ring buffer as they arrive. For each incoming block, verify its parent hash against the buffer. On mismatch, walk back to find the fork point.
Scenario Analysis
Scenario 1: Stream correctly rewinds to fork point
1 → 2 → 3 → REORG → 2
| Current | Proposed | |
|---|---|---|
| RPC calls | 3 | 0 |
| End buffer state | 1 (var holds 3) |
1, 2, 3 |
Current: Check block 3 hash on-chain (missing), check block 2 (missing), check block 1 (match). Stream 2..=3, fetch block 3 for future checks.
Proposed: Block 2 arrives, parent hash matches stored block 1 hash. Stream block 2, update buffer, continue.
Scenario 2: Stream returns a block past the fork point
1 → 2 → 3 → (2 reorged) → 3
| Current | Proposed | |
|---|---|---|
| RPC calls | 3 | 1 |
| End buffer state | 1 (var holds 3) |
1, 2, 3 |
Current: Block 3 arrives, check stored block 3 hash on-chain (missing), check block 2 (missing), check block 1 (match). Stream 2..=3, fetch block 3.
Proposed: Block 3 arrives, parent hash doesn't match stored block 2 hash. Fetch block 2, its parent matches block 1. Stream 2 → 3, update buffer.
Scenario 3: Stream skips a range with reorg mid-gap
1 → 2 → 3 → (6 reorged) → 8
| Current | Proposed | |
|---|---|---|
| RPC calls | 1 | 5 |
| End buffer state | 1, 2, 3 (var holds 8) |
1, 2, ..., 8 |
Current: Check stored block 3 hash on-chain (exists). No reorg detected. Stream 4 → 8.
Proposed: Fetch hashes for blocks 4–7, verify chain consistency i.e. 4 parents matches 3 and 8 parents matches 7. Stream 4 → 8, update buffer. The scanner will process blocks 4 → 8, which already reflect the post-reorg canonical chain
Edge Cases to Consider
- Reorg deeper than buffer size : Fetch finalised block and send that range instead.
Conclusion
The proposed approach is cleaner and more performant for the common cases (scenarios 1 and 2). Scenario 3 requires more RPC calls but maintains fuller buffer state which may be beneficial for subsequent reorg detection.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the current reorg detection and block-stream handling described in the issue. Compare the ring-buffer design against the three scenarios and the deeper-than-buffer edge case; done means parent-hash verification handles the proposed reorgs, preserves the expected buffer state, and uses the stated RPC behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- blockchain
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100