OpenZeppelin / OpenZeppelin/Event-Scanner

Refactor reorg detection to use ring buffer parent hash verification

Open
#214 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

priority: medium type: refactor
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.