Skip to content

refactor: remove current_sync_peer from network manager - #511

Merged
xdustinface merged 1 commit into
v0.42-devfrom
refactor/drop-current-sync-peer
Mar 18, 2026
Merged

refactor: remove current_sync_peer from network manager#511
xdustinface merged 1 commit into
v0.42-devfrom
refactor/drop-current-sync-peer

Conversation

@xdustinface

@xdustinfacexdustinface commented Mar 10, 2026

Copy link
Copy Markdown
Collaborator

Simplify peer selection in send_to_single_peer by removing the sticky sync peer tracking. Peers are now selected directly based on message type requirements and the round-robin counter.

Based on:

Summary by CodeRabbit

Release Notes

  • Refactor
    • Enhanced network peer selection mechanism with capability-based matching and improved fallback handling.
    • Streamlined peer management by removing sticky peer tracking system.

@coderabbitai

coderabbitaiBot commented Mar 10, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The PR refactors PeerNetworkManager to remove sticky peer tracking via the current_sync_peer field and replaces the selection logic with a service-capability-based approach using a new next_peer round-robin helper method for improved peer selection.

Changes

Cohort / File(s)Summary
Peer Selection Refactoring
dash-spv/src/network/manager.rs
Removed current_sync_peer field and sticky-sync peer tracking. Introduced preferred_service logic to map messages to required capabilities. Added next_peer helper for round-robin peer selection. Updated send_to_single_peer and distributed-sending paths to use the new selection mechanism instead of legacy headers2-sticky logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 No more sticky peers causing delay,
Round-robin hops lead us the way,
Service capabilities light the path,
Smarter selection—no more aftermath,
Peers dance fairly, in balance they sway! 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely describes the main change: removing the current_sync_peer field from the network manager.
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/drop-current-sync-peer
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@codecov

codecovBot commented Mar 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.18%. Comparing base (d5bec1e) to head (5da971f).
⚠️ Report is 2 commits behind head on v0.42-dev.

Files with missing linesPatch %Lines
dash-spv/src/network/manager.rs50.00%10 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## v0.42-dev #511 +/- ##
=============================================
+ Coverage 66.13% 66.18% +0.04% 
=============================================
Files 311 311 Lines 64757 64717 -40 =============================================
+ Hits 42829 42832 +3 + Misses 21928 21885 -43 
FlagCoverage Δ
core75.13% <ø> (ø)
ffi37.14% <ø> (ø)
rpc28.28% <ø> (ø)
spv81.09% <50.00%> (+0.28%)⬆️
wallet65.49% <ø> (ø)
Files with missing linesCoverage Δ
dash-spv/src/network/manager.rs60.10% <50.00%> (+3.02%)⬆️

... and 1 file with indirect coverage changes

@xdustinface
xdustinfaceforce-pushed the refactor/peer-service-lookup branch from bbaf01d to 36be3ddCompareMarch 12, 2026 01:03
@github-actionsgithub-actionsBot added the merge-conflict The PR conflicts with the target branch. label Mar 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@xdustinface
xdustinfaceforce-pushed the refactor/drop-current-sync-peer branch from f2fe73b to d6f2108CompareMarch 12, 2026 01:06
@github-actionsgithub-actionsBot removed the merge-conflict The PR conflicts with the target branch. label Mar 12, 2026
@xdustinface
xdustinfaceforce-pushed the refactor/peer-service-lookup branch from 36be3dd to 22e4161CompareMarch 13, 2026 02:48
@github-actionsgithub-actionsBot added the merge-conflict The PR conflicts with the target branch. label Mar 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@xdustinface
xdustinfaceforce-pushed the refactor/peer-service-lookup branch from 22e4161 to e5f3bc6CompareMarch 13, 2026 03:11
@xdustinfacexdustinface mentioned this pull request Mar 16, 2026
@QuantumExplorer

Copy link
Copy Markdown
Member

Review from Claude

Issue 1: send_to_single_peer ignores headers2_disabled set for preferred peers

Severity: Medium

The new send_to_single_peer uses self.pool.peer_with_service(ServiceFlags::NODE_HEADERS_COMPRESSED) for GetHeaders/GetHeaders2 but does NOT check self.headers2_disabled. By contrast, send_distributed correctly filters:

let disabled = self.headers2_disabled.lock().await;
headers2_peers.retain(|(addr, _)| !disabled.contains(addr));

If the "first" peer returned by peer_with_service is in headers2_disabled (due to a prior decompression failure), it will be selected repeatedly, downgraded to plain GetHeaders, while other healthy headers2 peers sit idle.

Issue 2: peer_with_service always returns the same peer — accidental stickiness

Severity: Medium

peer_with_service iterates the HashMap and returns the first match. Since HashMap iteration order is stable until the map is modified, this creates accidental stickiness — but it's fragile and breaks whenever peers join/leave (HashMap rehash).

This is neither properly sticky (for sync consistency, like the old current_sync_peer) nor properly round-robin (for load distribution). For headers sync specifically, if the "first" peer changes mid-sync due to a peer add/remove, you get wasted round-trips as the new peer re-serves headers you already have.

Suggested fix for both: Either (a) apply round-robin to service-filtered peers (collect all matching, then use next_peer), and filter headers2_disabled in the single-peer path too, or (b) if stickiness is desired for headers, make it explicit.

Base automatically changed from refactor/peer-service-lookup to v0.42-devMarch 17, 2026 12:55
Simplify peer selection in `send_to_single_peer` by removing the
sticky sync peer tracking. Peers are now selected directly based
on message type requirements and the round-robin counter.
@xdustinface
xdustinfaceforce-pushed the refactor/drop-current-sync-peer branch from d6f2108 to 5da971fCompareMarch 17, 2026 12:58
@xdustinface
xdustinface marked this pull request as ready for review March 17, 2026 12:58
@github-actionsgithub-actionsBot removed the merge-conflict The PR conflicts with the target branch. label Mar 17, 2026

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

986-1021: Add regression tests for the new single-peer selection behavior.

Please add unit tests for: (1) excluding headers2_disabled peers in single-peer headers flow, and (2) round-robin across capability-filtered peer subsets.

As per coding guidelines, **/*.rs: Write unit tests for new functionality in Rust code.

Also applies to: 1070-1084

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dash-spv/src/network/manager.rs` around lines 986 - 1021, Add unit tests
exercising send_to_single_peer to cover (1) that peers with headers2_disabled
are excluded from the single-peer headers flow by simulating peers returned by
Pool::peer_with_service and ensuring NetworkMessage::GetHeaders2 is not sent to
those peers, and (2) that next_peer performs round-robin across
capability-filtered subsets by creating multiple peers with the same service
flags and asserting subsequent send_to_single_peer calls cycle through their
addresses; use the existing Pool::get_all_peers, Pool::peer_with_service,
send_to_single_peer, next_peer and send_message_to_peer hooks to inject fake
peers/messages and verify selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@dash-spv/src/network/manager.rs`:
- Around line 998-1000: The code marks NetworkMessage::GetHeaders2 as optional
(returns Some((ServiceFlags::NODE_HEADERS_COMPRESSED, false))) which allows
selecting peers without headers2 support and then attempting to send GetHeaders2
later; either make GetHeaders2 required by flipping the tuple to
Some((ServiceFlags::NODE_HEADERS_COMPRESSED, true)) so peer selection only
chooses peers advertising NODE_HEADERS_COMPRESSED, or add downgrade logic at the
send site that checks the chosen peer's service flags and sends a plain
GetHeaders when NODE_HEADERS_COMPRESSED is not present (ensure the send path
that currently emits GetHeaders2 consults the peer's flags first).
- Around line 1004-1015: The current preferred_service branch directly uses
pool.peer_with_service(...) which bypasses the round-robin helper and won't
exclude headers2_disabled peers; replace that direct selection with a filtered
round-robin selection similar to send_distributed: query the available peers
supporting the given flags (e.g. pool.peers_with_service(flags) or equivalent),
filter out headers2_disabled peers, if the filtered list is empty handle the
required=true case by logging and returning NetworkError::ProtocolError,
otherwise call next_peer(&filtered_peers) to pick the address/peer and log the
selection; keep existing behavior for the None => self.next_peer(&peers) branch.
---
Nitpick comments:
In `@dash-spv/src/network/manager.rs`:
- Around line 986-1021: Add unit tests exercising send_to_single_peer to cover
(1) that peers with headers2_disabled are excluded from the single-peer headers
flow by simulating peers returned by Pool::peer_with_service and ensuring
NetworkMessage::GetHeaders2 is not sent to those peers, and (2) that next_peer
performs round-robin across capability-filtered subsets by creating multiple
peers with the same service flags and asserting subsequent send_to_single_peer
calls cycle through their addresses; use the existing Pool::get_all_peers,
Pool::peer_with_service, send_to_single_peer, next_peer and send_message_to_peer
hooks to inject fake peers/messages and verify selection behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1e08ee24-f489-46db-811a-719fc2a7ff83

📥 Commits

Reviewing files that changed from the base of the PR and between d5bec1e and 5da971f.

📒 Files selected for processing (1)
  • dash-spv/src/network/manager.rs

Comment threaddash-spv/src/network/manager.rs
Comment threaddash-spv/src/network/manager.rs
@github-actionsgithub-actionsBot added the ready-for-review CodeRabbit has approved this PR label Mar 17, 2026
@xdustinface
xdustinface merged commit 38ed754 into v0.42-devMar 18, 2026
42 checks passed
@xdustinface
xdustinface deleted the refactor/drop-current-sync-peer branch March 18, 2026 14:13
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-reviewCodeRabbit has approved this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@xdustinface@QuantumExplorer@ZocoLini