Beispiel #1
0
    def __init__(
        self,
        key_pair: KeyPair,
        peer_id: PeerID,
        peer_updater: PeerUpdater,
        status_provider: StatusProvider,
        finalized_root_provider: Callable[[Epoch], Root],
        block_provider_by_slot: BlockProviderBySlot,
        block_provider_by_root: BlockProviderByRoot,
        metadata_provider: MetadataProvider,
        fork_digest_provider: ForkDigestProvider,
        eth2_config: Eth2Config,
    ) -> None:
        peer_store = PeerStore()
        peer_store.add_key_pair(peer_id, key_pair)

        muxer_transports_by_protocol = {MPLEX_PROTOCOL_ID: Mplex}
        noise_key = ed25519.create_new_key_pair()
        security_transports_by_protocol = {
            TProtocol(secio.ID):
            secio.Transport(key_pair),
            TProtocol(noise.PROTOCOL_ID):
            noise.Transport(key_pair, noise_key.private_key)
        }
        upgrader = TransportUpgrader(security_transports_by_protocol,
                                     muxer_transports_by_protocol)

        transport = TCP()

        swarm = Swarm(peer_id, peer_store, upgrader, transport)
        BasicHost.__init__(self, swarm)

        self._peer_updater = peer_updater
        self._status_provider = status_provider
        self._finalized_root_provider_by_epoch = finalized_root_provider
        self._block_provider_by_slot = block_provider_by_slot
        self._block_provider_by_root = block_provider_by_root
        self._metadata_provider = metadata_provider

        self._request_responder = RequestResponder(
            self._peer_updater,
            self._status_provider,
            self._block_provider_by_slot,
            self._block_provider_by_root,
            self._metadata_provider,
        )
        self._install_req_resp_protocols()

        self._gossiper = Gossiper(fork_digest_provider, self)

        self._peers: Set[PeerID] = set()
Beispiel #2
0
    async def negotiate(
        self, communicator: IMultiselectCommunicator
    ) -> Tuple[TProtocol, StreamHandlerFn]:
        """
        Negotiate performs protocol selection
        :param stream: stream to negotiate on
        :return: selected protocol name, handler function
        :raise MultiselectError: raised when negotiation failed
        """
        await self.handshake(communicator)

        while True:
            try:
                command = await communicator.read()
            except MultiselectCommunicatorError as error:
                raise MultiselectError(error)

            if command == "ls":
                # TODO: handle ls command
                pass
            else:
                protocol = TProtocol(command)
                if protocol in self.handlers:
                    try:
                        await communicator.write(protocol)
                    except MultiselectCommunicatorError as error:
                        raise MultiselectError(error)

                    return protocol, self.handlers[protocol]
                try:
                    await communicator.write(PROTOCOL_NOT_FOUND_MSG)
                except MultiselectCommunicatorError as error:
                    raise MultiselectError(error)
Beispiel #3
0
    async def negotiate(
        self, communicator: IMultiselectCommunicator
    ) -> Tuple[TProtocol, StreamHandlerFn]:
        """
        Negotiate performs protocol selection
        :param stream: stream to negotiate on
        :return: selected protocol name, handler function
        :raise Exception: negotiation failed exception
        """

        # Perform handshake to ensure multiselect protocol IDs match
        await self.handshake(communicator)

        # Read and respond to commands until a valid protocol ID is sent
        while True:
            # Read message
            command = await communicator.read()

            # Command is ls or a protocol
            if command == "ls":
                # TODO: handle ls command
                pass
            else:
                protocol = TProtocol(command)
                if protocol in self.handlers:
                    # Tell counterparty we have decided on a protocol
                    await communicator.write(protocol)

                    # Return the decided on protocol
                    return protocol, self.handlers[protocol]
                # Tell counterparty this protocol was not found
                await communicator.write(PROTOCOL_NOT_FOUND_MSG)
Beispiel #4
0
async def perform_two_host_set_up(
    handler: StreamHandlerFn = echo_stream_handler
) -> Tuple[BasicHost, BasicHost]:
    transport_opt_list = [["/ip4/127.0.0.1/tcp/0"], ["/ip4/127.0.0.1/tcp/0"]]
    (node_a, node_b) = await set_up_nodes_by_transport_opt(transport_opt_list)

    node_b.set_stream_handler(TProtocol("/echo/1.0.0"), handler)

    # Associate the peer with local ip address (see default parameters of Libp2p())
    node_a.get_peerstore().add_addrs(node_b.get_id(), node_b.get_addrs(), 10)
    return node_a, node_b
Beispiel #5
0
def initialize_default_swarm(
    key_pair: KeyPair,
    id_opt: ID = None,
    transport_opt: Sequence[str] = None,
    muxer_opt: TMuxerOptions = None,
    sec_opt: TSecurityOptions = None,
    peerstore_opt: IPeerStore = None,
) -> Swarm:
    """
    initialize swarm when no swarm is passed in.

    :param id_opt: optional id for host
    :param transport_opt: optional choice of transport upgrade
    :param muxer_opt: optional choice of stream muxer
    :param sec_opt: optional choice of security upgrade
    :param peerstore_opt: optional peerstore
    :return: return a default swarm instance
    """

    if not id_opt:
        id_opt = generate_peer_id_from(key_pair)

    # TODO: Parse `transport_opt` to determine transport
    transport = TCP()

    muxer_transports_by_protocol = muxer_opt or {MPLEX_PROTOCOL_ID: Mplex}
    security_transports_by_protocol = sec_opt or {
        TProtocol(PLAINTEXT_PROTOCOL_ID): InsecureTransport(key_pair),
        TProtocol(secio.ID): secio.Transport(key_pair),
    }
    upgrader = TransportUpgrader(security_transports_by_protocol,
                                 muxer_transports_by_protocol)

    peerstore = peerstore_opt or PeerStore()
    # Store our key pair in peerstore
    peerstore.add_key_pair(id_opt, key_pair)

    # TODO: Initialize discovery if not presented
    return Swarm(id_opt, peerstore, upgrader, transport)
Beispiel #6
0
def new_swarm(
    key_pair: KeyPair = None,
    muxer_opt: TMuxerOptions = None,
    sec_opt: TSecurityOptions = None,
    peerstore_opt: IPeerStore = None,
) -> INetworkService:
    """
    Create a swarm instance based on the parameters.

    :param key_pair: optional choice of the ``KeyPair``
    :param muxer_opt: optional choice of stream muxer
    :param sec_opt: optional choice of security upgrade
    :param peerstore_opt: optional peerstore
    :return: return a default swarm instance
    """

    if key_pair is None:
        key_pair = generate_new_rsa_identity()

    id_opt = generate_peer_id_from(key_pair)

    # TODO: Parse `listen_addrs` to determine transport
    transport = TCP()

    muxer_transports_by_protocol = muxer_opt or {MPLEX_PROTOCOL_ID: Mplex}
    security_transports_by_protocol = sec_opt or {
        TProtocol(PLAINTEXT_PROTOCOL_ID): InsecureTransport(key_pair),
        TProtocol(secio.ID): secio.Transport(key_pair),
    }
    upgrader = TransportUpgrader(security_transports_by_protocol,
                                 muxer_transports_by_protocol)

    peerstore = peerstore_opt or PeerStore()
    # Store our key pair in peerstore
    peerstore.add_key_pair(id_opt, key_pair)

    return Swarm(id_opt, peerstore, upgrader, transport)
Beispiel #7
0
async def net_stream_pair_factory(
    is_secure: bool
) -> Tuple[INetStream, BasicHost, INetStream, BasicHost]:
    protocol_id = TProtocol("/example/id/1")

    stream_1: INetStream

    # Just a proxy, we only care about the stream
    def handler(stream: INetStream) -> None:
        nonlocal stream_1
        stream_1 = stream

    host_0, host_1 = await host_pair_factory(is_secure)
    host_1.set_stream_handler(protocol_id, handler)

    stream_0 = await host_0.new_stream(host_1.get_id(), [protocol_id])
    return stream_0, host_0, stream_1, host_1
Beispiel #8
0
async def net_stream_pair_factory(
    security_protocol: TProtocol = None,
    muxer_opt: TMuxerOptions = None
) -> AsyncIterator[Tuple[INetStream, INetStream]]:
    protocol_id = TProtocol("/example/id/1")

    stream_1: INetStream

    # Just a proxy, we only care about the stream.
    # Add a barrier to avoid stream being removed.
    event_handler_finished = trio.Event()

    async def handler(stream: INetStream) -> None:
        nonlocal stream_1
        stream_1 = stream
        await event_handler_finished.wait()

    async with host_pair_factory(security_protocol=security_protocol,
                                 muxer_opt=muxer_opt) as hosts:
        hosts[1].set_stream_handler(protocol_id, handler)

        stream_0 = await hosts[0].new_stream(hosts[1].get_id(), [protocol_id])
        yield stream_0, stream_1
        event_handler_finished.set()
Beispiel #9
0
import logging
import random
from typing import Coroutine, List

from libp2p.network.exceptions import SwarmException
from libp2p.network.notifee_interface import INotifee
from libp2p.network.stream.exceptions import StreamError
from libp2p.network.stream.net_stream_interface import INetStream
from libp2p.typing import TProtocol

from aleph import __version__
from aleph.network import incoming_check
from . import singleton
from .pubsub import sub

PROTOCOL_ID = TProtocol("/aleph/p2p/0.1.0")
MAX_READ_LEN = 2 ** 32 - 1

LOGGER = logging.getLogger('P2P.protocol')

STREAM_COUNT = 5

HELLO_PACKET = {
    'command': 'hello'
}

CONNECT_LOCK = asyncio.Lock()

class AlephProtocol(INotifee):
    def __init__(self, host, streams_per_host=5):
        self.host = host
Beispiel #10
0
from libp2p.network.connection.exceptions import RawConnError
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from libp2p.security.base_session import BaseSession
from libp2p.security.base_transport import BaseSecureTransport
from libp2p.security.exceptions import HandshakeFailure
from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.typing import TProtocol
from libp2p.utils import encode_fixedint_prefixed, read_fixedint_prefixed

from .pb import plaintext_pb2

# Reference: https://github.com/libp2p/go-libp2p-core/blob/master/sec/insecure/insecure.go


PLAINTEXT_PROTOCOL_ID = TProtocol("/plaintext/2.0.0")


class InsecureSession(BaseSession):
    def __init__(
        self,
        local_peer: ID,
        local_private_key: PrivateKey,
        conn: ReadWriteCloser,
        is_initiator: bool,
        peer_id: Optional[ID] = None,
    ) -> None:
        super().__init__(local_peer, local_private_key, is_initiator, peer_id)
        self.conn = conn

    async def write(self, data: bytes) -> int:
Beispiel #11
0
import argparse
import asyncio
import urllib.request

import multiaddr

from libp2p import new_node
from libp2p.crypto.secp256k1 import create_new_key_pair
from libp2p.network.stream.net_stream_interface import INetStream
from libp2p.peer.peerinfo import info_from_p2p_addr
from libp2p.typing import TProtocol

PROTOCOL_ID = TProtocol("/echo/1.0.0")


async def _echo_stream_handler(stream: INetStream) -> None:
    # Wait until EOF
    msg = await stream.read()
    await stream.write(msg)
    await stream.close()


async def run(port: int,
              destination: str,
              localhost: bool,
              seed: int = None) -> None:
    if localhost:
        ip = "127.0.0.1"
    else:
        ip = urllib.request.urlopen("https://v4.ident.me/").read().decode(
            "utf8")
Beispiel #12
0
from libp2p.security.base_transport import BaseSecureTransport
from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.typing import TProtocol

from .exceptions import (
    IncompatibleChoices,
    InconsistentNonce,
    InvalidSignatureOnExchange,
    PeerMismatchException,
    SecioException,
    SedesException,
    SelfEncryption,
)
from .pb.spipe_pb2 import Exchange, Propose

ID = TProtocol("/secio/1.0.0")

NONCE_SIZE = 16  # bytes

# NOTE: the following is only a subset of allowable parameters according to the
# `secio` specification.
DEFAULT_SUPPORTED_EXCHANGES = "P-256"
DEFAULT_SUPPORTED_CIPHERS = "AES-128"
DEFAULT_SUPPORTED_HASHES = "SHA256"


class SecureSession(BaseSession):
    buf: io.BytesIO
    low_watermark: int
    high_watermark: int
Beispiel #13
0
import asyncio
import logging

from libp2p.network.stream.exceptions import StreamEOF, StreamReset
from libp2p.network.stream.net_stream_interface import INetStream
from libp2p.peer.id import ID as PeerID
from libp2p.typing import TProtocol

ID = TProtocol("/ipfs/ping/1.0.0")
PING_LENGTH = 32
RESP_TIMEOUT = 60

logger = logging.getLogger("libp2p.host.ping")


async def _handle_ping(stream: INetStream, peer_id: PeerID) -> bool:
    """Return a boolean indicating if we expect more pings from the peer at
    ``peer_id``."""
    try:
        payload = await asyncio.wait_for(stream.read(PING_LENGTH),
                                         RESP_TIMEOUT)
    except asyncio.TimeoutError as error:
        logger.debug("Timed out waiting for ping from %s: %s", peer_id, error)
        raise
    except StreamEOF:
        logger.debug("Other side closed while waiting for ping from %s",
                     peer_id)
        return False
    except StreamReset as error:
        logger.debug("Other side reset while waiting for ping from %s: %s",
                     peer_id, error)
Beispiel #14
0
import asyncio
import logging
import random
from typing import Any, Dict, Iterable, List, Sequence, Set

from libp2p.peer.id import ID
from libp2p.pubsub import floodsub
from libp2p.typing import TProtocol
from libp2p.utils import encode_varint_prefixed

from .mcache import MessageCache
from .pb import rpc_pb2
from .pubsub import Pubsub
from .pubsub_router_interface import IPubsubRouter

PROTOCOL_ID = TProtocol("/meshsub/1.0.0")

logger = logging.getLogger("libp2p.pubsub.gossipsub")


class GossipSub(IPubsubRouter):

    protocols: List[TProtocol]
    pubsub: Pubsub

    degree: int
    degree_high: int
    degree_low: int

    time_to_live: int
Beispiel #15
0
import logging
from typing import Iterable, List, Sequence

from libp2p.peer.id import ID
from libp2p.typing import TProtocol
from libp2p.utils import encode_varint_prefixed

from .pb import rpc_pb2
from .pubsub import Pubsub
from .pubsub_router_interface import IPubsubRouter

PROTOCOL_ID = TProtocol("/floodsub/1.0.0")

logger = logging.getLogger("libp2p.pubsub.floodsub")


class FloodSub(IPubsubRouter):

    protocols: List[TProtocol]

    pubsub: Pubsub

    def __init__(self, protocols: Sequence[TProtocol]) -> None:
        self.protocols = list(protocols)
        self.pubsub = None

    def get_protocols(self) -> List[TProtocol]:
        """
        :return: the list of protocols supported by the router
        """
        return self.protocols
Beispiel #16
0
import logging

from multiaddr import Multiaddr

from libp2p.host.host_interface import IHost
from libp2p.network.stream.net_stream_interface import INetStream
from libp2p.typing import StreamHandlerFn, TProtocol

from .pb.identify_pb2 import Identify

ID = TProtocol("/ipfs/id/1.0.0")
PROTOCOL_VERSION = "ipfs/0.1.0"
# TODO dynamically generate the agent version
AGENT_VERSION = "py-libp2p/alpha"
logger = logging.getLogger("libp2p.identity.identify")


def _multiaddr_to_bytes(maddr: Multiaddr) -> bytes:
    return maddr.to_bytes()


def _mk_identify_protobuf(host: IHost) -> Identify:
    public_key = host.get_public_key()
    laddrs = host.get_addrs()
    protocols = host.get_mux().get_protocols()

    return Identify(
        protocol_version=PROTOCOL_VERSION,
        agent_version=AGENT_VERSION,
        public_key=public_key.serialize(),
        listen_addrs=map(_multiaddr_to_bytes, laddrs),
Beispiel #17
0
import argparse
import sys

import multiaddr
import trio

from libp2p import new_host
from libp2p.network.stream.net_stream_interface import INetStream
from libp2p.peer.peerinfo import info_from_p2p_addr
from libp2p.typing import TProtocol

PROTOCOL_ID = TProtocol("/chat/1.0.0")
MAX_READ_LEN = 2**32 - 1


async def read_data(stream: INetStream) -> None:
    while True:
        read_bytes = await stream.read(MAX_READ_LEN)
        if read_bytes is not None:
            read_string = read_bytes.decode()
            if read_string != "\n":
                # Green console colour: 	\x1b[32m
                # Reset console colour: 	\x1b[0m
                print("\x1b[32m %s\x1b[0m " % read_string, end="")


async def write_data(stream: INetStream) -> None:
    async_f = trio.wrap_file(sys.stdin)
    while True:
        line = await async_f.readline()
        await stream.write(line.encode())
Beispiel #18
0
from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.stream_muxer.abc import IMuxedConn, IMuxedStream
from libp2p.typing import TProtocol
from libp2p.utils import (
    decode_uvarint_from_stream,
    encode_uvarint,
    encode_varint_prefixed,
    read_varint_prefixed_bytes,
)

from .constants import HeaderTags
from .datastructures import StreamID
from .exceptions import MplexUnavailable
from .mplex_stream import MplexStream

MPLEX_PROTOCOL_ID = TProtocol("/mplex/6.7.0")


class Mplex(IMuxedConn):
    """
    reference: https://github.com/libp2p/go-mplex/blob/master/multiplex.go
    """

    secured_conn: ISecureConn
    peer_id: ID
    next_channel_id: int
    streams: Dict[StreamID, MplexStream]
    streams_lock: asyncio.Lock
    new_stream_queue: "asyncio.Queue[IMuxedStream]"
    event_shutting_down: asyncio.Event
    event_closed: asyncio.Event