Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/mininode.py
Show First 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | class P2PConnection(asyncio.Protocol): | ||||
- deserializing and serializing the P2P message header | - deserializing and serializing the P2P message header | ||||
- logging messages as they are sent and received | - logging messages as they are sent and received | ||||
This class contains no logic for handing the P2P message payloads. It must be | This class contains no logic for handing the P2P message payloads. It must be | ||||
sub-classed and the on_message() callback overridden.""" | sub-classed and the on_message() callback overridden.""" | ||||
def __init__(self): | def __init__(self): | ||||
# The underlying transport of the connection. | # The underlying transport of the connection. | ||||
# Should only call methods on this from the NetworkThread, c.f. call_soon_threadsafe | # Should only call methods on this from the NetworkThread, c.f. | ||||
# call_soon_threadsafe | |||||
self._transport = None | self._transport = None | ||||
@property | @property | ||||
def is_connected(self): | def is_connected(self): | ||||
return self._transport is not None | return self._transport is not None | ||||
def peer_connect(self, dstaddr, dstport, net="regtest"): | def peer_connect(self, dstaddr, dstport, net="regtest"): | ||||
assert not self.is_connected | assert not self.is_connected | ||||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | def __init__(self): | ||||
self.last_message = {} | self.last_message = {} | ||||
# A count of the number of ping messages we've sent to the node | # A count of the number of ping messages we've sent to the node | ||||
self.ping_counter = 1 | self.ping_counter = 1 | ||||
# The network services received from the peer | # The network services received from the peer | ||||
self.nServices = 0 | self.nServices = 0 | ||||
def peer_connect(self, *args, services=NODE_NETWORK, send_version=True, **kwargs): | def peer_connect(self, *args, services=NODE_NETWORK, | ||||
send_version=True, **kwargs): | |||||
create_conn = super().peer_connect(*args, **kwargs) | create_conn = super().peer_connect(*args, **kwargs) | ||||
if send_version: | if send_version: | ||||
# Send a version msg | # Send a version msg | ||||
vt = msg_version() | vt = msg_version() | ||||
vt.nServices = services | vt.nServices = services | ||||
vt.addrTo.ip = self.dstaddr | vt.addrTo.ip = self.dstaddr | ||||
vt.addrTo.port = self.dstport | vt.addrTo.port = self.dstport | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | |||||
mininode_lock = threading.RLock() | mininode_lock = threading.RLock() | ||||
class NetworkThread(threading.Thread): | class NetworkThread(threading.Thread): | ||||
network_event_loop = None | network_event_loop = None | ||||
def __init__(self): | def __init__(self): | ||||
super().__init__(name="NetworkThread") | super().__init__(name="NetworkThread") | ||||
# There is only one event loop and no more than one thread must be created | # There is only one event loop and no more than one thread must be | ||||
# created | |||||
assert not self.network_event_loop | assert not self.network_event_loop | ||||
NetworkThread.network_event_loop = asyncio.new_event_loop() | NetworkThread.network_event_loop = asyncio.new_event_loop() | ||||
def run(self): | def run(self): | ||||
"""Start the network thread.""" | """Start the network thread.""" | ||||
self.network_event_loop.run_forever() | self.network_event_loop.run_forever() | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | def on_getheaders(self, message): | ||||
# Truncate the list if there are too many headers | # Truncate the list if there are too many headers | ||||
headers_list = headers_list[:-maxheaders - 1:-1] | headers_list = headers_list[:-maxheaders - 1:-1] | ||||
response = msg_headers(headers_list) | response = msg_headers(headers_list) | ||||
if response is not None: | if response is not None: | ||||
self.send_message(response) | self.send_message(response) | ||||
def send_blocks_and_test(self, blocks, node, *, success=True, request_block=True, reject_reason=None, expect_disconnect=False, timeout=60): | def send_blocks_and_test(self, blocks, node, *, success=True, request_block=True, | ||||
reject_reason=None, expect_disconnect=False, timeout=60): | |||||
"""Send blocks to test node and test whether the tip advances. | """Send blocks to test node and test whether the tip advances. | ||||
- add all blocks to our block_store | - add all blocks to our block_store | ||||
- send a headers message for the final block | - send a headers message for the final block | ||||
- the on_getheaders handler will ensure that any getheaders are responded to | - the on_getheaders handler will ensure that any getheaders are responded to | ||||
- if request_block is True: wait for getdata for each of the blocks. The on_getdata handler will | - if request_block is True: wait for getdata for each of the blocks. The on_getdata handler will | ||||
ensure that any getdata messages are responded to | ensure that any getdata messages are responded to | ||||
- if success is True: assert that the node's tip advances to the most recent block | - if success is True: assert that the node's tip advances to the most recent block | ||||
Show All 14 Lines | def send_blocks_and_test(self, blocks, node, *, success=True, request_block=True, | ||||
lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock) | lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock) | ||||
if expect_disconnect: | if expect_disconnect: | ||||
self.wait_for_disconnect() | self.wait_for_disconnect() | ||||
else: | else: | ||||
self.sync_with_ping() | self.sync_with_ping() | ||||
if success: | if success: | ||||
wait_until(lambda: node.getbestblockhash() == | wait_until(lambda: node.getbestblockhash() | ||||
blocks[-1].hash, timeout=timeout) | == blocks[-1].hash, timeout=timeout) | ||||
else: | else: | ||||
assert node.getbestblockhash() != blocks[-1].hash | assert node.getbestblockhash() != blocks[-1].hash | ||||
def send_txs_and_test(self, txs, node, *, success=True, expect_disconnect=False, reject_reason=None): | def send_txs_and_test(self, txs, node, *, success=True, | ||||
expect_disconnect=False, reject_reason=None): | |||||
"""Send txs to test node and test whether they're accepted to the mempool. | """Send txs to test node and test whether they're accepted to the mempool. | ||||
- add all txs to our tx_store | - add all txs to our tx_store | ||||
- send tx messages for all txs | - send tx messages for all txs | ||||
- if success is True/False: assert that the txs are/are not accepted to the mempool | - if success is True/False: assert that the txs are/are not accepted to the mempool | ||||
- if expect_disconnect is True: Skip the sync with ping | - if expect_disconnect is True: Skip the sync with ping | ||||
- if reject_reason is set: assert that the correct reject message is logged.""" | - if reject_reason is set: assert that the correct reject message is logged.""" | ||||
Show All 25 Lines |