Skip to content

fix: keep sending ISDLOCK invs to non-MN peers with watchquorums#7293

Merged
PastaPastaPasta merged 1 commit intodashpay:developfrom
knst:fix-6994-watch
Apr 28, 2026
Merged

fix: keep sending ISDLOCK invs to non-MN peers with watchquorums#7293
PastaPastaPasta merged 1 commit intodashpay:developfrom
knst:fix-6994-watch

Conversation

@knst
Copy link
Copy Markdown
Collaborator

@knst knst commented Apr 27, 2026

Issue being fixed or feature implemented

PR #6994 made masternodes skip ISDLOCK inv announcements to any peer with m_wants_recsigs set, on the premise that such peers can reconstruct the ISLOCK from the recsig.

It works for MN peers but it does not work for quorum observers running with -watchquorums: those nodes also opt in to recsigs via QSENDRECSIGS but they don't have a signer worker running, so they cannot reconstruct an ISDLOCK from a recsig and they still need the inv.

nodes[0] runs with -watchquorums and had progressively sent QSENDRECSIGS to all four MN peers; by the third call every MN saw nodes[0].m_wants_recsigs=true and skipped the inv to it.

What was done?

The ISDLOCK is skipped now only on the peer being verified masternode. Move the policy from PushInv (called for every inv type) to the three sites that actually relay MSG_ISDLOCK and have CNode in scope.

How Has This Been Tested?

Run functional test interface_dash_zmq.py multiple times.
This PR drops failure rate from 50% to 0.

Breaking Changes

N/A

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone

PR dashpay#6994 made masternodes skip ISDLOCK inv announcements to any peer with
m_wants_recsigs set, on the premise that such peers can reconstruct the ISLOCK
from the recsig.

It works for MN peers but it does not work for quorum observers running with
-watchquorums: those nodes also opt in to recsigs via QSENDRECSIGS but they
don't have a signer worker running, so they cannot reconstruct an ISDLOCK from
a recsig and they still need the inv.

nodes[0] runs with -watchquorums and had progressively sent QSENDRECSIGS to all
four MN peers; by the third call every MN saw nodes[0].m_wants_recsigs=true and
skipped the inv to it.

This commit make the ISDLOCK skipped only on the peer being verified masternode.
Move the policy from PushInv (called for every inv type) to the three sites that
actually relay MSG_ISDLOCK and have CNode in scope.
@knst knst added this to the 24 milestone Apr 27, 2026
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@github-actions
Copy link
Copy Markdown

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@thepastaclaw
Copy link
Copy Markdown

thepastaclaw commented Apr 27, 2026

✅ Review complete (commit f6bb02d)

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Walkthrough

The changes refactor inventory announcement filtering logic in net processing by introducing a new helper function PeerReconstructsISLockFromRecsig that checks if a peer both wants recsigs and is a verified masternode. Previously, PushInv suppressed MSG_ISDLOCK inventory announcements for all peers requesting recsigs. This blanket suppression is now removed and replaced with narrower conditional checks in RelayInvFiltered and SendMessages that use the new helper, alongside logging and control flow updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the changeset, explaining the issue fixed (overly broad suppression in PR #6994), the solution (narrower suppression only for verified masternodes), testing performed, and checklist items.
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.
Title check ✅ Passed The title clearly summarizes the main fix: keeping ISDLOCK inventory announcements sent to non-masternode peers that want recsigs, directly addressing the core issue resolved in the PR.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@knst knst requested review from PastaPastaPasta and UdjinM6 April 27, 2026 18:20
@knst knst changed the title fix: keep sending ISDLOCK invs to non-MN peers that want recsigs fix: keep sending ISDLOCK invs to non-MN peers with watchquorums Apr 27, 2026
Copy link
Copy Markdown

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

Verified the targeted fix on net_processing.cpp: a new helper PeerReconstructsISLockFromRecsig narrows the ISDLOCK inv suppression to verified masternodes that opted into recsigs, restoring relay to non-MN watchquorums peers. No correctness regressions found. Two suggestions and one nitpick stand: a small heuristic gap, duplicated skip-and-log blocks across the two RelayInvFiltered overloads, and absence of a dedicated regression test for the watchquorums + recsigs scenario.

Reviewed commit: f6bb02d

🟡 2 suggestion(s) | 💬 1 nitpick(s)

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/net_processing.cpp`:
- [SUGGESTION] lines 1201-1203: Add a direct regression test for ISDLOCK relay to watchquorums peers
  The fix relies entirely on PeerReconstructsISLockFromRecsig to keep ISDLOCK invs flowing to non-masternode peers that opted into recsigs (e.g. nodes started with -watchquorums). The PR changes only src/net_processing.cpp and adds no test that pins this behavior down. The original regression in PR #6994 was masked because interface_dash_zmq.py covers the failure mode only indirectly (and was flaky enough to miss it ~50% of the time). A dedicated functional or unit assertion that a non-MN peer that has sent QSENDRECSIGS still receives MSG_ISDLOCK after all connected MNs have set m_wants_recsigs=true would prevent the next refactor from collapsing the three sites back into a PushInv-level filter and reintroducing the same bug.
- [SUGGESTION] lines 1196-1204: Helper assumes every verified-MN peer can reconstruct an ISDLOCK
  PeerReconstructsISLockFromRecsig treats `m_wants_recsigs && verified-MN` as sufficient to assume the peer will reconstruct an ISDLOCK locally from the recsig. That holds for masternodes that are members of the relevant InstantSend quorum running the signer worker, but it is not strictly enforced: a verified MN that is not in the active quorum (or is outside the recovery window) will still receive recsigs but lacks the share data needed to assemble the ISDLOCK, and under this code we will not send it the inv either. The behavior is still strictly safer than the pre-fix state and other MN peers will fill the gap, but the comment overstates the invariant. Tightening the comment to call this out as a best-effort optimization (or confirming the IS team is comfortable with the edge case) would prevent future readers from over-trusting the predicate.

Comment thread src/net_processing.cpp
Comment thread src/net_processing.cpp
Comment on lines +1196 to +1204
// Returns true when peer is a verified masternode that has opted in to receive recsigs.
// Such peers participate in the signing flow that populates creatingInstantSendLocks, so
// they can reconstruct an ISDLOCK locally from the recsig and don't need the ISDLOCK inv.
// Non-MN peers (e.g. nodes running with -watchquorums) also opt in to recsigs via
// QSENDRECSIGS but still need ISDLOCK invs because they don't run the signing flow.
static bool PeerReconstructsISLockFromRecsig(const CNode& pnode, const Peer& peer)
{
return peer.m_wants_recsigs && !pnode.GetVerifiedProRegTxHash().IsNull();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Suggestion: Helper assumes every verified-MN peer can reconstruct an ISDLOCK

PeerReconstructsISLockFromRecsig treats m_wants_recsigs && verified-MN as sufficient to assume the peer will reconstruct an ISDLOCK locally from the recsig. That holds for masternodes that are members of the relevant InstantSend quorum running the signer worker, but it is not strictly enforced: a verified MN that is not in the active quorum (or is outside the recovery window) will still receive recsigs but lacks the share data needed to assemble the ISDLOCK, and under this code we will not send it the inv either. The behavior is still strictly safer than the pre-fix state and other MN peers will fill the gap, but the comment overstates the invariant. Tightening the comment to call this out as a best-effort optimization (or confirming the IS team is comfortable with the edge case) would prevent future readers from over-trusting the predicate.

source: ['claude']

🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/net_processing.cpp`:
- [SUGGESTION] lines 1196-1204: Helper assumes every verified-MN peer can reconstruct an ISDLOCK
  PeerReconstructsISLockFromRecsig treats `m_wants_recsigs && verified-MN` as sufficient to assume the peer will reconstruct an ISDLOCK locally from the recsig. That holds for masternodes that are members of the relevant InstantSend quorum running the signer worker, but it is not strictly enforced: a verified MN that is not in the active quorum (or is outside the recovery window) will still receive recsigs but lacks the share data needed to assemble the ISDLOCK, and under this code we will not send it the inv either. The behavior is still strictly safer than the pre-fix state and other MN peers will fill the gap, but the comment overstates the invariant. Tightening the comment to call this out as a best-effort optimization (or confirming the IS team is comfortable with the edge case) would prevent future readers from over-trusting the predicate.

Comment thread src/net_processing.cpp
Comment on lines 2547 to +2581
@@ -2566,6 +2574,11 @@ void PeerManagerImpl::RelayInvFiltered(const CInv& inv, const uint256& relatedTx
return;
}
} // LOCK(tx_relay->m_bloom_filter_mutex)
if (inv.type == MSG_ISDLOCK && PeerReconstructsISLockFromRecsig(*pnode, *peer)) {
LogPrint(BCLog::NET, "%s -- skipping ISDLOCK inv (peer wants recsigs): %s peer=%d\n",
__func__, inv.ToString(), peer->m_id);
return;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💬 Nitpick: Duplicated ISDLOCK skip-and-log block in both RelayInvFiltered overloads

The four-line if (inv.type == MSG_ISDLOCK && PeerReconstructsISLockFromRecsig(*pnode, *peer)) { LogPrint(...); return; } is copy-pasted into both RelayInvFiltered overloads (2547-2551 and 2577-2581) and is the structural twin of the guard at 6364. Extracting a small helper such as ShouldSkipISDLockInv(pnode, peer, inv) would avoid the three sites drifting apart in future edits. Pure readability/maintainability nit, not a defect.

source: ['claude']

Copy link
Copy Markdown
Member

@PastaPastaPasta PastaPastaPasta left a comment

Choose a reason for hiding this comment

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

utACK f6bb02d

@PastaPastaPasta PastaPastaPasta merged commit 67683f3 into dashpay:develop Apr 28, 2026
46 of 48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants