-
Notifications
You must be signed in to change notification settings - Fork 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.