async def test_find_node_neighbours(nursery, manually_driven_discovery_pair): alice, bob = manually_driven_discovery_pair # Add some nodes to bob's routing table so that it has something to use when replying to # alice's find_node. for _ in range(constants.KADEMLIA_BUCKET_SIZE * 2): bob.update_routing_table(NodeFactory()) # Collect all neighbours packets received by alice in a list for later inspection. received_neighbours = [] alice.recv_neighbours_v4 = lambda node, payload, hash_: received_neighbours.append((node, payload)) # noqa: E501 # Pretend that bob and alice have already bonded, otherwise bob will ignore alice's find_node. bob.update_routing_table(alice.this_node) alice.send_find_node_v4(bob.this_node, alice.this_node.id) with trio.fail_after(0.5): await bob.consume_datagram() # Alice needs to consume two datagrams here because we expect bob's response to be split # across two packets since a single one would be bigger than protocol's byte limit. await alice.consume_datagram() await alice.consume_datagram() # Bob should have sent two neighbours packets in order to keep the total packet size under the # 1280 bytes limit. assert len(received_neighbours) == 2 packet1, packet2 = received_neighbours neighbours = [] for packet in [packet1, packet2]: node, payload = packet assert node == bob.this_node neighbours.extend(discovery._extract_nodes_from_payload( node.address, payload[0], bob.logger)) assert len(neighbours) == constants.KADEMLIA_BUCKET_SIZE
def test_find_node_neighbours(): alice = get_discovery_protocol(b"alice") bob = get_discovery_protocol(b"bob") # Add some nodes to bob's routing table so that it has something to use when replying to # alice's find_node. for _ in range(kademlia.k_bucket_size * 2): bob.kademlia.update_routing_table(random_node()) # Connect alice's and bob's transports directly so we don't need to deal with the complexities # of going over the wire. link_transports(alice, bob) # Collect all neighbours packets received by alice in a list for later inspection. received_neighbours = [] alice.recv_neighbours = lambda node, payload, hash_: received_neighbours.append((node, payload)) # Pretend that bob and alice have already bonded, otherwise bob will ignore alice's find_node. bob.kademlia.update_routing_table(alice.this_node) alice.send_find_node(bob.this_node, alice.this_node.id) # Bob should have sent two neighbours packets in order to keep the total packet size under the # 1280 bytes limit. assert len(received_neighbours) == 2 packet1, packet2 = received_neighbours neighbours = [] for packet in [packet1, packet2]: node, payload = packet assert node == bob.this_node neighbours.extend(discovery._extract_nodes_from_payload(payload[0])) assert len(neighbours) == kademlia.k_bucket_size
def _test_find_node_neighbours(alice, bob): # Add some nodes to bob's routing table so that it has something to use when replying to # alice's find_node. for _ in range(constants.KADEMLIA_BUCKET_SIZE * 2): bob.update_routing_table(NodeFactory()) # Connect alice's and bob's transports directly so we don't need to deal with the complexities # of going over the wire. link_transports(alice, bob) # Collect all neighbours packets received by alice in a list for later inspection. received_neighbours = [] alice.recv_neighbours_v4 = lambda node, payload, hash_: received_neighbours.append( (node, payload)) # noqa: E501 # Pretend that bob and alice have already bonded, otherwise bob will ignore alice's find_node. bob.update_routing_table(alice.this_node) alice.send_find_node_v4(bob.this_node, alice.this_node.id) # Bob should have sent two neighbours packets in order to keep the total packet size under the # 1280 bytes limit. assert len(received_neighbours) == 2 packet1, packet2 = received_neighbours neighbours = [] for packet in [packet1, packet2]: node, payload = packet assert node == bob.this_node neighbours.extend( discovery._extract_nodes_from_payload(node.address, payload[0], bob.logger)) assert len(neighbours) == constants.KADEMLIA_BUCKET_SIZE
def _test_find_node_neighbours(use_v5): alice = get_discovery_protocol(b"alice") bob = get_discovery_protocol(b"bob") # Add some nodes to bob's routing table so that it has something to use when replying to # alice's find_node. for _ in range(kademlia.k_bucket_size * 2): bob.update_routing_table(random_node()) # Connect alice's and bob's transports directly so we don't need to deal with the complexities # of going over the wire. link_transports(alice, bob) # Collect all neighbours packets received by alice in a list for later inspection. received_neighbours = [] alice.recv_neighbours_v4 = lambda node, payload, hash_: received_neighbours.append( (node, payload)) # noqa: E501 # Pretend that bob and alice have already bonded, otherwise bob will ignore alice's find_node. bob.update_routing_table(alice.this_node) if use_v5: alice.send_find_node_v5(bob.this_node, alice.this_node.id) else: alice.send_find_node_v4(bob.this_node, alice.this_node.id) # Bob should have sent two neighbours packets in order to keep the total packet size under the # 1280 bytes limit. assert len(received_neighbours) == 2 packet1, packet2 = received_neighbours neighbours = [] for packet in [packet1, packet2]: node, payload = packet assert node == bob.this_node neighbours.extend(discovery._extract_nodes_from_payload(payload[0])) assert len(neighbours) == kademlia.k_bucket_size
async def test_find_node_neighbours(manually_driven_discovery_pair, monkeypatch): alice, bob = manually_driven_discovery_pair nodes_in_rt = 0 # Ensure we have plenty of nodes in our RT's buckets so that the NEIGHBOURS response sent by # bob is split into multiple messages. while nodes_in_rt < (constants.KADEMLIA_BUCKET_SIZE * 2): node = NodeFactory() eviction_candidate = bob.routing.update(node.id) if eviction_candidate is not None: continue nodes_in_rt += 1 bob.enr_db.set_enr(node.enr) # Collect all neighbours packets received by alice in a list for later inspection. received_neighbours = [] async def recv_neighbours(node, payload, hash_): received_neighbours.append((node, payload)) monkeypatch.setattr(alice, 'recv_neighbours_v4', recv_neighbours) # Pretend that bob and alice have already bonded, otherwise bob will ignore alice's find_node. bob._last_pong_at[alice.this_node.id] = int(time.monotonic()) await alice.send_find_node_v4(bob.this_node, alice.pubkey.to_bytes()) with trio.fail_after(1): await bob.consume_datagram() # Alice needs to consume two datagrams here because we expect bob's response to be split # across two packets since a single one would be bigger than protocol's byte limit. await alice.consume_datagram() await alice.consume_datagram() # Bob should have sent two neighbours packets in order to keep the total packet size # under the 1280 bytes limit. However, the two consume_datagram() calls above will have # spawned background tasks so we take a few short naps here to wait for them to complete. while len(received_neighbours) != 2: await trio.sleep(0.01) packet1, packet2 = received_neighbours neighbours = [] for packet in [packet1, packet2]: node, payload = packet assert node == bob.this_node neighbours.extend(_extract_nodes_from_payload( node.address, payload[0], bob.logger)) assert len(neighbours) == constants.KADEMLIA_BUCKET_SIZE
async def test_find_node_neighbours(nursery, manually_driven_discovery_pair): alice, bob = manually_driven_discovery_pair # Add some nodes to bob's routing table so that it has something to use when replying to # alice's find_node. for _ in range(constants.KADEMLIA_BUCKET_SIZE * 2): await bob.update_routing_table(NodeFactory()) # Collect all neighbours packets received by alice in a list for later inspection. received_neighbours = [] async def recv_neighbours(node, payload, hash_): received_neighbours.append((node, payload)) alice.recv_neighbours_v4 = recv_neighbours # Pretend that bob and alice have already bonded, otherwise bob will ignore alice's find_node. bob.node_db.set_last_pong_time(alice.this_node.id, int(time.monotonic())) alice.send_find_node_v4(bob.this_node, alice.pubkey.to_bytes()) with trio.fail_after(1): await bob.consume_datagram() # Alice needs to consume two datagrams here because we expect bob's response to be split # across two packets since a single one would be bigger than protocol's byte limit. await alice.consume_datagram() await alice.consume_datagram() # Bob should have sent two neighbours packets in order to keep the total packet size # under the 1280 bytes limit. However, the two consume_datagram() calls above will have # spawned background tasks so we take a few short naps here to wait for them to complete. while len(received_neighbours) != 2: await trio.sleep(0.01) packet1, packet2 = received_neighbours neighbours = [] for packet in [packet1, packet2]: node, payload = packet assert node == bob.this_node neighbours.extend( _extract_nodes_from_payload(node.address, payload[0], bob.logger)) assert len(neighbours) == constants.KADEMLIA_BUCKET_SIZE