async def rpc_random_walk( self, sender: Node, walk_initiator: Node, index: int, limit: int, link_type: LinkType, ) -> NodeAddr: random_node: Node self._add_sender_to_queue(sender) if index >= limit: return self._origin_node if link_type == LinkType.IN: random_node = random_choice_safe( self._link_store.get_in_links_copy(), self._origin_node ) else: random_node = random_choice_safe( self._link_store.get_out_links_copy(), self._origin_node ) if random_node in {self._origin_node, sender, tuple(walk_initiator)}: return self._origin_node result_node = await self.call_random_walk( random_node, index + 1, limit, link_type, walk_initiator ) return result_node
async def select(self) -> Node: try: random_node = random_choice_safe( self._link_store.get_in_links_copy()) if not random_node: random_node = self._links_queue.pop() return await self._protocol.call_random_walk( random_node, 0, defaults.DEFAULT_WALK_LENGTH, LinkType.IN) except (RPCError, IndexError): pass return None # todo: raise error?
async def rpc_give_me_in_node(self, sender: NodeAddr) -> None: self._add_sender_to_queue(sender) in_node_given = False while not in_node_given: try: random_in_node = random_choice_safe( self._link_store.get_in_links_copy(), self._origin_node ) if random_in_node not in {self._origin_node, sender}: await self.call_change_your_out_node(random_in_node, Node(*sender)) in_node_given = True except RPCError: pass
async def _add_in_links(self): for _ in range(self._num_links - len(self._link_store.get_in_links_copy())): try: random_node = random_choice_safe( self._link_store.get_out_links_copy()) if not random_node: random_node = self._links_queue.pop() node = await self._protocol.call_random_walk( random_node, 0, defaults.DEFAULT_WALK_LENGTH, LinkType.OUT) await self._protocol.call_give_me_in_node(node) except (RPCError, IndexError): pass
async def _init_links(self, bootstrap_nodes): for _ in range(self._num_links): random_bootstrap_addr = random_choice_safe(bootstrap_nodes) random_bootstrap = Node(*random_bootstrap_addr) try: neighbor = await self._protocol.call_random_walk( random_bootstrap, 0, defaults.DEFAULT_WALK_LENGTH, LinkType.IN) await self._protocol.call_give_me_in_node(neighbor) await self._protocol.call_im_your_in_node(neighbor) self._link_store.add_out_link(neighbor) bootstrap_nodes.append(neighbor) bootstrap_nodes = list(set(bootstrap_nodes)) except RPCError: pass