async def test_request( message_dispatcher, remote_enr, remote_endpoint, incoming_message_channels, outgoing_message_channels, nursery, ): request_id = message_dispatcher.get_free_request_id(remote_enr.node_id) request = PingMessageFactory(request_id=request_id) response = PingMessageFactory(request_id=request_id) async def handle_request_on_remote(): outgoing_message = await outgoing_message_channels[1].receive() assert outgoing_message.message == request assert outgoing_message.receiver_endpoint == remote_endpoint assert outgoing_message.receiver_node_id == remote_enr.node_id await incoming_message_channels[0].send( IncomingMessage( message=response, sender_endpoint=remote_endpoint, sender_node_id=remote_enr.node_id, )) nursery.start_soon(handle_request_on_remote) received_response = await message_dispatcher.request( remote_enr.node_id, request) assert received_response.message == response assert received_response.sender_endpoint == remote_endpoint assert received_response.sender_node_id == remote_enr.node_id
async def test_packer_full_handshake(nursery, packer, remote_packer, enr, remote_enr, endpoint, remote_endpoint, outgoing_message_channels, remote_outgoing_message_channels, incoming_message_channels, remote_incoming_message_channels): # to remote outgoing_message = OutgoingMessage( message=PingMessageFactory(), receiver_endpoint=remote_endpoint, receiver_node_id=remote_enr.node_id, ) outgoing_message_channels[0].send_nowait(outgoing_message) with trio.fail_after(0.5): incoming_message = await remote_incoming_message_channels[1].receive() assert incoming_message.message == outgoing_message.message assert incoming_message.sender_endpoint == endpoint assert incoming_message.sender_node_id == enr.node_id # from remote outgoing_message = OutgoingMessage( message=PingMessageFactory(), receiver_endpoint=endpoint, receiver_node_id=enr.node_id, ) remote_outgoing_message_channels[0].send_nowait(outgoing_message) with trio.fail_after(0.5): incoming_message = await incoming_message_channels[1].receive() assert incoming_message.message == outgoing_message.message assert incoming_message.sender_endpoint == remote_endpoint assert incoming_message.sender_node_id == remote_enr.node_id
def test_successful_handshake(): initiator_private_key = PrivateKeyFactory().to_bytes() recipient_private_key = PrivateKeyFactory().to_bytes() initiator_enr = ENRFactory(private_key=initiator_private_key) recipient_enr = ENRFactory(private_key=recipient_private_key) initial_message = PingMessageFactory() initiator = HandshakeInitiatorFactory( local_private_key=initiator_private_key, local_enr=initiator_enr, remote_enr=recipient_enr, initial_message=initial_message, ) recipient = HandshakeRecipientFactory( local_private_key=recipient_private_key, local_enr=recipient_enr, remote_enr=initiator_enr, initiating_packet_auth_tag=initiator.first_packet_to_send.auth_tag) initiator_result = initiator.complete_handshake( recipient.first_packet_to_send) recipient_result = recipient.complete_handshake( initiator_result.auth_header_packet) assert_session_keys_equal(initiator_result.session_keys, recipient_result.session_keys) assert initiator_result.message is None assert initiator_result.enr is None assert initiator_result.auth_header_packet is not None assert recipient_result.message == initial_message assert recipient_result.enr is None assert recipient_result.auth_header_packet is None
async def test_ping_handler_requests_updated_enr(ping_handler, incoming_message_channels, outgoing_message_channels, local_enr, remote_enr, routing_table): ping = PingMessageFactory(enr_seq=remote_enr.sequence_number + 1) incoming_message = IncomingMessageFactory(message=ping) await incoming_message_channels[0].send(incoming_message) await wait_all_tasks_blocked() first_outgoing_message = outgoing_message_channels[1].receive_nowait() await wait_all_tasks_blocked() second_outgoing_message = outgoing_message_channels[1].receive_nowait() assert { first_outgoing_message.message.__class__, second_outgoing_message.message.__class__, } == {PongMessage, FindNodeMessage} outgoing_find_node = (first_outgoing_message if isinstance( first_outgoing_message.message, FindNodeMessage) else second_outgoing_message) assert outgoing_find_node.message.distance == 0 assert outgoing_find_node.receiver_endpoint == incoming_message.sender_endpoint assert outgoing_find_node.receiver_node_id == incoming_message.sender_node_id
async def test_ping_handler_sends_pong(ping_handler, incoming_message_channels, outgoing_message_channels, local_enr): ping = PingMessageFactory() incoming_message = IncomingMessageFactory(message=ping) await incoming_message_channels[0].send(incoming_message) await wait_all_tasks_blocked() outgoing_message = outgoing_message_channels[1].receive_nowait() assert isinstance(outgoing_message.message, PongMessage) assert outgoing_message.message.request_id == ping.request_id assert outgoing_message.message.enr_seq == local_enr.sequence_number assert outgoing_message.receiver_endpoint == incoming_message.sender_endpoint assert outgoing_message.receiver_node_id == incoming_message.sender_node_id
async def test_peer_packer_sends_auth_header( peer_packer, enr, remote_private_key, remote_enr, remote_endpoint, incoming_packet_channels, outgoing_packet_channels, outgoing_message_channels, nursery, ): outgoing_message = OutgoingMessage( PingMessageFactory(), remote_endpoint, peer_packer.remote_node_id, ) outgoing_message_channels[0].send_nowait(outgoing_message) with trio.fail_after(0.5): outgoing_auth_tag_packet = await outgoing_packet_channels[1].receive() handshake_recipient = HandshakeRecipientFactory( local_private_key=remote_private_key, local_enr=remote_enr, remote_private_key=peer_packer.local_private_key, remote_enr=enr, remote_node_id=peer_packer.local_node_id, initiating_packet_auth_tag=outgoing_auth_tag_packet.packet.auth_tag, ) incoming_packet = IncomingPacket( handshake_recipient.first_packet_to_send, sender_endpoint=remote_endpoint, ) incoming_packet_channels[0].send_nowait(incoming_packet) with trio.fail_after(0.5): outgoing_auth_header_packet = await outgoing_packet_channels[ 1].receive() assert peer_packer.is_post_handshake assert isinstance(outgoing_auth_header_packet.packet, AuthHeaderPacket) assert outgoing_auth_header_packet.receiver_endpoint == remote_endpoint handshake_result = handshake_recipient.complete_handshake( outgoing_auth_header_packet.packet, ) initiator_keys = peer_packer.session_keys recipient_keys = handshake_result.session_keys assert initiator_keys.auth_response_key == recipient_keys.auth_response_key assert initiator_keys.encryption_key == recipient_keys.decryption_key assert initiator_keys.decryption_key == recipient_keys.encryption_key
async def test_peer_packer_initiates_handshake(peer_packer, outgoing_message_channels, outgoing_packet_channels, nursery): outgoing_message = OutgoingMessage( PingMessageFactory(), EndpointFactory(), peer_packer.remote_node_id, ) outgoing_message_channels[0].send_nowait(outgoing_message) with trio.fail_after(0.5): outgoing_packet = await outgoing_packet_channels[1].receive() assert peer_packer.is_during_handshake assert outgoing_packet.receiver_endpoint == outgoing_message.receiver_endpoint assert isinstance(outgoing_packet.packet, AuthTagPacket)
async def test_request_handling(message_dispatcher, incoming_message_channels, remote_enr, remote_endpoint): ping_send_channel, ping_receive_channel = trio.open_memory_channel(0) async with message_dispatcher.add_request_handler( PingMessage) as request_subscription: incoming_message = IncomingMessage( message=PingMessageFactory(), sender_endpoint=remote_endpoint, sender_node_id=remote_enr.node_id, ) await incoming_message_channels[0].send(incoming_message) with trio.fail_after(1): handled_incoming_message = await request_subscription.receive() assert handled_incoming_message == incoming_message
async def test_ping_handler_updates_routing_table(ping_handler, incoming_message_channels, outgoing_message_channels, local_enr, remote_enr, routing_table): other_node_id = NodeIDFactory() routing_table.add(other_node_id) assert routing_table.get_oldest_entry() == remote_enr.node_id ping = PingMessageFactory() incoming_message = IncomingMessageFactory( message=ping, sender_node_id=remote_enr.node_id, ) await incoming_message_channels[0].send(incoming_message) await wait_all_tasks_blocked() assert routing_table.get_oldest_entry() == other_node_id
async def test_response_handling(message_dispatcher, remote_enr, incoming_message_channels): request_id = message_dispatcher.get_free_request_id(remote_enr.node_id) async with message_dispatcher.add_response_handler( remote_enr.node_id, request_id, ) as response_subscription: incoming_message = IncomingMessage( message=PingMessageFactory(request_id=request_id, ), sender_endpoint=remote_endpoint, sender_node_id=remote_enr.node_id, ) await incoming_message_channels[0].send(incoming_message) with trio.fail_after(1): handled_response = await response_subscription.receive() assert handled_response == incoming_message
async def test_packer_sends_packets(nursery, packer, remote_enr, remote_endpoint, outgoing_message_channels, outgoing_packet_channels): assert not packer.is_peer_packer_registered(remote_enr.node_id) # send message outgoing_message = OutgoingMessage( message=PingMessageFactory(), receiver_endpoint=remote_endpoint, receiver_node_id=remote_enr.node_id, ) outgoing_message_channels[0].send_nowait(outgoing_message) with trio.fail_after(0.5): outgoing_packet = await outgoing_packet_channels[1].receive() assert packer.is_peer_packer_registered(remote_enr.node_id) assert isinstance(outgoing_packet.packet, AuthTagPacket) assert outgoing_packet.receiver_endpoint == remote_endpoint
async def test_ping_handler_updates_routing_table(ping_handler_service, incoming_message_channels, outgoing_message_channels, local_enr, remote_enr, routing_table): distance = compute_log_distance(remote_enr.node_id, local_enr.node_id) other_node_id = NodeIDFactory.at_log_distance(local_enr.node_id, distance) routing_table.update(other_node_id) assert routing_table.get_nodes_at_log_distance(distance) == (other_node_id, remote_enr.node_id) ping = PingMessageFactory() incoming_message = IncomingMessageFactory( message=ping, sender_node_id=remote_enr.node_id, ) await incoming_message_channels[0].send(incoming_message) await wait_all_tasks_blocked() assert routing_table.get_nodes_at_log_distance(distance) == (remote_enr.node_id, other_node_id)