1 #!/usr/bin/env python3
2 # Copyright (c) 2016-present 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 """Test various net timeouts.
6 7 - Create three peers:
8 9 no_verack_node - we never send a verack in response to their version
10 no_version_node - we never send a version (only a ping)
11 no_send_node - we never send any P2P message.
12 13 - Wait 1 second
14 - Assert that we're connected
15 - Send a ping to no_verack_node and no_version_node
16 - Wait 1 second
17 - Assert that we're still connected
18 - Send a ping to no_verack_node and no_version_node
19 - Wait 2 seconds
20 - Assert that we're no longer connected (timeout to receive version/verack is 3 seconds)
21 """
22 23 from test_framework.messages import msg_ping
24 from test_framework.p2p import P2PInterface
25 from test_framework.test_framework import BitcoinTestFramework
26 27 import time
28 29 30 class TestP2PConn(P2PInterface):
31 def on_version(self, message):
32 # Don't send a verack in response
33 pass
34 35 36 class TimeoutsTest(BitcoinTestFramework):
37 def set_test_params(self):
38 self.setup_clean_chain = True
39 self.num_nodes = 1
40 # set timeout to receive version/verack to 3 seconds
41 self.extra_args = [["-peertimeout=3"]]
42 43 def mock_forward(self, delta):
44 self.mock_time += delta
45 self.nodes[0].setmocktime(self.mock_time)
46 47 def run_test(self):
48 self.mock_time = int(time.time())
49 self.mock_forward(0)
50 51 # Setup the p2p connections, making sure the connections are established before the mocktime is bumped
52 with self.nodes[0].assert_debug_log(['Added connection peer=0'], timeout=2):
53 no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn(), wait_for_verack=False)
54 with self.nodes[0].assert_debug_log(['Added connection peer=1'], timeout=2):
55 no_version_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False)
56 with self.nodes[0].assert_debug_log(['Added connection peer=2'], timeout=2):
57 no_send_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False)
58 59 # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the
60 # verack, since we never sent one
61 no_verack_node.wait_for_verack()
62 63 self.mock_forward(1)
64 65 assert no_verack_node.is_connected
66 assert no_version_node.is_connected
67 assert no_send_node.is_connected
68 69 with self.nodes[0].assert_debug_log(['Unsupported message "ping" prior to verack from peer=0'], timeout=2):
70 no_verack_node.send_without_ping(msg_ping())
71 72 with self.nodes[0].assert_debug_log(['non-version message before version handshake. Message "ping" from peer=1'], timeout=2):
73 no_version_node.send_without_ping(msg_ping())
74 75 self.mock_forward(1)
76 assert "version" in no_verack_node.last_message
77 78 assert no_verack_node.is_connected
79 assert no_version_node.is_connected
80 assert no_send_node.is_connected
81 82 no_verack_node.send_without_ping(msg_ping())
83 no_version_node.send_without_ping(msg_ping())
84 85 if self.options.v2transport:
86 expected_timeout_logs = [
87 "version handshake timeout, disconnecting peer=0",
88 "version handshake timeout, disconnecting peer=1",
89 "version handshake timeout, disconnecting peer=2",
90 ]
91 else:
92 expected_timeout_logs = [
93 "version handshake timeout, disconnecting peer=0",
94 "socket no message in first 3 seconds, never sent to peer, disconnecting peer=1",
95 "socket no message in first 3 seconds, never received from peer, never sent to peer, disconnecting peer=2",
96 ]
97 98 with self.nodes[0].assert_debug_log(expected_msgs=expected_timeout_logs):
99 self.mock_forward(2)
100 no_verack_node.wait_for_disconnect(timeout=1)
101 no_version_node.wait_for_disconnect(timeout=1)
102 no_send_node.wait_for_disconnect(timeout=1)
103 104 self.stop_nodes(0)
105 self.nodes[0].assert_start_raises_init_error(
106 expected_msg='Error: peertimeout must be a positive integer.',
107 extra_args=['-peertimeout=0'],
108 )
109 110 111 if __name__ == '__main__':
112 TimeoutsTest(__file__).main()
113