test: cover disconnect on private broadcast peer with relay=false
What changed, and why it matters
This commit only adds a new automated test to Bitcoin Core. It verifies that when a node connects to a 'private broadcast' peer which signals it does not relay transactions (relay=false), the node disconnects that peer. There is no change to production code, no bug fix, and no security vulnerability introduced or patched.
No action required; this is a benign test-only change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff extends test/functional/p2p_private_broadcast.py with a NoRelayP2PInterface subclass that sets the version message relay field to 0, and a test case that checks the tx_originator node disconnects such a peer with the debug log message ‘Disconnecting: does not support transaction relay (connected in vain)’. This is purely test coverage for existing behavior.
Changed components
test/functional/p2p_private_broadcast.pyInspect captured patch +27 / −0
diff --git a/test/functional/p2p_private_broadcast.py b/test/functional/p2p_private_broadcast.py
index 638028af..054058e9 100755
--- a/test/functional/p2p_private_broadcast.py
+++ b/test/functional/p2p_private_broadcast.py
@@ -49,6 +49,12 @@ P2P_PRIVATE_VERSION = 70016
NUM_PRIVATE_BROADCAST_PER_TX = 3
+class NoRelayP2PInterface(P2PInterface):
+ def peer_connect_send_version(self, services):
+ super().peer_connect_send_version(services)
+ self.on_connection_send_msg.relay = 0
+
+
class P2PPrivateBroadcast(BitcoinTestFramework):
def set_test_params(self):
self.disable_autoconnect = False
@@ -59,6 +65,9 @@ class P2PPrivateBroadcast(BitcoinTestFramework):
self.destinations_lock = threading.Lock()
+ self.trigger_no_relay_peer = False
+ self.no_relay_peer = None
+
def find_connection_type_in_debug_log(to_addr, to_port):
"""
Scan the debug log of tx_originator for a connection attempt to to_addr:to_port.
@@ -106,6 +115,11 @@ class P2PPrivateBroadcast(BitcoinTestFramework):
if conn_type == "outbound-full-relay" and not any(dest["conn_type"] == "outbound-full-relay" for dest in self.destinations):
listener = P2PDataStore()
target_name = "Python P2PDataStore"
+ elif conn_type == "private-broadcast" and self.trigger_no_relay_peer:
+ listener = NoRelayP2PInterface()
+ target_name = "Python NoRelayP2PInterface"
+ self.trigger_no_relay_peer = False
+ self.no_relay_peer = listener
else:
listener = P2PInterface()
target_name = "Python P2PInterface"
@@ -379,6 +393,19 @@ class P2PPrivateBroadcast(BitcoinTestFramework):
"0" * 64,
)
+ self.log.info("Checking that a private broadcast destination signaling relay=false gets disconnected")
+ tx_no_relay = wallet.create_self_transfer()
+ disconnect_msg = "Disconnecting: does not support transaction relay (connected in vain)"
+ with tx_originator.assert_debug_log(expected_msgs=[disconnect_msg]):
+ with self.destinations_lock:
+ self.no_relay_peer = None
+ self.trigger_no_relay_peer = True
+ tx_originator.sendrawtransaction(hexstring=tx_no_relay["hex"], maxfeerate=0.1)
+ self.wait_until(lambda: self.no_relay_peer is not None)
+ self.no_relay_peer.wait_until(lambda: self.no_relay_peer.message_count["version"] == 1, check_connected=False)
+ self.no_relay_peer.wait_for_disconnect()
+ assert_equal(self.no_relay_peer.message_count, {"version": 1})
+
# Stop the SOCKS5 proxy server to avoid it being upset by the bitcoin
# node disconnecting in the middle of the SOCKS5 handshake when we
# restart below.
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.