p2p_timeouts.py raw

   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