Skip to content

fix(dash-spv): prevent filter sync stalls from stale progress guards#754

Open
xdustinface wants to merge 3 commits into
v0.42-devfrom
fix/filter-sync-stall-guards
Open

fix(dash-spv): prevent filter sync stalls from stale progress guards#754
xdustinface wants to merge 3 commits into
v0.42-devfrom
fix/filter-sync-stall-guards

Conversation

@xdustinface
Copy link
Copy Markdown
Collaborator

@xdustinface xdustinface commented May 11, 2026

  • Use committed_height instead of stored_height in the handle_new_filter_headers guard so the manager detects uncommitted work after restart
  • Make filter_header_tip_height monotonic to prevent start_sync from regressing the tip on reconnection
  • Re-queue filter batches in send_pending when block headers are unavailable instead of permanently losing them
  • Add second try_commit_batches pass after scan to eliminate one-tick delay for incremental updates

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Filter synchronization now gracefully handles missing headers instead of halting the sync process.
  • Improvements

    • Enhanced batch processing efficiency during filter synchronization.
    • Improved state transition logic for filter header management.
  • Tests

    • Extended test coverage for filter synchronization behavior and edge cases.

Review Change Stack

…ders`

The guard `stored_height < filter_header_tip_height` fails to trigger scanning when filters are fully stored but not yet committed to wallet. After a restart where `stored_height` equals the tip, the guard evaluates to false and the manager silently stalls. Using `committed_height` correctly detects uncommitted work.

Also conditionally skip `send_pending` when `stored_height` already covers the tip, avoiding unnecessary download operations when only scan work is needed.
`start_sync` calls `update_filter_header_tip_height(stored_filters_tip)` on reconnection, which can be lower than the tip already set by `handle_new_filter_headers`. This regresses the download target and causes the pipeline to lose knowledge of available filter headers.

Apply the same monotonic guard pattern already used by `update_target_height`.
…headers

`take_pending` removes batches from the coordinator's pending queue. If `get_header` then returns `None` (header not yet stored), the batch is permanently lost because it's neither pending nor in-flight. Re-queue via `coordinator.enqueue` and continue to the next batch instead.

Also add a second `try_commit_batches` pass after `scan_ready_batches` in `try_process_batch` so that single-block incremental updates are committed in the same tick rather than waiting for the next one.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

The PR optimizes filter synchronization robustness by enforcing monotonic progress tracking, refining manager state logic to use committed heights, allowing inline batch commits, and gracefully handling missing batch headers. Three modules coordinate these changes with corresponding test coverage.

Changes

Filter Sync Resilience and Commit Optimization

Layer / File(s) Summary
Progress Monotonic Height Tracking
dash-spv/src/sync/filters/progress.rs
update_filter_header_tip_height now checks that incoming height exceeds current tip before updating, ensuring monotonic increases and bumping last_activity only on strict growth. Test added to verify strict monotonicity.
Manager State Transitions with Committed Height
dash-spv/src/sync/filters/manager.rs
handle_new_filter_headers uses committed_height instead of stored_height for guard logic, controlling state transitions to Syncing and lookahead batch creation. Tests added for edge cases: stored equals tip, and fully committed state.
Batch Commit Phase in Processing
dash-spv/src/sync/filters/manager.rs
try_process_batch inserts try_commit_batches() after scan_ready_batches(), allowing recently scanned batches to be committed in the same call. Regression test verifies scan-and-commit completes with event emission.
Pipeline Missing Header Resilience
dash-spv/src/sync/filters/pipeline.rs
send_pending now matches on header lookup results: missing headers (Ok(None)) and read errors are logged and re-enqueued for retry; only successful retrievals trigger GetCFilters requests. Test verifies defer-and-retry behavior across two invocations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Heights now climb in steady strides,
Commits arrive before the tide,
Missing headers? No despair—
We'll queue and try again with care!
State and storage find their way,
Filters flow without delay.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'prevent filter sync stalls from stale progress guards' directly summarizes the main fix: addressing sync stalls caused by stale progress guard logic (specifically replacing stored_height with committed_height).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/filter-sync-stall-guards

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
dash-spv/src/sync/filters/manager.rs (1)

426-431: 💤 Low value

Consider whether try_create_lookahead_batches benefits from the same in-tick commit.

The added Phase 3 cleanly removes the one-tick delay for incremental updates already in active_batches at entry. However, try_create_lookahead_batches (Phase 4) may itself create and scan_batch a small lookahead batch with pending_blocks == 0; that batch then sits scanned-but-uncommitted until the next try_process_batch call. If incremental tips routinely arrive via the lookahead path (e.g., during steady-state catch-up of small ranges), a fourth commit pass after Phase 4 would close that gap too. Optional — the documented use case (incremental single-block updates feeding an existing batch) is already covered.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dash-spv/src/sync/filters/manager.rs` around lines 426 - 431, The new Phase 4
(try_create_lookahead_batches) can create and scan small lookahead batches that
remain uncommitted until the next tick; add a final in-tick commit pass after
try_create_lookahead_batches by invoking the same commit logic
(try_commit_batches) again so any newly-created scanned-but-uncommitted
lookahead batches are committed immediately; locate the sequence around
try_commit_batches(), try_create_lookahead_batches() in manager.rs and insert a
second await of try_commit_batches() (or otherwise call the underlying commit
routine) after the call to try_create_lookahead_batches() to ensure no scanned
batches are left uncommitted this tick.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@dash-spv/src/sync/filters/manager.rs`:
- Around line 426-431: The new Phase 4 (try_create_lookahead_batches) can create
and scan small lookahead batches that remain uncommitted until the next tick;
add a final in-tick commit pass after try_create_lookahead_batches by invoking
the same commit logic (try_commit_batches) again so any newly-created
scanned-but-uncommitted lookahead batches are committed immediately; locate the
sequence around try_commit_batches(), try_create_lookahead_batches() in
manager.rs and insert a second await of try_commit_batches() (or otherwise call
the underlying commit routine) after the call to try_create_lookahead_batches()
to ensure no scanned batches are left uncommitted this tick.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 489bcd1b-6cd3-442c-838d-c24ae0fa5558

📥 Commits

Reviewing files that changed from the base of the PR and between dca03ce and 97de546.

📒 Files selected for processing (3)
  • dash-spv/src/sync/filters/manager.rs
  • dash-spv/src/sync/filters/pipeline.rs
  • dash-spv/src/sync/filters/progress.rs

@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

❌ Patch coverage is 95.96774% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.27%. Comparing base (dca03ce) to head (97de546).

Files with missing lines Patch % Lines
dash-spv/src/sync/filters/pipeline.rs 86.11% 5 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #754      +/-   ##
=============================================
+ Coverage      72.22%   72.27%   +0.04%     
=============================================
  Files            320      320              
  Lines          69631    69745     +114     
=============================================
+ Hits           50294    50405     +111     
- Misses         19337    19340       +3     
Flag Coverage Δ
core 76.30% <ø> (ø)
ffi 45.27% <ø> (-0.02%) ⬇️
rpc 20.00% <ø> (ø)
spv 89.88% <95.96%> (+0.06%) ⬆️
wallet 71.22% <ø> (ø)
Files with missing lines Coverage Δ
dash-spv/src/sync/filters/manager.rs 97.64% <100.00%> (+0.14%) ⬆️
dash-spv/src/sync/filters/progress.rs 100.00% <100.00%> (ø)
dash-spv/src/sync/filters/pipeline.rs 97.82% <86.11%> (-0.39%) ⬇️

... and 6 files with indirect coverage changes

@github-actions github-actions Bot added the ready-for-review CodeRabbit has approved this PR label May 11, 2026
@xdustinface xdustinface requested a review from ZocoLini May 11, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review CodeRabbit has approved this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant