Tribler / py-ipv8

Python implementation of Tribler's IPv8 p2p-networking layer
GNU Lesser General Public License v3.0
231 stars 46 forks source link

Add external bootstrap server inject script #946

Closed qstokkink closed 3 years ago

qstokkink commented 3 years ago

We can use bootstrap servers from external parties in our stack. We already have lazy resolution of DNS names, external mechanisms can use the exact same method.

Note that external bootstrap servers have different protocols, so these will have to be modularized.

Proposed design:

Possible hurdles:

The interface custom scripts should fill, would be the following:

class Bootstrapper(ABC):
    """
    A script to connect to external bootstrapping resources, using external hardware.

    When not to crash:
     - Loading this module file when missing dependencies.
     - Initializing a subclass when the service is unavailable (return ``False``).
     - Failing to retrieve peers for a service (return an empty iterable, e.g. ``[]``).

    When to crash:
     - Initializing this module subclass when missing dependencies.
    """

    @abstractmethod
    def initialize(self, overlay: Overlay) -> bool:
        """
        Start connecting to this bootstrapping service. Don't perform any network traffic in ``__init__``!

        :param overlay: the network overlay to initialize for.
        :returns: whether the initialization was successful.
        """
        pass

    @abstractmethod
    async def get_addresses(self, overlay: Overlay, timeout: float) -> Iterable[Address]:
        """
        Return some IPv8 addresses (if available) from this bootstrapping service.
        These addresses should be walkable (not blocked by a NAT or firewall).

        :param overlay: the network overlay to get peers for.
        :param timeout: the maximum time we wish to wait until we get any result (i.e. an empty list).
        :returns: the addresses for the given service_id.
        """
        pass

    @abstractmethod
    def keep_alive(self, overlay: Overlay) -> None:
        """
        Periodically called to keep this bootstrap connection alive.

        :param overlay: the network overlay to keep alive.
        """
        pass

    @abstractmethod
    def blacklist(self) -> Iterable[Address]:
        """
        Returns the blacklisted addresses for this Bootstrapper.
        """
        pass
qstokkink commented 3 years ago

We will be needing a body of scripts to communicate with external bootstrapping nodes using their respective protocols.

Delving into all available options and protocol specifications is a bit much to handle for a single person. Therefore, I invite anyone with a passing interest in this to create and contribute their scripts for their favorite external protocol 😃

If you want to take on one of the mechanisms, please post that here so we don't do double-work.

devos50 commented 3 years ago

Hmm, adding bootstrapping capabilities using IRC (specifically the freenode.net servers) would be interesting. I will consider implementing it if I find some time during the upcoming holiday 👍

Another hurdle is that these capabilities most likely require additional libraries/dependencies to be added. We probably want to have conditional imports here, and disable the bootstrap method if its dependencies cannot be imported.

qstokkink commented 3 years ago

Cool, thanks. I'll also add that hurdle in the O.P.

Since bootstrap methods have to be explicitly loaded from the configuration, I do think that crashing on a failed module load is appropriate though.

qstokkink commented 3 years ago

Once the basic infrastructure is available I'll look into hooking in Bittorrent DHT bootstrap nodes, perhaps to accompany the initial PR.