コード例 #1
0
def test_at_log_distance():
    for i in range(10000):
        node = NodeIDFactory()
        distance = random.randint(1, 256)
        other = at_log_distance(node, distance)
        actual = compute_log_distance(node, other)
        assert actual == distance
コード例 #2
0
async def test_network_explore(tester, alice):
    async with AsyncExitStack() as stack:
        networks = await stack.enter_async_context(
            tester.alexandria.network_group(8))

        # give the the network some time to interconnect.
        with trio.fail_after(20):
            for _ in range(1000):
                await trio.lowlevel.checkpoint()

        bootnodes = tuple(network.enr_manager.enr for network in networks)
        alice_network = await stack.enter_async_context(
            alice.alexandria.network(bootnodes=bootnodes))

        # give alice a little time to connect to the network as well
        with trio.fail_after(20):
            for _ in range(1000):
                await trio.lowlevel.checkpoint()

        assert len(set(alice_network.routing_table.iter_all_random())) == 8

        target_node_id = at_log_distance(alice.node_id, 256)
        node_ids_by_distance = tuple(
            sorted(
                tuple(network.local_node_id for network in networks),
                key=lambda node_id: compute_log_distance(
                    target_node_id, node_id),
            ))
        best_node_ids_by_distance = set(node_ids_by_distance[:3])

        async with alice_network.explore(target_node_id) as enr_aiter:
            with trio.fail_after(60):
                found_enrs = tuple([enr async for enr in enr_aiter])

        found_node_ids = tuple(enr.node_id for enr in found_enrs)
        assert len(found_node_ids) == len(networks) + 1

        # Ensure that one of the three closest node ids was in the returned node ids
        assert best_node_ids_by_distance.intersection(found_node_ids)
コード例 #3
0
ファイル: network.py プロジェクト: njgheorghita/ddht
    async def _manage_routing_table(self) -> None:
        # First load all the bootnode ENRs into our database
        for enr in self._bootnodes:
            try:
                self.enr_db.set_enr(enr)
            except OldSequenceNumber:
                pass

        # Now repeatedly try to bond with each bootnode until one succeeds.
        while self.manager.is_running:
            with trio.move_on_after(20):
                async with trio.open_nursery() as nursery:
                    for enr in self._bootnodes:
                        if enr.node_id == self.local_node_id:
                            continue
                        endpoint = Endpoint.from_enr(enr)
                        nursery.start_soon(self._bond, enr.node_id, endpoint)

                    await self._routing_table_ready.wait()
                    break

        # Now we enter into an infinite loop that continually probes the
        # network to beep the routing table fresh.  We both perform completely
        # random lookups, as well as targeted lookups on the outermost routing
        # table buckets which are not full.
        #
        # The `TokenBucket` allows us to burst at the beginning, making quick
        # successive probes, then slowing down once the
        #
        # TokenBucket starts with 10 tokens, refilling at 1 token every 30
        # seconds.
        token_bucket = TokenBucket(1 / 30, 10)

        async with trio.open_nursery() as nursery:
            while self.manager.is_running:
                await token_bucket.take()

                # Get the logarithmic distance to the "largest" buckets
                # that are not full.
                non_full_bucket_distances = tuple(
                    idx + 1
                    for idx, bucket in enumerate(self.routing_table.buckets)
                    if len(bucket) < self.routing_table.bucket_size  # noqa: E501
                )[-16:]

                # Probe one of the not-full-buckets with a weighted preference
                # towards the largest buckets.
                distance_to_probe = weighted_choice(non_full_bucket_distances)
                target_node_id = at_log_distance(self.local_node_id, distance_to_probe)

                async with self.recursive_find_nodes(target_node_id) as enr_aiter:
                    async for enr in enr_aiter:
                        if enr.node_id == self.local_node_id:
                            continue

                        try:
                            self.enr_db.set_enr(enr)
                        except OldSequenceNumber:
                            pass

                        nursery.start_soon(self._bond, enr.node_id)
コード例 #4
0
ファイル: crawler.py プロジェクト: njgheorghita/ddht
 def __init__(self, network: NetworkProtocol, concurrency: int = 32) -> None:
     target = at_log_distance(network.local_node_id, 256)
     self._explorer = CrawlerExplorer(network, target, concurrency)