Beispiel #1
0
async def test_advertisement_collector_validate_multiple_mismatched_hash_tree_roots(
    bob,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector

    advertisement_a = AdvertisementFactory(private_key=bob.private_key)
    advertisement_b = AdvertisementFactory(
        private_key=bob.private_key,
        content_key=advertisement_a.content_key,
    )
    advertisement_c = AdvertisementFactory(
        private_key=bob.private_key,
        content_key=advertisement_a.content_key,
    )

    assert advertisement_a.hash_tree_root != advertisement_b.hash_tree_root
    assert advertisement_b.hash_tree_root != advertisement_c.hash_tree_root

    advertisement_db = alice_alexandria_network.remote_advertisement_db

    advertisement_db.add(advertisement_a)
    advertisement_db.add(advertisement_b)

    with pytest.raises(NotImplementedError):
        await ad_collector.validate_advertisement(advertisement_c)
Beispiel #2
0
async def test_broadcast_log(alice, bob, conn):
    ad_a = AdvertisementFactory(private_key=alice.private_key)
    ad_b = AdvertisementFactory(private_key=alice.private_key)
    ad_c = AdvertisementFactory(private_key=alice.private_key)
    ad_d = AdvertisementFactory(private_key=bob.private_key)
    ad_e = AdvertisementFactory(private_key=bob.private_key)

    all_ads = (ad_a, ad_b, ad_c, ad_d, ad_e)

    broadcast_log = BroadcastLog(conn, max_records=8)

    # not logged when empty
    for ad in all_ads:
        assert not broadcast_log.was_logged(alice.node_id, ad)
        assert not broadcast_log.was_logged(bob.node_id, ad)

    broadcast_log.log(alice.node_id, ad_a)

    assert broadcast_log.was_logged(alice.node_id, ad_a)
    assert not broadcast_log.was_logged(bob.node_id, ad_a)

    # we insert 8 more, which should evict alice's entries for `ad_a`
    for ad in all_ads[1:]:
        broadcast_log.log(alice.node_id, ad)
        broadcast_log.log(bob.node_id, ad)

    assert not broadcast_log.was_logged(alice.node_id, ad_a)
Beispiel #3
0
def test_advertisement_to_and_from_sedes_payload():
    advertisement = AdvertisementFactory()

    sedes_payload = advertisement.to_sedes_payload()
    result = Advertisement.from_sedes_payload(sedes_payload)

    assert result == advertisement
Beispiel #4
0
async def test_alexandria_network_locate_multiple_responses(
        alice, bob, bob_network, bob_alexandria_client,
        alice_alexandria_network):
    advertisements = tuple(
        AdvertisementFactory(content_key=b"\x01test-key") for _ in range(20))
    num_messages = len(
        partition_advertisements(advertisements, MAX_PAYLOAD_SIZE))
    assert num_messages > 1

    async with bob_alexandria_client.subscribe(LocateMessage) as subscription:

        async def _respond():
            request = await subscription.receive()
            await bob_alexandria_client.send_locations(
                request.sender_node_id,
                request.sender_endpoint,
                advertisements=advertisements,
                request_id=request.request_id,
            )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            with trio.fail_after(1):
                locations = await alice_alexandria_network.locate(
                    bob.node_id,
                    content_key=b"\x01test-key",
                )
                assert locations == advertisements
Beispiel #5
0
async def test_alexandria_network_locate_single_response(
        alice, bob, bob_network, bob_alexandria_client,
        alice_alexandria_network):
    advertisement = AdvertisementFactory(private_key=alice.private_key)

    async with bob_alexandria_client.subscribe(LocateMessage) as subscription:

        async def _respond():
            request = await subscription.receive()
            await bob_alexandria_client.send_locations(
                request.sender_node_id,
                request.sender_endpoint,
                advertisements=(advertisement, ),
                request_id=request.request_id,
            )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            with trio.fail_after(1):
                locations = await alice_alexandria_network.locate(
                    bob.node_id,
                    content_key=advertisement.content_key,
                )
                assert len(locations) == 1
                location = locations[0]

                assert location == advertisement
Beispiel #6
0
async def test_alexandria_network_advertise_multiple_messages(
        alice, bob, bob_network, bob_alexandria_client,
        alice_alexandria_network):
    advertisements = tuple(
        AdvertisementFactory(private_key=alice.private_key) for _ in range(20))
    num_messages = len(
        partition_advertisements(advertisements, MAX_PAYLOAD_SIZE))

    async with bob_alexandria_client.subscribe(
            AdvertiseMessage) as subscription:

        async def _respond():
            for _ in range(num_messages):
                request = await subscription.receive()
                await bob_alexandria_client.send_ack(
                    request.sender_node_id,
                    request.sender_endpoint,
                    advertisement_radius=12345,
                    acked=(True, ) * len(request.message.payload),
                    request_id=request.request_id,
                )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            with trio.fail_after(1):
                ack_payload = await alice_alexandria_network.advertise(
                    bob.node_id,
                    advertisements=advertisements,
                )

            assert len(ack_payload.acked) == len(advertisements)
Beispiel #7
0
async def test_advertisement_collector_validate_remote_node_unreachable(
        bob, alice_alexandria_network, autojump_clock):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(private_key=bob.private_key)

    with pytest.raises(ValidationError, match="liveliness"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #8
0
async def test_advertisement_collector_handle_existing_valid_remote_advertisement(
    alice,
    bob,
    alice_alexandria_network,
    bob_alexandria_network,
    autojump_clock,
):
    content = ContentFactory(2048)
    proof = compute_proof(content, sedes=content_sedes)
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(
        private_key=bob.private_key,
        hash_tree_root=proof.get_hash_tree_root(),
    )
    bob_alexandria_network.commons_content_storage.set_content(
        advertisement.content_key,
        content,
    )

    alice_alexandria_network.remote_advertisement_db.add(advertisement)

    assert alice_alexandria_network.remote_advertisement_db.exists(
        advertisement)

    async with ad_collector.new_advertisement.subscribe() as subscription:
        with trio.fail_after(5):
            await ad_collector.handle_advertisement(advertisement)
        with pytest.raises(trio.TooSlowError):
            with trio.fail_after(5):
                await subscription.receive()

    assert alice_alexandria_network.remote_advertisement_db.exists(
        advertisement)
Beispiel #9
0
async def test_alexandria_client_locate_single_response(
        alice, bob, alice_alexandria_client, bob_alexandria_client):
    advertisements = (AdvertisementFactory(private_key=alice.private_key), )

    async with bob_alexandria_client.subscribe(LocateMessage) as subscription:

        async def _respond():
            request = await subscription.receive()
            await bob_alexandria_client.send_locations(
                request.sender_node_id,
                request.sender_endpoint,
                advertisements=advertisements,
                request_id=request.request_id,
            )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            responses = await alice_alexandria_client.locate(
                bob.node_id,
                bob.endpoint,
                content_key=advertisements[0].content_key,
                request_id=b"\x01",
            )
            assert len(responses) == 1
            response = responses[0]
            assert isinstance(response.message, LocationsMessage)
            assert response.message.payload.total == 1
            assert response.message.payload.locations == advertisements
            assert response.request_id == b"\x01"
Beispiel #10
0
async def test_advertisement_collector_acks_false_if_advertisements_already_known(
    alice,
    bob,
    alice_alexandria_client,
    bob_alexandria_network,
    autojump_clock,
):
    content = ContentFactory(2048)
    proof = compute_proof(content, sedes=content_sedes)
    advertisement = AdvertisementFactory(
        private_key=bob.private_key,
        hash_tree_root=proof.get_hash_tree_root(),
    )
    bob_alexandria_network.commons_content_storage.set_content(
        advertisement.content_key,
        content,
    )
    bob_alexandria_network.local_advertisement_db.add(advertisement)

    with pytest.raises(trio.TooSlowError):
        with trio.fail_after(10):
            async with bob_alexandria_network.advertisement_collector.new_advertisement.subscribe_and_wait(
            ):  # noqa: E501
                ack_message = await alice_alexandria_client.advertise(
                    bob.node_id,
                    bob.endpoint,
                    advertisements=(advertisement, ),
                )

    assert len(ack_message.payload.acked) == 1
    assert ack_message.payload.acked[0] is False
Beispiel #11
0
async def test_advertisement_collector_check_interest_outside_radius(
    alice,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement_db = alice_alexandria_network.remote_advertisement_db
    assert alice_alexandria_network.max_advertisement_count <= 32

    advertisements = tuple(
        sorted(
            (AdvertisementFactory()
             for _ in range(alice_alexandria_network.max_advertisement_count +
                            1)),
            key=lambda ad: compute_content_distance(ad.content_id, alice.
                                                    node_id),
        ))
    furthest = advertisements[-1]

    assert alice_alexandria_network.local_advertisement_radius == 2**256 - 1
    assert ad_collector.check_interest(furthest) is True

    for ad in advertisements[:alice_alexandria_network.
                             max_advertisement_count]:
        advertisement_db.add(ad)

    expected_radius = compute_content_distance(advertisements[-2].content_id,
                                               alice.node_id)
    assert expected_radius < 2**256 - 1

    assert alice_alexandria_network.local_advertisement_radius == expected_radius
    assert ad_collector.check_interest(furthest) is False
Beispiel #12
0
async def test_advertisement_collector_handle_new_valid_remote_advertisement(
    alice,
    bob,
    alice_alexandria_network,
    bob_alexandria_network,
):
    content = ContentFactory(2048)
    proof = compute_proof(content, sedes=content_sedes)
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(
        private_key=bob.private_key,
        hash_tree_root=proof.get_hash_tree_root(),
    )
    bob_alexandria_network.commons_content_storage.set_content(
        advertisement.content_key,
        content,
    )

    assert not alice_alexandria_network.remote_advertisement_db.exists(
        advertisement)

    with trio.fail_after(5):
        async with ad_collector.new_advertisement.subscribe_and_wait():
            await ad_collector.handle_advertisement(advertisement)

    assert alice_alexandria_network.remote_advertisement_db.exists(
        advertisement)
Beispiel #13
0
async def test_alexandria_network_advertise_wrong_ack_count(
        alice, bob, bob_network, bob_alexandria_client,
        alice_alexandria_network):
    advertisements = (AdvertisementFactory(private_key=alice.private_key), )

    async with bob_alexandria_client.subscribe(
            AdvertiseMessage) as subscription:

        async def _respond():
            request = await subscription.receive()
            await bob_alexandria_client.send_ack(
                request.sender_node_id,
                request.sender_endpoint,
                advertisement_radius=12345,
                acked=(True, False, True),  # wrong number
                request_id=request.request_id,
            )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            with pytest.raises(ValidationError):
                with trio.fail_after(2):
                    await alice_alexandria_network.advertise(
                        bob.node_id,
                        advertisements=advertisements,
                    )
Beispiel #14
0
async def test_remote_advertisement_manager_advertisement_radius(
    alice,
    alice_alexandria_network,
    autojump_clock,
):
    ad_manager = alice_alexandria_network.remote_advertisement_manager
    assert ad_manager.max_advertisement_count <= 32
    assert ad_manager.advertisement_radius == MAX_RADIUS

    advertisements = tuple(
        sorted(
            (AdvertisementFactory()
             for _ in range(alice_alexandria_network.max_advertisement_count +
                            1)),
            key=lambda ad: compute_content_distance(alice.node_id, ad.
                                                    content_id),
        ))
    for advertisement in advertisements:
        ad_manager.advertisement_db.add(advertisement)

    await ad_manager.purge_distant_ads()

    expected_radius = compute_content_distance(advertisements[-2].content_id,
                                               alice.node_id)
    assert expected_radius < MAX_RADIUS
    assert ad_manager.advertisement_radius == expected_radius
Beispiel #15
0
async def test_content_provider_serves_advertisements(
    alice,
    bob,
    alice_alexandria_network,
    bob_alexandria_client,
):
    content_key = b"test-content-key"
    advertisement_db = AdvertisementDatabase(sqlite3.connect(":memory:"))
    advertisements = tuple(
        AdvertisementFactory(content_key=content_key) for _ in range(5))
    for advertisement in advertisements:
        advertisement_db.add(advertisement)

    advertisement_provider = AdvertisementProvider(
        bob_alexandria_client,
        (advertisement_db, ),
    )
    async with background_trio_service(advertisement_provider):
        # this ensures that the subscription is in place.
        await advertisement_provider.ready()

        with trio.fail_after(2):
            result = await alice_alexandria_network.locate(
                bob.node_id,
                content_key=content_key,
            )
            assert set(result) == set(advertisements)
Beispiel #16
0
async def test_alexandria_client_advertise(alice, bob, bob_network,
                                           bob_alexandria_client,
                                           alice_alexandria_client):
    advertisements = (AdvertisementFactory(private_key=alice.private_key), )

    async with bob_network.dispatcher.subscribe(
            TalkRequestMessage) as subscription:

        async def _respond():
            request = await subscription.receive()
            await bob_alexandria_client.send_ack(
                request.sender_node_id,
                request.sender_endpoint,
                advertisement_radius=12345,
                acked=(True, ),
                request_id=request.request_id,
            )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            with trio.fail_after(1):
                ack_message = await alice_alexandria_client.advertise(
                    bob.node_id,
                    bob.endpoint,
                    advertisements=advertisements,
                )
                assert isinstance(ack_message, AckMessage)
                assert ack_message.payload.advertisement_radius == 12345
Beispiel #17
0
async def test_alexandria_network_advertise_multi_message(
        alice, bob, bob_network, bob_alexandria_client,
        alice_alexandria_network):
    advertisements = tuple(
        AdvertisementFactory(private_key=alice.private_key) for i in range(16))
    assert len(partition_advertisements(advertisements, MAX_PAYLOAD_SIZE)) > 1
    async with bob_alexandria_client.subscribe(
            AdvertiseMessage) as subscription:

        async def _respond():
            async for request in subscription:
                await bob_alexandria_client.send_ack(
                    request.sender_node_id,
                    request.sender_endpoint,
                    advertisement_radius=12345,
                    acked=(True, ) * len(request.message.payload),
                    request_id=request.request_id,
                )

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_respond)

            with trio.fail_after(2):
                ack_payload = await alice_alexandria_network.advertise(
                    bob.node_id,
                    advertisements=advertisements,
                )

            nursery.cancel_scope.cancel()

        assert isinstance(ack_payload, AckPayload)
        assert ack_payload.advertisement_radius == 12345
        assert ack_payload.acked == (True, ) * 16
Beispiel #18
0
async def test_advertisement_collector_validate_local_expired(
    alice,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory.expired(private_key=alice.private_key)

    with pytest.raises(ValidationError, match="expired"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #19
0
async def test_advertisement_collector_validate_already_in_remote_database(
    bob,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(private_key=bob.private_key)
    alice_alexandria_network.remote_advertisement_db.add(advertisement)

    with pytest.raises(ValidationError, match="known"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #20
0
async def test_advertisement_collector_validate_invalid_signature(
    alice_alexandria_network, ):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(
        signature_v=1,
        signature_r=1357924680,
        signature_s=2468013579,
    )

    with pytest.raises(ValidationError, match="signature"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #21
0
def test_advertisement_with_invalid_signature():
    ad = AdvertisementFactory.invalid()

    assert not ad.is_valid

    with pytest.raises(BadSignature):
        ad.node_id
    with pytest.raises(BadSignature):
        ad.public_key
    with pytest.raises(BadSignature):
        ad.verify()
Beispiel #22
0
async def test_advertisement_collector_validate_remote_fail_initial_proof_check(
    bob,
    alice_alexandria_network,
    bob_alexandria_network,
    autojump_clock,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(private_key=bob.private_key)

    with pytest.raises(ValidationError, match="proof retrieval"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #23
0
async def test_advertisement_collector_validate_local_content_not_found(
    alice,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(private_key=alice.private_key)

    content_storage = alice_alexandria_network.commons_content_storage
    assert not content_storage.has_content(advertisement.content_key)

    with pytest.raises(ValidationError, match="not found"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #24
0
async def test_advertisement_collector_validate_local_hash_tree_root_mismatch(
    alice,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(private_key=alice.private_key)

    content_storage = alice_alexandria_network.commons_content_storage
    content_storage.set_content(advertisement.content_key, ContentFactory())

    with pytest.raises(ValidationError, match="Mismatched roots"):
        await ad_collector.validate_advertisement(advertisement)
Beispiel #25
0
async def test_advertisement_collector_check_interest_already_in_remote_db(
    bob,
    alice_alexandria_network,
):
    ad_collector = alice_alexandria_network.advertisement_collector
    advertisement = AdvertisementFactory(private_key=bob.private_key)

    assert ad_collector.check_interest(advertisement) is True

    alice_alexandria_network.remote_advertisement_db.add(advertisement)

    assert ad_collector.check_interest(advertisement) is False
Beispiel #26
0
def test_advertise_message_encoded_size(content_keys):
    advertisements = tuple(
        AdvertisementFactory(content_key=content_key) for content_key in content_keys
    )
    ssz_payload = tuple(ad.to_sedes_payload() for ad in advertisements)
    encoded = ssz.encode(ssz_payload, sedes=AdvertiseSedes)

    num_advertisements = len(advertisements)

    assert len(encoded) == (
        num_advertisements * ADVERTISEMENT_FIXED_SIZE
        + sum(len(content_key) for content_key in content_keys)
    )
Beispiel #27
0
async def test_alexandria_client_advertise_timeout(
    alice,
    bob,
    alice_alexandria_client,
    autojump_clock,
):
    advertisements = (AdvertisementFactory(private_key=alice.private_key), )

    with pytest.raises(trio.TooSlowError):
        await alice_alexandria_client.advertise(
            bob.node_id,
            bob.endpoint,
            advertisements=advertisements,
        )
Beispiel #28
0
async def test_alexandria_client_advertise_too_many(
    alice,
    bob,
    alice_alexandria_client,
    bob_alexandria_client,
):
    advertisements = tuple(
        AdvertisementFactory(private_key=alice.private_key) for _ in range(32))

    with pytest.raises(Exception, match="Payload too large"):
        await alice_alexandria_client.advertise(
            bob.node_id,
            bob.endpoint,
            advertisements=advertisements,
        )
Beispiel #29
0
async def test_alexandria_network_advertise_invalid_signature(
        alice, bob, bob_network, bob_alexandria_client,
        alice_alexandria_network):
    advertisement = AdvertisementFactory(
        signature_v=1,
        signature_r=1357924680,
        signature_s=2468013579,
    )
    assert not advertisement.is_valid

    with pytest.raises(Exception, match="invalid"):
        await alice_alexandria_network.advertise(
            bob.node_id,
            advertisements=(advertisement, ),
        )
Beispiel #30
0
async def test_alexandria_client_send_advertisements(alice, bob, bob_network,
                                                     alice_alexandria_client):
    advertisements = (AdvertisementFactory(private_key=alice.private_key), )

    async with bob_network.dispatcher.subscribe(
            TalkRequestMessage) as subscription:
        await alice_alexandria_client.send_advertisements(
            bob.node_id,
            bob.endpoint,
            advertisements=advertisements,
        )
        with trio.fail_after(1):
            talk_response = await subscription.receive()
        message = decode_message(talk_response.message.payload)
        assert isinstance(message, AdvertiseMessage)
        assert message.payload == advertisements