-
Notifications
You must be signed in to change notification settings - Fork 1.2k
test: adds QSENDRECSIGS functional tests for watchquorum nodes #7301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |||||||||
| # Distributed under the MIT software license, see the accompanying | ||||||||||
| # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||||||||
|
|
||||||||||
| from test_framework.messages import msg_qsendrecsigs | ||||||||||
| from test_framework.p2p import P2PInterface | ||||||||||
| from test_framework.test_framework import DashTestFramework | ||||||||||
| from test_framework.util import assert_equal, assert_raises_rpc_error, force_finish_mnsync | ||||||||||
|
|
||||||||||
|
|
@@ -12,6 +14,24 @@ | |||||||||
| Tests InstantSend functionality (prevent doublespend for unconfirmed transactions) | ||||||||||
| ''' | ||||||||||
|
|
||||||||||
| class RecSigsObserver(P2PInterface): | ||||||||||
| """Non-MN peer that opts in to recsigs and records every ISDLOCK inv it sees.""" | ||||||||||
|
|
||||||||||
| def __init__(self): | ||||||||||
| super().__init__() | ||||||||||
| self.isdlock_inv_seen = False | ||||||||||
|
|
||||||||||
| def send_qsendrecsigs(self, wants_recsigs=True): | ||||||||||
| self.send_message(msg_qsendrecsigs(wants_recsigs)) | ||||||||||
|
|
||||||||||
| def on_inv(self, message): | ||||||||||
| for inv in message.inv: | ||||||||||
| # MSG_ISDLOCK inv type, see src/protocol.h | ||||||||||
| if inv.type == 31: | ||||||||||
| self.isdlock_inv_seen = True | ||||||||||
|
Comment on lines
+28
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 source: ['claude'] |
||||||||||
| super().on_inv(message) | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class InstantSendTest(DashTestFramework): | ||||||||||
| def add_options(self, parser): | ||||||||||
| self.add_wallet_options(parser) | ||||||||||
|
|
@@ -36,6 +56,7 @@ def run_test(self): | |||||||||
|
|
||||||||||
| self.test_mempool_doublespend() | ||||||||||
| self.test_block_doublespend() | ||||||||||
| self.test_isdlock_relayed_to_recsigs_observer() | ||||||||||
| self.test_instantsend_after_restart() | ||||||||||
|
|
||||||||||
| def test_block_doublespend(self): | ||||||||||
|
|
@@ -131,6 +152,27 @@ def test_mempool_doublespend(self): | |||||||||
| # mine more blocks | ||||||||||
| 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") | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💬 Nitpick: Test mentions The log line claims "Non-MN peer started with -watchquorums must still get ISDLOCK invs", but 💡 Suggested change
Suggested change
source: ['claude', 'codex'] |
||||||||||
| 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" | ||||||||||
|
Comment on lines
+170
to
+171
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This assertion only checks Useful? React with 👍 / 👎. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. smth like 75b876f should do it
Comment on lines
+170
to
+171
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Use
💡 Suggested change
Suggested change
source: ['claude', 'codex'] 🤖 Fix this with AI agents |
||||||||||
|
|
||||||||||
| for node, _ in observers: | ||||||||||
| node.disconnect_p2ps() | ||||||||||
|
Comment on lines
+155
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Test framing references The log line says source: ['claude'] 🤖 Fix this with AI agents |
||||||||||
|
|
||||||||||
| def test_instantsend_after_restart(self): | ||||||||||
| self.log.info("Testing InstantSend works after full restart without new blocks") | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -69,6 +69,7 @@ | |||||||||||||
| msg_pong, | ||||||||||||||
| msg_qdata, | ||||||||||||||
| msg_qgetdata, | ||||||||||||||
| msg_qsendrecsigs, | ||||||||||||||
| msg_sendaddrv2, | ||||||||||||||
| msg_sendcmpct, | ||||||||||||||
| msg_sendheaders, | ||||||||||||||
|
|
@@ -177,7 +178,7 @@ | |||||||||||||
| b"qjustify": None, | ||||||||||||||
| b"qpcommit": None, | ||||||||||||||
| b"qrinfo": None, | ||||||||||||||
| b"qsendrecsigs": None, | ||||||||||||||
| b"qsendrecsigs": msg_qsendrecsigs, | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Changing Useful? React with 👍 / 👎. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Add a default Previously 💡 Suggested change
Suggested change
source: ['claude'] 🤖 Fix this with AI agents
UdjinM6 marked this conversation as resolved.
|
||||||||||||||
| b"qsigrec": None, | ||||||||||||||
| b"qsigsesann": None, | ||||||||||||||
| b"qsigshare": None, | ||||||||||||||
|
|
@@ -621,6 +622,7 @@ def on_isdlock(self, message): pass | |||||||||||||
| def on_platformban(self, message): pass | ||||||||||||||
| def on_qgetdata(self, message): pass | ||||||||||||||
| def on_qdata(self, message): pass | ||||||||||||||
| def on_qsendrecsigs(self, message): pass | ||||||||||||||
| def on_qwatch(self, message): pass | ||||||||||||||
|
|
||||||||||||||
| def on_verack(self, message): pass | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
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.pyand used elsewhere in the framework. The bare literal31with an explanatory comment works, but addingMSG_ISDLOCK = 31to messages.py and importing it would match the rest of the framework and survive a future renumber gracefully. The corresponding C++ enum value lives insrc/protocol.h.source: ['claude']