3.0.ipv8.dht.community ====================== .. py:module:: 3.0.ipv8.dht.community Attributes ---------- .. autoapisummary:: 3.0.ipv8.dht.community.DHTValue 3.0.ipv8.dht.community.PING_INTERVAL 3.0.ipv8.dht.community.TOKEN_EXPIRATION_TIME 3.0.ipv8.dht.community.DHT_ENTRY_STR 3.0.ipv8.dht.community.DHT_ENTRY_STR_SIGNED 3.0.ipv8.dht.community.MAX_ENTRY_SIZE 3.0.ipv8.dht.community.MAX_ENTRY_AGE 3.0.ipv8.dht.community.MAX_CRAWL_NODES 3.0.ipv8.dht.community.MAX_CRAWL_REQUESTS 3.0.ipv8.dht.community.MAX_CRAWL_TASKS 3.0.ipv8.dht.community.MAX_VALUES_IN_STORE 3.0.ipv8.dht.community.MAX_VALUES_IN_FIND 3.0.ipv8.dht.community.MAX_NODES_IN_FIND 3.0.ipv8.dht.community.TARGET_NODES 3.0.ipv8.dht.community.FindResultType Classes ------- .. autoapisummary:: 3.0.ipv8.dht.community.Request 3.0.ipv8.dht.community.Crawl 3.0.ipv8.dht.community.DHTCommunity Functions --------- .. autoapisummary:: 3.0.ipv8.dht.community.gather_without_errors 3.0.ipv8.dht.community.merge_results Module Contents --------------- .. py:data:: DHTValue .. py:data:: PING_INTERVAL :value: 25 .. py:data:: TOKEN_EXPIRATION_TIME :value: 600 .. py:data:: DHT_ENTRY_STR :value: 0 .. py:data:: DHT_ENTRY_STR_SIGNED :value: 1 .. py:data:: MAX_ENTRY_SIZE :value: 170 .. py:data:: MAX_ENTRY_AGE :value: 3600 .. py:data:: MAX_CRAWL_NODES :value: 8 .. py:data:: MAX_CRAWL_REQUESTS :value: 24 .. py:data:: MAX_CRAWL_TASKS :value: 4 .. py:data:: MAX_VALUES_IN_STORE :value: 8 .. py:data:: MAX_VALUES_IN_FIND :value: 8 .. py:data:: MAX_NODES_IN_FIND :value: 8 .. py:data:: TARGET_NODES :value: 8 .. py:function:: gather_without_errors(*futures: asyncio.Future) -> list :async: Gather only the successful results from the given futures. .. py:data:: FindResultType .. py:function:: merge_results(results: tuple[list[FindResultType], Ellipsis]) -> tuple[FindResultType, Ellipsis] Merge the results from a tuple of lists into a flat tuple. .. py:class:: Request(community: DHTCommunity, msg_type: str, node: 3.0.ipv8.dht.routing.Node, params: list | None = None, consume_errors: bool = False, timeout: float = 5.0) Bases: :py:obj:`3.0.ipv8.requestcache.RandomNumberCache` This request cache keeps track of all outstanding requests within the DHTCommunity. .. py:attribute:: msg_type .. py:attribute:: node .. py:attribute:: params .. py:attribute:: future :type: asyncio.Future .. py:attribute:: start_time .. py:attribute:: consume_errors .. py:attribute:: timeout .. py:property:: timeout_delay :type: float The time in seconds after which this request is to be timed out. .. py:method:: on_timeout() -> None Cancel our completion future, if it's not already done. .. py:method:: on_complete() -> None Update our associated node's success metrics. .. py:class:: Crawl(target: bytes, routing_table: 3.0.ipv8.dht.routing.RoutingTable, force_nodes: bool = False, offset: int = 0) Class to manage crawls in the Community, in search of a specific target key. .. py:class:: TodoNode Node that still need to be contacted. .. py:attribute:: node_to_contact :type: 3.0.ipv8.dht.routing.Node .. py:attribute:: node_to_puncture :type: 3.0.ipv8.dht.routing.Node | None .. py:method:: __iter__() -> collections.abc.Iterator Make this dataclass iterable. .. py:attribute:: target .. py:attribute:: routing_table .. py:attribute:: nodes_todo :type: list[Crawl] .. py:attribute:: nodes_tried :type: set[3.0.ipv8.dht.routing.Node] .. py:attribute:: responses :type: list[tuple[3.0.ipv8.dht.routing.Node, dict[str, list[bytes] | list[3.0.ipv8.dht.routing.Node]]]] :value: [] .. py:attribute:: force_nodes .. py:attribute:: offset .. py:method:: add_response(sender: 3.0.ipv8.dht.routing.Node, response: dict[str, list[bytes] | list[3.0.ipv8.dht.routing.Node]]) -> None Register a response by the given node. .. py:property:: done :type: bool Check if we exhausted our tries or we have no nodes left to query. .. py:property:: cache_candidate :type: 3.0.ipv8.dht.routing.Node | None Return closest node to the target that did not respond with values. .. py:property:: values :type: list[bytes] Get the currently known values for our crawl. .. py:property:: nodes :type: list[3.0.ipv8.dht.routing.Node] Get the nodes we have already contacted to retrieve values. .. py:class:: DHTCommunity(settings: 3.0.ipv8.community.CommunitySettings) Bases: :py:obj:`3.0.ipv8.community.Community` Community for storing/finding key-value pairs. .. py:attribute:: community_id .. py:attribute:: network .. py:attribute:: storages :type: dict[type[3.0.ipv8.types.Address], 3.0.ipv8.dht.storage.Storage] .. py:attribute:: routing_tables :type: dict[type[3.0.ipv8.types.Address], 3.0.ipv8.dht.routing.RoutingTable] .. py:attribute:: request_cache .. py:attribute:: tokens :type: dict[bytes, tuple[float, bytes]] .. py:attribute:: token_secrets :type: collections.deque[bytes] .. py:method:: get_serializer() -> 3.0.ipv8.messaging.serialization.Serializer Extend our serializer with a node list packer. .. py:method:: get_available_strategies() -> dict[str, type[3.0.ipv8.peerdiscovery.discovery.DiscoveryStrategy]] Extend our available strategies with our maintenance strategy. .. py:method:: unload() -> None :async: Shut down our request cache and then unload the overlay. .. py:method:: get_address_class(node: 3.0.ipv8.types.Peer) -> type[3.0.ipv8.types.Address] Get the class of the given node's address. .. py:method:: get_routing_table(node: 3.0.ipv8.types.Peer) -> 3.0.ipv8.dht.routing.RoutingTable Get the routing table that the given node belongs to. .. py:method:: get_storage(node: 3.0.ipv8.dht.routing.Node) -> 3.0.ipv8.dht.storage.Storage Get or create a Storage object for the given node. .. py:method:: get_my_node_id(node: 3.0.ipv8.types.Peer) -> bytes Get our own node id to share with the given node. .. py:method:: get_requesting_node(peer: 3.0.ipv8.types.Peer) -> 3.0.ipv8.dht.routing.Node | None Add the given peer to the appropriate routing table and return it or None if it is already blocked. .. py:method:: introduction_request_callback(peer: 3.0.ipv8.types.Peer, dist: 3.0.ipv8.messaging.payload_headers.GlobalTimeDistributionPayload, payload: 3.0.ipv8.messaging.payload.IntroductionRequestPayload | 3.0.ipv8.messaging.payload.NewIntroductionRequestPayload) -> None Call our node discovery logic when an introduction request is received from it. .. py:method:: introduction_response_callback(peer: 3.0.ipv8.types.Peer, dist: 3.0.ipv8.messaging.payload_headers.GlobalTimeDistributionPayload, payload: 3.0.ipv8.messaging.payload.IntroductionResponsePayload | 3.0.ipv8.messaging.payload.NewIntroductionResponsePayload) -> None Call our node discovery logic when an introduction response is received from it. .. py:method:: on_node_discovered(public_key_bin: bytes, source_address: 3.0.ipv8.types.Address) -> None Handler for potentially new nodes. .. py:method:: ping(node: 3.0.ipv8.dht.routing.Node) -> asyncio.Future Send a ping to the given node. .. py:method:: on_ping_request(peer: 3.0.ipv8.types.Peer, payload: 3.0.ipv8.dht.payload.PingRequestPayload, data: bytes) -> None When we receive a ping request through a valid node, send a response. .. py:method:: on_ping_response(peer: 3.0.ipv8.types.Peer, payload: 3.0.ipv8.dht.payload.PingResponsePayload, data: bytes) -> None When receive a response to our ping, update the node's metrics. .. py:method:: serialize_value(data: bytes, sign: bool = True) -> bytes Serialize the given bytes. .. py:method:: unserialize_value(value: bytes) -> tuple[bytes, bytes | None, int] | None Unserialize data from the given serialized value. .. py:method:: add_value(key: bytes, value: bytes, storage: 3.0.ipv8.dht.storage.Storage, max_age: float = MAX_ENTRY_AGE) -> None Add a serialized value under the given key into a storage. .. py:method:: store_value(key: bytes, data: bytes, sign: bool = False) -> list[3.0.ipv8.dht.routing.Node] :async: Attempt to store a value at the given key and return the nodes that store it. .. py:method:: _store(key: bytes, value: bytes) -> list[3.0.ipv8.dht.routing.Node] :async: Attempt to store a serialized value at the given key and return the nodes that store it. .. py:method:: store_on_nodes(key: bytes, values: list[bytes], nodes: list[3.0.ipv8.dht.routing.Node]) -> list[3.0.ipv8.dht.routing.Node] :async: Store the given values under a given key on the given nodes. .. py:method:: on_store_request(peer: 3.0.ipv8.types.Peer, payload: 3.0.ipv8.dht.payload.StoreRequestPayload) -> None Store or forward the given requested value. .. py:method:: on_store_response(peer: 3.0.ipv8.types.Peer, payload: 3.0.ipv8.dht.payload.StoreResponsePayload) -> None We got confirmation of storage. .. py:method:: _send_find_request(node: 3.0.ipv8.dht.routing.Node, target: bytes, force_nodes: bool, offset: int = 0) -> asyncio.Future .. py:method:: _contact_node(crawl: Crawl, node: 3.0.ipv8.dht.routing.Node, puncture_node: 3.0.ipv8.dht.routing.Node) -> None :async: .. py:method:: _find(crawl: Crawl, debug: bool = False) -> list[3.0.ipv8.dht.routing.Node] | list[DHTValue] | tuple[list[DHTValue], Crawl] :async: .. py:method:: post_process_values(values: list[bytes]) -> list[DHTValue] Unpack signed and unsigned values and filter out duplicates. .. py:method:: find(target: bytes, force_nodes: bool, offset: int, debug: Literal[False]) -> tuple[DHTValue, Ellipsis] | tuple[3.0.ipv8.dht.routing.Node, Ellipsis] find(target: bytes, force_nodes: bool, offset: int, debug: Literal[True]) -> tuple[tuple[DHTValue, Ellipsis], list[Crawl]] find(target: bytes, force_nodes: bool, offset: int, debug: bool) -> tuple[DHTValue, Ellipsis] | tuple[3.0.ipv8.dht.routing.Node, Ellipsis] | tuple[tuple[DHTValue, Ellipsis], list[Crawl]] :async: Get the values belonging to the given target key. .. py:method:: find_values(target: bytes, offset: int = 0, debug: bool = False) -> tuple[DHTValue, Ellipsis] | tuple[3.0.ipv8.dht.routing.Node, Ellipsis] | tuple[tuple[DHTValue, Ellipsis], list[Crawl]] :async: Find the values belonging to the target key. .. py:method:: find_nodes(target: bytes, debug: bool = False) -> collections.abc.Sequence[3.0.ipv8.dht.routing.Node] :async: Find the values belonging to the target key. .. py:method:: on_find_request(peer: 3.0.ipv8.types.Peer, payload: 3.0.ipv8.dht.payload.FindRequestPayload) -> None Try to perform a search for the requested target. .. py:method:: on_find_response(peer: 3.0.ipv8.types.Peer, payload: 3.0.ipv8.dht.payload.FindResponsePayload) -> None We got a response for our find requests. .. py:method:: node_maintenance() -> None :async: Refresh old result values. .. py:method:: value_maintenance() -> None Remove expired values from the storage objects. .. py:method:: token_maintenance() -> None Make sure tokens are periodically refreshed. .. py:method:: generate_token(node: 3.0.ipv8.dht.routing.Node) -> bytes Generate a token for the given node. .. py:method:: check_token(node: 3.0.ipv8.dht.routing.Node, token: bytes) -> bool Check if the presented token is valid for the given node.