Skip to content

test: adds QSENDRECSIGS functional tests for watchquorum nodes#7301

Open
knst wants to merge 2 commits intodashpay:developfrom
knst:tests-for-7293
Open

test: adds QSENDRECSIGS functional tests for watchquorum nodes#7301
knst wants to merge 2 commits intodashpay:developfrom
knst:tests-for-7293

Conversation

@knst
Copy link
Copy Markdown
Collaborator

@knst knst commented Apr 30, 2026

Issue being fixed or feature implemented

Addresses #7293 (comment)

What was done?

Adds functional tests for QSENDRECSIGS for watch-quorum nodes.

How Has This Been Tested?

Run on the top of #7293 and on develop with #7293 reverted.

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

@knst knst added this to the 24 milestone Apr 30, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@thepastaclaw
Copy link
Copy Markdown

thepastaclaw commented Apr 30, 2026

✅ Review complete (commit 59dec1c)

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a4fea7360

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

b"qpcommit": None,
b"qrinfo": None,
b"qsendrecsigs": None,
b"qsendrecsigs": msg_qsendrecsigs,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep qsendrecsigs ignored until callback exists

Changing MESSAGEMAP to decode qsendrecsigs makes P2PInterface.on_message() dispatch to on_qsendrecsigs, but P2PInterface has no such callback method, so receiving this message raises AttributeError and tears down the test peer. This is reachable when nodes send QSENDRECSIGS to authenticated quorum-relay peers (see the send paths in CMNAuth::ProcessMessage / CConnman::SetMasternodeQuorumRelayMembers), so this mapping change can break functional tests that use default P2PInterface on those connections.

Useful? React with 👍 / 👎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aa499b50-6586-463b-9122-89d7f46543ec

📥 Commits

Reviewing files that changed from the base of the PR and between fef1071 and 59dec1c.

📒 Files selected for processing (3)
  • test/functional/p2p_instantsend.py
  • test/functional/test_framework/messages.py
  • test/functional/test_framework/p2p.py
✅ Files skipped from review due to trivial changes (2)
  • test/functional/p2p_instantsend.py
  • test/functional/test_framework/messages.py

Walkthrough

Adds a test-only wire message qsendrecsigs to the functional test framework and a RecSigsObserver(P2PInterface) that can send QSENDRECSIGS and record receipt of MSG_ISDLOCK inv vectors. Adds P2PInterface.on_qsendrecsigs() callback and maps qsendrecsigs in MESSAGEMAP. Introduces test test_isdlock_relayed_to_recsigs_observer() which attaches one observer per masternode, opts them into recsigs, triggers an InstantSend transaction to produce an IS lock, syncs observers, asserts at least one observed a MSG_ISDLOCK inv, and then disconnects the observers.

Sequence Diagram

sequenceDiagram
    participant Test as Test Case
    participant MN as Masternode
    participant Obs as RecSigsObserver
    participant Net as P2P Network

    Test->>Obs: create observer per MN
    Test->>Obs: send_qsendrecsigs(wants_recsigs=True)
    Obs->>MN: establish P2P connection
    Test->>Test: broadcast InstantSend transaction
    MN->>Net: announce MSG_ISDLOCK (inv)
    Net->>Obs: deliver inv containing MSG_ISDLOCK
    Obs->>Obs: on_inv() sets isdlock_inv_seen
    Test->>Obs: sync_with_ping()
    Test->>Test: assert at least one observer saw MSG_ISDLOCK
    Test->>Obs: disconnect observers
Loading

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 0.00% 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
Title check ✅ Passed The title clearly and specifically describes the main change: adding functional tests for QSENDRECSIGS message targeting watch-quorum nodes, which aligns with the changeset.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose (adding functional tests for QSENDRECSIGS), referencing the issue being addressed, and describing testing methodology.
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 unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

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

The new functional test adds useful coverage for the QSENDRECSIGS regression fixed in #7293, but has a few notable issues: (1) mapping qsendrecsigs to a deserializer in MESSAGEMAP without adding a default on_qsendrecsigs callback creates a latent AttributeError for any P2PInterface mock that becomes a verified quorum-relay MN peer; (2) the assertion uses any() so the test passes even if 3 of 4 MNs still suppress the inv, which is exactly the partial regression it should catch; (3) the test uses raw QSENDRECSIGS rather than starting a node with -watchquorums, despite the log line claiming otherwise.

Reviewed commit: 3a4fea7

🟡 2 suggestion(s) | 💬 2 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 `test/functional/p2p_instantsend.py`:
- [SUGGESTION] lines 169-170: `any()` makes the regression check too weak — use `all()`
  PR #7293 fixed every masternode peer to stop suppressing `MSG_ISDLOCK` for non-MN recsig consumers. The server-side filter at `net_processing.cpp:1201-1204` (`PeerReconstructsISLockFromRecsig`) only suppresses the inv when the peer is a verified MN, so every one of the 4 MNs is expected to relay the inv to its attached non-MN observer. Asserting `any(...)` lets the test pass even if 3 out of 4 MNs are still broken — i.e., a partial regression of #7293 would slip through, which is precisely what this test should catch. Tighten to `all(...)`, ideally wrapped in a `wait_until` to give propagation room.

In `test/functional/test_framework/p2p.py`:
- [SUGGESTION] line 181: Add a default `on_qsendrecsigs` callback to P2PInterface
  Previously `MESSAGEMAP[b"qsendrecsigs"] = None` caused incoming QSENDRECSIGS messages to be silently dropped at p2p.py:414. After this change, the message is deserialized and dispatched via `on_message` → `getattr(self, 'on_qsendrecsigs')(message)` (p2p.py:562). No default `on_qsendrecsigs` is defined alongside the other Dash defaults at lines 617–625. Today this is latent: `p2p_quorum_data.py` calls the `mnauth` RPC on P2P mocks, but its fake proRegTxHashes don't match real relay quorum members so `mnauth.cpp:161-167` doesn't push QSENDRECSIGS back. Any future test that performs MNAUTH with a real MN proRegTxHash that is also in a relay quorum will receive QSENDRECSIGS and crash with AttributeError. The fix is one line.

Comment thread test/functional/p2p_instantsend.py Outdated
Comment on lines +169 to +170
assert any(o.isdlock_inv_seen for o in observers), \
"non-MN peer with QSENDRECSIGS got no MSG_ISDLOCK inv"
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: any() makes the regression check too weak — use all()

PR #7293 fixed every masternode peer to stop suppressing MSG_ISDLOCK for non-MN recsig consumers. The server-side filter at net_processing.cpp:1201-1204 (PeerReconstructsISLockFromRecsig) only suppresses the inv when the peer is a verified MN, so every one of the 4 MNs is expected to relay the inv to its attached non-MN observer. Asserting any(...) lets the test pass even if 3 out of 4 MNs are still broken — i.e., a partial regression of #7293 would slip through, which is precisely what this test should catch. Tighten to all(...), ideally wrapped in a wait_until to give propagation room.

💡 Suggested change
Suggested change
assert any(o.isdlock_inv_seen for o in observers), \
"non-MN peer with QSENDRECSIGS got no MSG_ISDLOCK inv"
self.wait_until(lambda: all(o.isdlock_inv_seen for o in observers),
timeout=10)
assert all(o.isdlock_inv_seen for o in observers), \
"some non-MN peers with QSENDRECSIGS got no MSG_ISDLOCK inv"

source: ['claude', 'codex']

🤖 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 `test/functional/p2p_instantsend.py`:
- [SUGGESTION] lines 169-170: `any()` makes the regression check too weak — use `all()`
  PR #7293 fixed every masternode peer to stop suppressing `MSG_ISDLOCK` for non-MN recsig consumers. The server-side filter at `net_processing.cpp:1201-1204` (`PeerReconstructsISLockFromRecsig`) only suppresses the inv when the peer is a verified MN, so every one of the 4 MNs is expected to relay the inv to its attached non-MN observer. Asserting `any(...)` lets the test pass even if 3 out of 4 MNs are still broken — i.e., a partial regression of #7293 would slip through, which is precisely what this test should catch. Tighten to `all(...)`, ideally wrapped in a `wait_until` to give propagation room.

b"qpcommit": None,
b"qrinfo": None,
b"qsendrecsigs": None,
b"qsendrecsigs": msg_qsendrecsigs,
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: Add a default on_qsendrecsigs callback to P2PInterface

Previously MESSAGEMAP[b"qsendrecsigs"] = None caused incoming QSENDRECSIGS messages to be silently dropped at p2p.py:414. After this change, the message is deserialized and dispatched via on_messagegetattr(self, 'on_qsendrecsigs')(message) (p2p.py:562). No default on_qsendrecsigs is defined alongside the other Dash defaults at lines 617–625. Today this is latent: p2p_quorum_data.py calls the mnauth RPC on P2P mocks, but its fake proRegTxHashes don't match real relay quorum members so mnauth.cpp:161-167 doesn't push QSENDRECSIGS back. Any future test that performs MNAUTH with a real MN proRegTxHash that is also in a relay quorum will receive QSENDRECSIGS and crash with AttributeError. The fix is one line.

💡 Suggested change
Suggested change
b"qsendrecsigs": msg_qsendrecsigs,
def on_qsendrecsigs(self, message): pass
def on_mnlistdiff(self, message): pass
def on_clsig(self, message): pass
def on_islock(self, message): pass
def on_isdlock(self, message): pass

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 `test/functional/test_framework/p2p.py`:
- [SUGGESTION] line 181: Add a default `on_qsendrecsigs` callback to P2PInterface
  Previously `MESSAGEMAP[b"qsendrecsigs"] = None` caused incoming QSENDRECSIGS messages to be silently dropped at p2p.py:414. After this change, the message is deserialized and dispatched via `on_message` → `getattr(self, 'on_qsendrecsigs')(message)` (p2p.py:562). No default `on_qsendrecsigs` is defined alongside the other Dash defaults at lines 617–625. Today this is latent: `p2p_quorum_data.py` calls the `mnauth` RPC on P2P mocks, but its fake proRegTxHashes don't match real relay quorum members so `mnauth.cpp:161-167` doesn't push QSENDRECSIGS back. Any future test that performs MNAUTH with a real MN proRegTxHash that is also in a relay quorum will receive QSENDRECSIGS and crash with AttributeError. The fix is one line.

self.generate(self.nodes[0], 2)

def test_isdlock_relayed_to_recsigs_observer(self):
self.log.info("Non-MN peer started with -watchquorums must still get ISDLOCK invs")
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: Test mentions -watchquorums but never sets the flag — either fix the log or actually exercise the watcher path

The log line claims "Non-MN peer started with -watchquorums must still get ISDLOCK invs", but set_dash_test_params(8, 4) doesn't pass extra_args=["-watchquorums"] to any node — the test instead attaches P2PInterface mocks and sends QSENDRECSIGS manually. That does cover the generic m_wants_recsigs && !verified_masternode server branch, which is the same code path #7293 fixed, but the production scenario reported in the bug was a full node running with -watchquorums. Either (a) rephrase the log to match what the test actually does ("Non-MN peer that opted in via QSENDRECSIGS must still get ISDLOCK invs"), or (b) start a real node with -watchquorums to exercise the watcher init path end-to-end.

💡 Suggested change
Suggested change
self.log.info("Non-MN peer started with -watchquorums must still get ISDLOCK invs")
self.log.info("Non-MN peer that opted in via QSENDRECSIGS must still get ISDLOCK invs")

source: ['claude', 'codex']

Comment on lines +29 to +31
# MSG_ISDLOCK inv type, see src/protocol.h
if inv.type == 31:
self.isdlock_inv_seen = True
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: Prefer a named constant for MSG_ISDLOCK type id

MSG_TX (1) and MSG_BLOCK (2) are defined as named constants in test_framework/messages.py and used elsewhere in the framework. The bare literal 31 with an explanatory comment works, but adding MSG_ISDLOCK = 31 to messages.py and importing it would match the rest of the framework and survive a future renumber gracefully. The corresponding C++ enum value lives in src/protocol.h.

source: ['claude']

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.

No blockers from me on the current head; remaining comments are advisory suggestions/nits.

@UdjinM6
Copy link
Copy Markdown

UdjinM6 commented May 3, 2026

pls consider a1caa31

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fef1071cfa

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread test/functional/test_framework/p2p.py
@knst knst requested review from PastaPastaPasta and UdjinM6 May 3, 2026 19:17
…vers

Match the m_wants_recsigs name used in net_processing.cpp, and explicitly
disconnect the RecSigsObserver peers instead of relying on the next
sub-test's restart to clean them up.

+fixed mapping qsendrecsigs to msg_qsendrecsigs

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@knst knst force-pushed the tests-for-7293 branch from fef1071 to 59dec1c Compare May 3, 2026 19:34
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59dec1c9ab

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +170 to +171
assert any(obs.isdlock_inv_seen for _, obs in observers), \
"non-MN peer with QSENDRECSIGS got no MSG_ISDLOCK inv"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require every observer to receive the ISDLOCK inv

This assertion only checks any(...), so the test passes even if most watchquorum masternodes fail to relay MSG_ISDLOCK to opted-in non-MN peers. Because this test is meant to validate relay behavior across the watchquorum nodes set up just above, using any can hide partial regressions and let quorum-relay breakages slip through CI undetected.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

smth like 75b876f should do it

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

PR adds a regression test for QSENDRECSIGS opt-in non-MN peers receiving MSG_ISDLOCK invs, plus the framework plumbing for msg_qsendrecsigs. Logic is sound and exercises PeerReconstructsISLockFromRecsig correctly. Main concern is that the assertion uses any instead of all, weakening per-peer regression coverage. No blockers.

Reviewed commit: 59dec1c

🟡 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 `test/functional/p2p_instantsend.py`:
- [SUGGESTION] lines 170-171: Use `all(...)` instead of `any(...)` — the bug being guarded is per-peer state
  `PeerReconstructsISLockFromRecsig()` is evaluated per peer at every ISDLOCK relay site (src/net_processing.cpp:1201, 2547, 2577, 6363) against `peer.m_wants_recsigs`, which is per-CNode. The test attaches one opted-in observer to each masternode, but `any(...)` only requires one observer to see the inv. A regression where some watch-quorum peers incorrectly suppress MSG_ISDLOCK would still pass as long as a single MN delivers it. Tighten to `all(...)` so each per-peer ISDLOCK relay decision is exercised, and a partial regression is caught with a diagnosable failure.
- [SUGGESTION] lines 155-174: Test framing references `-watchquorums` but no node is started with it
  The log line says `Non-MN peer started with -watchquorums must still get ISDLOCK invs`, but the test attaches a generic non-MN P2PInterface that manually sends QSENDRECSIGS=true. That correctly exercises the protocol-level surface in PeerReconstructsISLockFromRecsig, but does not cover the end-to-end path where a real node started with `-watchquorums` issues QSENDRECSIGS at handshake (see src/net.cpp / src/evo/mnauth.cpp). Either rename the log/test to reflect what is actually tested (e.g. `non-MN peer that opts into recsigs`), or add a second variant that spins up a node with `-watchquorums` to also cover the integration path.

Comment on lines +170 to +171
assert any(obs.isdlock_inv_seen for _, obs in observers), \
"non-MN peer with QSENDRECSIGS got no MSG_ISDLOCK inv"
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: Use all(...) instead of any(...) — the bug being guarded is per-peer state

PeerReconstructsISLockFromRecsig() is evaluated per peer at every ISDLOCK relay site (src/net_processing.cpp:1201, 2547, 2577, 6363) against peer.m_wants_recsigs, which is per-CNode. The test attaches one opted-in observer to each masternode, but any(...) only requires one observer to see the inv. A regression where some watch-quorum peers incorrectly suppress MSG_ISDLOCK would still pass as long as a single MN delivers it. Tighten to all(...) so each per-peer ISDLOCK relay decision is exercised, and a partial regression is caught with a diagnosable failure.

💡 Suggested change
Suggested change
assert any(obs.isdlock_inv_seen for _, obs in observers), \
"non-MN peer with QSENDRECSIGS got no MSG_ISDLOCK inv"
assert all(obs.isdlock_inv_seen for _, obs in observers), \
"each non-MN peer with QSENDRECSIGS must get a MSG_ISDLOCK inv"

source: ['claude', 'codex']

🤖 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 `test/functional/p2p_instantsend.py`:
- [SUGGESTION] lines 170-171: Use `all(...)` instead of `any(...)` — the bug being guarded is per-peer state
  `PeerReconstructsISLockFromRecsig()` is evaluated per peer at every ISDLOCK relay site (src/net_processing.cpp:1201, 2547, 2577, 6363) against `peer.m_wants_recsigs`, which is per-CNode. The test attaches one opted-in observer to each masternode, but `any(...)` only requires one observer to see the inv. A regression where some watch-quorum peers incorrectly suppress MSG_ISDLOCK would still pass as long as a single MN delivers it. Tighten to `all(...)` so each per-peer ISDLOCK relay decision is exercised, and a partial regression is caught with a diagnosable failure.

Comment on lines +155 to +174
def test_isdlock_relayed_to_recsigs_observer(self):
self.log.info("Non-MN peer started with -watchquorums must still get ISDLOCK invs")
observers = []
for mn in self.mninfo:
node = mn.get_node(self)
obs = node.add_p2p_connection(RecSigsObserver())
obs.send_qsendrecsigs(True)
obs.sync_with_ping()
observers.append((node, obs))

txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
self.wait_for_instantlock(txid)
for _, obs in observers:
obs.sync_with_ping()

assert any(obs.isdlock_inv_seen for _, obs in observers), \
"non-MN peer with QSENDRECSIGS got no MSG_ISDLOCK inv"

for node, _ in observers:
node.disconnect_p2ps()
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: Test framing references -watchquorums but no node is started with it

The log line says Non-MN peer started with -watchquorums must still get ISDLOCK invs, but the test attaches a generic non-MN P2PInterface that manually sends QSENDRECSIGS=true. That correctly exercises the protocol-level surface in PeerReconstructsISLockFromRecsig, but does not cover the end-to-end path where a real node started with -watchquorums issues QSENDRECSIGS at handshake (see src/net.cpp / src/evo/mnauth.cpp). Either rename the log/test to reflect what is actually tested (e.g. non-MN peer that opts into recsigs), or add a second variant that spins up a node with -watchquorums to also cover the integration path.

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 `test/functional/p2p_instantsend.py`:
- [SUGGESTION] lines 155-174: Test framing references `-watchquorums` but no node is started with it
  The log line says `Non-MN peer started with -watchquorums must still get ISDLOCK invs`, but the test attaches a generic non-MN P2PInterface that manually sends QSENDRECSIGS=true. That correctly exercises the protocol-level surface in PeerReconstructsISLockFromRecsig, but does not cover the end-to-end path where a real node started with `-watchquorums` issues QSENDRECSIGS at handshake (see src/net.cpp / src/evo/mnauth.cpp). Either rename the log/test to reflect what is actually tested (e.g. `non-MN peer that opts into recsigs`), or add a second variant that spins up a node with `-watchquorums` to also cover the integration path.

Comment on lines +28 to +31
for inv in message.inv:
# MSG_ISDLOCK inv type, see src/protocol.h
if inv.type == 31:
self.isdlock_inv_seen = True
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: Define MSG_ISDLOCK constant in messages.py instead of literal 31

Other inv types in test_framework/messages.py are exposed as named constants (MSG_TX=1, MSG_BLOCK=2, etc.) and their numeric values mirror src/protocol.h. The literal 31 with an inline comment diverges from that convention and breaks silently if the value is renumbered. Add MSG_ISDLOCK = 31 to messages.py and import it here.

source: ['claude']

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.

3 participants