Skip to content

fix(dash-spv): reissue requeued masternode requests from tick - #953

Merged
xdustinface merged 1 commit into
devfrom
fix/masternode-tick-requeue-stall
Aug 11, 2026
Merged

fix(dash-spv): reissue requeued masternode requests from tick#953
xdustinface merged 1 commit into
devfrom
fix/masternode-tick-requeue-stall

Conversation

@xdustinface

@xdustinface xdustinface commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

MasternodesManager::tick only ran the MnListDiff timeout-and-resend branch while requests were in flight. A single-peer disconnect requeues every in-flight getmnlistd as pending via on_peer_disconnect, leaving zero in flight, so the pending work was never reissued: responses arriving after the requeue are dropped as untracked and no other path calls send_pending. Masternode sync then stalled permanently with no error logged. Observed on a mainnet fresh sync where a stalled-peer eviction hit mid-pipeline, freezing at diffs_processed: 6 with 42 requests stranded until restart.

Gate the branch on the pipeline having outstanding work instead, so requeued pending requests go out on the next tick. MnListDiffPipeline::active_count becomes test-only.

Summary by CodeRabbit

  • Bug Fixes
    • Improved masternode list synchronization after peer disconnections.
    • Pending synchronization requests are now correctly requeued and resent during the next update cycle.
    • Timeout handling now continues while synchronization is incomplete, ensuring interrupted requests are processed reliably.

`MasternodesManager::tick` only ran the MnListDiff timeout-and-resend branch while requests were in flight. A single-peer disconnect requeues every in-flight `getmnlistd` as pending via `on_peer_disconnect`, leaving zero in flight, so the pending work was never reissued: responses arriving after the requeue are dropped as untracked and no other path calls `send_pending`. Masternode sync then stalled permanently with no error logged. Observed on a mainnet fresh sync where a stalled-peer eviction hit mid-pipeline, freezing at `diffs_processed: 6` with 42 requests stranded until restart.

Gate the branch on the pipeline having outstanding work instead, so requeued pending requests go out on the next tick. `MnListDiffPipeline::active_count` becomes test-only.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 745f4451-a946-4453-aee5-e1511f19d785

📥 Commits

Reviewing files that changed from the base of the PR and between 94eba8e and 877e659.

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

📝 Walkthrough

Walkthrough

The MnListDiff timeout path now processes incomplete pipelines after peer disconnects. A Tokio integration test verifies that queued requests are resent and tracked as active. The active-count helper is limited to test builds.

Changes

MnListDiff requeue handling

Layer / File(s) Summary
Process incomplete MnListDiff pipelines
dash-spv/src/sync/masternodes/sync_manager.rs
The timeout path checks for an incomplete pipeline and processes requeued MnListDiff requests after peer disconnects.
Validate request resend and tracking
dash-spv/src/sync/masternodes/manager.rs, dash-spv/src/sync/masternodes/pipeline.rs
The integration test verifies that two disconnected requests are resent and marked active. The active_count helper is compiled only for tests.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: zocolini

🚥 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 clearly and concisely describes the main fix: reissuing requeued masternode requests from tick.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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/masternode-tick-requeue-stall

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

@xdustinface
xdustinface merged commit 34886d9 into dev Aug 11, 2026
34 of 35 checks passed
@xdustinface
xdustinface deleted the fix/masternode-tick-requeue-stall branch August 11, 2026 10:18
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.57%. Comparing base (94eba8e) to head (877e659).
⚠️ Report is 1 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #953      +/-   ##
==========================================
+ Coverage   75.52%   75.57%   +0.04%     
==========================================
  Files         329      329              
  Lines       79136    79169      +33     
==========================================
+ Hits        59769    59829      +60     
+ Misses      19367    19340      -27     
Flag Coverage Δ
core 77.29% <ø> (ø)
ffi 49.03% <ø> (ø)
rpc 20.00% <ø> (ø)
spv 91.57% <100.00%> (+0.15%) ⬆️
wallet 77.46% <ø> (ø)
Files with missing lines Coverage Δ
dash-spv/src/sync/masternodes/manager.rs 93.90% <100.00%> (+0.39%) ⬆️
dash-spv/src/sync/masternodes/pipeline.rs 97.89% <ø> (ø)
dash-spv/src/sync/masternodes/sync_manager.rs 82.23% <ø> (+0.98%) ⬆️

... and 4 files with indirect coverage changes

ZocoLini added a commit that referenced this pull request Aug 11, 2026
The old network module gave each sync manager an `on_peer_disconnect`
hook that requeued its own in-flight work, and three separate fixes
landed against it (#941, #943, #953) — one for the
block pipeline, one for progress being discarded along with the requeue,
one for requeued work never being reissued. The broker owns a request
from send to response, so it replaced all three hooks with a single
central requeue, and their regression tests went with the hooks: the
replacement path had no coverage at all, in the area with the worst
track record.

Both callers — the timeout monitor kicking a stalled peer and the pump
seeing a socket close — did this inline and identically, buried in
spawned tasks where nothing could reach them. Lift it into
`requeue_requests_from` and pin the three properties the old tests
guarded:

- a departed peer's requests come back, a healthy peer's do not
- the key stays registered as `Queued`, so a pipeline re-declaring the
  request cannot queue a duplicate on top of the retry
- only the response retires the key, so a requeued request stays owned
  by someone

Checked against injected regressions: dropping the key instead of
requeuing it fails two of the three, and requeuing nothing fails all
three.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ToH2xGXqVcxiwMkNYaWkh7
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