Merge pull request #406 from mhchia/feature/noise-patterxx

Noise: `PatternXX` and testing with go
This commit is contained in:
Kevin Mai-Husan Chia
2020-02-28 17:13:00 +08:00
committed by GitHub
48 changed files with 1178 additions and 596 deletions

View File

@ -16,11 +16,11 @@ matrix:
env: TOXENV=docs env: TOXENV=docs
- python: 3.7 - python: 3.7
dist: xenial dist: xenial
env: TOXENV=py37-interop env: TOXENV=py37-interop GOBINPKG=go1.13.8.linux-amd64.tar.gz
sudo: true sudo: true
before_install: before_install:
- wget https://dl.google.com/go/go1.12.6.linux-amd64.tar.gz - wget https://dl.google.com/go/$GOBINPKG
- sudo tar -C /usr/local -xzf go1.12.6.linux-amd64.tar.gz - sudo tar -C /usr/local -xzf $GOBINPKG
- export GOPATH=$HOME/go - export GOPATH=$HOME/go
- export GOROOT=/usr/local/go - export GOROOT=/usr/local/go
- export PATH=$GOROOT/bin:$GOPATH/bin:$PATH - export PATH=$GOROOT/bin:$GOPATH/bin:$PATH

View File

@ -11,10 +11,26 @@ Subpackages
Submodules 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: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:

View File

@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
class Closer(ABC): class Closer(ABC):
@abstractmethod
async def close(self) -> None: async def close(self) -> None:
... ...
@ -32,3 +33,33 @@ class ReadWriter(Reader, Writer):
class ReadWriteCloser(Reader, Writer, Closer): class ReadWriteCloser(Reader, Writer, Closer):
pass 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."""

View File

@ -23,3 +23,7 @@ class MissingMessageException(MsgioException):
class DecryptionFailedException(MsgioException): class DecryptionFailedException(MsgioException):
pass pass
class MessageTooLarge(MsgioException):
pass

View File

@ -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. 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 abc import abstractmethod
from typing import Optional, cast
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.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" BYTE_ORDER = "big"
async def read_length(reader: Reader) -> int: async def read_length(reader: Reader, size_len_bytes: int) -> int:
length_bytes = await read_exactly(reader, SIZE_LEN_BYTES) length_bytes = await read_exactly(reader, size_len_bytes)
return int.from_bytes(length_bytes, byteorder=BYTE_ORDER) return int.from_bytes(length_bytes, byteorder=BYTE_ORDER)
def encode_msg_with_length(msg_bytes: bytes) -> bytes: def encode_msg_with_length(msg_bytes: bytes, size_len_bytes: int) -> bytes:
len_prefix = len(msg_bytes).to_bytes(SIZE_LEN_BYTES, "big") 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 return len_prefix + msg_bytes
class MsgIOWriter(WriteCloser): class BaseMsgReadWriter(MsgReadWriteCloser):
write_closer: WriteCloser read_write_closer: ReadWriteCloser
size_len_bytes: int
def __init__(self, write_closer: WriteCloser) -> None: def __init__(self, read_write_closer: ReadWriteCloser) -> None:
self.write_closer = write_closer self.read_write_closer = read_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()
async def read_msg(self) -> bytes: async def read_msg(self) -> bytes:
length = await self.next_msg_len() length = await self.next_msg_len()
return await read_exactly(self.read_write_closer, length)
data = await read_exactly(self.read_closer, length) @abstractmethod
if len(data) < length: async def next_msg_len(self) -> int:
self.next_length = length - len(data) ...
else:
self.next_length = None @abstractmethod
return data 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: async def next_msg_len(self) -> int:
if self.next_length is None: return await read_length(self.read_write_closer, self.size_len_bytes)
self.next_length = await read_length(self.read_closer)
return self.next_length
async def close(self) -> None: def encode_msg(self, msg: bytes) -> bytes:
await self.read_closer.close() return encode_msg_with_length(msg, self.size_len_bytes)
class MsgIOReadWriter(MsgIOReader, MsgIOWriter, Closer): class VarIntLengthMsgReadWriter(BaseMsgReadWriter):
def __init__(self, read_write_closer: ReadWriteCloser) -> None: max_msg_size: int
super().__init__(cast(ReadCloser, read_write_closer))
async def close(self) -> None: async def next_msg_len(self) -> int:
await self.read_closer.close() 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)

View File

@ -11,20 +11,22 @@ class BaseSession(ISecureConn):
local_peer: ID local_peer: ID
local_private_key: PrivateKey local_private_key: PrivateKey
remote_peer_id: ID remote_peer: ID
remote_permanent_pubkey: PublicKey remote_permanent_pubkey: PublicKey
def __init__( def __init__(
self, self,
*,
local_peer: ID, local_peer: ID,
local_private_key: PrivateKey, local_private_key: PrivateKey,
remote_peer: ID,
remote_permanent_pubkey: PublicKey,
is_initiator: bool, is_initiator: bool,
peer_id: Optional[ID] = None,
) -> None: ) -> None:
self.local_peer = local_peer self.local_peer = local_peer
self.local_private_key = local_private_key self.local_private_key = local_private_key
self.remote_peer_id = peer_id self.remote_peer = remote_peer
self.remote_permanent_pubkey = None self.remote_permanent_pubkey = remote_permanent_pubkey
self.is_initiator = is_initiator self.is_initiator = is_initiator
def get_local_peer(self) -> ID: def get_local_peer(self) -> ID:
@ -34,7 +36,7 @@ class BaseSession(ISecureConn):
return self.local_private_key return self.local_private_key
def get_remote_peer(self) -> ID: def get_remote_peer(self) -> ID:
return self.remote_peer_id return self.remote_peer
def get_remote_public_key(self) -> Optional[PublicKey]: def get_remote_public_key(self) -> Optional[PublicKey]:
return self.remote_permanent_pubkey return self.remote_permanent_pubkey

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: libp2p/security/insecure/pb/plaintext.proto # 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 message as _message
from google.protobuf import reflection as _reflection from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports) # @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
@ -20,7 +20,6 @@ DESCRIPTOR = _descriptor.FileDescriptor(
name='libp2p/security/insecure/pb/plaintext.proto', name='libp2p/security/insecure/pb/plaintext.proto',
package='plaintext.pb', package='plaintext.pb',
syntax='proto2', 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') 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,]) dependencies=[libp2p_dot_crypto_dot_pb_dot_crypto__pb2.DESCRIPTOR,])
@ -41,21 +40,21 @@ _EXCHANGE = _descriptor.Descriptor(
has_default_value=False, default_value=_b(""), has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None, is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR), options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name='pubkey', full_name='plaintext.pb.Exchange.pubkey', index=1, name='pubkey', full_name='plaintext.pb.Exchange.pubkey', index=1,
number=2, type=11, cpp_type=10, label=1, number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None, has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None, is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR), options=None, file=DESCRIPTOR),
], ],
extensions=[ extensions=[
], ],
nested_types=[], nested_types=[],
enum_types=[ enum_types=[
], ],
serialized_options=None, options=None,
is_extendable=False, is_extendable=False,
syntax='proto2', syntax='proto2',
extension_ranges=[], 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 DESCRIPTOR.message_types_by_name['Exchange'] = _EXCHANGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
Exchange = _reflection.GeneratedProtocolMessageType('Exchange', (_message.Message,), { Exchange = _reflection.GeneratedProtocolMessageType('Exchange', (_message.Message,), dict(
'DESCRIPTOR' : _EXCHANGE, DESCRIPTOR = _EXCHANGE,
'__module__' : 'libp2p.security.insecure.pb.plaintext_pb2' __module__ = 'libp2p.security.insecure.pb.plaintext_pb2'
# @@protoc_insertion_point(class_scope:plaintext.pb.Exchange) # @@protoc_insertion_point(class_scope:plaintext.pb.Exchange)
}) ))
_sym_db.RegisterMessage(Exchange) _sym_db.RegisterMessage(Exchange)

View File

@ -1,10 +1,9 @@
from typing import Optional
from libp2p.crypto.exceptions import MissingDeserializerError from libp2p.crypto.exceptions import MissingDeserializerError
from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.crypto.keys import PrivateKey, PublicKey
from libp2p.crypto.pb import crypto_pb2 from libp2p.crypto.pb import crypto_pb2
from libp2p.crypto.serialization import deserialize_public_key from libp2p.crypto.serialization import deserialize_public_key
from libp2p.io.abc import ReadWriteCloser from libp2p.io.abc import ReadWriteCloser
from libp2p.io.msgio import VarIntLengthMsgReadWriter
from libp2p.network.connection.exceptions import RawConnError from libp2p.network.connection.exceptions import RawConnError
from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID 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.exceptions import HandshakeFailure
from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.typing import TProtocol from libp2p.typing import TProtocol
from libp2p.utils import encode_fixedint_prefixed, read_fixedint_prefixed
from .pb import plaintext_pb2 from .pb import plaintext_pb2
@ -23,16 +21,28 @@ from .pb import plaintext_pb2
PLAINTEXT_PROTOCOL_ID = TProtocol("/plaintext/2.0.0") PLAINTEXT_PROTOCOL_ID = TProtocol("/plaintext/2.0.0")
class PlaintextHandshakeReadWriter(VarIntLengthMsgReadWriter):
max_msg_size = 1 << 16
class InsecureSession(BaseSession): class InsecureSession(BaseSession):
def __init__( def __init__(
self, self,
*,
local_peer: ID, local_peer: ID,
local_private_key: PrivateKey, local_private_key: PrivateKey,
conn: ReadWriteCloser, remote_peer: ID,
remote_permanent_pubkey: PublicKey,
is_initiator: bool, is_initiator: bool,
peer_id: Optional[ID] = None, conn: ReadWriteCloser,
) -> None: ) -> 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 self.conn = conn
async def write(self, data: bytes) -> None: async def write(self, data: bytes) -> None:
@ -44,60 +54,69 @@ class InsecureSession(BaseSession):
async def close(self) -> None: async def close(self) -> None:
await self.conn.close() 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: async def run_handshake(
remote_msg_bytes = await read_fixedint_prefixed(self.conn) local_peer: ID,
except RawConnError as e: local_private_key: PrivateKey,
raise HandshakeFailure("connection closed") from e conn: IRawConnection,
remote_msg = plaintext_pb2.Exchange() is_initiator: bool,
remote_msg.ParseFromString(remote_msg_bytes) remote_peer_id: ID,
received_peer_id = ID(remote_msg.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. try:
# We only need to check it when we are the initiator, because only in that condition remote_msg_bytes = await read_writer.read_msg()
# we possibly knows the `ID` of the remote. except RawConnError as e:
if self.is_initiator and self.remote_peer_id != received_peer_id: raise HandshakeFailure("connection closed") from e
raise HandshakeFailure( remote_msg = plaintext_pb2.Exchange()
"remote peer sent unexpected peer ID. " remote_msg.ParseFromString(remote_msg_bytes)
f"expected={self.remote_peer_id} received={received_peer_id}" received_peer_id = ID(remote_msg.id)
)
# Verify if the given `pubkey` matches the given `peer_id` # Verify if the receive `ID` matches the one we originally initialize the session.
try: # We only need to check it when we are the initiator, because only in that condition
received_pubkey = deserialize_public_key( # we possibly knows the `ID` of the remote.
remote_msg.pubkey.SerializeToString() if is_initiator and remote_peer_id != received_peer_id:
) raise HandshakeFailure(
except ValueError as e: "remote peer sent unexpected peer ID. "
raise HandshakeFailure( f"expected={remote_peer_id} received={received_peer_id}"
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}"
)
# Nothing is wrong. Store the `pubkey` and `peer_id` in the session. # Verify if the given `pubkey` matches the given `peer_id`
self.remote_permanent_pubkey = received_pubkey try:
# Only need to set peer's id when we don't know it before, received_pubkey = deserialize_public_key(remote_msg.pubkey.SerializeToString())
# i.e. we are not the connection initiator. except ValueError as e:
if not self.is_initiator: raise HandshakeFailure(
self.remote_peer_id = received_peer_id 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): class InsecureTransport(BaseSecureTransport):
@ -113,9 +132,9 @@ class InsecureTransport(BaseSecureTransport):
:return: secure connection object (that implements secure_conn_interface) :return: secure connection object (that implements secure_conn_interface)
""" """
session = InsecureSession(self.local_peer, self.local_private_key, conn, False) return await run_handshake(
await session.run_handshake() self.local_peer, self.local_private_key, conn, False, None
return session )
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: 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) :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 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: def make_exchange_message(pubkey: PublicKey) -> plaintext_pb2.Exchange:

View File

@ -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()

View 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

View 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)

View 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)

View File

@ -1,32 +1,28 @@
from abc import ABC, abstractmethod 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 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.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID from libp2p.peer.id import ID
from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.security.secure_session import SecureSession
from .connection import NoiseConnection from .exceptions import (
HandshakeHasNotFinished,
# FIXME: Choose a serious bound number. InvalidSignature,
NUM_BYTES_TO_READ = 2048 NoiseStateError,
PeerIDMismatchesPubkey,
)
# TODO: Merged into `BasePattern`? from .io import NoiseHandshakeReadWriter, NoiseTransportReadWriter
class PreHandshakeConnection: from .messages import (
conn: IRawConnection NoiseHandshakePayload,
make_handshake_payload_sig,
def __init__(self, conn: IRawConnection) -> None: verify_handshake_payload_sig,
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)
class IPattern(ABC): class IPattern(ABC):
@ -46,71 +42,142 @@ class BasePattern(IPattern):
noise_static_key: PrivateKey noise_static_key: PrivateKey
local_peer: ID local_peer: ID
libp2p_privkey: PrivateKey libp2p_privkey: PrivateKey
early_data: bytes
def create_noise_state(self) -> NoiseState: def create_noise_state(self) -> NoiseState:
noise_state = NoiseState.from_name(self.protocol_name) noise_state = NoiseState.from_name(self.protocol_name)
noise_state.set_keypair_from_private_bytes( 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 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): class PatternXX(BasePattern):
def __init__( 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: ) -> None:
self.protocol_name = b"Noise_XX_25519_ChaChaPoly_SHA256" self.protocol_name = b"Noise_XX_25519_ChaChaPoly_SHA256"
self.local_peer = local_peer self.local_peer = local_peer
self.libp2p_privkey = libp2p_privkey self.libp2p_privkey = libp2p_privkey
self.noise_static_key = noise_static_key self.noise_static_key = noise_static_key
self.early_data = early_data
async def handshake_inbound(self, conn: IRawConnection) -> ISecureConn: async def handshake_inbound(self, conn: IRawConnection) -> ISecureConn:
noise_state = self.create_noise_state() noise_state = self.create_noise_state()
handshake_conn = PreHandshakeConnection(conn)
noise_state.set_as_responder() noise_state.set_as_responder()
noise_state.start_handshake() noise_state.start_handshake()
msg_0_encrypted = await handshake_conn.read_msg() handshake_state = noise_state.noise_protocol.handshake_state
# TODO: Parse and save the payload from the other side. read_writer = NoiseHandshakeReadWriter(conn, noise_state)
_ = noise_state.read_message(msg_0_encrypted)
# TODO: Send our payload. # Consume msg#1.
our_payload = b"server" await read_writer.read_msg()
msg_1_encrypted = noise_state.write_message(our_payload)
await handshake_conn.write_msg(msg_1_encrypted)
msg_2_encrypted = await handshake_conn.read_msg() # Send msg#2, which should include our handshake payload.
# TODO: Parse and save another payload from the other side. our_payload = self.make_handshake_payload()
_ = noise_state.read_message(msg_2_encrypted) 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: if not noise_state.handshake_finished:
raise Exception raise HandshakeHasNotFinished(
"handshake is done but it is not marked as finished in `noise_state`"
# FIXME: `remote_peer` should be derived from the messages. )
return NoiseConnection(self.local_peer, self.libp2p_privkey, None, conn, False) 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( async def handshake_outbound(
self, conn: IRawConnection, remote_peer: ID self, conn: IRawConnection, remote_peer: ID
) -> ISecureConn: ) -> ISecureConn:
noise_state = self.create_noise_state() noise_state = self.create_noise_state()
handshake_conn = PreHandshakeConnection(conn)
read_writer = NoiseHandshakeReadWriter(conn, noise_state)
noise_state.set_as_initiator() noise_state.set_as_initiator()
noise_state.start_handshake() noise_state.start_handshake()
msg_0 = noise_state.write_message() handshake_state = noise_state.noise_protocol.handshake_state
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)
# TODO: Send our payload. # Send msg#1, which is *not* encrypted.
our_payload = b"client" msg_1 = b""
msg_2_encrypted = noise_state.write_message(our_payload) await read_writer.write_msg(msg_1)
await handshake_conn.write_msg(msg_2_encrypted)
# 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: if not noise_state.handshake_finished:
raise Exception raise HandshakeHasNotFinished(
"handshake is done but it is not marked as finished in `noise_state`"
return NoiseConnection( )
self.local_peer, self.libp2p_privkey, remote_peer, conn, False 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)

View File

@ -1,5 +1,8 @@
syntax = "proto3";
package pb;
message NoiseHandshakePayload { message NoiseHandshakePayload {
optional bytes identity_key = 1; bytes identity_key = 1;
optional bytes identity_sig = 2; bytes identity_sig = 2;
optional bytes data = 3; bytes data = 3;
} }

View File

@ -17,9 +17,9 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name='libp2p/security/noise/pb/noise.proto', name='libp2p/security/noise/pb/noise.proto',
package='', package='pb',
syntax='proto2', syntax='proto3',
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') 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( _NOISEHANDSHAKEPAYLOAD = _descriptor.Descriptor(
name='NoiseHandshakePayload', name='NoiseHandshakePayload',
full_name='NoiseHandshakePayload', full_name='pb.NoiseHandshakePayload',
filename=None, filename=None,
file=DESCRIPTOR, file=DESCRIPTOR,
containing_type=None, containing_type=None,
fields=[ fields=[
_descriptor.FieldDescriptor( _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, number=1, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""), has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None, is_extension=False, extension_scope=None,
options=None, file=DESCRIPTOR), options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor( _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, number=2, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""), has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None, is_extension=False, extension_scope=None,
options=None, file=DESCRIPTOR), options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor( _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, number=3, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""), has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
@ -61,12 +61,12 @@ _NOISEHANDSHAKEPAYLOAD = _descriptor.Descriptor(
], ],
options=None, options=None,
is_extendable=False, is_extendable=False,
syntax='proto2', syntax='proto3',
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=40, serialized_start=44,
serialized_end=121, serialized_end=125,
) )
DESCRIPTOR.message_types_by_name['NoiseHandshakePayload'] = _NOISEHANDSHAKEPAYLOAD DESCRIPTOR.message_types_by_name['NoiseHandshakePayload'] = _NOISEHANDSHAKEPAYLOAD
@ -75,7 +75,7 @@ _sym_db.RegisterFileDescriptor(DESCRIPTOR)
NoiseHandshakePayload = _reflection.GeneratedProtocolMessageType('NoiseHandshakePayload', (_message.Message,), dict( NoiseHandshakePayload = _reflection.GeneratedProtocolMessageType('NoiseHandshakePayload', (_message.Message,), dict(
DESCRIPTOR = _NOISEHANDSHAKEPAYLOAD, DESCRIPTOR = _NOISEHANDSHAKEPAYLOAD,
__module__ = 'libp2p.security.noise.pb.noise_pb2' __module__ = 'libp2p.security.noise.pb.noise_pb2'
# @@protoc_insertion_point(class_scope:NoiseHandshakePayload) # @@protoc_insertion_point(class_scope:pb.NoiseHandshakePayload)
)) ))
_sym_db.RegisterMessage(NoiseHandshakePayload) _sym_db.RegisterMessage(NoiseHandshakePayload)

View File

@ -34,8 +34,6 @@ class NoiseHandshakePayload(google___protobuf___message___Message):
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ... def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ... def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,): 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: ... def ClearField(self, field_name: typing_extensions___Literal[u"data",u"identity_key",u"identity_sig"]) -> None: ...
else: 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: ... 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: ...

View File

@ -16,6 +16,10 @@ class Transport(ISecureTransport):
local_peer: ID local_peer: ID
early_data: bytes early_data: bytes
with_noise_pipes: bool 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? # TODO: A storage of seen noise static keys for pattern IK?
def __init__( def __init__(
@ -38,18 +42,17 @@ class Transport(ISecureTransport):
if self.with_noise_pipes: if self.with_noise_pipes:
raise NotImplementedError raise NotImplementedError
else: 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: 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() pattern = self.get_pattern()
return await pattern.handshake_inbound(conn) return await pattern.handshake_inbound(conn)
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: 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() pattern = self.get_pattern()
return await pattern.handshake_outbound(conn, peer_id) return await pattern.handshake_outbound(conn, peer_id)

View File

@ -1,5 +1,4 @@
from dataclasses import dataclass from dataclasses import dataclass
import io
import itertools import itertools
from typing import Optional, Tuple 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.key_exchange import create_ephemeral_key_pair
from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.crypto.keys import PrivateKey, PublicKey
from libp2p.crypto.serialization import deserialize_public_key from libp2p.crypto.serialization import deserialize_public_key
from libp2p.io.abc import EncryptedMsgReadWriter
from libp2p.io.exceptions import DecryptionFailedException, IOException 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.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID as PeerID 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.base_transport import BaseSecureTransport
from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.security.secure_session import SecureSession
from libp2p.typing import TProtocol from libp2p.typing import TProtocol
from .exceptions import ( from .exceptions import (
@ -41,6 +41,7 @@ from .pb.spipe_pb2 import Exchange, Propose
ID = TProtocol("/secio/1.0.0") ID = TProtocol("/secio/1.0.0")
NONCE_SIZE = 16 # bytes NONCE_SIZE = 16 # bytes
SIZE_SECIO_LEN_BYTES = 4
# NOTE: the following is only a subset of allowable parameters according to the # NOTE: the following is only a subset of allowable parameters according to the
# `secio` specification. # `secio` specification.
@ -49,30 +50,24 @@ DEFAULT_SUPPORTED_CIPHERS = "AES-128"
DEFAULT_SUPPORTED_HASHES = "SHA256" DEFAULT_SUPPORTED_HASHES = "SHA256"
class SecureSession(BaseSession): class SecioPacketReadWriter(FixedSizeLenMsgReadWriter):
buf: io.BytesIO size_len_bytes = SIZE_SECIO_LEN_BYTES
low_watermark: int
high_watermark: int
class SecioMsgReadWriter(EncryptedMsgReadWriter):
read_writer: SecioPacketReadWriter
def __init__( def __init__(
self, self,
local_peer: PeerID,
local_private_key: PrivateKey,
local_encryption_parameters: AuthenticatedEncryptionParameters, local_encryption_parameters: AuthenticatedEncryptionParameters,
remote_peer: PeerID,
remote_encryption_parameters: AuthenticatedEncryptionParameters, remote_encryption_parameters: AuthenticatedEncryptionParameters,
conn: MsgIOReadWriter, read_writer: SecioPacketReadWriter,
is_initiator: bool,
) -> None: ) -> None:
super().__init__(local_peer, local_private_key, is_initiator, remote_peer)
self.conn = conn
self.local_encryption_parameters = local_encryption_parameters self.local_encryption_parameters = local_encryption_parameters
self.remote_encryption_parameters = remote_encryption_parameters self.remote_encryption_parameters = remote_encryption_parameters
self._initialize_authenticated_encryption_for_local_peer() self._initialize_authenticated_encryption_for_local_peer()
self._initialize_authenticated_encryption_for_remote_peer() self._initialize_authenticated_encryption_for_remote_peer()
self.read_writer = read_writer
self._reset_internal_buffer()
def _initialize_authenticated_encryption_for_local_peer(self) -> None: def _initialize_authenticated_encryption_for_local_peer(self) -> None:
self.local_encrypter = Encrypter(self.local_encryption_parameters) self.local_encrypter = Encrypter(self.local_encryption_parameters)
@ -80,68 +75,28 @@ class SecureSession(BaseSession):
def _initialize_authenticated_encryption_for_remote_peer(self) -> None: def _initialize_authenticated_encryption_for_remote_peer(self) -> None:
self.remote_encrypter = Encrypter(self.remote_encryption_parameters) self.remote_encrypter = Encrypter(self.remote_encryption_parameters)
async def next_msg_len(self) -> int: def encrypt(self, data: bytes) -> bytes:
return await self.conn.next_msg_len() encrypted_data = self.local_encrypter.encrypt(data)
tag = self.local_encrypter.authenticate(encrypted_data)
return encrypted_data + tag
def _reset_internal_buffer(self) -> None: def decrypt(self, data: bytes) -> bytes:
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()
try: try:
decrypted_msg = self.remote_encrypter.decrypt_if_valid(msg) decrypted_data = self.remote_encrypter.decrypt_if_valid(data)
except InvalidMACException as e: except InvalidMACException as e:
raise DecryptionFailedException() from e raise DecryptionFailedException() from e
return decrypted_msg return decrypted_data
async def write(self, data: bytes) -> None:
await self.write_msg(data)
async def write_msg(self, msg: bytes) -> None: async def write_msg(self, msg: bytes) -> None:
encrypted_data = self.local_encrypter.encrypt(msg) data_encrypted = self.encrypt(msg)
tag = self.local_encrypter.authenticate(encrypted_data) await self.read_writer.write_msg(data_encrypted)
await self.conn.write_msg(encrypted_data + tag)
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) @dataclass(frozen=True)
@ -215,7 +170,7 @@ class SessionParameters:
pass 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) await read_writer.write_msg(msg)
return await read_writer.read_msg() return await read_writer.read_msg()
@ -279,7 +234,7 @@ async def _establish_session_parameters(
local_peer: PeerID, local_peer: PeerID,
local_private_key: PrivateKey, local_private_key: PrivateKey,
remote_peer: Optional[PeerID], remote_peer: Optional[PeerID],
conn: MsgIOReadWriter, conn: SecioPacketReadWriter,
nonce: bytes, nonce: bytes,
) -> Tuple[SessionParameters, bytes]: ) -> Tuple[SessionParameters, bytes]:
# establish shared encryption parameters # establish shared encryption parameters
@ -371,7 +326,7 @@ async def _establish_session_parameters(
def _mk_session_from( def _mk_session_from(
local_private_key: PrivateKey, local_private_key: PrivateKey,
session_parameters: SessionParameters, session_parameters: SessionParameters,
conn: MsgIOReadWriter, conn: SecioPacketReadWriter,
is_initiator: bool, is_initiator: bool,
) -> SecureSession: ) -> SecureSession:
key_set1, key_set2 = initialize_pair_for_encryption( key_set1, key_set2 = initialize_pair_for_encryption(
@ -382,22 +337,24 @@ def _mk_session_from(
if session_parameters.order < 0: if session_parameters.order < 0:
key_set1, key_set2 = key_set2, key_set1 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 = SecureSession(
session_parameters.local_peer, local_peer=session_parameters.local_peer,
local_private_key, local_private_key=local_private_key,
key_set1, remote_peer=session_parameters.remote_peer,
session_parameters.remote_peer, remote_permanent_pubkey=remote_permanent_pubkey,
key_set2, is_initiator=is_initiator,
conn, conn=secio_read_writer,
is_initiator,
) )
return session return session
async def _finish_handshake(session: SecureSession, remote_nonce: bytes) -> bytes: async def _finish_handshake(session: SecureSession, remote_nonce: bytes) -> bytes:
await session.write_msg(remote_nonce) await session.conn.write_msg(remote_nonce)
return await session.read_msg() return await session.conn.read_msg()
async def create_secure_session( async def create_secure_session(
@ -414,7 +371,7 @@ async def create_secure_session(
to the ``remote_peer``. Raise `SecioException` when `conn` closed. to the ``remote_peer``. Raise `SecioException` when `conn` closed.
Raise `InconsistentNonce` when handshake failed Raise `InconsistentNonce` when handshake failed
""" """
msg_io = MsgIOReadWriter(conn) msg_io = SecioPacketReadWriter(conn)
try: try:
session_parameters, remote_nonce = await _establish_session_parameters( session_parameters, remote_nonce = await _establish_session_parameters(
local_peer, local_private_key, remote_peer, msg_io, local_nonce local_peer, local_private_key, remote_peer, msg_io, local_nonce

View 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()

View File

@ -27,7 +27,6 @@ class SecurityMultistream(ABC):
Go implementation: github.com/libp2p/go-conn-security-multistream/ssms.go 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]" transports: "OrderedDict[TProtocol, ISecureTransport]"
multiselect: Multiselect multiselect: Multiselect
multiselect_client: MultiselectClient multiselect_client: MultiselectClient

View File

@ -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_exit_stack import AsyncExitStack
from async_generator import asynccontextmanager from async_generator import asynccontextmanager
@ -29,6 +29,11 @@ from libp2p.pubsub.gossipsub import GossipSub
from libp2p.pubsub.pubsub import Pubsub from libp2p.pubsub.pubsub import Pubsub
from libp2p.routing.interfaces import IPeerRouting from libp2p.routing.interfaces import IPeerRouting
from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID, InsecureTransport 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 from libp2p.security.noise.transport import Transport as NoiseTransport
import libp2p.security.secio.transport as secio import libp2p.security.secio.transport as secio
from libp2p.security.secure_conn_interface import ISecureConn 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.stream_muxer.mplex.mplex_stream import MplexStream
from libp2p.tools.constants import GOSSIPSUB_PARAMS from libp2p.tools.constants import GOSSIPSUB_PARAMS
from libp2p.transport.tcp.tcp import TCP 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.transport.upgrader import TransportUpgrader
from libp2p.typing import TProtocol from libp2p.typing import TProtocol
from .constants import FLOODSUB_PROTOCOL_ID, GOSSIPSUB_PROTOCOL_ID, LISTEN_MADDR from .constants import FLOODSUB_PROTOCOL_ID, GOSSIPSUB_PROTOCOL_ID, LISTEN_MADDR
from .utils import connect, connect_swarm 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 IDFactory(factory.Factory):
class Meta: class Meta:
model = ID model = ID
peer_id_bytes = factory.LazyFunction( 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 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: def noise_static_key_factory() -> PrivateKey:
return create_ed25519_key_pair().private_key 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( return NoiseTransport(
libp2p_keypair=create_secp256k1_key_pair(), libp2p_keypair=key_pair,
noise_privkey=noise_static_key_factory(), noise_privkey=noise_static_key_factory(),
early_data=None, early_data=None,
with_noise_pipes=False, 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 @asynccontextmanager
async def raw_conn_factory( async def raw_conn_factory(
nursery: trio.Nursery nursery: trio.Nursery
@ -109,8 +159,12 @@ async def raw_conn_factory(
async def noise_conn_factory( async def noise_conn_factory(
nursery: trio.Nursery nursery: trio.Nursery
) -> AsyncIterator[Tuple[ISecureConn, ISecureConn]]: ) -> AsyncIterator[Tuple[ISecureConn, ISecureConn]]:
local_transport = noise_transport_factory() local_transport = cast(
remote_transport = noise_transport_factory() NoiseTransport, noise_transport_factory(create_secp256k1_key_pair())
)
remote_transport = cast(
NoiseTransport, noise_transport_factory(create_secp256k1_key_pair())
)
local_secure_conn: ISecureConn = None local_secure_conn: ISecureConn = None
remote_secure_conn: ISecureConn = None remote_secure_conn: ISecureConn = None
@ -118,7 +172,7 @@ async def noise_conn_factory(
async def upgrade_local_conn() -> None: async def upgrade_local_conn() -> None:
nonlocal local_secure_conn nonlocal local_secure_conn
local_secure_conn = await local_transport.secure_outbound( 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: async def upgrade_remote_conn() -> None:
@ -143,9 +197,9 @@ class SwarmFactory(factory.Factory):
model = Swarm model = Swarm
class Params: class Params:
is_secure = False key_pair = factory.LazyFunction(default_key_pair_factory)
key_pair = factory.LazyFunction(generate_new_rsa_identity) security_protocol = DEFAULT_SECURITY_PROTOCOL_ID
muxer_opt = {MPLEX_PROTOCOL_ID: Mplex} muxer_opt = factory.LazyFunction(default_muxer_transport_factory)
peer_id = factory.LazyAttribute(lambda o: generate_peer_id_from(o.key_pair)) peer_id = factory.LazyAttribute(lambda o: generate_peer_id_from(o.key_pair))
peerstore = factory.LazyAttribute( peerstore = factory.LazyAttribute(
@ -153,7 +207,8 @@ class SwarmFactory(factory.Factory):
) )
upgrader = factory.LazyAttribute( upgrader = factory.LazyAttribute(
lambda o: TransportUpgrader( 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) transport = factory.LazyFunction(TCP)
@ -161,7 +216,10 @@ class SwarmFactory(factory.Factory):
@classmethod @classmethod
@asynccontextmanager @asynccontextmanager
async def create_and_listen( 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]: ) -> AsyncIterator[Swarm]:
# `factory.Factory.__init__` does *not* prepare a *default value* if we pass # `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 # 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] = {} optional_kwargs: Dict[str, Any] = {}
if key_pair is not None: if key_pair is not None:
optional_kwargs["key_pair"] = key_pair optional_kwargs["key_pair"] = key_pair
if security_protocol is not None:
optional_kwargs["security_protocol"] = security_protocol
if muxer_opt is not None: if muxer_opt is not None:
optional_kwargs["muxer_opt"] = muxer_opt optional_kwargs["muxer_opt"] = muxer_opt
swarm = cls(is_secure=is_secure, **optional_kwargs) swarm = cls(**optional_kwargs)
async with background_trio_service(swarm): async with background_trio_service(swarm):
await swarm.listen(LISTEN_MADDR) await swarm.listen(LISTEN_MADDR)
yield swarm yield swarm
@ -179,12 +239,17 @@ class SwarmFactory(factory.Factory):
@classmethod @classmethod
@asynccontextmanager @asynccontextmanager
async def create_batch_and_listen( 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, ...]]: ) -> AsyncIterator[Tuple[Swarm, ...]]:
async with AsyncExitStack() as stack: async with AsyncExitStack() as stack:
ctx_mgrs = [ ctx_mgrs = [
await stack.enter_async_context( 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) for _ in range(number)
] ]
@ -196,17 +261,27 @@ class HostFactory(factory.Factory):
model = BasicHost model = BasicHost
class Params: class Params:
is_secure = False key_pair = factory.LazyFunction(default_key_pair_factory)
key_pair = factory.LazyFunction(generate_new_rsa_identity) 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 @classmethod
@asynccontextmanager @asynccontextmanager
async def create_batch_and_listen( 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, ...]]: ) -> 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) hosts = tuple(BasicHost(swarm) for swarm in swarms)
yield hosts yield hosts
@ -230,20 +305,29 @@ class RoutedHostFactory(factory.Factory):
model = RoutedHost model = RoutedHost
class Params: 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( 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) router = factory.LazyFunction(DummyRouter)
@classmethod @classmethod
@asynccontextmanager @asynccontextmanager
async def create_batch_and_listen( 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, ...]]: ) -> AsyncIterator[Tuple[RoutedHost, ...]]:
routing_table = DummyRouter() 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: for host in hosts:
routing_table._add_peer(host.get_id(), host.get_addrs()) routing_table._add_peer(host.get_id(), host.get_addrs())
routed_hosts = tuple( routed_hosts = tuple(
@ -304,11 +388,14 @@ class PubsubFactory(factory.Factory):
cls, cls,
number: int, number: int,
routers: Sequence[IPubsubRouter], routers: Sequence[IPubsubRouter],
is_secure: bool = False,
cache_size: int = None, cache_size: int = None,
strict_signing: bool = False, strict_signing: bool = False,
security_protocol: TProtocol = None,
muxer_opt: TMuxerOptions = None,
) -> AsyncIterator[Tuple[Pubsub, ...]]: ) -> 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 # Pubsubs should exit before hosts
async with AsyncExitStack() as stack: async with AsyncExitStack() as stack:
pubsubs = [ pubsubs = [
@ -324,17 +411,23 @@ class PubsubFactory(factory.Factory):
async def create_batch_with_floodsub( async def create_batch_with_floodsub(
cls, cls,
number: int, number: int,
is_secure: bool = False,
cache_size: int = None, cache_size: int = None,
strict_signing: bool = False, strict_signing: bool = False,
protocols: Sequence[TProtocol] = None, protocols: Sequence[TProtocol] = None,
security_protocol: TProtocol = None,
muxer_opt: TMuxerOptions = None,
) -> AsyncIterator[Tuple[Pubsub, ...]]: ) -> AsyncIterator[Tuple[Pubsub, ...]]:
if protocols is not None: if protocols is not None:
floodsubs = FloodsubFactory.create_batch(number, protocols=list(protocols)) floodsubs = FloodsubFactory.create_batch(number, protocols=list(protocols))
else: else:
floodsubs = FloodsubFactory.create_batch(number) floodsubs = FloodsubFactory.create_batch(number)
async with cls._create_batch_with_router( 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: ) as pubsubs:
yield pubsubs yield pubsubs
@ -344,7 +437,6 @@ class PubsubFactory(factory.Factory):
cls, cls,
number: int, number: int,
*, *,
is_secure: bool = False,
cache_size: int = None, cache_size: int = None,
strict_signing: bool = False, strict_signing: bool = False,
protocols: Sequence[TProtocol] = None, protocols: Sequence[TProtocol] = None,
@ -356,6 +448,8 @@ class PubsubFactory(factory.Factory):
gossip_history: int = GOSSIPSUB_PARAMS.gossip_history, gossip_history: int = GOSSIPSUB_PARAMS.gossip_history,
heartbeat_interval: float = GOSSIPSUB_PARAMS.heartbeat_interval, heartbeat_interval: float = GOSSIPSUB_PARAMS.heartbeat_interval,
heartbeat_initial_delay: float = GOSSIPSUB_PARAMS.heartbeat_initial_delay, heartbeat_initial_delay: float = GOSSIPSUB_PARAMS.heartbeat_initial_delay,
security_protocol: TProtocol = None,
muxer_opt: TMuxerOptions = None,
) -> AsyncIterator[Tuple[Pubsub, ...]]: ) -> AsyncIterator[Tuple[Pubsub, ...]]:
if protocols is not None: if protocols is not None:
gossipsubs = GossipsubFactory.create_batch( gossipsubs = GossipsubFactory.create_batch(
@ -380,7 +474,12 @@ class PubsubFactory(factory.Factory):
) )
async with cls._create_batch_with_router( 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: ) as pubsubs:
async with AsyncExitStack() as stack: async with AsyncExitStack() as stack:
for router in gossipsubs: for router in gossipsubs:
@ -390,10 +489,10 @@ class PubsubFactory(factory.Factory):
@asynccontextmanager @asynccontextmanager
async def swarm_pair_factory( async def swarm_pair_factory(
is_secure: bool, muxer_opt: TMuxerOptions = None security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
) -> AsyncIterator[Tuple[Swarm, Swarm]]: ) -> AsyncIterator[Tuple[Swarm, Swarm]]:
async with SwarmFactory.create_batch_and_listen( 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: ) as swarms:
await connect_swarm(swarms[0], swarms[1]) await connect_swarm(swarms[0], swarms[1])
yield swarms[0], swarms[1] yield swarms[0], swarms[1]
@ -401,18 +500,22 @@ async def swarm_pair_factory(
@asynccontextmanager @asynccontextmanager
async def host_pair_factory( async def host_pair_factory(
is_secure: bool security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
) -> AsyncIterator[Tuple[BasicHost, BasicHost]]: ) -> 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]) await connect(hosts[0], hosts[1])
yield hosts[0], hosts[1] yield hosts[0], hosts[1]
@asynccontextmanager @asynccontextmanager
async def swarm_conn_pair_factory( 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]]: ) -> 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_0 = swarms[0].connections[swarms[1].get_peer_id()]
conn_1 = swarms[1].connections[swarms[0].get_peer_id()] conn_1 = swarms[1].connections[swarms[0].get_peer_id()]
yield cast(SwarmConn, conn_0), cast(SwarmConn, conn_1) yield cast(SwarmConn, conn_0), cast(SwarmConn, conn_1)
@ -420,10 +523,11 @@ async def swarm_conn_pair_factory(
@asynccontextmanager @asynccontextmanager
async def mplex_conn_pair_factory( async def mplex_conn_pair_factory(
is_secure: bool security_protocol: TProtocol = None
) -> AsyncIterator[Tuple[Mplex, Mplex]]: ) -> AsyncIterator[Tuple[Mplex, Mplex]]:
muxer_opt = {MPLEX_PROTOCOL_ID: Mplex} async with swarm_conn_pair_factory(
async with swarm_conn_pair_factory(is_secure, muxer_opt=muxer_opt) as swarm_pair: security_protocol=security_protocol, muxer_opt=default_muxer_transport_factory()
) as swarm_pair:
yield ( yield (
cast(Mplex, swarm_pair[0].muxed_conn), cast(Mplex, swarm_pair[0].muxed_conn),
cast(Mplex, swarm_pair[1].muxed_conn), cast(Mplex, swarm_pair[1].muxed_conn),
@ -432,9 +536,11 @@ async def mplex_conn_pair_factory(
@asynccontextmanager @asynccontextmanager
async def mplex_stream_pair_factory( async def mplex_stream_pair_factory(
is_secure: bool security_protocol: TProtocol = None
) -> AsyncIterator[Tuple[MplexStream, MplexStream]]: ) -> 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 mplex_conn_0, mplex_conn_1 = mplex_conn_pair_info
stream_0 = cast(MplexStream, await mplex_conn_0.open_stream()) stream_0 = cast(MplexStream, await mplex_conn_0.open_stream())
await trio.sleep(0.01) await trio.sleep(0.01)
@ -448,7 +554,7 @@ async def mplex_stream_pair_factory(
@asynccontextmanager @asynccontextmanager
async def net_stream_pair_factory( async def net_stream_pair_factory(
is_secure: bool security_protocol: TProtocol = None, muxer_opt: TMuxerOptions = None
) -> AsyncIterator[Tuple[INetStream, INetStream]]: ) -> AsyncIterator[Tuple[INetStream, INetStream]]:
protocol_id = TProtocol("/example/id/1") protocol_id = TProtocol("/example/id/1")
@ -463,7 +569,9 @@ async def net_stream_pair_factory(
stream_1 = stream stream_1 = stream
await event_handler_finished.wait() 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) hosts[1].set_stream_handler(protocol_id, handler)
stream_0 = await hosts[0].new_stream(hosts[1].get_id(), [protocol_id]) stream_0 = await hosts[0].new_stream(hosts[1].get_id(), [protocol_id])

View File

@ -8,6 +8,7 @@ import trio
from libp2p.peer.id import ID from libp2p.peer.id import ID
from libp2p.peer.peerinfo import PeerInfo, info_from_p2p_addr from libp2p.peer.peerinfo import PeerInfo, info_from_p2p_addr
from libp2p.typing import TProtocol
from .constants import LOCALHOST_IP from .constants import LOCALHOST_IP
from .envs import GO_BIN_PATH from .envs import GO_BIN_PATH
@ -20,16 +21,14 @@ class P2PDProcess(BaseInteractiveProcess):
def __init__( def __init__(
self, self,
control_maddr: Multiaddr, control_maddr: Multiaddr,
is_secure: bool, security_protocol: TProtocol,
is_pubsub_enabled: bool = True, is_pubsub_enabled: bool = True,
is_gossipsub: bool = True, is_gossipsub: bool = True,
is_pubsub_signing: bool = False, is_pubsub_signing: bool = False,
is_pubsub_signing_strict: bool = False, is_pubsub_signing_strict: bool = False,
) -> None: ) -> None:
args = [f"-listen={control_maddr!s}"] # NOTE: To support `-security`, we need to hack `go-libp2p-daemon`.
# NOTE: To support `-insecure`, we need to hack `go-libp2p-daemon`. args = [f"-listen={control_maddr!s}", f"-security={security_protocol}"]
if not is_secure:
args.append("-insecure=true")
if is_pubsub_enabled: if is_pubsub_enabled:
args.append("-pubsub") args.append("-pubsub")
if is_gossipsub: if is_gossipsub:
@ -85,7 +84,7 @@ class Daemon:
async def make_p2pd( async def make_p2pd(
daemon_control_port: int, daemon_control_port: int,
client_callback_port: int, client_callback_port: int,
is_secure: bool, security_protocol: TProtocol,
is_pubsub_enabled: bool = True, is_pubsub_enabled: bool = True,
is_gossipsub: bool = True, is_gossipsub: bool = True,
is_pubsub_signing: bool = False, is_pubsub_signing: bool = False,
@ -94,7 +93,7 @@ async def make_p2pd(
control_maddr = Multiaddr(f"/ip4/{LOCALHOST_IP}/tcp/{daemon_control_port}") control_maddr = Multiaddr(f"/ip4/{LOCALHOST_IP}/tcp/{daemon_control_port}")
p2pd_proc = P2PDProcess( p2pd_proc = P2PDProcess(
control_maddr, control_maddr,
is_secure, security_protocol,
is_pubsub_enabled, is_pubsub_enabled,
is_gossipsub, is_gossipsub,
is_pubsub_signing, is_pubsub_signing,

View File

@ -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}' f'`msg_bytes` is not delimited by b"\\n": `msg_bytes`={msg_bytes!r}'
) )
return msg_bytes[:-1] 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)

View File

@ -4,8 +4,8 @@ from libp2p.tools.factories import HostFactory
@pytest.fixture @pytest.fixture
def is_host_secure(): def security_protocol():
return False return None
@pytest.fixture @pytest.fixture
@ -14,6 +14,8 @@ def num_hosts():
@pytest.fixture @pytest.fixture
async def hosts(num_hosts, is_host_secure, nursery): async def hosts(num_hosts, security_protocol, nursery):
async with HostFactory.create_batch_and_listen(is_host_secure, num_hosts) as _hosts: async with HostFactory.create_batch_and_listen(
num_hosts, security_protocol=security_protocol
) as _hosts:
yield _hosts yield _hosts

View File

@ -92,8 +92,11 @@ async def no_common_protocol(host_a, host_b):
"test", [(hello_world), (connect_write), (connect_read), (no_common_protocol)] "test", [(hello_world), (connect_write), (connect_read), (no_common_protocol)]
) )
@pytest.mark.trio @pytest.mark.trio
async def test_chat(test, is_host_secure): async def test_chat(test, security_protocol):
async with HostFactory.create_batch_and_listen(is_host_secure, 2) as hosts: print("!@# ", security_protocol)
async with HostFactory.create_batch_and_listen(
2, security_protocol=security_protocol
) as hosts:
addr = hosts[0].get_addrs()[0] addr = hosts[0].get_addrs()[0]
info = info_from_p2p_addr(addr) info = info_from_p2p_addr(addr)
await hosts[1].connect(info) await hosts[1].connect(info)

View File

@ -8,8 +8,11 @@ from libp2p.tools.factories import host_pair_factory
@pytest.mark.trio @pytest.mark.trio
async def test_ping_once(is_host_secure): async def test_ping_once(security_protocol):
async with host_pair_factory(is_host_secure) as (host_a, host_b): 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,)) stream = await host_b.new_stream(host_a.get_id(), (ID,))
some_ping = secrets.token_bytes(PING_LENGTH) some_ping = secrets.token_bytes(PING_LENGTH)
await stream.write(some_ping) await stream.write(some_ping)
@ -23,8 +26,11 @@ SOME_PING_COUNT = 3
@pytest.mark.trio @pytest.mark.trio
async def test_ping_several(is_host_secure): async def test_ping_several(security_protocol):
async with host_pair_factory(is_host_secure) as (host_a, host_b): 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,)) stream = await host_b.new_stream(host_a.get_id(), (ID,))
for _ in range(SOME_PING_COUNT): for _ in range(SOME_PING_COUNT):
some_ping = secrets.token_bytes(PING_LENGTH) some_ping = secrets.token_bytes(PING_LENGTH)

View File

@ -7,7 +7,7 @@ from libp2p.tools.factories import HostFactory, RoutedHostFactory
@pytest.mark.trio @pytest.mark.trio
async def test_host_routing_success(): 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 # forces to use routing as no addrs are provided
await hosts[0].connect(PeerInfo(hosts[1].get_id(), [])) await hosts[0].connect(PeerInfo(hosts[1].get_id(), []))
await hosts[1].connect(PeerInfo(hosts[0].get_id(), [])) await hosts[1].connect(PeerInfo(hosts[0].get_id(), []))
@ -15,10 +15,9 @@ async def test_host_routing_success():
@pytest.mark.trio @pytest.mark.trio
async def test_host_routing_fail(): async def test_host_routing_fail():
is_secure = False
async with RoutedHostFactory.create_batch_and_listen( async with RoutedHostFactory.create_batch_and_listen(
is_secure, 2 2
) as routed_hosts, HostFactory.create_batch_and_listen(is_secure, 1) as basic_hosts: ) as routed_hosts, HostFactory.create_batch_and_listen(1) as basic_hosts:
# routing fails because host_c does not use routing # routing fails because host_c does not use routing
with pytest.raises(ConnectionFailure): with pytest.raises(ConnectionFailure):
await routed_hosts[0].connect(PeerInfo(basic_hosts[0].get_id(), [])) await routed_hosts[0].connect(PeerInfo(basic_hosts[0].get_id(), []))

View File

@ -6,8 +6,11 @@ from libp2p.tools.factories import host_pair_factory
@pytest.mark.trio @pytest.mark.trio
async def test_identify_protocol(is_host_secure): async def test_identify_protocol(security_protocol):
async with host_pair_factory(is_host_secure) as (host_a, host_b): 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,)) stream = await host_b.new_stream(host_a.get_id(), (ID,))
response = await stream.read() response = await stream.read()
await stream.close() await stream.close()

View File

@ -19,8 +19,10 @@ ACK_STR_3 = "ack_3:"
@pytest.mark.trio @pytest.mark.trio
async def test_simple_messages(is_host_secure): async def test_simple_messages(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:
hosts[1].set_stream_handler( hosts[1].set_stream_handler(
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0) 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 @pytest.mark.trio
async def test_double_response(is_host_secure): async def test_double_response(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:
async def double_response_stream_handler(stream): async def double_response_stream_handler(stream):
while True: while True:
@ -78,11 +82,13 @@ async def test_double_response(is_host_secure):
@pytest.mark.trio @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. # 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 # 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( hosts[0].set_stream_handler(
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0) 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 @pytest.mark.trio
async def test_multiple_streams_same_initiator_different_protocols(is_host_secure): async def test_multiple_streams_same_initiator_different_protocols(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:
hosts[1].set_stream_handler( hosts[1].set_stream_handler(
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0) 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 @pytest.mark.trio
async def test_multiple_streams_two_initiators(is_host_secure): async def test_multiple_streams_two_initiators(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:
hosts[0].set_stream_handler( hosts[0].set_stream_handler(
PROTOCOL_ID_2, create_echo_stream_handler(ACK_STR_2) 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 @pytest.mark.trio
async def test_triangle_nodes_connection(is_host_secure): async def test_triangle_nodes_connection(security_protocol):
async with HostFactory.create_batch_and_listen(is_host_secure, 3) as hosts: async with HostFactory.create_batch_and_listen(
3, security_protocol=security_protocol
) as hosts:
hosts[0].set_stream_handler( hosts[0].set_stream_handler(
PROTOCOL_ID_0, create_echo_stream_handler(ACK_STR_0) 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 @pytest.mark.trio
async def test_host_connect(is_host_secure): async def test_host_connect(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:
assert len(hosts[0].get_peerstore().peer_ids()) == 1 assert len(hosts[0].get_peerstore().peer_ids()) == 1
await connect(hosts[0], hosts[1]) await connect(hosts[0], hosts[1])

View File

@ -8,18 +8,22 @@ from libp2p.tools.factories import (
@pytest.fixture @pytest.fixture
async def net_stream_pair(is_host_secure): async def net_stream_pair(security_protocol):
async with net_stream_pair_factory(is_host_secure) as net_stream_pair: async with net_stream_pair_factory(
security_protocol=security_protocol
) as net_stream_pair:
yield net_stream_pair yield net_stream_pair
@pytest.fixture @pytest.fixture
async def swarm_pair(is_host_secure): async def swarm_pair(security_protocol):
async with swarm_pair_factory(is_host_secure) as swarms: async with swarm_pair_factory(security_protocol=security_protocol) as swarms:
yield swarms yield swarms
@pytest.fixture @pytest.fixture
async def swarm_conn_pair(is_host_secure): async def swarm_conn_pair(security_protocol):
async with swarm_conn_pair_factory(is_host_secure) as swarm_conn_pair: async with swarm_conn_pair_factory(
security_protocol=security_protocol
) as swarm_conn_pair:
yield swarm_conn_pair yield swarm_conn_pair

View File

@ -55,8 +55,8 @@ class MyNotifee(INotifee):
@pytest.mark.trio @pytest.mark.trio
async def test_notify(is_host_secure): async def test_notify(security_protocol):
swarms = [SwarmFactory(is_secure=is_host_secure) for _ in range(2)] swarms = [SwarmFactory(security_protocol=security_protocol) for _ in range(2)]
events_0_0 = [] events_0_0 = []
events_1_0 = [] events_1_0 = []

View File

@ -9,8 +9,10 @@ from libp2p.tools.utils import connect_swarm
@pytest.mark.trio @pytest.mark.trio
async def test_swarm_dial_peer(is_host_secure): async def test_swarm_dial_peer(security_protocol):
async with SwarmFactory.create_batch_and_listen(is_host_secure, 3) as swarms: async with SwarmFactory.create_batch_and_listen(
3, security_protocol=security_protocol
) as swarms:
# Test: No addr found. # Test: No addr found.
with pytest.raises(SwarmException): with pytest.raises(SwarmException):
await swarms[0].dial_peer(swarms[1].get_peer_id()) 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 @pytest.mark.trio
async def test_swarm_close_peer(is_host_secure): async def test_swarm_close_peer(security_protocol):
async with SwarmFactory.create_batch_and_listen(is_host_secure, 3) as swarms: async with SwarmFactory.create_batch_and_listen(
3, security_protocol=security_protocol
) as swarms:
# 0 <> 1 <> 2 # 0 <> 1 <> 2
await connect_swarm(swarms[0], swarms[1]) await connect_swarm(swarms[0], swarms[1])
await connect_swarm(swarms[1], swarms[2]) await connect_swarm(swarms[1], swarms[2])
@ -90,8 +94,10 @@ async def test_swarm_remove_conn(swarm_pair):
@pytest.mark.trio @pytest.mark.trio
async def test_swarm_multiaddr(is_host_secure): async def test_swarm_multiaddr(security_protocol):
async with SwarmFactory.create_batch_and_listen(is_host_secure, 3) as swarms: async with SwarmFactory.create_batch_and_listen(
3, security_protocol=security_protocol
) as swarms:
def clear(): def clear():
swarms[0].peerstore.clear_addrs(swarms[1].get_peer_id()) swarms[0].peerstore.clear_addrs(swarms[1].get_peer_id())

View File

@ -16,9 +16,11 @@ async def perform_simple_test(
expected_selected_protocol, expected_selected_protocol,
protocols_for_client, protocols_for_client,
protocols_with_handlers, 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: for protocol in protocols_with_handlers:
hosts[1].set_stream_handler( hosts[1].set_stream_handler(
protocol, create_echo_stream_handler(ACK_PREFIX) protocol, create_echo_stream_handler(ACK_PREFIX)
@ -38,28 +40,28 @@ async def perform_simple_test(
@pytest.mark.trio @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 expected_selected_protocol = PROTOCOL_ECHO
await perform_simple_test( await perform_simple_test(
expected_selected_protocol, expected_selected_protocol,
[expected_selected_protocol], [expected_selected_protocol],
[expected_selected_protocol], [expected_selected_protocol],
is_host_secure, security_protocol,
) )
@pytest.mark.trio @pytest.mark.trio
async def test_single_protocol_fails(is_host_secure): async def test_single_protocol_fails(security_protocol):
with pytest.raises(StreamFailure): with pytest.raises(StreamFailure):
await perform_simple_test( await perform_simple_test(
"", [PROTOCOL_ECHO], [PROTOCOL_POTATO], is_host_secure "", [PROTOCOL_ECHO], [PROTOCOL_POTATO], security_protocol
) )
# Cleanup not reached on error # Cleanup not reached on error
@pytest.mark.trio @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 expected_selected_protocol = PROTOCOL_ECHO
protocols_for_client = [PROTOCOL_ECHO, PROTOCOL_POTATO] protocols_for_client = [PROTOCOL_ECHO, PROTOCOL_POTATO]
protocols_for_listener = [PROTOCOL_FOO, PROTOCOL_ECHO] 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, expected_selected_protocol,
protocols_for_client, protocols_for_client,
protocols_for_listener, protocols_for_listener,
is_host_secure, security_protocol,
) )
@pytest.mark.trio @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 expected_selected_protocol = PROTOCOL_FOO
protocols_for_client = [PROTOCOL_ROCK, PROTOCOL_FOO] protocols_for_client = [PROTOCOL_ROCK, PROTOCOL_FOO]
protocols_for_listener = [PROTOCOL_FOO, PROTOCOL_ECHO] 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, expected_selected_protocol,
protocols_for_client, protocols_for_client,
protocols_for_listener, protocols_for_listener,
is_host_secure, security_protocol,
) )
@pytest.mark.trio @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_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"] protocols_for_listener = ["/aspyn/1.0.0", "/rob/1.0.0", "/zx/1.0.0", "/alex/1.0.0"]
with pytest.raises(StreamFailure): with pytest.raises(StreamFailure):
await perform_simple_test( await perform_simple_test(
"", protocols_for_client, protocols_for_listener, is_host_secure "", protocols_for_client, protocols_for_listener, security_protocol
) )

View File

@ -82,10 +82,11 @@ async def test_lru_cache_two_nodes(monkeypatch):
@pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params) @pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params)
@pytest.mark.trio @pytest.mark.trio
@pytest.mark.slow @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( await perform_test_from_obj(
test_case_obj, test_case_obj,
functools.partial( functools.partial(
PubsubFactory.create_batch_with_floodsub, is_secure=is_host_secure PubsubFactory.create_batch_with_floodsub,
security_protocol=security_protocol,
), ),
) )

View File

@ -236,7 +236,7 @@ async def test_validate_msg(is_topic_1_val_passed, is_topic_2_val_passed):
@pytest.mark.trio @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): async def wait_for_event_occurring(event):
await trio.hazmat.checkpoint() await trio.hazmat.checkpoint()
with trio.fail_after(0.1): 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) yield Events(event_push_msg, event_handle_subscription, event_handle_rpc)
async with PubsubFactory.create_batch_with_floodsub( async with PubsubFactory.create_batch_with_floodsub(
1, is_secure=is_host_secure 1, security_protocol=security_protocol
) as pubsubs_fsub, net_stream_pair_factory(is_secure=is_host_secure) as stream_pair: ) as pubsubs_fsub, net_stream_pair_factory(
security_protocol=security_protocol
) as stream_pair:
await pubsubs_fsub[0].subscribe(TESTING_TOPIC) await pubsubs_fsub[0].subscribe(TESTING_TOPIC)
# Kick off the task `continuously_read_stream` # Kick off the task `continuously_read_stream`
nursery.start_soon(pubsubs_fsub[0].continuously_read_stream, stream_pair[0]) nursery.start_soon(pubsubs_fsub[0].continuously_read_stream, stream_pair[0])
@ -394,10 +396,12 @@ async def test_handle_talk():
@pytest.mark.trio @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( async with PubsubFactory.create_batch_with_floodsub(
1, is_secure=is_host_secure 1, security_protocol=security_protocol
) as pubsubs_fsub, net_stream_pair_factory(is_secure=is_host_secure) as stream_pair: ) as pubsubs_fsub, net_stream_pair_factory(
security_protocol=security_protocol
) as stream_pair:
peer_id = IDFactory() peer_id = IDFactory()
mock_peers = {peer_id: stream_pair[0]} mock_peers = {peer_id: stream_pair[0]}
with monkeypatch.context() as m: with monkeypatch.context() as m:

View 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))

View 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

View File

@ -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

View File

@ -1,88 +1,49 @@
import pytest import pytest
import trio
from libp2p import new_host
from libp2p.crypto.rsa import create_new_key_pair from libp2p.crypto.rsa import create_new_key_pair
from libp2p.security.insecure.transport import InsecureSession, InsecureTransport from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID, InsecureSession
from libp2p.tools.constants import LISTEN_MADDR from libp2p.security.noise.transport import PROTOCOL_ID as NOISE_PROTOCOL_ID
from libp2p.tools.utils import connect from libp2p.security.secio.transport import ID as SECIO_PROTOCOL_ID
from libp2p.security.secure_session import SecureSession
# TODO: Add tests for multiple streams being opened on different from libp2p.tools.factories import host_pair_factory
# protocols through the same connection
def peer_id_for_node(node):
return node.get_id()
initiator_key_pair = create_new_key_pair() initiator_key_pair = create_new_key_pair()
noninitiator_key_pair = create_new_key_pair() noninitiator_key_pair = create_new_key_pair()
async def perform_simple_test( async def perform_simple_test(assertion_func, security_protocol):
assertion_func, transports_for_initiator, transports_for_noninitiator async with host_pair_factory(security_protocol=security_protocol) as hosts:
): conn_0 = hosts[0].get_network().connections[hosts[1].get_id()]
# Create libp2p nodes and connect them, then secure the connection, then check conn_1 = hosts[1].get_network().connections[hosts[0].get_id()]
# 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)]
# Perform assertion # Perform assertion
assertion_func(node1_conn.muxed_conn.secured_conn) assertion_func(conn_0.muxed_conn.secured_conn)
assertion_func(node2_conn.muxed_conn.secured_conn) assertion_func(conn_1.muxed_conn.secured_conn)
@pytest.mark.trio @pytest.mark.trio
async def test_single_insecure_security_transport_succeeds(): @pytest.mark.parametrize(
transports_for_initiator = {"foo": InsecureTransport(initiator_key_pair)} "security_protocol, transport_type",
transports_for_noninitiator = {"foo": InsecureTransport(noninitiator_key_pair)} (
(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): def assertion_func(conn):
assert isinstance(conn, InsecureSession) assert isinstance(conn, transport_type)
await perform_simple_test( await perform_simple_test(assertion_func, security_protocol)
assertion_func, transports_for_initiator, transports_for_noninitiator
)
@pytest.mark.trio @pytest.mark.trio
async def test_default_insecure_security(): async def test_default_insecure_security():
transports_for_initiator = None
transports_for_noninitiator = None
conn1 = None
conn2 = None
def assertion_func(conn): def assertion_func(conn):
nonlocal conn1 assert isinstance(conn, InsecureSession)
nonlocal conn2
if not conn1:
conn1 = conn
elif not conn2:
conn2 = conn
else:
assert conn1 == conn2
await perform_simple_test( await perform_simple_test(assertion_func, None)
assertion_func, transports_for_initiator, transports_for_noninitiator
)

View File

@ -4,14 +4,18 @@ from libp2p.tools.factories import mplex_conn_pair_factory, mplex_stream_pair_fa
@pytest.fixture @pytest.fixture
async def mplex_conn_pair(is_host_secure): async def mplex_conn_pair(security_protocol):
async with mplex_conn_pair_factory(is_host_secure) as mplex_conn_pair: async with mplex_conn_pair_factory(
security_protocol=security_protocol
) as mplex_conn_pair:
assert mplex_conn_pair[0].is_initiator assert mplex_conn_pair[0].is_initiator
assert not mplex_conn_pair[1].is_initiator assert not mplex_conn_pair[1].is_initiator
yield mplex_conn_pair[0], mplex_conn_pair[1] yield mplex_conn_pair[0], mplex_conn_pair[1]
@pytest.fixture @pytest.fixture
async def mplex_stream_pair(is_host_secure): async def mplex_stream_pair(security_protocol):
async with mplex_stream_pair_factory(is_host_secure) as mplex_stream_pair: async with mplex_stream_pair_factory(
security_protocol=security_protocol
) as mplex_stream_pair:
yield mplex_stream_pair yield mplex_stream_pair

View File

@ -6,14 +6,16 @@ import pytest
import trio import trio
from libp2p.io.abc import ReadWriteCloser 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.factories import HostFactory, PubsubFactory
from libp2p.tools.interop.daemon import make_p2pd from libp2p.tools.interop.daemon import make_p2pd
from libp2p.tools.interop.utils import connect from libp2p.tools.interop.utils import connect
@pytest.fixture @pytest.fixture(params=[PLAINTEXT_PROTOCOL_ID, NOISE_PROTOCOL_ID])
def is_host_secure(): def security_protocol(request):
return False return request.param
@pytest.fixture @pytest.fixture
@ -38,7 +40,11 @@ def is_pubsub_signing_strict():
@pytest.fixture @pytest.fixture
async def p2pds( 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: async with AsyncExitStack() as stack:
p2pds = [ p2pds = [
@ -46,7 +52,7 @@ async def p2pds(
make_p2pd( make_p2pd(
get_unused_tcp_port(), get_unused_tcp_port(),
get_unused_tcp_port(), get_unused_tcp_port(),
is_host_secure, security_protocol,
is_gossipsub=is_gossipsub, is_gossipsub=is_gossipsub,
is_pubsub_signing=is_pubsub_signing, is_pubsub_signing=is_pubsub_signing,
is_pubsub_signing_strict=is_pubsub_signing_strict, is_pubsub_signing_strict=is_pubsub_signing_strict,
@ -62,14 +68,16 @@ async def p2pds(
@pytest.fixture @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: if is_gossipsub:
yield PubsubFactory.create_batch_with_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: else:
yield PubsubFactory.create_batch_with_floodsub( 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 @pytest.fixture
async def py_to_daemon_stream_pair(p2pds, is_host_secure, is_to_fail_daemon_stream): async def py_to_daemon_stream_pair(p2pds, security_protocol, is_to_fail_daemon_stream):
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts: async with HostFactory.create_batch_and_listen(
1, security_protocol=security_protocol
) as hosts:
assert len(p2pds) >= 1 assert len(p2pds) >= 1
host = hosts[0] host = hosts[0]
p2pd = p2pds[0] p2pd = p2pds[0]

View File

@ -28,7 +28,7 @@ func main() {
// Parse options from the command line // Parse options from the command line
listenF := flag.Int("l", 0, "wait for incoming connections") listenF := flag.Int("l", 0, "wait for incoming connections")
target := flag.String("d", "", "target peer to dial") 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") seed := flag.Int64("seed", 0, "set random seed for id generation")
flag.Parse() flag.Parse()
@ -37,7 +37,7 @@ func main() {
} }
// Make a host that listens on the given multiaddress // 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 { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -4,8 +4,11 @@ go 1.12
require ( require (
github.com/ipfs/go-log v0.0.1 github.com/ipfs/go-log v0.0.1
github.com/libp2p/go-libp2p v0.3.1 github.com/libp2p/go-libp2p v0.5.1
github.com/libp2p/go-libp2p-core v0.2.2 github.com/libp2p/go-libp2p-core v0.3.0
github.com/multiformats/go-multiaddr v0.0.4 github.com/libp2p/go-libp2p-noise v0.0.0-20200203154915-813ed1ee6a46
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc 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
) )

View File

@ -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-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/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/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/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/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/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-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 h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= 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/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-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= 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/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.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-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-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/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/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/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-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 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 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/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/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.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.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.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/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.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 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 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/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/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.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/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/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= 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.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= 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.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.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-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.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.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.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-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 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= 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/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/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.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/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/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/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 h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ=
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= 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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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= 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-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 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= 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 h1:opd8/1Sm9zFG37LzNQsIzMTMeBabhlcX5VlvLrNZPV0=
github.com/libp2p/go-libp2p v0.3.1/go.mod h1:e6bwxbdYH1HqWTz8faTChKGR0BjPc8p+6SyP8GTTR7Y= 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 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.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.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.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 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.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.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.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.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.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 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs=
github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= 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-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 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.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 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-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= 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-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 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw=
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= 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-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-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.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 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.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.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 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng=
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= 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.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 h1:9A8oQqPIZvbaRyrjViHeDYS7fE7fNtP7BRWdJrBHbe8=
github.com/libp2p/go-libp2p-swarm v0.2.1/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU= 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.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.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.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.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 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw=
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= 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= 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-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 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI=
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= 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.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 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= 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= 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-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 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o=
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= 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 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4=
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= 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.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 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI=
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 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.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 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 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.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 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 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/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/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= 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.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 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.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/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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.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.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 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 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 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 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.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.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 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4=
github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 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.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 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8=
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= 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 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.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 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g=
github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= 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 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 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.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 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.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 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ=
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= 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.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.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.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/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= 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/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/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 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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/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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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/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/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-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 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.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 h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg=
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= 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 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA=
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= 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-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 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds=
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= 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/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= 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 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 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-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-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-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-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-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 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU=
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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/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-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-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-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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/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-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-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-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 h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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-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-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-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-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.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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-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-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-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.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 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/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=

View File

@ -11,13 +11,16 @@ import (
"github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host" "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" ma "github.com/multiformats/go-multiaddr"
) )
// MakeBasicHost creates a LibP2P host with a random peer ID listening on the // 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. // 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 // If the seed is zero, use real cryptographic randomness. Otherwise, use a
// deterministic randomness source to make generated keys stay the same // 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(), libp2p.DisableRelay(),
} }
if insecure { if protocolID == plaintext.ID {
opts = append(opts, libp2p.NoSecurity) 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...) 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] addr := basicHost.Addrs()[0]
fullAddr := addr.Encapsulate(hostAddr) fullAddr := addr.Encapsulate(hostAddr)
log.Printf("I am %s\n", fullAddr) log.Printf("I am %s\n", fullAddr)
if insecure { log.Printf("Now run \"./echo -l %d -d %s -security %s\" on a different terminal\n", listenPort+1, fullAddr, protocolID)
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)
}
return basicHost, nil return basicHost, nil
} }

View File

@ -6,8 +6,10 @@ from libp2p.tools.interop.utils import connect
@pytest.mark.trio @pytest.mark.trio
async def test_connect(is_host_secure, p2pds): async def test_connect(security_protocol, p2pds):
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts: async with HostFactory.create_batch_and_listen(
1, security_protocol=security_protocol
) as hosts:
p2pd = p2pds[0] p2pd = p2pds[0]
host = hosts[0] host = hosts[0]
assert len(await p2pd.control.list_peers()) == 0 assert len(await p2pd.control.list_peers()) == 0

View File

@ -20,11 +20,9 @@ class EchoProcess(BaseInteractiveProcess):
_peer_info: PeerInfo _peer_info: PeerInfo
def __init__( def __init__(
self, port: int, is_secure: bool, destination: Multiaddr = None self, port: int, security_protocol: TProtocol, destination: Multiaddr = None
) -> None: ) -> None:
args = [f"-l={port}"] args = [f"-l={port}", f"-security={security_protocol}"]
if not is_secure:
args.append("-insecure")
if destination is not None: if destination is not None:
args.append(f"-d={str(destination)}") args.append(f"-d={str(destination)}")
@ -61,9 +59,11 @@ class EchoProcess(BaseInteractiveProcess):
@pytest.mark.trio @pytest.mark.trio
async def test_insecure_conn_py_to_go(is_host_secure): async def test_insecure_conn_py_to_go(security_protocol):
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts: async with HostFactory.create_batch_and_listen(
go_proc = EchoProcess(get_unused_tcp_port(), is_host_secure) 1, security_protocol=security_protocol
) as hosts:
go_proc = EchoProcess(get_unused_tcp_port(), security_protocol)
await go_proc.start() await go_proc.start()
host = hosts[0] host = hosts[0]
@ -78,8 +78,10 @@ async def test_insecure_conn_py_to_go(is_host_secure):
@pytest.mark.trio @pytest.mark.trio
async def test_insecure_conn_go_to_py(is_host_secure): async def test_insecure_conn_go_to_py(security_protocol):
async with HostFactory.create_batch_and_listen(is_host_secure, 1) as hosts: async with HostFactory.create_batch_and_listen(
1, security_protocol=security_protocol
) as hosts:
host = hosts[0] host = hosts[0]
expected_data = "Hello, world!\n" expected_data = "Hello, world!\n"
reply_data = "Replyooo!\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) host.set_stream_handler(ECHO_PROTOCOL_ID, _handle_echo)
py_maddr = host.get_addrs()[0] 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 go_proc.start()
await event_handler_finished.wait() await event_handler_finished.wait()

View File

@ -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.parametrize("num_p2pds", (2,))
@pytest.mark.trio @pytest.mark.trio
async def test_pubsub( 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 pubsub_factory = None
if is_gossipsub: if is_gossipsub:
@ -63,7 +63,7 @@ async def test_pubsub(
pubsub_factory = PubsubFactory.create_batch_with_floodsub pubsub_factory = PubsubFactory.create_batch_with_floodsub
async with pubsub_factory( 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: ) as pubsubs:
# #
# Test: Recognize pubsub peers on connection. # Test: Recognize pubsub peers on connection.