Skip to content

Add MaxRollbackDepth to prevent deep reorg processing#3

Open
mpainenz wants to merge 3 commits intodogeorg:mainfrom
mpainenz:add-max-rollback-depth
Open

Add MaxRollbackDepth to prevent deep reorg processing#3
mpainenz wants to merge 3 commits intodogeorg:mainfrom
mpainenz:add-max-rollback-depth

Conversation

@mpainenz
Copy link

@mpainenz mpainenz commented Dec 8, 2025

Add optional MaxRollbackDepth and MaxRollbackWaitDuration parameters to WalkerOptions to gracefully handle deep reorgs that exceed the configured depth limit.

  • Added MaxRollbackDepth int64 field to WalkerOptions (0 = unlimited)
  • Added MaxRollbackWaitDuration time.Duration field to WalkerOptions (0 = return immediately)
  • Updated undoBlocks() to check rollback depth during backtracking
  • When depth exceeds MaxRollbackDepth, walker stops building undo and returns nil
  • If MaxRollbackWaitDuration > 0, walker waits before retrying instead of stopping
  • After waiting, walker retries checking the block to see if RPC node has re-indexed
  • Wait logic implemented in both Run() and followTheChain() methods

The wait-and-retry mechanism give the core node time to re-index after a deep reorg, allowing the walker to resume once blocks are back on-chain.

Example output while waiting:

2025/12/09 01:39:28 DogeWalker: polling for the next block
2025/12/09 01:39:28 DogeWalker: MaxRollbackDepth exceeded (101 > 100). Stopping service.
2025/12/09 01:39:28 DogeWalker: Deep reorg detected, waiting 5s for RPC node to re-index...
2025/12/09 01:39:33 DogeWalker: MaxRollbackDepth exceeded (101 > 100). Stopping service.
2025/12/09 01:39:33 DogeWalker: Deep reorg detected, waiting 5s for RPC node to re-index...
2025/12/09 01:39:38 DogeWalker: MaxRollbackDepth exceeded (101 > 100). Stopping service.
2025/12/09 01:39:38 DogeWalker: Deep reorg detected, waiting 5s for RPC node to re-index...

And ones re-indexing catches up...

2025/12/09 01:40:45 DogeWalker: received tip-change
2025/12/09 01:40:45 [Tracker] BLOCK: 50 2d7739a106d59be9d89057a844e642c860bbdf4339ae14bb593f6021b8c0da42
2025/12/09 01:40:45 [Tracker] published block height update: height=50 hash=2d7739a106d59be9d89057a844e642c860bbdf4339ae14bb593f6021b8c0da42

Add optional MaxRollbackDepth parameter to WalkerOptions to stop the
walker service when a reorg exceeds the configured depth limit.

- Added MaxRollbackDepth int64 field to WalkerOptions (0 = unlimited)
- Updated undoBlocks() to check rollback depth during backtracking
- Walker stops (returns running=false) if depth exceeds limit

This prevents processing dangerous deep reorgs that could corrupt
downstream state by stopping before emitting an undo command.
@mpainenz mpainenz marked this pull request as draft December 8, 2025 23:38
@mpainenz mpainenz marked this pull request as ready for review December 8, 2025 23:39
@SomeoneWeird SomeoneWeird requested a review from raffecat December 8, 2025 23:51
@mpainenz mpainenz marked this pull request as draft December 9, 2025 00:11
@mpainenz
Copy link
Author

mpainenz commented Dec 9, 2025

Sorry, not quite working as expected during e2e test. Moved to draft

…g incomplete undo

When MaxRollbackDepth is exceeded, undoBlocks() was returning a partially
populated undo object (with UndoBlocks but without LastValidHeight/LastValidHash).
This could allow an invalid undo command to be sent to consumers.

Fix:
- Return nil instead of incomplete undo when limit exceeded
- Add nil checks in callers before sending undo commands

This ensures deep reorgs exceeding the limit are properly stopped without
sending invalid undo commands, while normal reorgs continue to work correctly.
- Add MaxRollbackWaitDuration option to WalkerOptions
- Implement wait and retry mechanism when MaxRollbackDepth is exceeded
- When deep reorg detected, wait configured duration before retrying
- Prevents restart loop by giving RPC node time to re-index
- Zero value (0) means return immediately (backward compatible)
- Default wait duration: 5 seconds (configured in indexer)
@mpainenz mpainenz marked this pull request as ready for review December 9, 2025 02:18
@mpainenz
Copy link
Author

mpainenz commented Dec 9, 2025

In this implementation, if the max undo block length is surpassed, the walker would resume once it reaches a new tip, and it wouldn't emit an undo. This would work in the case of a re-indexing, but perhaps not for some other event such as corruption.

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