Merge pull request #406 from mhchia/feature/noise-patterxx
Noise: `PatternXX` and testing with go
This commit is contained in:
commit
9d68de8c21
|
@ -16,11 +16,11 @@ matrix:
|
|||
env: TOXENV=docs
|
||||
- python: 3.7
|
||||
dist: xenial
|
||||
env: TOXENV=py37-interop
|
||||
env: TOXENV=py37-interop GOBINPKG=go1.13.8.linux-amd64.tar.gz
|
||||
sudo: true
|
||||
before_install:
|
||||
- wget https://dl.google.com/go/go1.12.6.linux-amd64.tar.gz
|
||||
- sudo tar -C /usr/local -xzf go1.12.6.linux-amd64.tar.gz
|
||||
- wget https://dl.google.com/go/$GOBINPKG
|
||||
- sudo tar -C /usr/local -xzf $GOBINPKG
|
||||
- export GOPATH=$HOME/go
|
||||
- export GOROOT=/usr/local/go
|
||||
- export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
|
||||
|
|
|
@ -11,10 +11,26 @@ Subpackages
|
|||
Submodules
|
||||
----------
|
||||
|
||||
libp2p.security.noise.connection module
|
||||
libp2p.security.noise.exceptions module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: libp2p.security.noise.connection
|
||||
.. automodule:: libp2p.security.noise.exceptions
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
libp2p.security.noise.io module
|
||||
-------------------------------
|
||||
|
||||
.. automodule:: libp2p.security.noise.io
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
libp2p.security.noise.messages module
|
||||
-------------------------------------
|
||||
|
||||
.. automodule:: libp2p.security.noise.messages
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
|
@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
|
|||
|
||||
|
||||
class Closer(ABC):
|
||||
@abstractmethod
|
||||
async def close(self) -> None:
|
||||
...
|
||||
|
||||
|
@ -32,3 +33,33 @@ class ReadWriter(Reader, Writer):
|
|||
|
||||
class ReadWriteCloser(Reader, Writer, Closer):
|
||||
pass
|
||||
|
||||
|
||||
class MsgReader(ABC):
|
||||
@abstractmethod
|
||||
async def read_msg(self) -> bytes:
|
||||
...
|
||||
|
||||
|
||||
class MsgWriter(ABC):
|
||||
@abstractmethod
|
||||
async def write_msg(self, msg: bytes) -> None:
|
||||
...
|
||||
|
||||
|
||||
class MsgReadWriteCloser(MsgReader, MsgWriter, Closer):
|
||||
pass
|
||||
|
||||
|
||||
class Encrypter(ABC):
|
||||
@abstractmethod
|
||||
def encrypt(self, data: bytes) -> bytes:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def decrypt(self, data: bytes) -> bytes:
|
||||
...
|
||||
|
||||
|
||||
class EncryptedMsgReadWriter(MsgReadWriteCloser, Encrypter):
|
||||
"""Read/write message with encryption/decryption."""
|
||||
|
|
|
@ -23,3 +23,7 @@ class MissingMessageException(MsgioException):
|
|||
|
||||
class DecryptionFailedException(MsgioException):
|
||||
pass
|
||||
|
||||
|
||||
class MessageTooLarge(MsgioException):
|
||||
pass
|
||||
|
|
|
@ -5,79 +5,85 @@ from that repo: "a simple package to r/w length-delimited slices."
|
|||
|
||||
NOTE: currently missing the capability to indicate lengths by "varint" method.
|
||||
"""
|
||||
# TODO unify w/ https://github.com/libp2p/py-libp2p/blob/1aed52856f56a4b791696bbcbac31b5f9c2e88c9/libp2p/utils.py#L85-L99 # noqa: E501
|
||||
from typing import Optional, cast
|
||||
from abc import abstractmethod
|
||||
|
||||
from libp2p.io.abc import Closer, ReadCloser, Reader, ReadWriteCloser, WriteCloser
|
||||
from libp2p.io.abc import MsgReadWriteCloser, Reader, ReadWriteCloser
|
||||
from libp2p.io.utils import read_exactly
|
||||
from libp2p.utils import decode_uvarint_from_stream, encode_varint_prefixed
|
||||
|
||||
from .exceptions import MessageTooLarge
|
||||
|
||||
SIZE_LEN_BYTES = 4
|
||||
BYTE_ORDER = "big"
|
||||
|
||||
|
||||
async def read_length(reader: Reader) -> int:
|
||||
length_bytes = await read_exactly(reader, SIZE_LEN_BYTES)
|
||||
async def read_length(reader: Reader, size_len_bytes: int) -> int:
|
||||
length_bytes = await read_exactly(reader, size_len_bytes)
|
||||
return int.from_bytes(length_bytes, byteorder=BYTE_ORDER)
|
||||
|
||||
|
||||
def encode_msg_with_length(msg_bytes: bytes) -> bytes:
|
||||
len_prefix = len(msg_bytes).to_bytes(SIZE_LEN_BYTES, "big")
|
||||
def encode_msg_with_length(msg_bytes: bytes, size_len_bytes: int) -> bytes:
|
||||
try:
|
||||
len_prefix = len(msg_bytes).to_bytes(size_len_bytes, byteorder=BYTE_ORDER)
|
||||
except OverflowError:
|
||||
raise ValueError(
|
||||
"msg_bytes is too large for `size_len_bytes` bytes length: "
|
||||
f"msg_bytes={msg_bytes!r}, size_len_bytes={size_len_bytes}"
|
||||
)
|
||||
return len_prefix + msg_bytes
|
||||
|
||||
|
||||
class MsgIOWriter(WriteCloser):
|
||||
write_closer: WriteCloser
|
||||
class BaseMsgReadWriter(MsgReadWriteCloser):
|
||||
read_write_closer: ReadWriteCloser
|
||||
size_len_bytes: int
|
||||
|
||||
def __init__(self, write_closer: WriteCloser) -> None:
|
||||
self.write_closer = write_closer
|
||||
|
||||
async def write(self, data: bytes) -> None:
|
||||
await self.write_msg(data)
|
||||
|
||||
async def write_msg(self, msg: bytes) -> None:
|
||||
data = encode_msg_with_length(msg)
|
||||
await self.write_closer.write(data)
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.write_closer.close()
|
||||
|
||||
|
||||
class MsgIOReader(ReadCloser):
|
||||
read_closer: ReadCloser
|
||||
next_length: Optional[int]
|
||||
|
||||
def __init__(self, read_closer: ReadCloser) -> None:
|
||||
# NOTE: the following line is required to satisfy the
|
||||
# multiple inheritance but `mypy` does not like it...
|
||||
super().__init__(read_closer) # type: ignore
|
||||
self.read_closer = read_closer
|
||||
self.next_length = None
|
||||
|
||||
async def read(self, n: int = None) -> bytes:
|
||||
return await self.read_msg()
|
||||
def __init__(self, read_write_closer: ReadWriteCloser) -> None:
|
||||
self.read_write_closer = read_write_closer
|
||||
|
||||
async def read_msg(self) -> bytes:
|
||||
length = await self.next_msg_len()
|
||||
return await read_exactly(self.read_write_closer, length)
|
||||
|
||||
data = await read_exactly(self.read_closer, length)
|
||||
if len(data) < length:
|
||||
self.next_length = length - len(data)
|
||||
else:
|
||||
self.next_length = None
|
||||
return data
|
||||
@abstractmethod
|
||||
async def next_msg_len(self) -> int:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def encode_msg(self, msg: bytes) -> bytes:
|
||||
...
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.read_write_closer.close()
|
||||
|
||||
async def write_msg(self, msg: bytes) -> None:
|
||||
encoded_msg = self.encode_msg(msg)
|
||||
await self.read_write_closer.write(encoded_msg)
|
||||
|
||||
|
||||
class FixedSizeLenMsgReadWriter(BaseMsgReadWriter):
|
||||
size_len_bytes: int
|
||||
|
||||
async def next_msg_len(self) -> int:
|
||||
if self.next_length is None:
|
||||
self.next_length = await read_length(self.read_closer)
|
||||
return self.next_length
|
||||
return await read_length(self.read_write_closer, self.size_len_bytes)
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.read_closer.close()
|
||||
def encode_msg(self, msg: bytes) -> bytes:
|
||||
return encode_msg_with_length(msg, self.size_len_bytes)
|
||||
|
||||
|
||||
class MsgIOReadWriter(MsgIOReader, MsgIOWriter, Closer):
|
||||
def __init__(self, read_write_closer: ReadWriteCloser) -> None:
|
||||
super().__init__(cast(ReadCloser, read_write_closer))
|
||||
class VarIntLengthMsgReadWriter(BaseMsgReadWriter):
|
||||
max_msg_size: int
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.read_closer.close()
|
||||
async def next_msg_len(self) -> int:
|
||||
msg_len = await decode_uvarint_from_stream(self.read_write_closer)
|
||||
if msg_len > self.max_msg_size:
|
||||
raise MessageTooLarge(
|
||||
f"msg_len={msg_len} > max_msg_size={self.max_msg_size}"
|
||||
)
|
||||
return msg_len
|
||||
|
||||
def encode_msg(self, msg: bytes) -> bytes:
|
||||
msg_len = len(msg)
|
||||
if msg_len > self.max_msg_size:
|
||||
raise MessageTooLarge(
|
||||
f"msg_len={msg_len} > max_msg_size={self.max_msg_size}"
|
||||
)
|
||||
return encode_varint_prefixed(msg)
|
||||
|
|
|
@ -11,20 +11,22 @@ class BaseSession(ISecureConn):
|
|||
|
||||
local_peer: ID
|
||||
local_private_key: PrivateKey
|
||||
remote_peer_id: ID
|
||||
remote_peer: ID
|
||||
remote_permanent_pubkey: PublicKey
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
local_peer: ID,
|
||||
local_private_key: PrivateKey,
|
||||
remote_peer: ID,
|
||||
remote_permanent_pubkey: PublicKey,
|
||||
is_initiator: bool,
|
||||
peer_id: Optional[ID] = None,
|
||||
) -> None:
|
||||
self.local_peer = local_peer
|
||||
self.local_private_key = local_private_key
|
||||
self.remote_peer_id = peer_id
|
||||
self.remote_permanent_pubkey = None
|
||||
self.remote_peer = remote_peer
|
||||
self.remote_permanent_pubkey = remote_permanent_pubkey
|
||||
self.is_initiator = is_initiator
|
||||
|
||||
def get_local_peer(self) -> ID:
|
||||
|
@ -34,7 +36,7 @@ class BaseSession(ISecureConn):
|
|||
return self.local_private_key
|
||||
|
||||
def get_remote_peer(self) -> ID:
|
||||
return self.remote_peer_id
|
||||
return self.remote_peer
|
||||
|
||||
def get_remote_public_key(self) -> Optional[PublicKey]:
|
||||
return self.remote_permanent_pubkey
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: libp2p/security/insecure/pb/plaintext.proto
|
||||
|
||||
|
@ -8,6 +7,7 @@ from google.protobuf import descriptor as _descriptor
|
|||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf import descriptor_pb2
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
@ -20,7 +20,6 @@ DESCRIPTOR = _descriptor.FileDescriptor(
|
|||
name='libp2p/security/insecure/pb/plaintext.proto',
|
||||
package='plaintext.pb',
|
||||
syntax='proto2',
|
||||
serialized_options=None,
|
||||
serialized_pb=_b('\n+libp2p/security/insecure/pb/plaintext.proto\x12\x0cplaintext.pb\x1a\x1dlibp2p/crypto/pb/crypto.proto\"<\n\x08\x45xchange\x12\n\n\x02id\x18\x01 \x01(\x0c\x12$\n\x06pubkey\x18\x02 \x01(\x0b\x32\x14.crypto.pb.PublicKey')
|
||||
,
|
||||
dependencies=[libp2p_dot_crypto_dot_pb_dot_crypto__pb2.DESCRIPTOR,])
|
||||
|
@ -41,21 +40,21 @@ _EXCHANGE = _descriptor.Descriptor(
|
|||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='pubkey', full_name='plaintext.pb.Exchange.pubkey', index=1,
|
||||
number=2, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto2',
|
||||
extension_ranges=[],
|
||||
|
@ -69,11 +68,11 @@ _EXCHANGE.fields_by_name['pubkey'].message_type = libp2p_dot_crypto_dot_pb_dot_c
|
|||
DESCRIPTOR.message_types_by_name['Exchange'] = _EXCHANGE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
Exchange = _reflection.GeneratedProtocolMessageType('Exchange', (_message.Message,), {
|
||||
'DESCRIPTOR' : _EXCHANGE,
|
||||
'__module__' : 'libp2p.security.insecure.pb.plaintext_pb2'
|
||||
Exchange = _reflection.GeneratedProtocolMessageType('Exchange', (_message.Message,), dict(
|
||||
DESCRIPTOR = _EXCHANGE,
|
||||
__module__ = 'libp2p.security.insecure.pb.plaintext_pb2'
|
||||
# @@protoc_insertion_point(class_scope:plaintext.pb.Exchange)
|
||||
})
|
||||
))
|
||||
_sym_db.RegisterMessage(Exchange)
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
from typing import Optional
|
||||
|
||||
from libp2p.crypto.exceptions import MissingDeserializerError
|
||||
from libp2p.crypto.keys import PrivateKey, PublicKey
|
||||
from libp2p.crypto.pb import crypto_pb2
|
||||
from libp2p.crypto.serialization import deserialize_public_key
|
||||
from libp2p.io.abc import ReadWriteCloser
|
||||
from libp2p.io.msgio import VarIntLengthMsgReadWriter
|
||||
from libp2p.network.connection.exceptions import RawConnError
|
||||
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
||||
from libp2p.peer.id import ID
|
||||
|
@ -13,7 +12,6 @@ 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
|
||||
|
||||
|
@ -23,16 +21,28 @@ from .pb import plaintext_pb2
|
|||
PLAINTEXT_PROTOCOL_ID = TProtocol("/plaintext/2.0.0")
|
||||
|
||||
|
||||
class PlaintextHandshakeReadWriter(VarIntLengthMsgReadWriter):
|
||||
max_msg_size = 1 << 16
|
||||
|
||||
|
||||
class InsecureSession(BaseSession):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
local_peer: ID,
|
||||
local_private_key: PrivateKey,
|
||||
conn: ReadWriteCloser,
|
||||
remote_peer: ID,
|
||||
remote_permanent_pubkey: PublicKey,
|
||||
is_initiator: bool,
|
||||
peer_id: Optional[ID] = None,
|
||||
conn: ReadWriteCloser,
|
||||
) -> None:
|
||||
super().__init__(local_peer, local_private_key, is_initiator, peer_id)
|
||||
super().__init__(
|
||||
local_peer=local_peer,
|
||||
local_private_key=local_private_key,
|
||||
remote_peer=remote_peer,
|
||||
remote_permanent_pubkey=remote_permanent_pubkey,
|
||||
is_initiator=is_initiator,
|
||||
)
|
||||
self.conn = conn
|
||||
|
||||
async def write(self, data: bytes) -> None:
|
||||
|
@ -44,60 +54,69 @@ class InsecureSession(BaseSession):
|
|||
async def close(self) -> None:
|
||||
await self.conn.close()
|
||||
|
||||
async def run_handshake(self) -> None:
|
||||
"""Raise `HandshakeFailure` when handshake failed."""
|
||||
msg = make_exchange_message(self.local_private_key.get_public_key())
|
||||
msg_bytes = msg.SerializeToString()
|
||||
encoded_msg_bytes = encode_fixedint_prefixed(msg_bytes)
|
||||
try:
|
||||
await self.write(encoded_msg_bytes)
|
||||
except RawConnError as e:
|
||||
raise HandshakeFailure("connection closed") from e
|
||||
|
||||
try:
|
||||
remote_msg_bytes = await read_fixedint_prefixed(self.conn)
|
||||
except RawConnError as e:
|
||||
raise HandshakeFailure("connection closed") from e
|
||||
remote_msg = plaintext_pb2.Exchange()
|
||||
remote_msg.ParseFromString(remote_msg_bytes)
|
||||
received_peer_id = ID(remote_msg.id)
|
||||
async def run_handshake(
|
||||
local_peer: ID,
|
||||
local_private_key: PrivateKey,
|
||||
conn: IRawConnection,
|
||||
is_initiator: bool,
|
||||
remote_peer_id: ID,
|
||||
) -> ISecureConn:
|
||||
"""Raise `HandshakeFailure` when handshake failed."""
|
||||
msg = make_exchange_message(local_private_key.get_public_key())
|
||||
msg_bytes = msg.SerializeToString()
|
||||
read_writer = PlaintextHandshakeReadWriter(conn)
|
||||
try:
|
||||
await read_writer.write_msg(msg_bytes)
|
||||
except RawConnError as e:
|
||||
raise HandshakeFailure("connection closed") from e
|
||||
|
||||
# Verify if the receive `ID` matches the one we originally initialize the session.
|
||||
# We only need to check it when we are the initiator, because only in that condition
|
||||
# we possibly knows the `ID` of the remote.
|
||||
if self.is_initiator and self.remote_peer_id != received_peer_id:
|
||||
raise HandshakeFailure(
|
||||
"remote peer sent unexpected peer ID. "
|
||||
f"expected={self.remote_peer_id} received={received_peer_id}"
|
||||
)
|
||||
try:
|
||||
remote_msg_bytes = await read_writer.read_msg()
|
||||
except RawConnError as e:
|
||||
raise HandshakeFailure("connection closed") from e
|
||||
remote_msg = plaintext_pb2.Exchange()
|
||||
remote_msg.ParseFromString(remote_msg_bytes)
|
||||
received_peer_id = ID(remote_msg.id)
|
||||
|
||||
# Verify if the given `pubkey` matches the given `peer_id`
|
||||
try:
|
||||
received_pubkey = deserialize_public_key(
|
||||
remote_msg.pubkey.SerializeToString()
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HandshakeFailure(
|
||||
f"unknown `key_type` of remote_msg.pubkey={remote_msg.pubkey}"
|
||||
) from e
|
||||
except MissingDeserializerError as error:
|
||||
raise HandshakeFailure() from error
|
||||
peer_id_from_received_pubkey = ID.from_pubkey(received_pubkey)
|
||||
if peer_id_from_received_pubkey != received_peer_id:
|
||||
raise HandshakeFailure(
|
||||
"peer id and pubkey from the remote mismatch: "
|
||||
f"received_peer_id={received_peer_id}, remote_pubkey={received_pubkey}, "
|
||||
f"peer_id_from_received_pubkey={peer_id_from_received_pubkey}"
|
||||
)
|
||||
# Verify if the receive `ID` matches the one we originally initialize the session.
|
||||
# We only need to check it when we are the initiator, because only in that condition
|
||||
# we possibly knows the `ID` of the remote.
|
||||
if is_initiator and remote_peer_id != received_peer_id:
|
||||
raise HandshakeFailure(
|
||||
"remote peer sent unexpected peer ID. "
|
||||
f"expected={remote_peer_id} received={received_peer_id}"
|
||||
)
|
||||
|
||||
# Nothing is wrong. Store the `pubkey` and `peer_id` in the session.
|
||||
self.remote_permanent_pubkey = received_pubkey
|
||||
# Only need to set peer's id when we don't know it before,
|
||||
# i.e. we are not the connection initiator.
|
||||
if not self.is_initiator:
|
||||
self.remote_peer_id = received_peer_id
|
||||
# Verify if the given `pubkey` matches the given `peer_id`
|
||||
try:
|
||||
received_pubkey = deserialize_public_key(remote_msg.pubkey.SerializeToString())
|
||||
except ValueError as e:
|
||||
raise HandshakeFailure(
|
||||
f"unknown `key_type` of remote_msg.pubkey={remote_msg.pubkey}"
|
||||
) from e
|
||||
except MissingDeserializerError as error:
|
||||
raise HandshakeFailure() from error
|
||||
peer_id_from_received_pubkey = ID.from_pubkey(received_pubkey)
|
||||
if peer_id_from_received_pubkey != received_peer_id:
|
||||
raise HandshakeFailure(
|
||||
"peer id and pubkey from the remote mismatch: "
|
||||
f"received_peer_id={received_peer_id}, remote_pubkey={received_pubkey}, "
|
||||
f"peer_id_from_received_pubkey={peer_id_from_received_pubkey}"
|
||||
)
|
||||
|
||||
# TODO: Store `pubkey` and `peer_id` to `PeerStore`
|
||||
secure_conn = InsecureSession(
|
||||
local_peer=local_peer,
|
||||
local_private_key=local_private_key,
|
||||
remote_peer=received_peer_id,
|
||||
remote_permanent_pubkey=received_pubkey,
|
||||
is_initiator=is_initiator,
|
||||
conn=conn,
|
||||
)
|
||||
|
||||
# TODO: Store `pubkey` and `peer_id` to `PeerStore`
|
||||
|
||||
return secure_conn
|
||||
|
||||
|
||||
class InsecureTransport(BaseSecureTransport):
|
||||
|
@ -113,9 +132,9 @@ class InsecureTransport(BaseSecureTransport):
|
|||
|
||||
:return: secure connection object (that implements secure_conn_interface)
|
||||
"""
|
||||
session = InsecureSession(self.local_peer, self.local_private_key, conn, False)
|
||||
await session.run_handshake()
|
||||
return session
|
||||
return await run_handshake(
|
||||
self.local_peer, self.local_private_key, conn, False, None
|
||||
)
|
||||
|
||||
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
||||
"""
|
||||
|
@ -124,11 +143,9 @@ class InsecureTransport(BaseSecureTransport):
|
|||
|
||||
:return: secure connection object (that implements secure_conn_interface)
|
||||
"""
|
||||
session = InsecureSession(
|
||||
return await run_handshake(
|
||||
self.local_peer, self.local_private_key, conn, True, peer_id
|
||||
)
|
||||
await session.run_handshake()
|
||||
return session
|
||||
|
||||
|
||||
def make_exchange_message(pubkey: PublicKey) -> plaintext_pb2.Exchange:
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
from libp2p.crypto.keys import PrivateKey
|
||||
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
||||
from libp2p.peer.id import ID
|
||||
from libp2p.security.base_session import BaseSession
|
||||
|
||||
|
||||
class NoiseConnection(BaseSession):
|
||||
conn: IRawConnection
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
local_peer: ID,
|
||||
local_private_key: PrivateKey,
|
||||
remote_peer: ID,
|
||||
conn: IRawConnection,
|
||||
is_initiator: bool,
|
||||
) -> None:
|
||||
super().__init__(local_peer, local_private_key, is_initiator, remote_peer)
|
||||
self.conn = conn
|
||||
|
||||
async def read(self, n: int = None) -> bytes:
|
||||
# TODO: Add decryption logic here
|
||||
return await self.conn.read(n)
|
||||
|
||||
async def write(self, data: bytes) -> None:
|
||||
# TODO: Add encryption logic here
|
||||
await self.conn.write(data)
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.conn.close()
|
22
libp2p/security/noise/exceptions.py
Normal file
22
libp2p/security/noise/exceptions.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from libp2p.security.exceptions import HandshakeFailure
|
||||
|
||||
|
||||
class NoiseFailure(HandshakeFailure):
|
||||
pass
|
||||
|
||||
|
||||
class HandshakeHasNotFinished(NoiseFailure):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidSignature(NoiseFailure):
|
||||
pass
|
||||
|
||||
|
||||
class NoiseStateError(NoiseFailure):
|
||||
"""Raised when anything goes wrong in the noise state in `noiseprotocol`
|
||||
package."""
|
||||
|
||||
|
||||
class PeerIDMismatchesPubkey(NoiseFailure):
|
||||
pass
|
73
libp2p/security/noise/io.py
Normal file
73
libp2p/security/noise/io.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
from typing import cast
|
||||
|
||||
from noise.connection import NoiseConnection as NoiseState
|
||||
|
||||
from libp2p.io.abc import EncryptedMsgReadWriter, MsgReadWriteCloser, ReadWriteCloser
|
||||
from libp2p.io.msgio import FixedSizeLenMsgReadWriter
|
||||
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
||||
|
||||
SIZE_NOISE_MESSAGE_LEN = 2
|
||||
MAX_NOISE_MESSAGE_LEN = 2 ** (8 * SIZE_NOISE_MESSAGE_LEN) - 1
|
||||
SIZE_NOISE_MESSAGE_BODY_LEN = 2
|
||||
MAX_NOISE_MESSAGE_BODY_LEN = MAX_NOISE_MESSAGE_LEN - SIZE_NOISE_MESSAGE_BODY_LEN
|
||||
BYTE_ORDER = "big"
|
||||
|
||||
# | Noise packet |
|
||||
# < 2 bytes -><- 65535 ->
|
||||
# | noise msg len | noise msg |
|
||||
|
||||
|
||||
class NoisePacketReadWriter(FixedSizeLenMsgReadWriter):
|
||||
size_len_bytes = SIZE_NOISE_MESSAGE_LEN
|
||||
|
||||
|
||||
class BaseNoiseMsgReadWriter(EncryptedMsgReadWriter):
|
||||
"""
|
||||
The base implementation of noise message reader/writer.
|
||||
|
||||
`encrypt` and `decrypt` are not implemented here, which should be
|
||||
implemented by the subclasses.
|
||||
"""
|
||||
|
||||
read_writer: MsgReadWriteCloser
|
||||
noise_state: NoiseState
|
||||
|
||||
# FIXME: This prefix is added in msg#3 in Go. Check whether it's a desired behavior.
|
||||
prefix: bytes = b"\x00" * 32
|
||||
|
||||
def __init__(self, conn: IRawConnection, noise_state: NoiseState) -> None:
|
||||
self.read_writer = NoisePacketReadWriter(cast(ReadWriteCloser, conn))
|
||||
self.noise_state = noise_state
|
||||
|
||||
async def write_msg(self, data: bytes, prefix_encoded: bool = False) -> None:
|
||||
data_encrypted = self.encrypt(data)
|
||||
if prefix_encoded:
|
||||
await self.read_writer.write_msg(self.prefix + data_encrypted)
|
||||
else:
|
||||
await self.read_writer.write_msg(data_encrypted)
|
||||
|
||||
async def read_msg(self, prefix_encoded: bool = False) -> bytes:
|
||||
noise_msg_encrypted = await self.read_writer.read_msg()
|
||||
if prefix_encoded:
|
||||
return self.decrypt(noise_msg_encrypted[len(self.prefix) :])
|
||||
else:
|
||||
return self.decrypt(noise_msg_encrypted)
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.read_writer.close()
|
||||
|
||||
|
||||
class NoiseHandshakeReadWriter(BaseNoiseMsgReadWriter):
|
||||
def encrypt(self, data: bytes) -> bytes:
|
||||
return self.noise_state.write_message(data)
|
||||
|
||||
def decrypt(self, data: bytes) -> bytes:
|
||||
return self.noise_state.read_message(data)
|
||||
|
||||
|
||||
class NoiseTransportReadWriter(BaseNoiseMsgReadWriter):
|
||||
def encrypt(self, data: bytes) -> bytes:
|
||||
return self.noise_state.encrypt(data)
|
||||
|
||||
def decrypt(self, data: bytes) -> bytes:
|
||||
return self.noise_state.decrypt(data)
|
56
libp2p/security/noise/messages.py
Normal file
56
libp2p/security/noise/messages.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
from libp2p.crypto.keys import PrivateKey, PublicKey
|
||||
from libp2p.crypto.serialization import deserialize_public_key
|
||||
|
||||
from .pb import noise_pb2 as noise_pb
|
||||
|
||||
SIGNED_DATA_PREFIX = "noise-libp2p-static-key:"
|
||||
|
||||
|
||||
@dataclass
|
||||
class NoiseHandshakePayload:
|
||||
id_pubkey: PublicKey
|
||||
id_sig: bytes
|
||||
early_data: bytes = None
|
||||
|
||||
def serialize(self) -> bytes:
|
||||
msg = noise_pb.NoiseHandshakePayload(
|
||||
identity_key=self.id_pubkey.serialize(), identity_sig=self.id_sig
|
||||
)
|
||||
if self.early_data is not None:
|
||||
msg.data = self.early_data
|
||||
return msg.SerializeToString()
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, protobuf_bytes: bytes) -> "NoiseHandshakePayload":
|
||||
msg = noise_pb.NoiseHandshakePayload.FromString(protobuf_bytes)
|
||||
return cls(
|
||||
id_pubkey=deserialize_public_key(msg.identity_key),
|
||||
id_sig=msg.identity_sig,
|
||||
early_data=msg.data if msg.data != b"" else None,
|
||||
)
|
||||
|
||||
|
||||
def make_data_to_be_signed(noise_static_pubkey: PublicKey) -> bytes:
|
||||
prefix_bytes = SIGNED_DATA_PREFIX.encode("utf-8")
|
||||
return prefix_bytes + noise_static_pubkey.to_bytes()
|
||||
|
||||
|
||||
def make_handshake_payload_sig(
|
||||
id_privkey: PrivateKey, noise_static_pubkey: PublicKey
|
||||
) -> bytes:
|
||||
data = make_data_to_be_signed(noise_static_pubkey)
|
||||
return id_privkey.sign(data)
|
||||
|
||||
|
||||
def verify_handshake_payload_sig(
|
||||
payload: NoiseHandshakePayload, noise_static_pubkey: PublicKey
|
||||
) -> bool:
|
||||
"""
|
||||
Verify if the signature
|
||||
1. is composed of the data `SIGNED_DATA_PREFIX`++`noise_static_pubkey` and
|
||||
2. signed by the private key corresponding to `id_pubkey`
|
||||
"""
|
||||
expected_data = make_data_to_be_signed(noise_static_pubkey)
|
||||
return payload.id_pubkey.verify(expected_data, payload.id_sig)
|
|
@ -1,32 +1,28 @@
|
|||
from abc import ABC, abstractmethod
|
||||
|
||||
from noise.connection import Keypair as NoiseKeypair
|
||||
from noise.backends.default.keypairs import KeyPair as NoiseKeyPair
|
||||
from noise.connection import Keypair as NoiseKeypairEnum
|
||||
from noise.connection import NoiseConnection as NoiseState
|
||||
|
||||
from libp2p.crypto.keys import PrivateKey
|
||||
from libp2p.crypto.ed25519 import Ed25519PublicKey
|
||||
from libp2p.crypto.keys import PrivateKey, PublicKey
|
||||
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
||||
from libp2p.peer.id import ID
|
||||
from libp2p.security.secure_conn_interface import ISecureConn
|
||||
from libp2p.security.secure_session import SecureSession
|
||||
|
||||
from .connection import NoiseConnection
|
||||
|
||||
# FIXME: Choose a serious bound number.
|
||||
NUM_BYTES_TO_READ = 2048
|
||||
|
||||
|
||||
# TODO: Merged into `BasePattern`?
|
||||
class PreHandshakeConnection:
|
||||
conn: IRawConnection
|
||||
|
||||
def __init__(self, conn: IRawConnection) -> None:
|
||||
self.conn = conn
|
||||
|
||||
async def write_msg(self, data: bytes) -> None:
|
||||
# TODO:
|
||||
await self.conn.write(data)
|
||||
|
||||
async def read_msg(self) -> bytes:
|
||||
return await self.conn.read(NUM_BYTES_TO_READ)
|
||||
from .exceptions import (
|
||||
HandshakeHasNotFinished,
|
||||
InvalidSignature,
|
||||
NoiseStateError,
|
||||
PeerIDMismatchesPubkey,
|
||||
)
|
||||
from .io import NoiseHandshakeReadWriter, NoiseTransportReadWriter
|
||||
from .messages import (
|
||||
NoiseHandshakePayload,
|
||||
make_handshake_payload_sig,
|
||||
verify_handshake_payload_sig,
|
||||
)
|
||||
|
||||
|
||||
class IPattern(ABC):
|
||||
|
@ -46,71 +42,142 @@ class BasePattern(IPattern):
|
|||
noise_static_key: PrivateKey
|
||||
local_peer: ID
|
||||
libp2p_privkey: PrivateKey
|
||||
early_data: bytes
|
||||
|
||||
def create_noise_state(self) -> NoiseState:
|
||||
noise_state = NoiseState.from_name(self.protocol_name)
|
||||
noise_state.set_keypair_from_private_bytes(
|
||||
NoiseKeypair.STATIC, self.noise_static_key.to_bytes()
|
||||
NoiseKeypairEnum.STATIC, self.noise_static_key.to_bytes()
|
||||
)
|
||||
return noise_state
|
||||
|
||||
def make_handshake_payload(self) -> NoiseHandshakePayload:
|
||||
signature = make_handshake_payload_sig(
|
||||
self.libp2p_privkey, self.noise_static_key.get_public_key()
|
||||
)
|
||||
return NoiseHandshakePayload(self.libp2p_privkey.get_public_key(), signature)
|
||||
|
||||
|
||||
class PatternXX(BasePattern):
|
||||
def __init__(
|
||||
self, local_peer: ID, libp2p_privkey: PrivateKey, noise_static_key: PrivateKey
|
||||
self,
|
||||
local_peer: ID,
|
||||
libp2p_privkey: PrivateKey,
|
||||
noise_static_key: PrivateKey,
|
||||
early_data: bytes = None,
|
||||
) -> None:
|
||||
self.protocol_name = b"Noise_XX_25519_ChaChaPoly_SHA256"
|
||||
self.local_peer = local_peer
|
||||
self.libp2p_privkey = libp2p_privkey
|
||||
self.noise_static_key = noise_static_key
|
||||
self.early_data = early_data
|
||||
|
||||
async def handshake_inbound(self, conn: IRawConnection) -> ISecureConn:
|
||||
noise_state = self.create_noise_state()
|
||||
handshake_conn = PreHandshakeConnection(conn)
|
||||
noise_state.set_as_responder()
|
||||
noise_state.start_handshake()
|
||||
msg_0_encrypted = await handshake_conn.read_msg()
|
||||
# TODO: Parse and save the payload from the other side.
|
||||
_ = noise_state.read_message(msg_0_encrypted)
|
||||
handshake_state = noise_state.noise_protocol.handshake_state
|
||||
read_writer = NoiseHandshakeReadWriter(conn, noise_state)
|
||||
|
||||
# TODO: Send our payload.
|
||||
our_payload = b"server"
|
||||
msg_1_encrypted = noise_state.write_message(our_payload)
|
||||
await handshake_conn.write_msg(msg_1_encrypted)
|
||||
# Consume msg#1.
|
||||
await read_writer.read_msg()
|
||||
|
||||
msg_2_encrypted = await handshake_conn.read_msg()
|
||||
# TODO: Parse and save another payload from the other side.
|
||||
_ = noise_state.read_message(msg_2_encrypted)
|
||||
# Send msg#2, which should include our handshake payload.
|
||||
our_payload = self.make_handshake_payload()
|
||||
msg_2 = our_payload.serialize()
|
||||
await read_writer.write_msg(msg_2)
|
||||
|
||||
# Receive and consume msg#3.
|
||||
msg_3 = await read_writer.read_msg(prefix_encoded=True)
|
||||
peer_handshake_payload = NoiseHandshakePayload.deserialize(msg_3)
|
||||
|
||||
if handshake_state.rs is None:
|
||||
raise NoiseStateError(
|
||||
"something is wrong in the underlying noise `handshake_state`: "
|
||||
"we received and consumed msg#3, which should have included the"
|
||||
" remote static public key, but it is not present in the handshake_state"
|
||||
)
|
||||
remote_pubkey = self._get_pubkey_from_noise_keypair(handshake_state.rs)
|
||||
|
||||
if not verify_handshake_payload_sig(peer_handshake_payload, remote_pubkey):
|
||||
raise InvalidSignature
|
||||
remote_peer_id_from_pubkey = ID.from_pubkey(peer_handshake_payload.id_pubkey)
|
||||
|
||||
# TODO: Add a specific exception
|
||||
if not noise_state.handshake_finished:
|
||||
raise Exception
|
||||
|
||||
# FIXME: `remote_peer` should be derived from the messages.
|
||||
return NoiseConnection(self.local_peer, self.libp2p_privkey, None, conn, False)
|
||||
raise HandshakeHasNotFinished(
|
||||
"handshake is done but it is not marked as finished in `noise_state`"
|
||||
)
|
||||
transport_read_writer = NoiseTransportReadWriter(conn, noise_state)
|
||||
return SecureSession(
|
||||
local_peer=self.local_peer,
|
||||
local_private_key=self.libp2p_privkey,
|
||||
remote_peer=remote_peer_id_from_pubkey,
|
||||
remote_permanent_pubkey=remote_pubkey,
|
||||
is_initiator=False,
|
||||
conn=transport_read_writer,
|
||||
)
|
||||
|
||||
async def handshake_outbound(
|
||||
self, conn: IRawConnection, remote_peer: ID
|
||||
) -> ISecureConn:
|
||||
noise_state = self.create_noise_state()
|
||||
handshake_conn = PreHandshakeConnection(conn)
|
||||
|
||||
read_writer = NoiseHandshakeReadWriter(conn, noise_state)
|
||||
noise_state.set_as_initiator()
|
||||
noise_state.start_handshake()
|
||||
msg_0 = noise_state.write_message()
|
||||
await handshake_conn.write_msg(msg_0)
|
||||
msg_1_encrypted = await handshake_conn.read_msg()
|
||||
# TODO: Parse and save the payload from the other side.
|
||||
_ = noise_state.read_message(msg_1_encrypted)
|
||||
handshake_state = noise_state.noise_protocol.handshake_state
|
||||
|
||||
# TODO: Send our payload.
|
||||
our_payload = b"client"
|
||||
msg_2_encrypted = noise_state.write_message(our_payload)
|
||||
await handshake_conn.write_msg(msg_2_encrypted)
|
||||
# Send msg#1, which is *not* encrypted.
|
||||
msg_1 = b""
|
||||
await read_writer.write_msg(msg_1)
|
||||
|
||||
# Read msg#2 from the remote, which contains the public key of the peer.
|
||||
msg_2 = await read_writer.read_msg()
|
||||
peer_handshake_payload = NoiseHandshakePayload.deserialize(msg_2)
|
||||
|
||||
if handshake_state.rs is None:
|
||||
raise NoiseStateError(
|
||||
"something is wrong in the underlying noise `handshake_state`: "
|
||||
"we received and consumed msg#3, which should have included the"
|
||||
" remote static public key, but it is not present in the handshake_state"
|
||||
)
|
||||
remote_pubkey = self._get_pubkey_from_noise_keypair(handshake_state.rs)
|
||||
|
||||
if not verify_handshake_payload_sig(peer_handshake_payload, remote_pubkey):
|
||||
raise InvalidSignature
|
||||
remote_peer_id_from_pubkey = ID.from_pubkey(peer_handshake_payload.id_pubkey)
|
||||
if remote_peer_id_from_pubkey != remote_peer:
|
||||
raise PeerIDMismatchesPubkey(
|
||||
"peer id does not correspond to the received pubkey: "
|
||||
f"remote_peer={remote_peer}, "
|
||||
f"remote_peer_id_from_pubkey={remote_peer_id_from_pubkey}"
|
||||
)
|
||||
|
||||
# Send msg#3, which includes our encrypted payload and our noise static key.
|
||||
our_payload = self.make_handshake_payload()
|
||||
msg_3 = our_payload.serialize()
|
||||
await read_writer.write_msg(msg_3, prefix_encoded=True)
|
||||
|
||||
# TODO: Add a specific exception
|
||||
if not noise_state.handshake_finished:
|
||||
raise Exception
|
||||
|
||||
return NoiseConnection(
|
||||
self.local_peer, self.libp2p_privkey, remote_peer, conn, False
|
||||
raise HandshakeHasNotFinished(
|
||||
"handshake is done but it is not marked as finished in `noise_state`"
|
||||
)
|
||||
transport_read_writer = NoiseTransportReadWriter(conn, noise_state)
|
||||
return SecureSession(
|
||||
local_peer=self.local_peer,
|
||||
local_private_key=self.libp2p_privkey,
|
||||
remote_peer=remote_peer_id_from_pubkey,
|
||||
remote_permanent_pubkey=remote_pubkey,
|
||||
is_initiator=True,
|
||||
conn=transport_read_writer,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _get_pubkey_from_noise_keypair(key_pair: NoiseKeyPair) -> PublicKey:
|
||||
# Use `Ed25519PublicKey` since 25519 is used in our pattern.
|
||||
# NOTE: Ignore the warning for now, since it is also not fixed in `noiseprotocol`.
|
||||
# "CryptographyDeprecationWarning: public_bytes now requires
|
||||
# encoding and format arguments. Support for calling without arguments will be
|
||||
# removed in cryptography 2.7"
|
||||
raw_bytes = key_pair.public.public_bytes()
|
||||
return Ed25519PublicKey.from_bytes(raw_bytes)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
syntax = "proto3";
|
||||
package pb;
|
||||
|
||||
message NoiseHandshakePayload {
|
||||
optional bytes identity_key = 1;
|
||||
optional bytes identity_sig = 2;
|
||||
optional bytes data = 3;
|
||||
bytes identity_key = 1;
|
||||
bytes identity_sig = 2;
|
||||
bytes data = 3;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ _sym_db = _symbol_database.Default()
|
|||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='libp2p/security/noise/pb/noise.proto',
|
||||
package='',
|
||||
syntax='proto2',
|
||||
serialized_pb=_b('\n$libp2p/security/noise/pb/noise.proto\"Q\n\x15NoiseHandshakePayload\x12\x14\n\x0cidentity_key\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_sig\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c')
|
||||
package='pb',
|
||||
syntax='proto3',
|
||||
serialized_pb=_b('\n$libp2p/security/noise/pb/noise.proto\x12\x02pb\"Q\n\x15NoiseHandshakePayload\x12\x14\n\x0cidentity_key\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_sig\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x62\x06proto3')
|
||||
)
|
||||
|
||||
|
||||
|
@ -27,27 +27,27 @@ DESCRIPTOR = _descriptor.FileDescriptor(
|
|||
|
||||
_NOISEHANDSHAKEPAYLOAD = _descriptor.Descriptor(
|
||||
name='NoiseHandshakePayload',
|
||||
full_name='NoiseHandshakePayload',
|
||||
full_name='pb.NoiseHandshakePayload',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='identity_key', full_name='NoiseHandshakePayload.identity_key', index=0,
|
||||
name='identity_key', full_name='pb.NoiseHandshakePayload.identity_key', index=0,
|
||||
number=1, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='identity_sig', full_name='NoiseHandshakePayload.identity_sig', index=1,
|
||||
name='identity_sig', full_name='pb.NoiseHandshakePayload.identity_sig', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='NoiseHandshakePayload.data', index=2,
|
||||
name='data', full_name='pb.NoiseHandshakePayload.data', index=2,
|
||||
number=3, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
|
@ -61,12 +61,12 @@ _NOISEHANDSHAKEPAYLOAD = _descriptor.Descriptor(
|
|||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto2',
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=40,
|
||||
serialized_end=121,
|
||||
serialized_start=44,
|
||||
serialized_end=125,
|
||||
)
|
||||
|
||||
DESCRIPTOR.message_types_by_name['NoiseHandshakePayload'] = _NOISEHANDSHAKEPAYLOAD
|
||||
|
@ -75,7 +75,7 @@ _sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
|||
NoiseHandshakePayload = _reflection.GeneratedProtocolMessageType('NoiseHandshakePayload', (_message.Message,), dict(
|
||||
DESCRIPTOR = _NOISEHANDSHAKEPAYLOAD,
|
||||
__module__ = 'libp2p.security.noise.pb.noise_pb2'
|
||||
# @@protoc_insertion_point(class_scope:NoiseHandshakePayload)
|
||||
# @@protoc_insertion_point(class_scope:pb.NoiseHandshakePayload)
|
||||
))
|
||||
_sym_db.RegisterMessage(NoiseHandshakePayload)
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ class NoiseHandshakePayload(google___protobuf___message___Message):
|
|||
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
|
||||
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
|
||||
if sys.version_info >= (3,):
|
||||
def HasField(self, field_name: typing_extensions___Literal[u"data",u"identity_key",u"identity_sig"]) -> bool: ...
|
||||
def ClearField(self, field_name: typing_extensions___Literal[u"data",u"identity_key",u"identity_sig"]) -> None: ...
|
||||
else:
|
||||
def HasField(self, field_name: typing_extensions___Literal[u"data",b"data",u"identity_key",b"identity_key",u"identity_sig",b"identity_sig"]) -> bool: ...
|
||||
def ClearField(self, field_name: typing_extensions___Literal[u"data",b"data",u"identity_key",b"identity_key",u"identity_sig",b"identity_sig"]) -> None: ...
|
||||
|
|
|
@ -16,6 +16,10 @@ class Transport(ISecureTransport):
|
|||
local_peer: ID
|
||||
early_data: bytes
|
||||
with_noise_pipes: bool
|
||||
|
||||
# NOTE: Implementations that support Noise Pipes must decide whether to use
|
||||
# an XX or IK handshake based on whether they possess a cached static
|
||||
# Noise key for the remote peer.
|
||||
# TODO: A storage of seen noise static keys for pattern IK?
|
||||
|
||||
def __init__(
|
||||
|
@ -38,18 +42,17 @@ class Transport(ISecureTransport):
|
|||
if self.with_noise_pipes:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
return PatternXX(self.local_peer, self.libp2p_privkey, self.noise_privkey)
|
||||
return PatternXX(
|
||||
self.local_peer,
|
||||
self.libp2p_privkey,
|
||||
self.noise_privkey,
|
||||
self.early_data,
|
||||
)
|
||||
|
||||
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
||||
# TODO: SecureInbound attempts to complete a noise-libp2p handshake initiated
|
||||
# by a remote peer over the given InsecureConnection.
|
||||
pattern = self.get_pattern()
|
||||
return await pattern.handshake_inbound(conn)
|
||||
|
||||
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
||||
# TODO: Validate libp2p pubkey with `peer_id`. Abort if not correct.
|
||||
# NOTE: Implementations that support Noise Pipes must decide whether to use
|
||||
# an XX or IK handshake based on whether they possess a cached static
|
||||
# Noise key for the remote peer.
|
||||
pattern = self.get_pattern()
|
||||
return await pattern.handshake_outbound(conn, peer_id)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from dataclasses import dataclass
|
||||
import io
|
||||
import itertools
|
||||
from typing import Optional, Tuple
|
||||
|
||||
|
@ -18,13 +17,14 @@ from libp2p.crypto.exceptions import MissingDeserializerError
|
|||
from libp2p.crypto.key_exchange import create_ephemeral_key_pair
|
||||
from libp2p.crypto.keys import PrivateKey, PublicKey
|
||||
from libp2p.crypto.serialization import deserialize_public_key
|
||||
from libp2p.io.abc import EncryptedMsgReadWriter
|
||||
from libp2p.io.exceptions import DecryptionFailedException, IOException
|
||||
from libp2p.io.msgio import MsgIOReadWriter
|
||||
from libp2p.io.msgio import FixedSizeLenMsgReadWriter
|
||||
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
||||
from libp2p.peer.id import ID as PeerID
|
||||
from libp2p.security.base_session import BaseSession
|
||||
from libp2p.security.base_transport import BaseSecureTransport
|
||||
from libp2p.security.secure_conn_interface import ISecureConn
|
||||
from libp2p.security.secure_session import SecureSession
|
||||
from libp2p.typing import TProtocol
|
||||
|
||||
from .exceptions import (
|
||||
|
@ -41,6 +41,7 @@ from .pb.spipe_pb2 import Exchange, Propose
|
|||
ID = TProtocol("/secio/1.0.0")
|
||||
|
||||
NONCE_SIZE = 16 # bytes
|
||||
SIZE_SECIO_LEN_BYTES = 4
|
||||
|
||||
# NOTE: the following is only a subset of allowable parameters according to the
|
||||
# `secio` specification.
|
||||
|
@ -49,30 +50,24 @@ DEFAULT_SUPPORTED_CIPHERS = "AES-128"
|
|||
DEFAULT_SUPPORTED_HASHES = "SHA256"
|
||||
|
||||
|
||||
class SecureSession(BaseSession):
|
||||
buf: io.BytesIO
|
||||
low_watermark: int
|
||||
high_watermark: int
|
||||
class SecioPacketReadWriter(FixedSizeLenMsgReadWriter):
|
||||
size_len_bytes = SIZE_SECIO_LEN_BYTES
|
||||
|
||||
|
||||
class SecioMsgReadWriter(EncryptedMsgReadWriter):
|
||||
read_writer: SecioPacketReadWriter
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
local_peer: PeerID,
|
||||
local_private_key: PrivateKey,
|
||||
local_encryption_parameters: AuthenticatedEncryptionParameters,
|
||||
remote_peer: PeerID,
|
||||
remote_encryption_parameters: AuthenticatedEncryptionParameters,
|
||||
conn: MsgIOReadWriter,
|
||||
is_initiator: bool,
|
||||
read_writer: SecioPacketReadWriter,
|
||||
) -> None:
|
||||
super().__init__(local_peer, local_private_key, is_initiator, remote_peer)
|
||||
self.conn = conn
|
||||
|
||||
self.local_encryption_parameters = local_encryption_parameters
|
||||
self.remote_encryption_parameters = remote_encryption_parameters
|
||||
self._initialize_authenticated_encryption_for_local_peer()
|
||||
self._initialize_authenticated_encryption_for_remote_peer()
|
||||
|
||||
self._reset_internal_buffer()
|
||||
self.read_writer = read_writer
|
||||
|
||||
def _initialize_authenticated_encryption_for_local_peer(self) -> None:
|
||||
self.local_encrypter = Encrypter(self.local_encryption_parameters)
|
||||
|
@ -80,68 +75,28 @@ class SecureSession(BaseSession):
|
|||
def _initialize_authenticated_encryption_for_remote_peer(self) -> None:
|
||||
self.remote_encrypter = Encrypter(self.remote_encryption_parameters)
|
||||
|
||||
async def next_msg_len(self) -> int:
|
||||
return await self.conn.next_msg_len()
|
||||
def encrypt(self, data: bytes) -> bytes:
|
||||
encrypted_data = self.local_encrypter.encrypt(data)
|
||||
tag = self.local_encrypter.authenticate(encrypted_data)
|
||||
return encrypted_data + tag
|
||||
|
||||
def _reset_internal_buffer(self) -> None:
|
||||
self.buf = io.BytesIO()
|
||||
self.low_watermark = 0
|
||||
self.high_watermark = 0
|
||||
|
||||
def _drain(self, n: int) -> bytes:
|
||||
if self.low_watermark == self.high_watermark:
|
||||
return bytes()
|
||||
|
||||
data = self.buf.getbuffer()[self.low_watermark : self.high_watermark]
|
||||
|
||||
if n is None:
|
||||
n = len(data)
|
||||
result = data[:n].tobytes()
|
||||
self.low_watermark += len(result)
|
||||
|
||||
if self.low_watermark == self.high_watermark:
|
||||
del data # free the memoryview so we can free the underlying BytesIO
|
||||
self.buf.close()
|
||||
self._reset_internal_buffer()
|
||||
return result
|
||||
|
||||
async def _fill(self) -> None:
|
||||
msg = await self.read_msg()
|
||||
self.buf.write(msg)
|
||||
self.low_watermark = 0
|
||||
self.high_watermark = len(msg)
|
||||
|
||||
async def read(self, n: int = None) -> bytes:
|
||||
if n == 0:
|
||||
return bytes()
|
||||
|
||||
data_from_buffer = self._drain(n)
|
||||
if len(data_from_buffer) > 0:
|
||||
return data_from_buffer
|
||||
|
||||
next_length = await self.next_msg_len()
|
||||
|
||||
if n < next_length:
|
||||
await self._fill()
|
||||
return self._drain(n)
|
||||
else:
|
||||
return await self.read_msg()
|
||||
|
||||
async def read_msg(self) -> bytes:
|
||||
msg = await self.conn.read_msg()
|
||||
def decrypt(self, data: bytes) -> bytes:
|
||||
try:
|
||||
decrypted_msg = self.remote_encrypter.decrypt_if_valid(msg)
|
||||
decrypted_data = self.remote_encrypter.decrypt_if_valid(data)
|
||||
except InvalidMACException as e:
|
||||
raise DecryptionFailedException() from e
|
||||
return decrypted_msg
|
||||
|
||||
async def write(self, data: bytes) -> None:
|
||||
await self.write_msg(data)
|
||||
return decrypted_data
|
||||
|
||||
async def write_msg(self, msg: bytes) -> None:
|
||||
encrypted_data = self.local_encrypter.encrypt(msg)
|
||||
tag = self.local_encrypter.authenticate(encrypted_data)
|
||||
await self.conn.write_msg(encrypted_data + tag)
|
||||
data_encrypted = self.encrypt(msg)
|
||||
await self.read_writer.write_msg(data_encrypted)
|
||||
|
||||
async def read_msg(self) -> bytes:
|
||||
msg_encrypted = await self.read_writer.read_msg()
|
||||
return self.decrypt(msg_encrypted)
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.read_writer.close()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -215,7 +170,7 @@ class SessionParameters:
|
|||
pass
|
||||
|
||||
|
||||
async def _response_to_msg(read_writer: MsgIOReadWriter, msg: bytes) -> bytes:
|
||||
async def _response_to_msg(read_writer: SecioPacketReadWriter, msg: bytes) -> bytes:
|
||||
await read_writer.write_msg(msg)
|
||||
return await read_writer.read_msg()
|
||||
|
||||
|
@ -279,7 +234,7 @@ async def _establish_session_parameters(
|
|||
local_peer: PeerID,
|
||||
local_private_key: PrivateKey,
|
||||
remote_peer: Optional[PeerID],
|
||||
conn: MsgIOReadWriter,
|
||||
conn: SecioPacketReadWriter,
|
||||
nonce: bytes,
|
||||
) -> Tuple[SessionParameters, bytes]:
|
||||
# establish shared encryption parameters
|
||||
|
@ -371,7 +326,7 @@ async def _establish_session_parameters(
|
|||
def _mk_session_from(
|
||||
local_private_key: PrivateKey,
|
||||
session_parameters: SessionParameters,
|
||||
conn: MsgIOReadWriter,
|
||||
conn: SecioPacketReadWriter,
|
||||
is_initiator: bool,
|
||||
) -> SecureSession:
|
||||
key_set1, key_set2 = initialize_pair_for_encryption(
|
||||
|
@ -382,22 +337,24 @@ def _mk_session_from(
|
|||
|
||||
if session_parameters.order < 0:
|
||||
key_set1, key_set2 = key_set2, key_set1
|
||||
|
||||
secio_read_writer = SecioMsgReadWriter(key_set1, key_set2, conn)
|
||||
remote_permanent_pubkey = (
|
||||
session_parameters.remote_encryption_parameters.permanent_public_key
|
||||
)
|
||||
session = SecureSession(
|
||||
session_parameters.local_peer,
|
||||
local_private_key,
|
||||
key_set1,
|
||||
session_parameters.remote_peer,
|
||||
key_set2,
|
||||
conn,
|
||||
is_initiator,
|
||||
local_peer=session_parameters.local_peer,
|
||||
local_private_key=local_private_key,
|
||||
remote_peer=session_parameters.remote_peer,
|
||||
remote_permanent_pubkey=remote_permanent_pubkey,
|
||||
is_initiator=is_initiator,
|
||||
conn=secio_read_writer,
|
||||
)
|
||||
return session
|
||||
|
||||
|
||||
async def _finish_handshake(session: SecureSession, remote_nonce: bytes) -> bytes:
|
||||
await session.write_msg(remote_nonce)
|
||||
return await session.read_msg()
|
||||
await session.conn.write_msg(remote_nonce)
|
||||
return await session.conn.read_msg()
|
||||
|
||||
|
||||
async def create_secure_session(
|
||||
|
@ -414,7 +371,7 @@ async def create_secure_session(
|
|||
to the ``remote_peer``. Raise `SecioException` when `conn` closed.
|
||||
Raise `InconsistentNonce` when handshake failed
|
||||
"""
|
||||
msg_io = MsgIOReadWriter(conn)
|
||||
msg_io = SecioPacketReadWriter(conn)
|
||||
try:
|
||||
session_parameters, remote_nonce = await _establish_session_parameters(
|
||||
local_peer, local_private_key, remote_peer, msg_io, local_nonce
|
||||
|
|
82
libp2p/security/secure_session.py
Normal file
82
libp2p/security/secure_session.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
import io
|
||||
|
||||
from libp2p.crypto.keys import PrivateKey, PublicKey
|
||||
from libp2p.io.abc import EncryptedMsgReadWriter
|
||||
from libp2p.peer.id import ID
|
||||
from libp2p.security.base_session import BaseSession
|
||||
|
||||
|
||||
class SecureSession(BaseSession):
|
||||
buf: io.BytesIO
|
||||
low_watermark: int
|
||||
high_watermark: int
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
local_peer: ID,
|
||||
local_private_key: PrivateKey,
|
||||
remote_peer: ID,
|
||||
remote_permanent_pubkey: PublicKey,
|
||||
is_initiator: bool,
|
||||
conn: EncryptedMsgReadWriter,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
local_peer=local_peer,
|
||||
local_private_key=local_private_key,
|
||||
remote_peer=remote_peer,
|
||||
remote_permanent_pubkey=remote_permanent_pubkey,
|
||||
is_initiator=is_initiator,
|
||||
)
|
||||
self.conn = conn
|
||||
|
||||
self._reset_internal_buffer()
|
||||
|
||||
def _reset_internal_buffer(self) -> None:
|
||||
self.buf = io.BytesIO()
|
||||
self.low_watermark = 0
|
||||
self.high_watermark = 0
|
||||
|
||||
def _drain(self, n: int) -> bytes:
|
||||
if self.low_watermark == self.high_watermark:
|
||||
return bytes()
|
||||
|
||||
data = self.buf.getbuffer()[self.low_watermark : self.high_watermark]
|
||||
|
||||
if n is None:
|
||||
n = len(data)
|
||||
result = data[:n].tobytes()
|
||||
self.low_watermark += len(result)
|
||||
|
||||
if self.low_watermark == self.high_watermark:
|
||||
del data # free the memoryview so we can free the underlying BytesIO
|
||||
self.buf.close()
|
||||
self._reset_internal_buffer()
|
||||
return result
|
||||
|
||||
def _fill(self, msg: bytes) -> None:
|
||||
self.buf.write(msg)
|
||||
self.low_watermark = 0
|
||||
self.high_watermark = len(msg)
|
||||
|
||||
async def read(self, n: int = None) -> bytes:
|
||||
if n == 0:
|
||||
return bytes()
|
||||
|
||||
data_from_buffer = self._drain(n)
|
||||
if len(data_from_buffer) > 0:
|
||||
return data_from_buffer
|
||||
|
||||
msg = await self.conn.read_msg()
|
||||
|
||||
if n < len(msg):
|
||||
self._fill(msg)
|
||||
return self._drain(n)
|
||||
else:
|
||||
return msg
|
||||
|
||||
async def write(self, data: bytes) -> None:
|
||||
await self.conn.write_msg(data)
|
||||
|
||||
async def close(self) -> None:
|
||||
await self.conn.close()
|
|
@ -27,7 +27,6 @@ class SecurityMultistream(ABC):
|
|||
Go implementation: github.com/libp2p/go-conn-security-multistream/ssms.go
|
||||
"""
|
||||
|
||||
# NOTE: Can be changed to `typing.OrderedDict` since Python 3.7.2.
|
||||
transports: "OrderedDict[TProtocol, ISecureTransport]"
|
||||
multiselect: Multiselect
|
||||
multiselect_client: MultiselectClient
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, AsyncIterator, Dict, List, Sequence, Tuple, cast
|
||||
from typing import Any, AsyncIterator, Callable, Dict, List, Sequence, Tuple, cast
|
||||
|
||||
from async_exit_stack import AsyncExitStack
|
||||
from async_generator import asynccontextmanager
|
||||
|
@ -29,6 +29,11 @@ from libp2p.pubsub.gossipsub import GossipSub
|
|||
from libp2p.pubsub.pubsub import Pubsub
|
||||
from libp2p.routing.interfaces import IPeerRouting
|
||||
from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID, InsecureTransport
|
||||
from libp2p.security.noise.messages import (
|
||||
NoiseHandshakePayload,
|
||||
make_handshake_payload_sig,
|
||||
)
|
||||
from libp2p.security.noise.transport import PROTOCOL_ID as NOISE_PROTOCOL_ID
|
||||
from libp2p.security.noise.transport import Transport as NoiseTransport
|
||||
import libp2p.security.secio.transport as secio
|
||||
from libp2p.security.secure_conn_interface import ISecureConn
|
||||
|
@ -37,20 +42,26 @@ from libp2p.stream_muxer.mplex.mplex import MPLEX_PROTOCOL_ID, Mplex
|
|||
from libp2p.stream_muxer.mplex.mplex_stream import MplexStream
|
||||
from libp2p.tools.constants import GOSSIPSUB_PARAMS
|
||||
from libp2p.transport.tcp.tcp import TCP
|
||||
from libp2p.transport.typing import TMuxerOptions
|
||||
from libp2p.transport.typing import TMuxerOptions, TSecurityOptions
|
||||
from libp2p.transport.upgrader import TransportUpgrader
|
||||
from libp2p.typing import TProtocol
|
||||
|
||||
from .constants import FLOODSUB_PROTOCOL_ID, GOSSIPSUB_PROTOCOL_ID, LISTEN_MADDR
|
||||
from .utils import connect, connect_swarm
|
||||
|
||||
DEFAULT_SECURITY_PROTOCOL_ID = PLAINTEXT_PROTOCOL_ID
|
||||
|
||||
|
||||
def default_key_pair_factory() -> KeyPair:
|
||||
return generate_new_rsa_identity()
|
||||
|
||||
|
||||
class IDFactory(factory.Factory):
|
||||
class Meta:
|
||||
model = ID
|
||||
|
||||
peer_id_bytes = factory.LazyFunction(
|
||||
lambda: generate_peer_id_from(generate_new_rsa_identity())
|
||||
lambda: generate_peer_id_from(default_key_pair_factory())
|
||||
)
|
||||
|
||||
|
||||
|
@ -60,28 +71,67 @@ def initialize_peerstore_with_our_keypair(self_id: ID, key_pair: KeyPair) -> Pee
|
|||
return peer_store
|
||||
|
||||
|
||||
def security_transport_factory(
|
||||
is_secure: bool, key_pair: KeyPair
|
||||
) -> Dict[TProtocol, ISecureTransport]:
|
||||
if not is_secure:
|
||||
return {PLAINTEXT_PROTOCOL_ID: InsecureTransport(key_pair)}
|
||||
else:
|
||||
return {secio.ID: secio.Transport(key_pair)}
|
||||
|
||||
|
||||
def noise_static_key_factory() -> PrivateKey:
|
||||
return create_ed25519_key_pair().private_key
|
||||
|
||||
|
||||
def noise_transport_factory() -> NoiseTransport:
|
||||
def noise_handshake_payload_factory() -> NoiseHandshakePayload:
|
||||
libp2p_keypair = create_secp256k1_key_pair()
|
||||
noise_static_privkey = noise_static_key_factory()
|
||||
return NoiseHandshakePayload(
|
||||
libp2p_keypair.public_key,
|
||||
make_handshake_payload_sig(
|
||||
libp2p_keypair.private_key, noise_static_privkey.get_public_key()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def plaintext_transport_factory(key_pair: KeyPair) -> ISecureTransport:
|
||||
return InsecureTransport(key_pair)
|
||||
|
||||
|
||||
def secio_transport_factory(key_pair: KeyPair) -> ISecureTransport:
|
||||
return secio.Transport(key_pair)
|
||||
|
||||
|
||||
def noise_transport_factory(key_pair: KeyPair) -> ISecureTransport:
|
||||
return NoiseTransport(
|
||||
libp2p_keypair=create_secp256k1_key_pair(),
|
||||
libp2p_keypair=key_pair,
|
||||
noise_privkey=noise_static_key_factory(),
|
||||
early_data=None,
|
||||
with_noise_pipes=False,
|
||||
)
|
||||
|
||||
|
||||
def security_options_factory_factory(
|
||||
protocol_id: TProtocol = None
|
||||
) -> Callable[[KeyPair], TSecurityOptions]:
|
||||
if protocol_id is None:
|
||||
protocol_id = DEFAULT_SECURITY_PROTOCOL_ID
|
||||
|
||||
def security_options_factory(key_pair: KeyPair) -> TSecurityOptions:
|
||||
transport_factory: Callable[[KeyPair], ISecureTransport]
|
||||
if protocol_id == PLAINTEXT_PROTOCOL_ID:
|
||||
transport_factory = plaintext_transport_factory
|
||||
elif protocol_id == secio.ID:
|
||||
transport_factory = secio_transport_factory
|
||||
elif protocol_id == NOISE_PROTOCOL_ID:
|
||||
transport_factory = noise_transport_factory
|
||||
else:
|
||||
raise Exception(f"security transport {protocol_id} is not supported")
|
||||
return {protocol_id: transport_factory(key_pair)}
|
||||
|
||||
return security_options_factory
|
||||
|
||||
|
||||
def mplex_transport_factory() -> TMuxerOptions:
|
||||
return {MPLEX_PROTOCOL_ID: Mplex}
|
||||
|
||||
|
||||
def default_muxer_transport_factory() -> TMuxerOptions:
|
||||
return mplex_transport_factory()
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def raw_conn_factory(
|
||||
nursery: trio.Nursery
|
||||
|
@ -109,8 +159,12 @@ async def raw_conn_factory(
|
|||
async def noise_conn_factory(
|
||||
nursery: trio.Nursery
|
||||
) -> AsyncIterator[Tuple[ISecureConn, ISecureConn]]:
|
||||
local_transport = noise_transport_factory()
|
||||
remote_transport = noise_transport_factory()
|
||||
local_transport = cast(
|
||||
NoiseTransport, noise_transport_factory(create_secp256k1_key_pair())
|
||||
)
|
||||
remote_transport = cast(
|
||||
NoiseTransport, noise_transport_factory(create_secp256k1_key_pair())
|
||||
)
|
||||
|
||||
local_secure_conn: ISecureConn = None
|
||||
remote_secure_conn: ISecureConn = None
|
||||
|
@ -118,7 +172,7 @@ async def noise_conn_factory(
|
|||
async def upgrade_local_conn() -> None:
|
||||
nonlocal local_secure_conn
|
||||
local_secure_conn = await local_transport.secure_outbound(
|
||||
local_conn, local_transport.local_peer
|
||||
local_conn, remote_transport.local_peer
|
||||
)
|
||||
|
||||
async def upgrade_remote_conn() -> None:
|
||||
|
@ -143,9 +197,9 @@ class SwarmFactory(factory.Factory):
|
|||
model = Swarm
|
||||
|
||||
class Params:
|
||||
is_secure = False
|
||||
key_pair = factory.LazyFunction(generate_new_rsa_identity)
|
||||
muxer_opt = {MPLEX_PROTOCOL_ID: Mplex}
|
||||
key_pair = factory.LazyFunction(default_key_pair_factory)
|
||||
security_protocol = DEFAULT_SECURITY_PROTOCOL_ID
|
||||
muxer_opt = factory.LazyFunction(default_muxer_transport_factory)
|
||||
|
||||
peer_id = factory.LazyAttribute(lambda o: generate_peer_id_from(o.key_pair))
|
||||
peerstore = factory.LazyAttribute(
|
||||
|
@ -153,7 +207,8 @@ class SwarmFactory(factory.Factory):
|
|||
)
|
||||
upgrader = factory.LazyAttribute(
|
||||
lambda o: TransportUpgrader(
|
||||
security_transport_factory(o.is_secure, o.key_pair), o.muxer_opt
|
||||
(security_options_factory_factory(o.security_protocol))(o.key_pair),
|
||||
o.muxer_opt,
|
||||
)
|
||||
)
|
||||
transport = factory.LazyFunction(TCP)
|
||||
|
@ -161,7 +216,10 @@ class SwarmFactory(factory.Factory):
|
|||
@classmethod
|
||||
@asynccontextmanager
|
||||
async def create_and_listen(
|
||||
cls, is_secure: bool, key_pair: KeyPair = None, muxer_opt: TMuxerOptions = None
|
||||
cls,
|
||||
key_pair: KeyPair = None,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Swarm]:
|
||||
# `factory.Factory.__init__` does *not* prepare a *default value* if we pass
|
||||
# an argument explicitly with `None`. If an argument is `None`, we don't pass it to
|
||||
|
@ -169,9 +227,11 @@ class SwarmFactory(factory.Factory):
|
|||
optional_kwargs: Dict[str, Any] = {}
|
||||
if key_pair is not None:
|
||||
optional_kwargs["key_pair"] = key_pair
|
||||
if security_protocol is not None:
|
||||
optional_kwargs["security_protocol"] = security_protocol
|
||||
if muxer_opt is not None:
|
||||
optional_kwargs["muxer_opt"] = muxer_opt
|
||||
swarm = cls(is_secure=is_secure, **optional_kwargs)
|
||||
swarm = cls(**optional_kwargs)
|
||||
async with background_trio_service(swarm):
|
||||
await swarm.listen(LISTEN_MADDR)
|
||||
yield swarm
|
||||
|
@ -179,12 +239,17 @@ class SwarmFactory(factory.Factory):
|
|||
@classmethod
|
||||
@asynccontextmanager
|
||||
async def create_batch_and_listen(
|
||||
cls, is_secure: bool, number: int, muxer_opt: TMuxerOptions = None
|
||||
cls,
|
||||
number: int,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Tuple[Swarm, ...]]:
|
||||
async with AsyncExitStack() as stack:
|
||||
ctx_mgrs = [
|
||||
await stack.enter_async_context(
|
||||
cls.create_and_listen(is_secure=is_secure, muxer_opt=muxer_opt)
|
||||
cls.create_and_listen(
|
||||
security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
)
|
||||
)
|
||||
for _ in range(number)
|
||||
]
|
||||
|
@ -196,17 +261,27 @@ class HostFactory(factory.Factory):
|
|||
model = BasicHost
|
||||
|
||||
class Params:
|
||||
is_secure = False
|
||||
key_pair = factory.LazyFunction(generate_new_rsa_identity)
|
||||
key_pair = factory.LazyFunction(default_key_pair_factory)
|
||||
security_protocol: TProtocol = None
|
||||
muxer_opt = factory.LazyFunction(default_muxer_transport_factory)
|
||||
|
||||
network = factory.LazyAttribute(lambda o: SwarmFactory(is_secure=o.is_secure))
|
||||
network = factory.LazyAttribute(
|
||||
lambda o: SwarmFactory(
|
||||
security_protocol=o.security_protocol, muxer_opt=o.muxer_opt
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@asynccontextmanager
|
||||
async def create_batch_and_listen(
|
||||
cls, is_secure: bool, number: int
|
||||
cls,
|
||||
number: int,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Tuple[BasicHost, ...]]:
|
||||
async with SwarmFactory.create_batch_and_listen(is_secure, number) as swarms:
|
||||
async with SwarmFactory.create_batch_and_listen(
|
||||
number, security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
) as swarms:
|
||||
hosts = tuple(BasicHost(swarm) for swarm in swarms)
|
||||
yield hosts
|
||||
|
||||
|
@ -230,20 +305,29 @@ class RoutedHostFactory(factory.Factory):
|
|||
model = RoutedHost
|
||||
|
||||
class Params:
|
||||
is_secure = False
|
||||
key_pair = factory.LazyFunction(default_key_pair_factory)
|
||||
security_protocol: TProtocol = None
|
||||
muxer_opt = factory.LazyFunction(default_muxer_transport_factory)
|
||||
|
||||
network = factory.LazyAttribute(
|
||||
lambda o: HostFactory(is_secure=o.is_secure).get_network()
|
||||
lambda o: HostFactory(
|
||||
security_protocol=o.security_protocol, muxer_opt=o.muxer_opt
|
||||
).get_network()
|
||||
)
|
||||
router = factory.LazyFunction(DummyRouter)
|
||||
|
||||
@classmethod
|
||||
@asynccontextmanager
|
||||
async def create_batch_and_listen(
|
||||
cls, is_secure: bool, number: int
|
||||
cls,
|
||||
number: int,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Tuple[RoutedHost, ...]]:
|
||||
routing_table = DummyRouter()
|
||||
async with HostFactory.create_batch_and_listen(is_secure, number) as hosts:
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
number, security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
) as hosts:
|
||||
for host in hosts:
|
||||
routing_table._add_peer(host.get_id(), host.get_addrs())
|
||||
routed_hosts = tuple(
|
||||
|
@ -304,11 +388,14 @@ class PubsubFactory(factory.Factory):
|
|||
cls,
|
||||
number: int,
|
||||
routers: Sequence[IPubsubRouter],
|
||||
is_secure: bool = False,
|
||||
cache_size: int = None,
|
||||
strict_signing: bool = False,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Tuple[Pubsub, ...]]:
|
||||
async with HostFactory.create_batch_and_listen(is_secure, number) as hosts:
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
number, security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
) as hosts:
|
||||
# Pubsubs should exit before hosts
|
||||
async with AsyncExitStack() as stack:
|
||||
pubsubs = [
|
||||
|
@ -324,17 +411,23 @@ class PubsubFactory(factory.Factory):
|
|||
async def create_batch_with_floodsub(
|
||||
cls,
|
||||
number: int,
|
||||
is_secure: bool = False,
|
||||
cache_size: int = None,
|
||||
strict_signing: bool = False,
|
||||
protocols: Sequence[TProtocol] = None,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Tuple[Pubsub, ...]]:
|
||||
if protocols is not None:
|
||||
floodsubs = FloodsubFactory.create_batch(number, protocols=list(protocols))
|
||||
else:
|
||||
floodsubs = FloodsubFactory.create_batch(number)
|
||||
async with cls._create_batch_with_router(
|
||||
number, floodsubs, is_secure, cache_size, strict_signing
|
||||
number,
|
||||
floodsubs,
|
||||
cache_size,
|
||||
strict_signing,
|
||||
security_protocol=security_protocol,
|
||||
muxer_opt=muxer_opt,
|
||||
) as pubsubs:
|
||||
yield pubsubs
|
||||
|
||||
|
@ -344,7 +437,6 @@ class PubsubFactory(factory.Factory):
|
|||
cls,
|
||||
number: int,
|
||||
*,
|
||||
is_secure: bool = False,
|
||||
cache_size: int = None,
|
||||
strict_signing: bool = False,
|
||||
protocols: Sequence[TProtocol] = None,
|
||||
|
@ -356,6 +448,8 @@ class PubsubFactory(factory.Factory):
|
|||
gossip_history: int = GOSSIPSUB_PARAMS.gossip_history,
|
||||
heartbeat_interval: float = GOSSIPSUB_PARAMS.heartbeat_interval,
|
||||
heartbeat_initial_delay: float = GOSSIPSUB_PARAMS.heartbeat_initial_delay,
|
||||
security_protocol: TProtocol = None,
|
||||
muxer_opt: TMuxerOptions = None,
|
||||
) -> AsyncIterator[Tuple[Pubsub, ...]]:
|
||||
if protocols is not None:
|
||||
gossipsubs = GossipsubFactory.create_batch(
|
||||
|
@ -380,7 +474,12 @@ class PubsubFactory(factory.Factory):
|
|||
)
|
||||
|
||||
async with cls._create_batch_with_router(
|
||||
number, gossipsubs, is_secure, cache_size, strict_signing
|
||||
number,
|
||||
gossipsubs,
|
||||
cache_size,
|
||||
strict_signing,
|
||||
security_protocol=security_protocol,
|
||||
muxer_opt=muxer_opt,
|
||||
) as pubsubs:
|
||||
async with AsyncExitStack() as stack:
|
||||
for router in gossipsubs:
|
||||
|
@ -390,10 +489,10 @@ class PubsubFactory(factory.Factory):
|
|||
|
||||
@asynccontextmanager
|
||||
async def swarm_pair_factory(
|
||||
is_secure: bool, muxer_opt: TMuxerOptions = None
|
||||
security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
|
||||
) -> AsyncIterator[Tuple[Swarm, Swarm]]:
|
||||
async with SwarmFactory.create_batch_and_listen(
|
||||
is_secure, 2, muxer_opt=muxer_opt
|
||||
2, security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
) as swarms:
|
||||
await connect_swarm(swarms[0], swarms[1])
|
||||
yield swarms[0], swarms[1]
|
||||
|
@ -401,18 +500,22 @@ async def swarm_pair_factory(
|
|||
|
||||
@asynccontextmanager
|
||||
async def host_pair_factory(
|
||||
is_secure: bool
|
||||
security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
|
||||
) -> AsyncIterator[Tuple[BasicHost, BasicHost]]:
|
||||
async with HostFactory.create_batch_and_listen(is_secure, 2) as hosts:
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
) as hosts:
|
||||
await connect(hosts[0], hosts[1])
|
||||
yield hosts[0], hosts[1]
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def swarm_conn_pair_factory(
|
||||
is_secure: bool, muxer_opt: TMuxerOptions = None
|
||||
security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
|
||||
) -> AsyncIterator[Tuple[SwarmConn, SwarmConn]]:
|
||||
async with swarm_pair_factory(is_secure) as swarms:
|
||||
async with swarm_pair_factory(
|
||||
security_protocol=security_protocol, muxer_opt=muxer_opt
|
||||
) as swarms:
|
||||
conn_0 = swarms[0].connections[swarms[1].get_peer_id()]
|
||||
conn_1 = swarms[1].connections[swarms[0].get_peer_id()]
|
||||
yield cast(SwarmConn, conn_0), cast(SwarmConn, conn_1)
|
||||
|
@ -420,10 +523,11 @@ async def swarm_conn_pair_factory(
|
|||
|
||||
@asynccontextmanager
|
||||
async def mplex_conn_pair_factory(
|
||||
is_secure: bool
|
||||
security_protocol: TProtocol = None
|
||||
) -> AsyncIterator[Tuple[Mplex, Mplex]]:
|
||||
muxer_opt = {MPLEX_PROTOCOL_ID: Mplex}
|
||||
async with swarm_conn_pair_factory(is_secure, muxer_opt=muxer_opt) as swarm_pair:
|
||||
async with swarm_conn_pair_factory(
|
||||
security_protocol=security_protocol, muxer_opt=default_muxer_transport_factory()
|
||||
) as swarm_pair:
|
||||
yield (
|
||||
cast(Mplex, swarm_pair[0].muxed_conn),
|
||||
cast(Mplex, swarm_pair[1].muxed_conn),
|
||||
|
@ -432,9 +536,11 @@ async def mplex_conn_pair_factory(
|
|||
|
||||
@asynccontextmanager
|
||||
async def mplex_stream_pair_factory(
|
||||
is_secure: bool
|
||||
security_protocol: TProtocol = None
|
||||
) -> AsyncIterator[Tuple[MplexStream, MplexStream]]:
|
||||
async with mplex_conn_pair_factory(is_secure) as mplex_conn_pair_info:
|
||||
async with mplex_conn_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as mplex_conn_pair_info:
|
||||
mplex_conn_0, mplex_conn_1 = mplex_conn_pair_info
|
||||
stream_0 = cast(MplexStream, await mplex_conn_0.open_stream())
|
||||
await trio.sleep(0.01)
|
||||
|
@ -448,7 +554,7 @@ async def mplex_stream_pair_factory(
|
|||
|
||||
@asynccontextmanager
|
||||
async def net_stream_pair_factory(
|
||||
is_secure: bool
|
||||
security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
|
||||
) -> AsyncIterator[Tuple[INetStream, INetStream]]:
|
||||
protocol_id = TProtocol("/example/id/1")
|
||||
|
||||
|
@ -463,7 +569,9 @@ async def net_stream_pair_factory(
|
|||
stream_1 = stream
|
||||
await event_handler_finished.wait()
|
||||
|
||||
async with host_pair_factory(is_secure) as hosts:
|
||||
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])
|
||||
|
|
|
@ -8,6 +8,7 @@ import trio
|
|||
|
||||
from libp2p.peer.id import ID
|
||||
from libp2p.peer.peerinfo import PeerInfo, info_from_p2p_addr
|
||||
from libp2p.typing import TProtocol
|
||||
|
||||
from .constants import LOCALHOST_IP
|
||||
from .envs import GO_BIN_PATH
|
||||
|
@ -20,16 +21,14 @@ class P2PDProcess(BaseInteractiveProcess):
|
|||
def __init__(
|
||||
self,
|
||||
control_maddr: Multiaddr,
|
||||
is_secure: bool,
|
||||
security_protocol: TProtocol,
|
||||
is_pubsub_enabled: bool = True,
|
||||
is_gossipsub: bool = True,
|
||||
is_pubsub_signing: bool = False,
|
||||
is_pubsub_signing_strict: bool = False,
|
||||
) -> None:
|
||||
args = [f"-listen={control_maddr!s}"]
|
||||
# NOTE: To support `-insecure`, we need to hack `go-libp2p-daemon`.
|
||||
if not is_secure:
|
||||
args.append("-insecure=true")
|
||||
# NOTE: To support `-security`, we need to hack `go-libp2p-daemon`.
|
||||
args = [f"-listen={control_maddr!s}", f"-security={security_protocol}"]
|
||||
if is_pubsub_enabled:
|
||||
args.append("-pubsub")
|
||||
if is_gossipsub:
|
||||
|
@ -85,7 +84,7 @@ class Daemon:
|
|||
async def make_p2pd(
|
||||
daemon_control_port: int,
|
||||
client_callback_port: int,
|
||||
is_secure: bool,
|
||||
security_protocol: TProtocol,
|
||||
is_pubsub_enabled: bool = True,
|
||||
is_gossipsub: bool = True,
|
||||
is_pubsub_signing: bool = False,
|
||||
|
@ -94,7 +93,7 @@ async def make_p2pd(
|
|||
control_maddr = Multiaddr(f"/ip4/{LOCALHOST_IP}/tcp/{daemon_control_port}")
|
||||
p2pd_proc = P2PDProcess(
|
||||
control_maddr,
|
||||
is_secure,
|
||||
security_protocol,
|
||||
is_pubsub_enabled,
|
||||
is_gossipsub,
|
||||
is_pubsub_signing,
|
||||
|
|
|
@ -78,20 +78,3 @@ async def read_delim(reader: Reader) -> bytes:
|
|||
f'`msg_bytes` is not delimited by b"\\n": `msg_bytes`={msg_bytes!r}'
|
||||
)
|
||||
return msg_bytes[:-1]
|
||||
|
||||
|
||||
SIZE_LEN_BYTES = 4
|
||||
|
||||
# Fixed-prefixed read/write, used by "/plaintext/2.0.0".
|
||||
# Reference: https://github.com/libp2p/go-msgio/blob/d5bbf59d3c4240266b1d2e5df9dc993454c42011/num.go#L11-L33 # noqa: E501 # noqa: E501
|
||||
|
||||
|
||||
def encode_fixedint_prefixed(msg_bytes: bytes) -> bytes:
|
||||
len_prefix = len(msg_bytes).to_bytes(SIZE_LEN_BYTES, "big")
|
||||
return len_prefix + msg_bytes
|
||||
|
||||
|
||||
async def read_fixedint_prefixed(reader: Reader) -> bytes:
|
||||
len_bytes = await reader.read(SIZE_LEN_BYTES)
|
||||
len_int = int.from_bytes(len_bytes, "big")
|
||||
return await reader.read(len_int)
|
||||
|
|
|
@ -4,8 +4,8 @@ from libp2p.tools.factories import HostFactory
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def is_host_secure():
|
||||
return False
|
||||
def security_protocol():
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -14,6 +14,8 @@ def num_hosts():
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
async def hosts(num_hosts, is_host_secure, nursery):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, num_hosts) as _hosts:
|
||||
async def hosts(num_hosts, security_protocol, nursery):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
num_hosts, security_protocol=security_protocol
|
||||
) as _hosts:
|
||||
yield _hosts
|
||||
|
|
|
@ -92,8 +92,11 @@ async def no_common_protocol(host_a, host_b):
|
|||
"test", [(hello_world), (connect_write), (connect_read), (no_common_protocol)]
|
||||
)
|
||||
@pytest.mark.trio
|
||||
async def test_chat(test, is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async def test_chat(test, security_protocol):
|
||||
print("!@# ", security_protocol)
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
addr = hosts[0].get_addrs()[0]
|
||||
info = info_from_p2p_addr(addr)
|
||||
await hosts[1].connect(info)
|
||||
|
|
|
@ -8,8 +8,11 @@ from libp2p.tools.factories import host_pair_factory
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_ping_once(is_host_secure):
|
||||
async with host_pair_factory(is_host_secure) as (host_a, host_b):
|
||||
async def test_ping_once(security_protocol):
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
):
|
||||
stream = await host_b.new_stream(host_a.get_id(), (ID,))
|
||||
some_ping = secrets.token_bytes(PING_LENGTH)
|
||||
await stream.write(some_ping)
|
||||
|
@ -23,8 +26,11 @@ SOME_PING_COUNT = 3
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_ping_several(is_host_secure):
|
||||
async with host_pair_factory(is_host_secure) as (host_a, host_b):
|
||||
async def test_ping_several(security_protocol):
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
):
|
||||
stream = await host_b.new_stream(host_a.get_id(), (ID,))
|
||||
for _ in range(SOME_PING_COUNT):
|
||||
some_ping = secrets.token_bytes(PING_LENGTH)
|
||||
|
|
|
@ -7,7 +7,7 @@ from libp2p.tools.factories import HostFactory, RoutedHostFactory
|
|||
|
||||
@pytest.mark.trio
|
||||
async def test_host_routing_success():
|
||||
async with RoutedHostFactory.create_batch_and_listen(False, 2) as hosts:
|
||||
async with RoutedHostFactory.create_batch_and_listen(2) as hosts:
|
||||
# forces to use routing as no addrs are provided
|
||||
await hosts[0].connect(PeerInfo(hosts[1].get_id(), []))
|
||||
await hosts[1].connect(PeerInfo(hosts[0].get_id(), []))
|
||||
|
@ -15,10 +15,9 @@ async def test_host_routing_success():
|
|||
|
||||
@pytest.mark.trio
|
||||
async def test_host_routing_fail():
|
||||
is_secure = False
|
||||
async with RoutedHostFactory.create_batch_and_listen(
|
||||
is_secure, 2
|
||||
) as routed_hosts, HostFactory.create_batch_and_listen(is_secure, 1) as basic_hosts:
|
||||
2
|
||||
) as routed_hosts, HostFactory.create_batch_and_listen(1) as basic_hosts:
|
||||
# routing fails because host_c does not use routing
|
||||
with pytest.raises(ConnectionFailure):
|
||||
await routed_hosts[0].connect(PeerInfo(basic_hosts[0].get_id(), []))
|
||||
|
|
|
@ -6,8 +6,11 @@ from libp2p.tools.factories import host_pair_factory
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_identify_protocol(is_host_secure):
|
||||
async with host_pair_factory(is_host_secure) as (host_a, host_b):
|
||||
async def test_identify_protocol(security_protocol):
|
||||
async with host_pair_factory(security_protocol=security_protocol) as (
|
||||
host_a,
|
||||
host_b,
|
||||
):
|
||||
stream = await host_b.new_stream(host_a.get_id(), (ID,))
|
||||
response = await stream.read()
|
||||
await stream.close()
|
||||
|
|
|
@ -19,8 +19,10 @@ ACK_STR_3 = "ack_3:"
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_simple_messages(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async def test_simple_messages(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
hosts[1].set_stream_handler(
|
||||
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0)
|
||||
)
|
||||
|
@ -38,8 +40,10 @@ async def test_simple_messages(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_double_response(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async def test_double_response(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
|
||||
async def double_response_stream_handler(stream):
|
||||
while True:
|
||||
|
@ -78,11 +82,13 @@ async def test_double_response(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_multiple_streams(is_host_secure):
|
||||
async def test_multiple_streams(security_protocol):
|
||||
# hosts[0] should be able to open a stream with hosts[1] and then vice versa.
|
||||
# Stream IDs should be generated uniquely so that the stream state is not overwritten
|
||||
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
hosts[0].set_stream_handler(
|
||||
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0)
|
||||
)
|
||||
|
@ -115,8 +121,10 @@ async def test_multiple_streams(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_multiple_streams_same_initiator_different_protocols(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async def test_multiple_streams_same_initiator_different_protocols(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
|
||||
hosts[1].set_stream_handler(
|
||||
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0)
|
||||
|
@ -161,8 +169,10 @@ async def test_multiple_streams_same_initiator_different_protocols(is_host_secur
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_multiple_streams_two_initiators(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async def test_multiple_streams_two_initiators(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
hosts[0].set_stream_handler(
|
||||
PROTOCOL_ID_2, create_echo_stream_handler(ACK_STR_2)
|
||||
)
|
||||
|
@ -217,8 +227,10 @@ async def test_multiple_streams_two_initiators(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_triangle_nodes_connection(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 3) as hosts:
|
||||
async def test_triangle_nodes_connection(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
3, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
|
||||
hosts[0].set_stream_handler(
|
||||
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0)
|
||||
|
@ -268,8 +280,10 @@ async def test_triangle_nodes_connection(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_host_connect(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async def test_host_connect(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
assert len(hosts[0].get_peerstore().peer_ids()) == 1
|
||||
|
||||
await connect(hosts[0], hosts[1])
|
||||
|
|
|
@ -8,18 +8,22 @@ from libp2p.tools.factories import (
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
async def net_stream_pair(is_host_secure):
|
||||
async with net_stream_pair_factory(is_host_secure) as net_stream_pair:
|
||||
async def net_stream_pair(security_protocol):
|
||||
async with net_stream_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as net_stream_pair:
|
||||
yield net_stream_pair
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def swarm_pair(is_host_secure):
|
||||
async with swarm_pair_factory(is_host_secure) as swarms:
|
||||
async def swarm_pair(security_protocol):
|
||||
async with swarm_pair_factory(security_protocol=security_protocol) as swarms:
|
||||
yield swarms
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def swarm_conn_pair(is_host_secure):
|
||||
async with swarm_conn_pair_factory(is_host_secure) as swarm_conn_pair:
|
||||
async def swarm_conn_pair(security_protocol):
|
||||
async with swarm_conn_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as swarm_conn_pair:
|
||||
yield swarm_conn_pair
|
||||
|
|
|
@ -55,8 +55,8 @@ class MyNotifee(INotifee):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_notify(is_host_secure):
|
||||
swarms = [SwarmFactory(is_secure=is_host_secure) for _ in range(2)]
|
||||
async def test_notify(security_protocol):
|
||||
swarms = [SwarmFactory(security_protocol=security_protocol) for _ in range(2)]
|
||||
|
||||
events_0_0 = []
|
||||
events_1_0 = []
|
||||
|
|
|
@ -9,8 +9,10 @@ from libp2p.tools.utils import connect_swarm
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_swarm_dial_peer(is_host_secure):
|
||||
async with SwarmFactory.create_batch_and_listen(is_host_secure, 3) as swarms:
|
||||
async def test_swarm_dial_peer(security_protocol):
|
||||
async with SwarmFactory.create_batch_and_listen(
|
||||
3, security_protocol=security_protocol
|
||||
) as swarms:
|
||||
# Test: No addr found.
|
||||
with pytest.raises(SwarmException):
|
||||
await swarms[0].dial_peer(swarms[1].get_peer_id())
|
||||
|
@ -38,8 +40,10 @@ async def test_swarm_dial_peer(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_swarm_close_peer(is_host_secure):
|
||||
async with SwarmFactory.create_batch_and_listen(is_host_secure, 3) as swarms:
|
||||
async def test_swarm_close_peer(security_protocol):
|
||||
async with SwarmFactory.create_batch_and_listen(
|
||||
3, security_protocol=security_protocol
|
||||
) as swarms:
|
||||
# 0 <> 1 <> 2
|
||||
await connect_swarm(swarms[0], swarms[1])
|
||||
await connect_swarm(swarms[1], swarms[2])
|
||||
|
@ -90,8 +94,10 @@ async def test_swarm_remove_conn(swarm_pair):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_swarm_multiaddr(is_host_secure):
|
||||
async with SwarmFactory.create_batch_and_listen(is_host_secure, 3) as swarms:
|
||||
async def test_swarm_multiaddr(security_protocol):
|
||||
async with SwarmFactory.create_batch_and_listen(
|
||||
3, security_protocol=security_protocol
|
||||
) as swarms:
|
||||
|
||||
def clear():
|
||||
swarms[0].peerstore.clear_addrs(swarms[1].get_peer_id())
|
||||
|
|
|
@ -16,9 +16,11 @@ async def perform_simple_test(
|
|||
expected_selected_protocol,
|
||||
protocols_for_client,
|
||||
protocols_with_handlers,
|
||||
is_host_secure,
|
||||
security_protocol,
|
||||
):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts:
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
2, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
for protocol in protocols_with_handlers:
|
||||
hosts[1].set_stream_handler(
|
||||
protocol, create_echo_stream_handler(ACK_PREFIX)
|
||||
|
@ -38,28 +40,28 @@ async def perform_simple_test(
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_single_protocol_succeeds(is_host_secure):
|
||||
async def test_single_protocol_succeeds(security_protocol):
|
||||
expected_selected_protocol = PROTOCOL_ECHO
|
||||
await perform_simple_test(
|
||||
expected_selected_protocol,
|
||||
[expected_selected_protocol],
|
||||
[expected_selected_protocol],
|
||||
is_host_secure,
|
||||
security_protocol,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_single_protocol_fails(is_host_secure):
|
||||
async def test_single_protocol_fails(security_protocol):
|
||||
with pytest.raises(StreamFailure):
|
||||
await perform_simple_test(
|
||||
"", [PROTOCOL_ECHO], [PROTOCOL_POTATO], is_host_secure
|
||||
"", [PROTOCOL_ECHO], [PROTOCOL_POTATO], security_protocol
|
||||
)
|
||||
|
||||
# Cleanup not reached on error
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_multiple_protocol_first_is_valid_succeeds(is_host_secure):
|
||||
async def test_multiple_protocol_first_is_valid_succeeds(security_protocol):
|
||||
expected_selected_protocol = PROTOCOL_ECHO
|
||||
protocols_for_client = [PROTOCOL_ECHO, PROTOCOL_POTATO]
|
||||
protocols_for_listener = [PROTOCOL_FOO, PROTOCOL_ECHO]
|
||||
|
@ -67,12 +69,12 @@ async def test_multiple_protocol_first_is_valid_succeeds(is_host_secure):
|
|||
expected_selected_protocol,
|
||||
protocols_for_client,
|
||||
protocols_for_listener,
|
||||
is_host_secure,
|
||||
security_protocol,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_multiple_protocol_second_is_valid_succeeds(is_host_secure):
|
||||
async def test_multiple_protocol_second_is_valid_succeeds(security_protocol):
|
||||
expected_selected_protocol = PROTOCOL_FOO
|
||||
protocols_for_client = [PROTOCOL_ROCK, PROTOCOL_FOO]
|
||||
protocols_for_listener = [PROTOCOL_FOO, PROTOCOL_ECHO]
|
||||
|
@ -80,15 +82,15 @@ async def test_multiple_protocol_second_is_valid_succeeds(is_host_secure):
|
|||
expected_selected_protocol,
|
||||
protocols_for_client,
|
||||
protocols_for_listener,
|
||||
is_host_secure,
|
||||
security_protocol,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_multiple_protocol_fails(is_host_secure):
|
||||
async def test_multiple_protocol_fails(security_protocol):
|
||||
protocols_for_client = [PROTOCOL_ROCK, PROTOCOL_FOO, "/bar/1.0.0"]
|
||||
protocols_for_listener = ["/aspyn/1.0.0", "/rob/1.0.0", "/zx/1.0.0", "/alex/1.0.0"]
|
||||
with pytest.raises(StreamFailure):
|
||||
await perform_simple_test(
|
||||
"", protocols_for_client, protocols_for_listener, is_host_secure
|
||||
"", protocols_for_client, protocols_for_listener, security_protocol
|
||||
)
|
||||
|
|
|
@ -82,10 +82,11 @@ async def test_lru_cache_two_nodes(monkeypatch):
|
|||
@pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params)
|
||||
@pytest.mark.trio
|
||||
@pytest.mark.slow
|
||||
async def test_gossipsub_run_with_floodsub_tests(test_case_obj, is_host_secure):
|
||||
async def test_gossipsub_run_with_floodsub_tests(test_case_obj, security_protocol):
|
||||
await perform_test_from_obj(
|
||||
test_case_obj,
|
||||
functools.partial(
|
||||
PubsubFactory.create_batch_with_floodsub, is_secure=is_host_secure
|
||||
PubsubFactory.create_batch_with_floodsub,
|
||||
security_protocol=security_protocol,
|
||||
),
|
||||
)
|
||||
|
|
|
@ -236,7 +236,7 @@ async def test_validate_msg(is_topic_1_val_passed, is_topic_2_val_passed):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_continuously_read_stream(monkeypatch, nursery, is_host_secure):
|
||||
async def test_continuously_read_stream(monkeypatch, nursery, security_protocol):
|
||||
async def wait_for_event_occurring(event):
|
||||
await trio.hazmat.checkpoint()
|
||||
with trio.fail_after(0.1):
|
||||
|
@ -271,8 +271,10 @@ async def test_continuously_read_stream(monkeypatch, nursery, is_host_secure):
|
|||
yield Events(event_push_msg, event_handle_subscription, event_handle_rpc)
|
||||
|
||||
async with PubsubFactory.create_batch_with_floodsub(
|
||||
1, is_secure=is_host_secure
|
||||
) as pubsubs_fsub, net_stream_pair_factory(is_secure=is_host_secure) as stream_pair:
|
||||
1, security_protocol=security_protocol
|
||||
) as pubsubs_fsub, net_stream_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as stream_pair:
|
||||
await pubsubs_fsub[0].subscribe(TESTING_TOPIC)
|
||||
# Kick off the task `continuously_read_stream`
|
||||
nursery.start_soon(pubsubs_fsub[0].continuously_read_stream, stream_pair[0])
|
||||
|
@ -394,10 +396,12 @@ async def test_handle_talk():
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_message_all_peers(monkeypatch, is_host_secure):
|
||||
async def test_message_all_peers(monkeypatch, security_protocol):
|
||||
async with PubsubFactory.create_batch_with_floodsub(
|
||||
1, is_secure=is_host_secure
|
||||
) as pubsubs_fsub, net_stream_pair_factory(is_secure=is_host_secure) as stream_pair:
|
||||
1, security_protocol=security_protocol
|
||||
) as pubsubs_fsub, net_stream_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as stream_pair:
|
||||
peer_id = IDFactory()
|
||||
mock_peers = {peer_id: stream_pair[0]}
|
||||
with monkeypatch.context() as m:
|
||||
|
|
27
tests/security/noise/test_msg_read_writer.py
Normal file
27
tests/security/noise/test_msg_read_writer.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import pytest
|
||||
|
||||
from libp2p.security.noise.io import MAX_NOISE_MESSAGE_LEN, NoisePacketReadWriter
|
||||
from libp2p.tools.factories import raw_conn_factory
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"noise_msg",
|
||||
(b"", b"data", pytest.param(b"A" * MAX_NOISE_MESSAGE_LEN, id="maximum length")),
|
||||
)
|
||||
@pytest.mark.trio
|
||||
async def test_noise_msg_read_write_round_trip(nursery, noise_msg):
|
||||
async with raw_conn_factory(nursery) as conns:
|
||||
reader, writer = (
|
||||
NoisePacketReadWriter(conns[0]),
|
||||
NoisePacketReadWriter(conns[1]),
|
||||
)
|
||||
await writer.write_msg(noise_msg)
|
||||
assert (await reader.read_msg()) == noise_msg
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_noise_msg_write_too_long(nursery):
|
||||
async with raw_conn_factory(nursery) as conns:
|
||||
writer = NoisePacketReadWriter(conns[0])
|
||||
with pytest.raises(ValueError):
|
||||
await writer.write_msg(b"1" * (MAX_NOISE_MESSAGE_LEN + 1))
|
33
tests/security/noise/test_noise.py
Normal file
33
tests/security/noise/test_noise.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import pytest
|
||||
|
||||
from libp2p.security.noise.messages import NoiseHandshakePayload
|
||||
from libp2p.tools.factories import noise_conn_factory, noise_handshake_payload_factory
|
||||
|
||||
DATA_0 = b"data_0"
|
||||
DATA_1 = b"1" * 1000
|
||||
DATA_2 = b"data_2"
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_noise_transport(nursery):
|
||||
async with noise_conn_factory(nursery):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_noise_connection(nursery):
|
||||
async with noise_conn_factory(nursery) as conns:
|
||||
local_conn, remote_conn = conns
|
||||
await local_conn.write(DATA_0)
|
||||
await local_conn.write(DATA_1)
|
||||
assert DATA_0 == (await remote_conn.read(len(DATA_0)))
|
||||
assert DATA_1 == (await remote_conn.read(len(DATA_1)))
|
||||
await local_conn.write(DATA_2)
|
||||
assert DATA_2 == (await remote_conn.read(len(DATA_2)))
|
||||
|
||||
|
||||
def test_noise_handshake_payload():
|
||||
payload = noise_handshake_payload_factory()
|
||||
payload_serialized = payload.serialize()
|
||||
payload_deserialized = NoiseHandshakePayload.deserialize(payload_serialized)
|
||||
assert payload == payload_deserialized
|
|
@ -1,20 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from libp2p.tools.factories import noise_conn_factory
|
||||
|
||||
DATA = b"testing_123"
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_noise_transport(nursery):
|
||||
async with noise_conn_factory(nursery):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_noise_connection(nursery):
|
||||
async with noise_conn_factory(nursery) as conns:
|
||||
local_conn, remote_conn = conns
|
||||
await local_conn.write(DATA)
|
||||
read_data = await remote_conn.read(len(DATA))
|
||||
assert read_data == DATA
|
|
@ -1,88 +1,49 @@
|
|||
import pytest
|
||||
import trio
|
||||
|
||||
from libp2p import new_host
|
||||
from libp2p.crypto.rsa import create_new_key_pair
|
||||
from libp2p.security.insecure.transport import InsecureSession, InsecureTransport
|
||||
from libp2p.tools.constants import LISTEN_MADDR
|
||||
from libp2p.tools.utils import connect
|
||||
|
||||
# TODO: Add tests for multiple streams being opened on different
|
||||
# protocols through the same connection
|
||||
|
||||
|
||||
def peer_id_for_node(node):
|
||||
return node.get_id()
|
||||
|
||||
from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID, InsecureSession
|
||||
from libp2p.security.noise.transport import PROTOCOL_ID as NOISE_PROTOCOL_ID
|
||||
from libp2p.security.secio.transport import ID as SECIO_PROTOCOL_ID
|
||||
from libp2p.security.secure_session import SecureSession
|
||||
from libp2p.tools.factories import host_pair_factory
|
||||
|
||||
initiator_key_pair = create_new_key_pair()
|
||||
|
||||
noninitiator_key_pair = create_new_key_pair()
|
||||
|
||||
|
||||
async def perform_simple_test(
|
||||
assertion_func, transports_for_initiator, transports_for_noninitiator
|
||||
):
|
||||
# Create libp2p nodes and connect them, then secure the connection, then check
|
||||
# the proper security was chosen
|
||||
# TODO: implement -- note we need to introduce the notion of communicating over a raw connection
|
||||
# for testing, we do NOT want to communicate over a stream so we can't just create two nodes
|
||||
# and use their conn because our mplex will internally relay messages to a stream
|
||||
|
||||
node1 = new_host(key_pair=initiator_key_pair, sec_opt=transports_for_initiator)
|
||||
node2 = new_host(
|
||||
key_pair=noninitiator_key_pair, sec_opt=transports_for_noninitiator
|
||||
)
|
||||
async with node1.run(listen_addrs=[LISTEN_MADDR]), node2.run(
|
||||
listen_addrs=[LISTEN_MADDR]
|
||||
):
|
||||
await connect(node1, node2)
|
||||
|
||||
# Wait a very short period to allow conns to be stored (since the functions
|
||||
# storing the conns are async, they may happen at slightly different times
|
||||
# on each node)
|
||||
await trio.sleep(0.1)
|
||||
|
||||
# Get conns
|
||||
node1_conn = node1.get_network().connections[peer_id_for_node(node2)]
|
||||
node2_conn = node2.get_network().connections[peer_id_for_node(node1)]
|
||||
async def perform_simple_test(assertion_func, security_protocol):
|
||||
async with host_pair_factory(security_protocol=security_protocol) as hosts:
|
||||
conn_0 = hosts[0].get_network().connections[hosts[1].get_id()]
|
||||
conn_1 = hosts[1].get_network().connections[hosts[0].get_id()]
|
||||
|
||||
# Perform assertion
|
||||
assertion_func(node1_conn.muxed_conn.secured_conn)
|
||||
assertion_func(node2_conn.muxed_conn.secured_conn)
|
||||
assertion_func(conn_0.muxed_conn.secured_conn)
|
||||
assertion_func(conn_1.muxed_conn.secured_conn)
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_single_insecure_security_transport_succeeds():
|
||||
transports_for_initiator = {"foo": InsecureTransport(initiator_key_pair)}
|
||||
transports_for_noninitiator = {"foo": InsecureTransport(noninitiator_key_pair)}
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"security_protocol, transport_type",
|
||||
(
|
||||
(PLAINTEXT_PROTOCOL_ID, InsecureSession),
|
||||
(SECIO_PROTOCOL_ID, SecureSession),
|
||||
(NOISE_PROTOCOL_ID, SecureSession),
|
||||
),
|
||||
)
|
||||
@pytest.mark.trio
|
||||
async def test_single_insecure_security_transport_succeeds(
|
||||
security_protocol, transport_type
|
||||
):
|
||||
def assertion_func(conn):
|
||||
assert isinstance(conn, InsecureSession)
|
||||
assert isinstance(conn, transport_type)
|
||||
|
||||
await perform_simple_test(
|
||||
assertion_func, transports_for_initiator, transports_for_noninitiator
|
||||
)
|
||||
await perform_simple_test(assertion_func, security_protocol)
|
||||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_default_insecure_security():
|
||||
transports_for_initiator = None
|
||||
transports_for_noninitiator = None
|
||||
|
||||
conn1 = None
|
||||
conn2 = None
|
||||
|
||||
def assertion_func(conn):
|
||||
nonlocal conn1
|
||||
nonlocal conn2
|
||||
if not conn1:
|
||||
conn1 = conn
|
||||
elif not conn2:
|
||||
conn2 = conn
|
||||
else:
|
||||
assert conn1 == conn2
|
||||
assert isinstance(conn, InsecureSession)
|
||||
|
||||
await perform_simple_test(
|
||||
assertion_func, transports_for_initiator, transports_for_noninitiator
|
||||
)
|
||||
await perform_simple_test(assertion_func, None)
|
||||
|
|
|
@ -4,14 +4,18 @@ from libp2p.tools.factories import mplex_conn_pair_factory, mplex_stream_pair_fa
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
async def mplex_conn_pair(is_host_secure):
|
||||
async with mplex_conn_pair_factory(is_host_secure) as mplex_conn_pair:
|
||||
async def mplex_conn_pair(security_protocol):
|
||||
async with mplex_conn_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as mplex_conn_pair:
|
||||
assert mplex_conn_pair[0].is_initiator
|
||||
assert not mplex_conn_pair[1].is_initiator
|
||||
yield mplex_conn_pair[0], mplex_conn_pair[1]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def mplex_stream_pair(is_host_secure):
|
||||
async with mplex_stream_pair_factory(is_host_secure) as mplex_stream_pair:
|
||||
async def mplex_stream_pair(security_protocol):
|
||||
async with mplex_stream_pair_factory(
|
||||
security_protocol=security_protocol
|
||||
) as mplex_stream_pair:
|
||||
yield mplex_stream_pair
|
||||
|
|
|
@ -6,14 +6,16 @@ import pytest
|
|||
import trio
|
||||
|
||||
from libp2p.io.abc import ReadWriteCloser
|
||||
from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID
|
||||
from libp2p.security.noise.transport import PROTOCOL_ID as NOISE_PROTOCOL_ID
|
||||
from libp2p.tools.factories import HostFactory, PubsubFactory
|
||||
from libp2p.tools.interop.daemon import make_p2pd
|
||||
from libp2p.tools.interop.utils import connect
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def is_host_secure():
|
||||
return False
|
||||
@pytest.fixture(params=[PLAINTEXT_PROTOCOL_ID, NOISE_PROTOCOL_ID])
|
||||
def security_protocol(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -38,7 +40,11 @@ def is_pubsub_signing_strict():
|
|||
|
||||
@pytest.fixture
|
||||
async def p2pds(
|
||||
num_p2pds, is_host_secure, is_gossipsub, is_pubsub_signing, is_pubsub_signing_strict
|
||||
num_p2pds,
|
||||
security_protocol,
|
||||
is_gossipsub,
|
||||
is_pubsub_signing,
|
||||
is_pubsub_signing_strict,
|
||||
):
|
||||
async with AsyncExitStack() as stack:
|
||||
p2pds = [
|
||||
|
@ -46,7 +52,7 @@ async def p2pds(
|
|||
make_p2pd(
|
||||
get_unused_tcp_port(),
|
||||
get_unused_tcp_port(),
|
||||
is_host_secure,
|
||||
security_protocol,
|
||||
is_gossipsub=is_gossipsub,
|
||||
is_pubsub_signing=is_pubsub_signing,
|
||||
is_pubsub_signing_strict=is_pubsub_signing_strict,
|
||||
|
@ -62,14 +68,16 @@ async def p2pds(
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
async def pubsubs(num_hosts, is_host_secure, is_gossipsub, is_pubsub_signing_strict):
|
||||
async def pubsubs(num_hosts, security_protocol, is_gossipsub, is_pubsub_signing_strict):
|
||||
if is_gossipsub:
|
||||
yield PubsubFactory.create_batch_with_gossipsub(
|
||||
num_hosts, is_secure=is_host_secure, strict_signing=is_pubsub_signing_strict
|
||||
num_hosts,
|
||||
security_protocol=security_protocol,
|
||||
strict_signing=is_pubsub_signing_strict,
|
||||
)
|
||||
else:
|
||||
yield PubsubFactory.create_batch_with_floodsub(
|
||||
num_hosts, is_host_secure, strict_signing=is_pubsub_signing_strict
|
||||
num_hosts, security_protocol, strict_signing=is_pubsub_signing_strict
|
||||
)
|
||||
|
||||
|
||||
|
@ -97,8 +105,10 @@ async def is_to_fail_daemon_stream():
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
async def py_to_daemon_stream_pair(p2pds, is_host_secure, is_to_fail_daemon_stream):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts:
|
||||
async def py_to_daemon_stream_pair(p2pds, security_protocol, is_to_fail_daemon_stream):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
1, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
assert len(p2pds) >= 1
|
||||
host = hosts[0]
|
||||
p2pd = p2pds[0]
|
||||
|
|
|
@ -28,7 +28,7 @@ func main() {
|
|||
// Parse options from the command line
|
||||
listenF := flag.Int("l", 0, "wait for incoming connections")
|
||||
target := flag.String("d", "", "target peer to dial")
|
||||
insecure := flag.Bool("insecure", false, "use an unencrypted connection")
|
||||
protocolID := flag.String("security", "", "security protocol used for secure channel")
|
||||
seed := flag.Int64("seed", 0, "set random seed for id generation")
|
||||
flag.Parse()
|
||||
|
||||
|
@ -37,7 +37,7 @@ func main() {
|
|||
}
|
||||
|
||||
// Make a host that listens on the given multiaddress
|
||||
ha, err := utils.MakeBasicHost(*listenF, *insecure, *seed)
|
||||
ha, err := utils.MakeBasicHost(*listenF, *protocolID, *seed)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@ go 1.12
|
|||
|
||||
require (
|
||||
github.com/ipfs/go-log v0.0.1
|
||||
github.com/libp2p/go-libp2p v0.3.1
|
||||
github.com/libp2p/go-libp2p-core v0.2.2
|
||||
github.com/multiformats/go-multiaddr v0.0.4
|
||||
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc
|
||||
github.com/libp2p/go-libp2p v0.5.1
|
||||
github.com/libp2p/go-libp2p-core v0.3.0
|
||||
github.com/libp2p/go-libp2p-noise v0.0.0-20200203154915-813ed1ee6a46
|
||||
github.com/libp2p/go-libp2p-secio v0.2.1
|
||||
github.com/multiformats/go-multiaddr v0.2.0
|
||||
github.com/whyrusleeping/go-logging v0.0.1
|
||||
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f // indirect
|
||||
)
|
||||
|
|
|
@ -2,12 +2,16 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
|||
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/ChainSafe/log15 v1.0.0/go.mod h1:5v1+ALHtdW0NfAeeoYyKmzCAMcAeqkdhIg4uxXWIgOg=
|
||||
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q=
|
||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
|
@ -28,27 +32,38 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
|
||||
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
|
||||
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
|
@ -59,11 +74,18 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
|||
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8=
|
||||
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.4 h1:UlfXKrZx1DjZoBhQHmNHLC1fK1dUJDN20Y28A7s+gJ8=
|
||||
github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
|
||||
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
|
||||
github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
|
||||
github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
|
||||
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
|
||||
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
|
||||
github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s=
|
||||
github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
|
||||
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
|
||||
github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||
github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
|
||||
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
|
||||
|
@ -85,11 +107,14 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
|
|||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ=
|
||||
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
|
||||
github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ=
|
||||
github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
|
@ -105,23 +130,37 @@ github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvM
|
|||
github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4=
|
||||
github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s=
|
||||
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
|
||||
github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM=
|
||||
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
|
||||
github.com/libp2p/go-libp2p v0.3.1 h1:opd8/1Sm9zFG37LzNQsIzMTMeBabhlcX5VlvLrNZPV0=
|
||||
github.com/libp2p/go-libp2p v0.3.1/go.mod h1:e6bwxbdYH1HqWTz8faTChKGR0BjPc8p+6SyP8GTTR7Y=
|
||||
github.com/libp2p/go-libp2p v0.5.1 h1:kZ9jg+2B9IIptRcltBHKBrQdhXNNSrjCoztvrMx7tqI=
|
||||
github.com/libp2p/go-libp2p v0.5.1/go.mod h1:Os7a5Z3B+ErF4v7zgIJ7nBHNu2LYt8ZMLkTQUB3G/wA=
|
||||
github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU=
|
||||
github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8=
|
||||
github.com/libp2p/go-libp2p-autonat v0.1.1 h1:WLBZcIRsjZlWdAZj9CiBSvU2wQXoUOiS1Zk1tM7DTJI=
|
||||
github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU=
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.1 h1:eopfG9fAg6rEHWQO1TSrLosXDgYbbbu/RTva/tBANus=
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.1/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.4 h1:Phzbmrg3BkVzbqd4ZZ149JxCuUWu2wZcXf/Kr6hZJj8=
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU=
|
||||
github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco=
|
||||
github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I=
|
||||
github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE=
|
||||
github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI=
|
||||
github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs=
|
||||
github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0=
|
||||
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
|
||||
github.com/libp2p/go-libp2p-core v0.3.0 h1:F7PqduvrztDtFsAa/bcheQ3azmNo+Nq7m8hQY5GiUW8=
|
||||
github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw=
|
||||
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
|
||||
github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs=
|
||||
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
|
||||
github.com/libp2p/go-libp2p-discovery v0.2.0 h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY=
|
||||
github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg=
|
||||
github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8=
|
||||
github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90=
|
||||
github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo=
|
||||
|
@ -129,21 +168,32 @@ github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8
|
|||
github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.5 h1:/mH8pXFVKleflDL1YwqMg27W9GD8kjEx7NY0P6eGc98=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE=
|
||||
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
|
||||
github.com/libp2p/go-libp2p-noise v0.0.0-20200203154915-813ed1ee6a46 h1:Ix0osa0VFHTGiRTpgp1IoIlkCKoE18wHHl/6dXjRKmA=
|
||||
github.com/libp2p/go-libp2p-noise v0.0.0-20200203154915-813ed1ee6a46/go.mod h1:sh2qxZXxvWv/bGcO6rZR4ElbEo3G0K5zCDHqcwOOJ4Y=
|
||||
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.4 h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5gZJobNXCE/k=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs=
|
||||
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
|
||||
github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng=
|
||||
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g=
|
||||
github.com/libp2p/go-libp2p-secio v0.2.1 h1:eNWbJTdyPA7NxhP7J3c5lT97DC5d+u+IldkgCYFTPVA=
|
||||
github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8=
|
||||
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
|
||||
github.com/libp2p/go-libp2p-swarm v0.2.1 h1:9A8oQqPIZvbaRyrjViHeDYS7fE7fNtP7BRWdJrBHbe8=
|
||||
github.com/libp2p/go-libp2p-swarm v0.2.1/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU=
|
||||
github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ=
|
||||
github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU=
|
||||
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
|
||||
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
|
||||
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
|
||||
github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
|
||||
github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
|
||||
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw=
|
||||
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA=
|
||||
github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8=
|
||||
|
@ -160,7 +210,13 @@ github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA
|
|||
github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
|
||||
github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI=
|
||||
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI=
|
||||
github.com/libp2p/go-nat v0.0.4 h1:KbizNnq8YIf7+Hn7+VFL/xE0eDrkPru2zIO9NMwL8UQ=
|
||||
github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo=
|
||||
github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls=
|
||||
github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0=
|
||||
github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
|
||||
github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg=
|
||||
github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
|
||||
github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
|
||||
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
|
||||
github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4=
|
||||
|
@ -170,8 +226,12 @@ github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROm
|
|||
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
|
||||
github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o=
|
||||
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
|
||||
github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw=
|
||||
github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY=
|
||||
github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4=
|
||||
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
|
||||
github.com/libp2p/go-ws-transport v0.2.0 h1:MJCw2OrPA9+76YNRvdo1wMnSOxb9Bivj6sVFY1Xrj6w=
|
||||
github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM=
|
||||
github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||
github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI=
|
||||
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||
|
@ -180,9 +240,13 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN
|
|||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
|
||||
|
@ -191,32 +255,53 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+
|
|||
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||
github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM=
|
||||
github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
|
||||
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
||||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
|
||||
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
|
||||
github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4=
|
||||
github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
|
||||
github.com/multiformats/go-multiaddr v0.2.0 h1:lR52sFwcTCuQb6bTfnXF6zA2XfyYvyd+5a9qECv/J90=
|
||||
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
|
||||
github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
|
||||
github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8=
|
||||
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
|
||||
github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA=
|
||||
github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0=
|
||||
github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA=
|
||||
github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q=
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
|
||||
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
|
||||
github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g=
|
||||
github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU=
|
||||
github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
|
||||
github.com/multiformats/go-multiaddr-net v0.1.1 h1:jFFKUuXTXv+3ARyHZi3XUqQO+YWMKgBdhEvuGRfnL6s=
|
||||
github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
|
||||
github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=
|
||||
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
|
||||
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||
github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik=
|
||||
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
|
||||
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM=
|
||||
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ=
|
||||
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
|
||||
github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M=
|
||||
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
@ -232,6 +317,7 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
|
|||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY=
|
||||
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
|
@ -246,22 +332,29 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
|
||||
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo=
|
||||
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
|
||||
github.com/whyrusleeping/go-logging v0.0.1 h1:fwpzlmT0kRC/Fmd0MdmGgJG/CXIZ6gFq46FQZjprUcc=
|
||||
github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE=
|
||||
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg=
|
||||
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=
|
||||
github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA=
|
||||
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA=
|
||||
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds=
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
|
||||
go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
@ -270,11 +363,15 @@ golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU=
|
||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -298,20 +395,31 @@ golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
|
|
|
@ -11,13 +11,16 @@ import (
|
|||
"github.com/libp2p/go-libp2p"
|
||||
"github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
plaintext "github.com/libp2p/go-libp2p-core/sec/insecure"
|
||||
noise "github.com/libp2p/go-libp2p-noise"
|
||||
secio "github.com/libp2p/go-libp2p-secio"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// MakeBasicHost creates a LibP2P host with a random peer ID listening on the
|
||||
// given multiaddress. It won't encrypt the connection if insecure is true.
|
||||
func MakeBasicHost(listenPort int, insecure bool, randseed int64) (host.Host, error) {
|
||||
func MakeBasicHost(listenPort int, protocolID string, randseed int64) (host.Host, error) {
|
||||
|
||||
// If the seed is zero, use real cryptographic randomness. Otherwise, use a
|
||||
// deterministic randomness source to make generated keys stay the same
|
||||
|
@ -42,8 +45,22 @@ func MakeBasicHost(listenPort int, insecure bool, randseed int64) (host.Host, er
|
|||
libp2p.DisableRelay(),
|
||||
}
|
||||
|
||||
if insecure {
|
||||
if protocolID == plaintext.ID {
|
||||
opts = append(opts, libp2p.NoSecurity)
|
||||
} else if protocolID == noise.ID {
|
||||
tpt, err := noise.New(priv, noise.NoiseKeyPair(nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts = append(opts, libp2p.Security(protocolID, tpt))
|
||||
} else if protocolID == secio.ID {
|
||||
tpt, err := secio.New(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts = append(opts, libp2p.Security(protocolID, tpt))
|
||||
} else {
|
||||
return nil, fmt.Errorf("security protocolID '%s' is not supported", protocolID)
|
||||
}
|
||||
|
||||
basicHost, err := libp2p.New(context.Background(), opts...)
|
||||
|
@ -59,11 +76,7 @@ func MakeBasicHost(listenPort int, insecure bool, randseed int64) (host.Host, er
|
|||
addr := basicHost.Addrs()[0]
|
||||
fullAddr := addr.Encapsulate(hostAddr)
|
||||
log.Printf("I am %s\n", fullAddr)
|
||||
if insecure {
|
||||
log.Printf("Now run \"./echo -l %d -d %s -insecure\" on a different terminal\n", listenPort+1, fullAddr)
|
||||
} else {
|
||||
log.Printf("Now run \"./echo -l %d -d %s\" on a different terminal\n", listenPort+1, fullAddr)
|
||||
}
|
||||
log.Printf("Now run \"./echo -l %d -d %s -security %s\" on a different terminal\n", listenPort+1, fullAddr, protocolID)
|
||||
|
||||
return basicHost, nil
|
||||
}
|
||||
|
|
|
@ -6,8 +6,10 @@ from libp2p.tools.interop.utils import connect
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_connect(is_host_secure, p2pds):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts:
|
||||
async def test_connect(security_protocol, p2pds):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
1, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
p2pd = p2pds[0]
|
||||
host = hosts[0]
|
||||
assert len(await p2pd.control.list_peers()) == 0
|
||||
|
|
|
@ -20,11 +20,9 @@ class EchoProcess(BaseInteractiveProcess):
|
|||
_peer_info: PeerInfo
|
||||
|
||||
def __init__(
|
||||
self, port: int, is_secure: bool, destination: Multiaddr = None
|
||||
self, port: int, security_protocol: TProtocol, destination: Multiaddr = None
|
||||
) -> None:
|
||||
args = [f"-l={port}"]
|
||||
if not is_secure:
|
||||
args.append("-insecure")
|
||||
args = [f"-l={port}", f"-security={security_protocol}"]
|
||||
if destination is not None:
|
||||
args.append(f"-d={str(destination)}")
|
||||
|
||||
|
@ -61,9 +59,11 @@ class EchoProcess(BaseInteractiveProcess):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_insecure_conn_py_to_go(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts:
|
||||
go_proc = EchoProcess(get_unused_tcp_port(), is_host_secure)
|
||||
async def test_insecure_conn_py_to_go(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
1, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
go_proc = EchoProcess(get_unused_tcp_port(), security_protocol)
|
||||
await go_proc.start()
|
||||
|
||||
host = hosts[0]
|
||||
|
@ -78,8 +78,10 @@ async def test_insecure_conn_py_to_go(is_host_secure):
|
|||
|
||||
|
||||
@pytest.mark.trio
|
||||
async def test_insecure_conn_go_to_py(is_host_secure):
|
||||
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts:
|
||||
async def test_insecure_conn_go_to_py(security_protocol):
|
||||
async with HostFactory.create_batch_and_listen(
|
||||
1, security_protocol=security_protocol
|
||||
) as hosts:
|
||||
host = hosts[0]
|
||||
expected_data = "Hello, world!\n"
|
||||
reply_data = "Replyooo!\n"
|
||||
|
@ -94,6 +96,6 @@ async def test_insecure_conn_go_to_py(is_host_secure):
|
|||
|
||||
host.set_stream_handler(ECHO_PROTOCOL_ID, _handle_echo)
|
||||
py_maddr = host.get_addrs()[0]
|
||||
go_proc = EchoProcess(get_unused_tcp_port(), is_host_secure, py_maddr)
|
||||
go_proc = EchoProcess(get_unused_tcp_port(), security_protocol, py_maddr)
|
||||
await go_proc.start()
|
||||
await event_handler_finished.wait()
|
||||
|
|
|
@ -54,7 +54,7 @@ def validate_pubsub_msg(msg: rpc_pb2.Message, data: bytes, from_peer_id: ID) ->
|
|||
@pytest.mark.parametrize("num_p2pds", (2,))
|
||||
@pytest.mark.trio
|
||||
async def test_pubsub(
|
||||
p2pds, is_gossipsub, is_host_secure, is_pubsub_signing_strict, nursery
|
||||
p2pds, is_gossipsub, security_protocol, is_pubsub_signing_strict, nursery
|
||||
):
|
||||
pubsub_factory = None
|
||||
if is_gossipsub:
|
||||
|
@ -63,7 +63,7 @@ async def test_pubsub(
|
|||
pubsub_factory = PubsubFactory.create_batch_with_floodsub
|
||||
|
||||
async with pubsub_factory(
|
||||
1, is_secure=is_host_secure, strict_signing=is_pubsub_signing_strict
|
||||
1, security_protocol=security_protocol, strict_signing=is_pubsub_signing_strict
|
||||
) as pubsubs:
|
||||
#
|
||||
# Test: Recognize pubsub peers on connection.
|
||||
|
|
Loading…
Reference in New Issue
Block a user