Skip to content

Commit c4a67d3

Browse files
committed
test: p2p: check disconnect due to lack of desirable service flags
1 parent 405ac81 commit c4a67d3

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

test/functional/p2p_handshake.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2024 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""
6+
Test P2P behaviour during the handshake phase (VERSION, VERACK messages).
7+
"""
8+
import itertools
9+
10+
from test_framework.test_framework import BitcoinTestFramework
11+
from test_framework.messages import (
12+
NODE_NETWORK,
13+
NODE_NONE,
14+
NODE_P2P_V2,
15+
NODE_WITNESS,
16+
)
17+
from test_framework.p2p import P2PInterface
18+
19+
20+
# usual desirable service flags for outbound non-pruned peers
21+
DESIRABLE_SERVICE_FLAGS = NODE_NETWORK | NODE_WITNESS
22+
23+
24+
class P2PHandshakeTest(BitcoinTestFramework):
25+
def set_test_params(self):
26+
self.num_nodes = 1
27+
28+
def add_outbound_connection(self, node, connection_type, services, wait_for_disconnect):
29+
peer = node.add_outbound_p2p_connection(
30+
P2PInterface(), p2p_idx=0, wait_for_disconnect=wait_for_disconnect,
31+
connection_type=connection_type, services=services,
32+
supports_v2_p2p=self.options.v2transport, advertise_v2_p2p=self.options.v2transport)
33+
if not wait_for_disconnect:
34+
# check that connection is alive past the version handshake and disconnect manually
35+
peer.sync_with_ping()
36+
peer.peer_disconnect()
37+
peer.wait_for_disconnect()
38+
39+
def test_desirable_service_flags(self, node, service_flag_tests, expect_disconnect):
40+
"""Check that connecting to a peer either fails or succeeds depending on its offered
41+
service flags in the VERSION message. The test is exercised for all relevant
42+
outbound connection types where the desirable service flags check is done."""
43+
CONNECTION_TYPES = ["outbound-full-relay", "block-relay-only", "addr-fetch"]
44+
for conn_type, services in itertools.product(CONNECTION_TYPES, service_flag_tests):
45+
if self.options.v2transport:
46+
services |= NODE_P2P_V2
47+
expected_result = "disconnect" if expect_disconnect else "connect"
48+
self.log.info(f' - services 0x{services:08x}, type "{conn_type}" [{expected_result}]')
49+
if expect_disconnect:
50+
expected_debug_log = f'does not offer the expected services ' \
51+
f'({services:08x} offered, {DESIRABLE_SERVICE_FLAGS:08x} expected)'
52+
with node.assert_debug_log([expected_debug_log]):
53+
self.add_outbound_connection(node, conn_type, services, wait_for_disconnect=True)
54+
else:
55+
self.add_outbound_connection(node, conn_type, services, wait_for_disconnect=False)
56+
57+
def run_test(self):
58+
node = self.nodes[0]
59+
self.log.info("Check that lacking desired service flags leads to disconnect (non-pruned peers)")
60+
self.test_desirable_service_flags(node, [NODE_NONE, NODE_NETWORK, NODE_WITNESS], expect_disconnect=True)
61+
self.test_desirable_service_flags(node, [NODE_NETWORK | NODE_WITNESS], expect_disconnect=False)
62+
63+
self.log.info("Check that feeler connections get disconnected immediately")
64+
with node.assert_debug_log([f"feeler connection completed"]):
65+
self.add_outbound_connection(node, "feeler", NODE_NONE, wait_for_disconnect=True)
66+
67+
68+
if __name__ == '__main__':
69+
P2PHandshakeTest().main()

test/functional/test_framework/messages.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
MAX_HEADERS_RESULTS = 2000 # Number of headers sent in one getheaders result
4747
MAX_INV_SIZE = 50000 # Maximum number of entries in an 'inv' protocol message
4848

49+
NODE_NONE = 0
4950
NODE_NETWORK = (1 << 0)
5051
NODE_BLOOM = (1 << 2)
5152
NODE_WITNESS = (1 << 3)

test/functional/test_runner.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@
395395
'rpc_getdescriptorinfo.py',
396396
'rpc_mempool_info.py',
397397
'rpc_help.py',
398+
'p2p_handshake.py',
399+
'p2p_handshake.py --v2transport',
398400
'feature_dirsymlinks.py',
399401
'feature_help.py',
400402
'feature_shutdown.py',

0 commit comments

Comments
 (0)