async def test_proxy_peer_requests(request, event_bus, other_event_bus, event_loop, chaindb_20, client_and_server): server_event_bus = event_bus client_event_bus = other_event_bus client_peer, server_peer = client_and_server client_peer_pool = MockPeerPoolWithConnectedPeers( [client_peer], event_bus=client_event_bus) server_peer_pool = MockPeerPoolWithConnectedPeers( [server_peer], event_bus=server_event_bus) async with AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(client_event_bus, client_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(server_event_bus, server_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( background_asyncio_service( ETHRequestServer(server_event_bus, TO_NETWORKING_BROADCAST_CONFIG, AsyncChainDB(chaindb_20.db)))) client_proxy_peer_pool = ETHProxyPeerPool( client_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(client_proxy_peer_pool)) proxy_peer_pool = ETHProxyPeerPool(server_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(proxy_peer_pool)) proxy_peer = await client_proxy_peer_pool.ensure_proxy_peer( client_peer.session) headers = await proxy_peer.eth_api.get_block_headers(0, 1, 0, False) assert len(headers) == 1 block_header = headers[0] assert block_header.block_number == 0 receipts = await proxy_peer.eth_api.get_receipts(headers) assert len(receipts) == 1 receipt = receipts[0] assert receipt[1][0] == block_header.receipt_root block_bundles = await proxy_peer.eth_api.get_block_bodies(headers) assert len(block_bundles) == 1 first_bundle = block_bundles[0] assert first_bundle[1][0] == block_header.transaction_root node_data = await proxy_peer.eth_api.get_node_data( (block_header.state_root, )) assert node_data[0][0] == block_header.state_root
async def test_proxy_peer_requests_with_timeouts(request, event_bus, other_event_bus, event_loop, client_and_server): server_event_bus = event_bus client_event_bus = other_event_bus client_peer, server_peer = client_and_server client_peer_pool = MockPeerPoolWithConnectedPeers( [client_peer], event_bus=client_event_bus) server_peer_pool = MockPeerPoolWithConnectedPeers( [server_peer], event_bus=server_event_bus) async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(client_event_bus, client_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(server_event_bus, server_peer_pool, handler_type=ETHPeerPoolEventServer)) # We just want an ETHRequestServer that doesn't answer us but we still have to run # *something* to at least subscribe to the events. Otherwise Lahja's safety check will yell # at us for sending requests into the void. for event_type in ETHRequestServer(None, None, None)._subscribed_events: server_event_bus.subscribe(event_type, lambda _: None) client_proxy_peer_pool = ETHProxyPeerPool( client_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(client_proxy_peer_pool)) server_proxy_peer_pool = ETHProxyPeerPool( server_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(server_proxy_peer_pool)) proxy_peer = await client_proxy_peer_pool.ensure_proxy_peer( client_peer.session) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_block_headers(0, 1, 0, False, timeout=0.01) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_receipts((), timeout=0.01) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_block_bodies((), timeout=0.01) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_node_data((), timeout=0.01)
async def test_requests_when_peer_in_client_vanishs(request, event_bus, other_event_bus, event_loop, chaindb_20, client_and_server): server_event_bus = event_bus client_event_bus = other_event_bus client_peer, server_peer = client_and_server client_peer_pool = MockPeerPoolWithConnectedPeers( [client_peer], event_bus=client_event_bus) server_peer_pool = MockPeerPoolWithConnectedPeers( [server_peer], event_bus=server_event_bus) async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(client_event_bus, client_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(server_event_bus, server_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( background_asyncio_service( ETHRequestServer(server_event_bus, TO_NETWORKING_BROADCAST_CONFIG, MainnetChain.vm_configuration, AsyncChainDB(chaindb_20.db)))) client_proxy_peer_pool = ETHProxyPeerPool( client_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(client_proxy_peer_pool)) server_proxy_peer_pool = ETHProxyPeerPool( server_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(server_proxy_peer_pool)) proxy_peer = await client_proxy_peer_pool.ensure_proxy_peer( client_peer.session) # We remove the peer from the client and assume to see PeerConnectionLost exceptions raised client_peer_pool.connected_nodes.pop(client_peer.session) with pytest.raises(PeerConnectionLost): await proxy_peer.eth_api.get_block_headers(0, 1, 0, False) with pytest.raises(PeerConnectionLost): await proxy_peer.eth_api.get_receipts(()) with pytest.raises(PeerConnectionLost): await proxy_peer.eth_api.get_block_bodies(()) with pytest.raises(PeerConnectionLost): await proxy_peer.eth_api.get_node_data(())
async def two_connected_tx_pools(event_bus, other_event_bus, event_loop, funded_address_private_key, chain_with_block_validation, tx_validator, client_and_server): alice_event_bus = event_bus bob_event_bus = other_event_bus bob, alice = client_and_server bob_peer_pool = MockPeerPoolWithConnectedPeers([bob], event_bus=bob_event_bus) alice_peer_pool = MockPeerPoolWithConnectedPeers([alice], event_bus=alice_event_bus) async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(bob_event_bus, bob_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(alice_event_bus, alice_peer_pool, handler_type=ETHPeerPoolEventServer)) bob_proxy_peer_pool = ETHProxyPeerPool(bob_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(bob_proxy_peer_pool)) alice_proxy_peer_pool = ETHProxyPeerPool( alice_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(alice_proxy_peer_pool)) alice_tx_pool = TxPool( alice_event_bus, alice_proxy_peer_pool, tx_validator, ) await stack.enter_async_context( background_asyncio_service(alice_tx_pool)) bob_tx_pool = TxPool( bob_event_bus, bob_proxy_peer_pool, tx_validator, ) await stack.enter_async_context(background_asyncio_service(bob_tx_pool) ) yield ( alice, alice_event_bus, alice_tx_pool, ), (bob, bob_event_bus, bob_tx_pool)
async def test_get_pooled_transactions_request(request, event_bus, other_event_bus, event_loop, chaindb_20, client_and_server): server_event_bus = event_bus client_event_bus = other_event_bus client_peer, server_peer = client_and_server if get_highest_eth_protocol_version(client_peer) < ETHProtocolV65.version: pytest.skip("Test not applicable below eth/65") client_peer_pool = MockPeerPoolWithConnectedPeers( [client_peer], event_bus=client_event_bus) server_peer_pool = MockPeerPoolWithConnectedPeers( [server_peer], event_bus=server_event_bus) async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(client_event_bus, client_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(server_event_bus, server_peer_pool, handler_type=ETHPeerPoolEventServer)) client_proxy_peer_pool = ETHProxyPeerPool( client_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(client_proxy_peer_pool)) proxy_peer_pool = ETHProxyPeerPool(server_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(proxy_peer_pool)) proxy_peer = await client_proxy_peer_pool.ensure_proxy_peer( client_peer.session) # The reason we run this test separately from the other request tests is because # GetPooledTransactions requests should be answered from the tx pool which the previous # test does not depend on. await stack.enter_async_context( background_asyncio_service( TxPool(server_event_bus, proxy_peer_pool, lambda _: True))) # The tx pool always answers these with an empty response txs = await proxy_peer.eth_api.get_pooled_transactions((decode_hex( '0x9ea39df6210064648ecbc465cd628fe52f69af53792e1c2f27840133435159d4' ), )) assert len(txs) == 0
async def test_proxy_peer_requests_with_timeouts(request, event_bus, other_event_bus, event_loop, client_and_server): server_event_bus = event_bus client_event_bus = other_event_bus client_peer, server_peer = client_and_server client_peer_pool = MockPeerPoolWithConnectedPeers( [client_peer], event_bus=client_event_bus) server_peer_pool = MockPeerPoolWithConnectedPeers( [server_peer], event_bus=server_event_bus) async with AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(client_event_bus, client_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(server_event_bus, server_peer_pool, handler_type=ETHPeerPoolEventServer)) client_proxy_peer_pool = ETHProxyPeerPool( client_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context(run_service(client_proxy_peer_pool)) server_proxy_peer_pool = ETHProxyPeerPool( server_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context(run_service(server_proxy_peer_pool)) proxy_peer = await client_proxy_peer_pool.ensure_proxy_peer( client_peer.session) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_block_headers(0, 1, 0, False, timeout=0.01) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_receipts((), timeout=0.01) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_block_bodies((), timeout=0.01) with pytest.raises(asyncio.TimeoutError): await proxy_peer.eth_api.get_node_data((), timeout=0.01)
def do_start(self) -> None: trinity_config = self.boot_info.trinity_config db = DBClient.connect(trinity_config.database_ipc_path) app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) if self.boot_info.trinity_config.network_id == MAINNET_NETWORK_ID: validator = DefaultTransactionValidator(chain, BYZANTIUM_MAINNET_BLOCK) elif self.boot_info.trinity_config.network_id == ROPSTEN_NETWORK_ID: validator = DefaultTransactionValidator(chain, BYZANTIUM_ROPSTEN_BLOCK) else: raise ValueError( "The TxPool component only supports MainnetChain or RopstenChain" ) proxy_peer_pool = ETHProxyPeerPool(self.event_bus, TO_NETWORKING_BROADCAST_CONFIG) self.tx_pool = TxPool(self.event_bus, proxy_peer_pool, validator) asyncio.ensure_future( exit_with_services(self.tx_pool, self._event_bus_service)) asyncio.ensure_future(self.tx_pool.run())
async def do_run(self, event_bus: EndpointAPI) -> None: proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with background_trio_service(proxy_peer_pool): service = NewBlockService(event_bus, proxy_peer_pool) async with background_trio_service(service) as manager: await manager.wait_finished()
def do_start(self) -> None: trinity_config = self.boot_info.trinity_config db_manager = create_db_consumer_manager( trinity_config.database_ipc_path) db = db_manager.get_db() # type: ignore app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) if self.boot_info.trinity_config.network_id == MAINNET_NETWORK_ID: validator = DefaultTransactionValidator(chain, BYZANTIUM_MAINNET_BLOCK) elif self.boot_info.trinity_config.network_id == ROPSTEN_NETWORK_ID: validator = DefaultTransactionValidator(chain, BYZANTIUM_ROPSTEN_BLOCK) else: # TODO: We could hint the user about e.g. a --tx-pool-no-validation flag to run the # tx pool without tx validation in this case raise ValueError( "The TxPool plugin only supports MainnetChain or RopstenChain") proxy_peer_pool = ETHProxyPeerPool(self.event_bus, TO_NETWORKING_BROADCAST_CONFIG) self.tx_pool = TxPool(self.event_bus, proxy_peer_pool, validator) asyncio.ensure_future(self.tx_pool.run())
async def do_run(cls, boot_info: BootInfo, event_bus: EndpointAPI) -> None: trinity_config = boot_info.trinity_config db = DBClient.connect(trinity_config.database_ipc_path) app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) if boot_info.trinity_config.network_id == MAINNET_NETWORK_ID: validator = DefaultTransactionValidator(chain, PETERSBURG_MAINNET_BLOCK) elif boot_info.trinity_config.network_id == ROPSTEN_NETWORK_ID: validator = DefaultTransactionValidator(chain, PETERSBURG_ROPSTEN_BLOCK) else: raise Exception("This code path should not be reachable") proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) tx_pool = TxPool(event_bus, proxy_peer_pool, validator) async with run_service(tx_pool): await tx_pool.cancellation()
async def do_run(cls, boot_info: BootInfo, event_bus: EndpointAPI) -> None: trinity_config = boot_info.trinity_config db = DBClient.connect(trinity_config.database_ipc_path) with db: app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) if boot_info.trinity_config.network_id == MAINNET_NETWORK_ID: validator = DefaultTransactionValidator( chain, ISTANBUL_MAINNET_BLOCK) elif boot_info.trinity_config.network_id == ROPSTEN_NETWORK_ID: validator = DefaultTransactionValidator( chain, ISTANBUL_ROPSTEN_BLOCK) elif boot_info.trinity_config.network_id == GOERLI_NETWORK_ID: validator = DefaultTransactionValidator( chain, ISTANBUL_GOERLI_BLOCK) else: raise Exception("This code path should not be reachable") proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with background_asyncio_service(proxy_peer_pool): tx_pool = TxPool(event_bus, proxy_peer_pool, validator) async with background_asyncio_service(tx_pool) as manager: await manager.wait_finished()
async def test_get_peers(event_bus, response, expected_count): do_mock = mock_request_response(GetConnectedPeersRequest, response, event_bus) async with do_mock: proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with run_service(proxy_peer_pool): peers = await proxy_peer_pool.get_peers() assert len(peers) == expected_count
async def do_run(self, event_bus: EndpointAPI) -> None: if self._boot_info.args.enable_metrics: metrics_service = metrics_service_from_args(self._boot_info.args) else: metrics_service = NOOP_METRICS_SERVICE proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with background_trio_service(proxy_peer_pool): async with background_trio_service(metrics_service): service = NewBlockService( event_bus, proxy_peer_pool, metrics_service.registry, self._boot_info) async with background_trio_service(service) as manager: await manager.wait_finished()
async def test_adds_new_peers(event_bus): do_mock = mock_request_response( GetConnectedPeersRequest, GetConnectedPeersResponseFactory.from_sessions((TEST_NODES[0],)), event_bus, ) async with do_mock: proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with run_service(proxy_peer_pool): assert len(await proxy_peer_pool.get_peers()) == 1 await event_bus.broadcast(PeerJoinedEvent(TEST_NODES[1])) # Give the peer a moment to pickup the peer await asyncio.sleep(0.01) assert len(await proxy_peer_pool.get_peers()) == 2
async def test_does_not_propagate_invalid_tx(event_bus, funded_address_private_key, chain_with_block_validation, tx_validator): chain = chain_with_block_validation initial_two_peers = TEST_NODES[:2] node_one = initial_two_peers[0] node_two = initial_two_peers[1] async with AsyncExitStack() as stack: await stack.enter_async_context( mock_request_response( GetConnectedPeersRequest, GetConnectedPeersResponse(initial_two_peers), event_bus, )) peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context(run_service(peer_pool)) tx_pool = TxPool(event_bus, peer_pool, tx_validator) await stack.enter_async_context(background_asyncio_service(tx_pool)) await asyncio.sleep(0.01) txs_broadcasted_by_peer1 = [ create_random_tx(chain, funded_address_private_key, is_valid=False), create_random_tx(chain, funded_address_private_key) ] outgoing_tx, got_txns = observe_outgoing_transactions(event_bus) # Peer1 sends some txs await event_bus.broadcast( TransactionsEvent(session=node_one, command=Transactions(txs_broadcasted_by_peer1))) await asyncio.wait_for(got_txns.wait(), timeout=0.1) # Check that Peer2 received only the second tx which is valid assert outgoing_tx == [ (node_two, (txs_broadcasted_by_peer1[1], )), ]
async def do_run(self, event_bus: EndpointAPI) -> None: boot_info = self._boot_info trinity_config = boot_info.trinity_config db = DBClient.connect(trinity_config.database_ipc_path) with db: app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) validator = DefaultTransactionValidator.from_network_id( chain, boot_info.trinity_config.network_id, ) proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with background_asyncio_service(proxy_peer_pool): tx_pool = TxPool(event_bus, proxy_peer_pool, validator) async with background_asyncio_service(tx_pool) as manager: await manager.wait_finished()
async def test_removes_peers(event_bus): do_mock = mock_request_response( GetConnectedPeersRequest, GetConnectedPeersResponseFactory.from_sessions(TEST_NODES[:2]), event_bus, ) async with do_mock: proxy_peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) async with run_service(proxy_peer_pool): assert len(await proxy_peer_pool.get_peers()) == 2 await event_bus.broadcast(PeerLeftEvent(TEST_NODES[0])) # Give the peer a moment to remove the peer await asyncio.sleep(0.01) peers = await proxy_peer_pool.get_peers() assert len(peers) == 1 assert peers[0].session == TEST_NODES[1]
async def test_proxy_peer_requests(request, event_bus, other_event_bus, event_loop, chaindb_20, client_and_server): server_event_bus = event_bus client_event_bus = other_event_bus client_peer, server_peer = client_and_server client_peer_pool = MockPeerPoolWithConnectedPeers( [client_peer], event_bus=client_event_bus) server_peer_pool = MockPeerPoolWithConnectedPeers( [server_peer], event_bus=server_event_bus) async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context( run_peer_pool_event_server(client_event_bus, client_peer_pool, handler_type=ETHPeerPoolEventServer)) await stack.enter_async_context( run_peer_pool_event_server(server_event_bus, server_peer_pool, handler_type=ETHPeerPoolEventServer)) base_db = chaindb_20.db await stack.enter_async_context( background_asyncio_service( ETHRequestServer( server_event_bus, TO_NETWORKING_BROADCAST_CONFIG, AsyncChainDB(base_db), ))) await stack.enter_async_context( background_asyncio_service( WitRequestServer( server_event_bus, TO_NETWORKING_BROADCAST_CONFIG, base_db, ))) client_proxy_peer_pool = ETHProxyPeerPool( client_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(client_proxy_peer_pool)) proxy_peer_pool = ETHProxyPeerPool(server_event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context( background_asyncio_service(proxy_peer_pool)) proxy_peer = await client_proxy_peer_pool.ensure_proxy_peer( client_peer.session) headers = await proxy_peer.eth_api.get_block_headers(0, 1, 0, False) assert len(headers) == 1 block_header = headers[0] assert block_header.block_number == 0 receipts = await proxy_peer.eth_api.get_receipts(headers) assert len(receipts) == 1 receipt = receipts[0] assert receipt[1][0] == block_header.receipt_root block_bundles = await proxy_peer.eth_api.get_block_bodies(headers) assert len(block_bundles) == 1 first_bundle = block_bundles[0] assert first_bundle[1][0] == block_header.transaction_root node_data = await proxy_peer.eth_api.get_node_data( (block_header.state_root, )) assert node_data[0][0] == block_header.state_root block_hash = block_header.hash node_hashes = tuple(Hash32Factory.create_batch(5)) # Populate the server's witness DB so that it can reply to our request. wit_db = AsyncWitnessDB(base_db) wit_db.persist_witness_hashes(block_hash, node_hashes) response = await proxy_peer.wit_api.get_block_witness_hashes(block_hash ) assert set(response) == set(node_hashes)
async def test_can_instantiate_proxy_pool(event_bus): ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG)
async def test_tx_propagation(event_bus, funded_address_private_key, chain_with_block_validation, tx_validator): initial_two_peers = TEST_NODES[:2] node_one = initial_two_peers[0] node_two = initial_two_peers[1] async with AsyncExitStack() as stack: await stack.enter_async_context(mock_request_response( GetConnectedPeersRequest, GetConnectedPeersResponseFactory.from_sessions(initial_two_peers), event_bus, )) peer_pool = ETHProxyPeerPool(event_bus, TO_NETWORKING_BROADCAST_CONFIG) await stack.enter_async_context(run_service(peer_pool)) tx_pool = TxPool(event_bus, peer_pool, tx_validator) await stack.enter_async_context(background_asyncio_service(tx_pool)) await asyncio.sleep(0.01) txs_broadcasted_by_peer1 = [ create_random_tx(chain_with_block_validation, funded_address_private_key) ] # this needs to go here to ensure that the subscription is *after* # the one installed by the transaction pool so that the got_txns # event will get set after the other handlers have been called. outgoing_tx, got_txns = observe_outgoing_transactions(event_bus) # Peer1 sends some txs await event_bus.broadcast( TransactionsEvent(session=node_one, command=Transactions(txs_broadcasted_by_peer1)) ) await asyncio.wait_for(got_txns.wait(), timeout=0.1) assert outgoing_tx == [ (node_two, tuple(txs_broadcasted_by_peer1)), ] # Clear the recording, we asserted all we want and would like to have a fresh start outgoing_tx.clear() # Peer1 sends same txs again await event_bus.broadcast( TransactionsEvent(session=node_one, command=Transactions(txs_broadcasted_by_peer1)) ) await asyncio.wait_for(got_txns.wait(), timeout=0.1) # Check that Peer2 doesn't receive them again assert len(outgoing_tx) == 0 # Peer2 sends exact same txs back await event_bus.broadcast( TransactionsEvent(session=node_two, command=Transactions(txs_broadcasted_by_peer1)) ) await asyncio.wait_for(got_txns.wait(), timeout=0.1) # Check that Peer1 won't get them as that is where they originally came from assert len(outgoing_tx) == 0 txs_broadcasted_by_peer2 = [ create_random_tx(chain_with_block_validation, funded_address_private_key), txs_broadcasted_by_peer1[0] ] # Peer2 sends old + new tx await event_bus.broadcast( TransactionsEvent(session=node_two, command=Transactions(txs_broadcasted_by_peer2)) ) await asyncio.wait_for(got_txns.wait(), timeout=0.1) # Not sure why this sleep is needed.... await asyncio.sleep(0.01) # Check that Peer1 receives only the one tx that it didn't know about assert outgoing_tx == [ (node_one, (txs_broadcasted_by_peer2[0],)), ]