diff --git a/test/functional/abc-p2p-compactblocks.py b/test/functional/abc-p2p-compactblocks.py --- a/test/functional/abc-p2p-compactblocks.py +++ b/test/functional/abc-p2p-compactblocks.py @@ -269,14 +269,39 @@ for i in range(100): out.append(get_spendable_output()) - # Check that compact block also work for big blocks + # There can be only one network thread running at a time. + # Adding a new P2P connection here will try to start the network thread + # at init, which will throw an assertion because it's already running. + # This requires a few steps to avoid this: + # 1/ Disconnect all the TestManager nodes + # 2/ Terminate the network thread + # 3/ Add the new P2P connection + # 4/ Reconnect all the TestManager nodes + # 5/ Restart the network thread + + # Disconnect all the TestManager nodes + [n.disconnect_node() for n in self.test.p2p_connections] + self.test.wait_for_disconnections() + self.test.clear_all_connections() + + # Wait for the network thread to terminate + network_thread_join() + + # Add the new connection node = self.nodes[0] - peer = TestNode() - peer.peer_connect('127.0.0.1', p2p_port(0)) + node.add_p2p_connection(TestNode()) + + # Reconnect TestManager nodes + self.test.add_all_connections(self.nodes) + + # Restart the network thread + network_thread_start() # Wait for connection to be etablished + peer = node.p2p peer.wait_for_verack() + # Check that compact block also work for big blocks # Wait for SENDCMPCT def received_sendcmpct(): return (peer.last_sendcmpct != None) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -38,10 +38,11 @@ CTransaction, CTxIn, CTxOut, + network_thread_join, + network_thread_start, P2PInterface, msg_block, - msg_headers, - network_thread_start) + msg_headers) from test_framework.script import (CScript, OP_TRUE) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal @@ -167,13 +168,22 @@ self.block_time += 1 height += 1 + # We're adding new connections so terminate the network thread + self.nodes[0].disconnect_p2ps() + network_thread_join() + # Start node1 and node2 with assumevalid so they accept a block with a bad signature. self.start_node(1, extra_args=["-assumevalid=" + hex(block102.sha256)]) - p2p1 = self.nodes[1].add_p2p_connection(BaseNode()) - p2p1.wait_for_verack() - self.start_node(2, extra_args=["-assumevalid=" + hex(block102.sha256)]) + + p2p0 = self.nodes[0].add_p2p_connection(BaseNode()) + p2p1 = self.nodes[1].add_p2p_connection(BaseNode()) p2p2 = self.nodes[2].add_p2p_connection(BaseNode()) + + network_thread_start() + + p2p0.wait_for_verack() + p2p1.wait_for_verack() p2p2.wait_for_verack() # send header lists to all three nodes diff --git a/test/functional/example_test.py b/test/functional/example_test.py --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -21,6 +21,7 @@ mininode_lock, msg_block, msg_getdata, + network_thread_join, network_thread_start, ) from test_framework.test_framework import BitcoinTestFramework @@ -135,7 +136,7 @@ def run_test(self): """Main test logic""" - # Create a P2P connection to one of the nodes + # Create P2P connections to two of the nodes self.nodes[0].add_p2p_connection(BaseNode()) # Start up network handling in another thread. This needs to be called @@ -195,7 +196,14 @@ connect_nodes(self.nodes[1], self.nodes[2]) self.log.info("Add P2P connection to node2") + # We can't add additional P2P connections once the network thread has started. Disconnect the connection + # to node0, wait for the network thread to terminate, then connect to node2. This is specific to + # the current implementation of the network thread and may be improved in future. + self.nodes[0].disconnect_p2ps() + network_thread_join() + self.nodes[2].add_p2p_connection(BaseNode()) + network_thread_start() self.nodes[2].p2p.wait_for_verack() self.log.info( diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p-acceptblock.py @@ -222,9 +222,13 @@ # The node should have requested the blocks at some point, so # disconnect/reconnect first self.nodes[0].disconnect_p2ps() - test_node = self.nodes[0].add_p2p_connection(P2PInterface()) + self.nodes[1].disconnect_p2ps() + network_thread_join() + test_node = self.nodes[0].add_p2p_connection(P2PInterface()) + network_thread_start() test_node.wait_for_verack() + test_node.send_message(msg_block(block_h1f)) test_node.sync_with_ping() diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p-leaktests.py @@ -148,8 +148,9 @@ self.nodes[0].disconnect_p2ps() - # Wait until all connections are closed + # Wait until all connections are closed and the network thread has terminated wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0) + network_thread_join() # Make sure no unexpected messages came in assert(no_version_bannode.unexpected_msg == False) diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -70,6 +70,10 @@ sub-classed and the on_message() callback overridden.""" def __init__(self): + # All P2PConnections must be created before starting the NetworkThread. + # assert that the network thread is not running. + assert not network_thread_running() + super().__init__(map=mininode_socket_map) def peer_connect(self, dstaddr, dstport, net="regtest"): @@ -457,6 +461,9 @@ def network_thread_start(): """Start the network thread.""" + # Only one network thread may run at a time + assert not network_thread_running() + NetworkThread().start()