Пример #1
0
    async def listen(self, maddr: Multiaddr, nursery: trio.Nursery) -> None:
        """
        put listener in listening mode and wait for incoming connections.

        :param maddr: maddr of peer
        :return: return True if successful
        """
        async def serve_tcp(
            handler: Callable[[trio.SocketStream], Awaitable[None]],
            port: int,
            host: str,
            task_status: TaskStatus[Sequence[trio.SocketListener]] = None,
        ) -> None:
            """Just a proxy function to add logging here."""
            logger.debug("serve_tcp %s %s", host, port)
            await trio.serve_tcp(handler,
                                 port,
                                 host=host,
                                 task_status=task_status)

        async def handler(stream: trio.SocketStream) -> None:
            tcp_stream = TrioTCPStream(stream)
            await self.handler(tcp_stream)

        listeners = await nursery.start(
            serve_tcp,
            handler,
            int(maddr.value_for_protocol("tcp")),
            maddr.value_for_protocol("ip4"),
        )
        self.listeners.extend(listeners)
Пример #2
0
async def make_p2pd_pair_unix(
    daemon_executable: str,
    enable_control: bool,
    enable_connmgr: bool,
    enable_dht: bool,
    enable_pubsub: bool,
) -> AsyncIterator[DaemonTuple]:
    name = str(uuid.uuid4())[:8]
    control_maddr = Multiaddr(f"/unix/tmp/test_p2pd_control_{name}.sock")
    listen_maddr = Multiaddr(f"/unix/tmp/test_p2pd_listen_{name}.sock")
    # Remove the existing unix socket files if they are existing
    try:
        os.unlink(control_maddr.value_for_protocol(protocols.P_UNIX))
    except FileNotFoundError:
        pass
    try:
        os.unlink(listen_maddr.value_for_protocol(protocols.P_UNIX))
    except FileNotFoundError:
        pass
    async with make_p2pd_pair(
            daemon_executable=daemon_executable,
            control_maddr=control_maddr,
            listen_maddr=listen_maddr,
            enable_control=enable_control,
            enable_connmgr=enable_connmgr,
            enable_dht=enable_dht,
            enable_pubsub=enable_pubsub,
    ) as pair:
        yield pair
Пример #3
0
 async def dial_peer_maddr(self, maddr: Multiaddr) -> None:
     """
     Parse `maddr`, get the ip:port and PeerID, and call `dial_peer` with the parameters.
     """
     ip = maddr.value_for_protocol(protocols.P_IP4)
     port = maddr.value_for_protocol(protocols.P_TCP)
     peer_id = ID.from_base58(maddr.value_for_protocol(protocols.P_P2P))
     await self.dial_peer(ip=ip, port=port, peer_id=peer_id)
Пример #4
0
    async def dial(self, maddr: Multiaddr) -> IRawConnection:
        """
        dial a transport to peer listening on multiaddr
        :param maddr: multiaddr of peer
        :return: `RawConnection` if successful
        """
        self.host = maddr.value_for_protocol("ip4")
        self.port = int(maddr.value_for_protocol("tcp"))

        reader, writer = await asyncio.open_connection(self.host, self.port)

        return RawConnection(reader, writer, True)
Пример #5
0
 async def dial_peer_maddr(self, maddr: Multiaddr) -> None:
     """
     Parse `maddr`, get the ip:port and PeerID, and call `dial_peer` with the parameters.
     """
     try:
         ip = maddr.value_for_protocol(protocols.P_IP4)
         port = maddr.value_for_protocol(protocols.P_TCP)
         peer_id = ID.from_base58(maddr.value_for_protocol(protocols.P_P2P))
         await self.dial_peer_with_retries(ip=ip, port=port, peer_id=peer_id)
     except Exception:
         traceback.print_exc()
         raise
Пример #6
0
def multiAddrTcp4(maddr):
    ipaddr, port = None, 0

    try:
        multi = Multiaddr(maddr)
    except BaseException:
        return ipaddr, port

    for proto in multi.protocols():
        if proto.name == 'ip4':
            ipaddr = multi.value_for_protocol(proto.code)
        if proto.name == 'tcp':
            port = int(multi.value_for_protocol(proto.code))

    return ipaddr, port
Пример #7
0
def multiAddrTcp4(maddr):
    ipaddr, port = None, 0

    try:
        multi = Multiaddr(maddr)
    except BaseException as err:
        log.debug(f'Invalid multiaddr {maddr}, error: {err}')
        return ipaddr, port

    for proto in multi.protocols():
        if proto.name == 'ip4':
            ipaddr = multi.value_for_protocol(proto.code)
        if proto.name == 'tcp':
            port = int(multi.value_for_protocol(proto.code))

    return ipaddr, port
Пример #8
0
    async def dial_peer_maddr_with_retries(self, maddr: Multiaddr) -> None:
        """
        Dial the peer with given multi-address repeatedly for `DIAL_RETRY_COUNT` times
        """
        try:
            p2p_id = maddr.value_for_protocol(protocols.P_P2P)
        except (BinaryParseError, ProtocolLookupError) as error:
            self.logger.debug("Invalid maddr: %s, error: %s", maddr, error)
            raise DialPeerError from error
        peer_id = ID.from_base58(p2p_id)

        for i in range(DIAL_RETRY_COUNT):
            try:
                # exponential backoff...
                await asyncio.sleep(2**i + random.random())
                await self.dial_peer_maddr(maddr, peer_id)
                return
            except DialPeerError:
                self.logger.debug(
                    "Could not dial peer: %s, maddr: %s retrying attempt %d of %d...",
                    peer_id,
                    maddr,
                    i,
                    DIAL_RETRY_COUNT,
                )
                continue
        raise DialPeerError
Пример #9
0
    async def dial(self, maddr: Multiaddr) -> IRawConnection:
        """
        dial a transport to peer listening on multiaddr
        :param maddr: multiaddr of peer
        :return: `RawConnection` if successful
        :raise OpenConnectionError: raised when failed to open connection
        """
        self.host = maddr.value_for_protocol("ip4")
        self.port = int(maddr.value_for_protocol("tcp"))

        try:
            reader, writer = await asyncio.open_connection(
                self.host, self.port)
        except (ConnectionAbortedError, ConnectionRefusedError) as error:
            raise OpenConnectionError(error)

        return RawConnection(reader, writer, True)
Пример #10
0
    async def dial(self, maddr: Multiaddr) -> IRawConnection:
        """
        dial a transport to peer listening on multiaddr.

        :param maddr: multiaddr of peer
        :return: `RawConnection` if successful
        :raise OpenConnectionError: raised when failed to open connection
        """
        self.host = maddr.value_for_protocol("ip4")
        self.port = int(maddr.value_for_protocol("tcp"))

        try:
            stream = await trio.open_tcp_stream(self.host, self.port)
        except OSError as error:
            raise OpenConnectionError from error
        read_write_closer = TrioTCPStream(stream)

        return RawConnection(read_write_closer, True)
Пример #11
0
async def make_p2pd_pair_unix(
        id_generator, enable_control, enable_connmgr, enable_dht, enable_pubsub):
    socket_id = id_generator()
    control_maddr = Multiaddr(f"/unix/tmp/test_p2pd_control_{socket_id}.sock")
    listen_maddr = Multiaddr(f"/unix/tmp/test_p2pd_listen_{socket_id}.sock")
    # remove the existing unix socket files if they are existing
    try:
        os.unlink(control_maddr.value_for_protocol(protocols.P_UNIX))
    except FileNotFoundError:
        pass
    try:
        os.unlink(listen_maddr.value_for_protocol(protocols.P_UNIX))
    except FileNotFoundError:
        pass
    return await _make_p2pd_pair(
        control_maddr=control_maddr,
        listen_maddr=listen_maddr,
        enable_control=enable_control,
        enable_connmgr=enable_connmgr,
        enable_dht=enable_dht,
        enable_pubsub=enable_pubsub,
    )
Пример #12
0
    async def listen(self, maddr: Multiaddr) -> bool:
        """
        put listener in listening mode and wait for incoming connections
        :param maddr: maddr of peer
        :return: return True if successful
        """
        self.server = await asyncio.start_server(
            self.handler,
            maddr.value_for_protocol("ip4"),
            maddr.value_for_protocol("tcp"),
        )
        socket = self.server.sockets[0]
        self.multiaddrs.append(_multiaddr_from_socket(socket))

        return True
Пример #13
0
 async def add_peer_from_maddr(self, maddr: Multiaddr) -> None:
     """
     Connect to the eth2 peer at ``maddr`` and incorporate them into
     our view of the network.
     """
     peer_id_encoded = maddr.value_for_protocol("p2p")
     peer_id = PeerID.from_base58(peer_id_encoded)
     try:
         await self.connect(PeerInfo(peer_id=peer_id, addrs=[maddr]))
         local_status = self._status_provider()
         remote_status = await self.exchange_status(peer_id, local_status)
         if self._peer_is_compatible(local_status, remote_status):
             self._peers.add(peer_id)
             await self._peer_updater(peer_id, remote_status)
         else:
             await self.disconnect(peer_id)
     except Exception as e:
         self.logger.exception(e)
Пример #14
0
    def __init__(
        self,
        local_node_key: PrivateKey,
        eth2_config: Eth2Config,
        clock: Clock,
        chain: BaseBeaconChain,
        validator_api_port: int,
        client_identifier: str,
        p2p_maddr: Multiaddr,
        preferred_nodes: Collection[Multiaddr],
        bootstrap_nodes: Collection[Multiaddr],
    ) -> None:
        self._local_key_pair = create_new_key_pair(local_node_key.to_bytes())
        self._eth2_config = eth2_config

        self._clock = clock
        self._chain = chain

        self._block_pool: Set[SignedBeaconBlock] = set()
        self._slashable_block_pool: Set[SignedBeaconBlock] = set()

        # FIXME: can we provide `p2p_maddr` as a default listening interface for `_mk_host`?
        peer_id = PeerID.from_pubkey(self._local_key_pair.public_key)
        if "p2p" in p2p_maddr:
            existing_peer_id = p2p_maddr.value_for_protocol("p2p")
            existing_p2p_maddr = Multiaddr(f"/p2p/{existing_peer_id}")
            self.logger.warning(
                "peer identity derived from local key pair %s overriding given identity %s",
                peer_id,
                existing_peer_id,
            )
            p2p_maddr = p2p_maddr.decapsulate(existing_p2p_maddr)
        self._p2p_maddr = p2p_maddr.encapsulate(Multiaddr(f"/p2p/{peer_id}"))

        # TODO: persist metadata and handle updates...
        self._metadata_provider = lambda: MetaData.create()
        self._peer_updater, self._peer_updates = trio.open_memory_channel[
            Tuple[PeerID, Any]](0)
        self._host = Host(
            self._local_key_pair,
            peer_id,
            self._accept_peer_updates,
            self._get_status,
            self._get_finalized_root_by_epoch,
            self._get_block_by_slot,
            self._get_block_by_root,
            self._metadata_provider,
            self._get_fork_digest,
            self._eth2_config,
        )
        self._preferred_nodes = preferred_nodes
        self._bootstrap_nodes = bootstrap_nodes

        self._sync_notifier, self._sync_requests = trio.open_memory_channel[
            SyncRequest](0)
        self._syncer = _mk_syncer()

        api_context = Context(
            client_identifier,
            eth2_config,
            self._syncer,
            self._chain,
            self._clock,
            _mk_block_broadcaster(self),
        )
        self.validator_api_port = validator_api_port
        self._validator_api_server = _mk_validator_api_server(
            self.validator_api_port, api_context)
Пример #15
0
def _derive_port(maddr: Multiaddr, orchestration_profile: str) -> Multiaddr:
    offset = ord(orchestration_profile[:1]) - ord("a")
    port = int(maddr.value_for_protocol("tcp")) + offset
    return Multiaddr.join(f"/ip4/{maddr.value_for_protocol('ip4')}",
                          f"/tcp/{port}")