mirror of
https://github.com/varun-r-mallya/py-libp2p.git
synced 2026-02-12 16:10:57 +00:00
Enforce pre-summary newline in docstrings
This commit is contained in:
@ -48,7 +48,8 @@ def generate_peer_id_from(key_pair: KeyPair) -> ID:
|
|||||||
def initialize_default_kademlia_router(
|
def initialize_default_kademlia_router(
|
||||||
ksize: int = 20, alpha: int = 3, id_opt: ID = None, storage: IStorage = None
|
ksize: int = 20, alpha: int = 3, id_opt: ID = None, storage: IStorage = None
|
||||||
) -> KadmeliaPeerRouter:
|
) -> KadmeliaPeerRouter:
|
||||||
"""initialize kadmelia router when no kademlia router is passed in.
|
"""
|
||||||
|
initialize kadmelia router when no kademlia router is passed in.
|
||||||
|
|
||||||
:param ksize: The k parameter from the paper
|
:param ksize: The k parameter from the paper
|
||||||
:param alpha: The alpha parameter from the paper
|
:param alpha: The alpha parameter from the paper
|
||||||
@ -78,7 +79,8 @@ def initialize_default_swarm(
|
|||||||
peerstore_opt: IPeerStore = None,
|
peerstore_opt: IPeerStore = None,
|
||||||
disc_opt: IPeerRouting = None,
|
disc_opt: IPeerRouting = None,
|
||||||
) -> Swarm:
|
) -> Swarm:
|
||||||
"""initialize swarm when no swarm is passed in.
|
"""
|
||||||
|
initialize swarm when no swarm is passed in.
|
||||||
|
|
||||||
:param id_opt: optional id for host
|
:param id_opt: optional id for host
|
||||||
:param transport_opt: optional choice of transport upgrade
|
:param transport_opt: optional choice of transport upgrade
|
||||||
@ -118,7 +120,8 @@ async def new_node(
|
|||||||
peerstore_opt: IPeerStore = None,
|
peerstore_opt: IPeerStore = None,
|
||||||
disc_opt: IPeerRouting = None,
|
disc_opt: IPeerRouting = None,
|
||||||
) -> IHost:
|
) -> IHost:
|
||||||
"""create new libp2p node.
|
"""
|
||||||
|
create new libp2p node.
|
||||||
|
|
||||||
:param key_pair: key pair for deriving an identity
|
:param key_pair: key pair for deriving an identity
|
||||||
:param swarm_opt: optional swarm
|
:param swarm_opt: optional swarm
|
||||||
|
|||||||
@ -56,7 +56,8 @@ class RSAPrivateKey(PrivateKey):
|
|||||||
|
|
||||||
|
|
||||||
def create_new_key_pair(bits: int = 2048, e: int = 65537) -> KeyPair:
|
def create_new_key_pair(bits: int = 2048, e: int = 65537) -> KeyPair:
|
||||||
"""Returns a new RSA keypair with the requested key size (``bits``) and the
|
"""
|
||||||
|
Returns a new RSA keypair with the requested key size (``bits``) and the
|
||||||
given public exponent ``e``.
|
given public exponent ``e``.
|
||||||
|
|
||||||
Sane defaults are provided for both values.
|
Sane defaults are provided for both values.
|
||||||
|
|||||||
@ -61,7 +61,8 @@ class Secp256k1PrivateKey(PrivateKey):
|
|||||||
|
|
||||||
|
|
||||||
def create_new_key_pair(secret: bytes = None) -> KeyPair:
|
def create_new_key_pair(secret: bytes = None) -> KeyPair:
|
||||||
"""Returns a new Secp256k1 keypair derived from the provided ``secret``, a
|
"""
|
||||||
|
Returns a new Secp256k1 keypair derived from the provided ``secret``, a
|
||||||
sequence of bytes corresponding to some integer between 0 and the group
|
sequence of bytes corresponding to some integer between 0 and the group
|
||||||
order.
|
order.
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,8 @@ logger = logging.getLogger("libp2p.network.basic_host")
|
|||||||
|
|
||||||
|
|
||||||
class BasicHost(IHost):
|
class BasicHost(IHost):
|
||||||
"""BasicHost is a wrapper of a `INetwork` implementation.
|
"""
|
||||||
|
BasicHost is a wrapper of a `INetwork` implementation.
|
||||||
|
|
||||||
It performs protocol negotiation on a stream with multistream-select
|
It performs protocol negotiation on a stream with multistream-select
|
||||||
right after a stream is initialized.
|
right after a stream is initialized.
|
||||||
@ -87,7 +88,8 @@ class BasicHost(IHost):
|
|||||||
def set_stream_handler(
|
def set_stream_handler(
|
||||||
self, protocol_id: TProtocol, stream_handler: StreamHandlerFn
|
self, protocol_id: TProtocol, stream_handler: StreamHandlerFn
|
||||||
) -> None:
|
) -> None:
|
||||||
"""set stream handler for given `protocol_id`
|
"""
|
||||||
|
set stream handler for given `protocol_id`
|
||||||
|
|
||||||
:param protocol_id: protocol id used on stream
|
:param protocol_id: protocol id used on stream
|
||||||
:param stream_handler: a stream handler function
|
:param stream_handler: a stream handler function
|
||||||
@ -119,7 +121,8 @@ class BasicHost(IHost):
|
|||||||
return net_stream
|
return net_stream
|
||||||
|
|
||||||
async def connect(self, peer_info: PeerInfo) -> None:
|
async def connect(self, peer_info: PeerInfo) -> None:
|
||||||
"""connect ensures there is a connection between this host and the peer
|
"""
|
||||||
|
connect ensures there is a connection between this host and the peer
|
||||||
with given `peer_info.peer_id`. connect will absorb the addresses in
|
with given `peer_info.peer_id`. connect will absorb the addresses in
|
||||||
peer_info into its internal peerstore. If there is not an active
|
peer_info into its internal peerstore. If there is not an active
|
||||||
connection, connect will issue a dial, and block until a connection is
|
connection, connect will issue a dial, and block until a connection is
|
||||||
|
|||||||
@ -40,7 +40,8 @@ class IHost(ABC):
|
|||||||
def set_stream_handler(
|
def set_stream_handler(
|
||||||
self, protocol_id: TProtocol, stream_handler: StreamHandlerFn
|
self, protocol_id: TProtocol, stream_handler: StreamHandlerFn
|
||||||
) -> None:
|
) -> None:
|
||||||
"""set stream handler for host.
|
"""
|
||||||
|
set stream handler for host.
|
||||||
|
|
||||||
:param protocol_id: protocol id used on stream
|
:param protocol_id: protocol id used on stream
|
||||||
:param stream_handler: a stream handler function
|
:param stream_handler: a stream handler function
|
||||||
@ -60,7 +61,8 @@ class IHost(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def connect(self, peer_info: PeerInfo) -> None:
|
async def connect(self, peer_info: PeerInfo) -> None:
|
||||||
"""connect ensures there is a connection between this host and the peer
|
"""
|
||||||
|
connect ensures there is a connection between this host and the peer
|
||||||
with given peer_info.peer_id. connect will absorb the addresses in
|
with given peer_info.peer_id. connect will absorb the addresses in
|
||||||
peer_info into its internal peerstore. If there is not an active
|
peer_info into its internal peerstore. If there is not an active
|
||||||
connection, connect will issue a dial, and block until a connection is
|
connection, connect will issue a dial, and block until a connection is
|
||||||
|
|||||||
@ -15,7 +15,8 @@ class RoutedHost(BasicHost):
|
|||||||
self._router = router
|
self._router = router
|
||||||
|
|
||||||
async def connect(self, peer_info: PeerInfo) -> None:
|
async def connect(self, peer_info: PeerInfo) -> None:
|
||||||
"""connect ensures there is a connection between this host and the peer
|
"""
|
||||||
|
connect ensures there is a connection between this host and the peer
|
||||||
with given `peer_info.peer_id`. See (basic_host).connect for more
|
with given `peer_info.peer_id`. See (basic_host).connect for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
"""``msgio`` is an implementation of `https://github.com/libp2p/go-msgio`.
|
"""
|
||||||
|
``msgio`` is an implementation of `https://github.com/libp2p/go-msgio`.
|
||||||
|
|
||||||
from that repo: "a simple package to r/w length-delimited slices."
|
from that repo: "a simple package to r/w length-delimited slices."
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,8 @@ class SpiderCrawl:
|
|||||||
"""Crawl the network and look for given 160-bit keys."""
|
"""Crawl the network and look for given 160-bit keys."""
|
||||||
|
|
||||||
def __init__(self, protocol, node, peers, ksize, alpha):
|
def __init__(self, protocol, node, peers, ksize, alpha):
|
||||||
"""Create a new C{SpiderCrawl}er.
|
"""
|
||||||
|
Create a new C{SpiderCrawl}er.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
protocol: A :class:`~kademlia.protocol.KademliaProtocol` instance.
|
protocol: A :class:`~kademlia.protocol.KademliaProtocol` instance.
|
||||||
@ -32,7 +33,8 @@ class SpiderCrawl:
|
|||||||
self.nearest.push(peers)
|
self.nearest.push(peers)
|
||||||
|
|
||||||
async def _find(self, rpcmethod):
|
async def _find(self, rpcmethod):
|
||||||
"""Get either a value or list of nodes.
|
"""
|
||||||
|
Get either a value or list of nodes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
rpcmethod: The protocol's callfindValue or call_find_node.
|
rpcmethod: The protocol's callfindValue or call_find_node.
|
||||||
@ -98,7 +100,8 @@ class ValueSpiderCrawl(SpiderCrawl):
|
|||||||
return await self.find()
|
return await self.find()
|
||||||
|
|
||||||
async def _handle_found_values(self, values):
|
async def _handle_found_values(self, values):
|
||||||
"""We got some values!
|
"""
|
||||||
|
We got some values!
|
||||||
|
|
||||||
Exciting. But let's make sure they're all the same or freak out
|
Exciting. But let's make sure they're all the same or freak out
|
||||||
a little bit. Also, make sure we tell the nearest node that
|
a little bit. Also, make sure we tell the nearest node that
|
||||||
@ -140,7 +143,8 @@ class NodeSpiderCrawl(SpiderCrawl):
|
|||||||
|
|
||||||
class RPCFindResponse:
|
class RPCFindResponse:
|
||||||
def __init__(self, response):
|
def __init__(self, response):
|
||||||
"""A wrapper for the result of a RPC find.
|
"""
|
||||||
|
A wrapper for the result of a RPC find.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
response: This will be a tuple of (<response received>, <value>)
|
response: This will be a tuple of (<response received>, <value>)
|
||||||
@ -160,7 +164,8 @@ class RPCFindResponse:
|
|||||||
return self.response[1]["value"]
|
return self.response[1]["value"]
|
||||||
|
|
||||||
def get_node_list(self):
|
def get_node_list(self):
|
||||||
"""Get the node list in the response.
|
"""
|
||||||
|
Get the node list in the response.
|
||||||
|
|
||||||
If there's no value, this should be set.
|
If there's no value, this should be set.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -57,7 +57,8 @@ class KadPeerHeap:
|
|||||||
"""A heap of peers ordered by distance to a given node."""
|
"""A heap of peers ordered by distance to a given node."""
|
||||||
|
|
||||||
def __init__(self, node, maxsize):
|
def __init__(self, node, maxsize):
|
||||||
"""Constructor.
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
@param node: The node to measure all distnaces from.
|
@param node: The node to measure all distnaces from.
|
||||||
@param maxsize: The maximum size that this heap can grow to.
|
@param maxsize: The maximum size that this heap can grow to.
|
||||||
@ -68,7 +69,8 @@ class KadPeerHeap:
|
|||||||
self.maxsize = maxsize
|
self.maxsize = maxsize
|
||||||
|
|
||||||
def remove(self, peers):
|
def remove(self, peers):
|
||||||
"""Remove a list of peer ids from this heap.
|
"""
|
||||||
|
Remove a list of peer ids from this heap.
|
||||||
|
|
||||||
Note that while this heap retains a constant visible size (based
|
Note that while this heap retains a constant visible size (based
|
||||||
on the iterator), it's actual size may be quite a bit larger
|
on the iterator), it's actual size may be quite a bit larger
|
||||||
@ -104,7 +106,8 @@ class KadPeerHeap:
|
|||||||
return heapq.heappop(self.heap)[1] if self else None
|
return heapq.heappop(self.heap)[1] if self else None
|
||||||
|
|
||||||
def push(self, nodes):
|
def push(self, nodes):
|
||||||
"""Push nodes onto heap.
|
"""
|
||||||
|
Push nodes onto heap.
|
||||||
|
|
||||||
@param nodes: This can be a single item or a C{list}.
|
@param nodes: This can be a single item or a C{list}.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -13,7 +13,8 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class KademliaServer:
|
class KademliaServer:
|
||||||
"""High level view of a node instance.
|
"""
|
||||||
|
High level view of a node instance.
|
||||||
|
|
||||||
This is the object that should be created to start listening as an
|
This is the object that should be created to start listening as an
|
||||||
active node on the network.
|
active node on the network.
|
||||||
@ -22,8 +23,8 @@ class KademliaServer:
|
|||||||
protocol_class = KademliaProtocol
|
protocol_class = KademliaProtocol
|
||||||
|
|
||||||
def __init__(self, ksize=20, alpha=3, node_id=None, storage=None):
|
def __init__(self, ksize=20, alpha=3, node_id=None, storage=None):
|
||||||
"""Create a server instance. This will start listening on the given
|
"""
|
||||||
port.
|
Create a server instance. This will start listening on the given port.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
ksize (int): The k parameter from the paper
|
ksize (int): The k parameter from the paper
|
||||||
@ -55,7 +56,8 @@ class KademliaServer:
|
|||||||
return self.protocol_class(self.node, self.storage, self.ksize)
|
return self.protocol_class(self.node, self.storage, self.ksize)
|
||||||
|
|
||||||
async def listen(self, port, interface="0.0.0.0"):
|
async def listen(self, port, interface="0.0.0.0"):
|
||||||
"""Start listening on the given port.
|
"""
|
||||||
|
Start listening on the given port.
|
||||||
|
|
||||||
Provide interface="::" to accept ipv6 address
|
Provide interface="::" to accept ipv6 address
|
||||||
"""
|
"""
|
||||||
@ -94,8 +96,9 @@ class KademliaServer:
|
|||||||
await self.set_digest(dkey, value)
|
await self.set_digest(dkey, value)
|
||||||
|
|
||||||
def bootstrappable_neighbors(self):
|
def bootstrappable_neighbors(self):
|
||||||
"""Get a :class:`list` of (ip, port) :class:`tuple` pairs suitable for
|
"""
|
||||||
use as an argument to the bootstrap method.
|
Get a :class:`list` of (ip, port) :class:`tuple` pairs suitable for use
|
||||||
|
as an argument to the bootstrap method.
|
||||||
|
|
||||||
The server should have been bootstrapped
|
The server should have been bootstrapped
|
||||||
already - this is just a utility for getting some neighbors and then
|
already - this is just a utility for getting some neighbors and then
|
||||||
@ -106,8 +109,8 @@ class KademliaServer:
|
|||||||
return [tuple(n)[-2:] for n in neighbors]
|
return [tuple(n)[-2:] for n in neighbors]
|
||||||
|
|
||||||
async def bootstrap(self, addrs):
|
async def bootstrap(self, addrs):
|
||||||
"""Bootstrap the server by connecting to other known nodes in the
|
"""
|
||||||
network.
|
Bootstrap the server by connecting to other known nodes in the network.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
addrs: A `list` of (ip, port) `tuple` pairs. Note that only IP
|
addrs: A `list` of (ip, port) `tuple` pairs. Note that only IP
|
||||||
@ -127,7 +130,8 @@ class KademliaServer:
|
|||||||
return create_kad_peerinfo(result[1], addr[0], addr[1]) if result[0] else None
|
return create_kad_peerinfo(result[1], addr[0], addr[1]) if result[0] else None
|
||||||
|
|
||||||
async def get(self, key):
|
async def get(self, key):
|
||||||
"""Get a key if the network has it.
|
"""
|
||||||
|
Get a key if the network has it.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:class:`None` if not found, the value otherwise.
|
:class:`None` if not found, the value otherwise.
|
||||||
@ -218,8 +222,8 @@ class KademliaServer:
|
|||||||
return svr
|
return svr
|
||||||
|
|
||||||
def save_state_regularly(self, fname, frequency=600):
|
def save_state_regularly(self, fname, frequency=600):
|
||||||
"""Save the state of node with a given regularity to the given
|
"""
|
||||||
filename.
|
Save the state of node with a given regularity to the given filename.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fname: File name to save retularly to
|
fname: File name to save retularly to
|
||||||
|
|||||||
@ -137,7 +137,8 @@ class KademliaProtocol(RPCProtocol):
|
|||||||
return self.handle_call_response(result, node_to_ask)
|
return self.handle_call_response(result, node_to_ask)
|
||||||
|
|
||||||
def welcome_if_new(self, node):
|
def welcome_if_new(self, node):
|
||||||
"""Given a new node, send it all the keys/values it should be storing,
|
"""
|
||||||
|
Given a new node, send it all the keys/values it should be storing,
|
||||||
then add it to the routing table.
|
then add it to the routing table.
|
||||||
|
|
||||||
@param node: A new node that just joined (or that we just found out
|
@param node: A new node that just joined (or that we just found out
|
||||||
@ -166,7 +167,8 @@ class KademliaProtocol(RPCProtocol):
|
|||||||
self.router.add_contact(node)
|
self.router.add_contact(node)
|
||||||
|
|
||||||
def handle_call_response(self, result, node):
|
def handle_call_response(self, result, node):
|
||||||
"""If we get a response, add the node to the routing table.
|
"""
|
||||||
|
If we get a response, add the node to the routing table.
|
||||||
|
|
||||||
If we get no response, make sure it's removed from the routing
|
If we get no response, make sure it's removed from the routing
|
||||||
table.
|
table.
|
||||||
|
|||||||
@ -52,8 +52,9 @@ class KBucket:
|
|||||||
return node.peer_id_bytes not in self.nodes
|
return node.peer_id_bytes not in self.nodes
|
||||||
|
|
||||||
def add_node(self, node):
|
def add_node(self, node):
|
||||||
"""Add a C{Node} to the C{KBucket}. Return True if successful, False
|
"""
|
||||||
if the bucket is full.
|
Add a C{Node} to the C{KBucket}. Return True if successful, False if
|
||||||
|
the bucket is full.
|
||||||
|
|
||||||
If the bucket is full, keep track of node in a replacement list,
|
If the bucket is full, keep track of node in a replacement list,
|
||||||
per section 4.1 of the paper.
|
per section 4.1 of the paper.
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import time
|
|||||||
|
|
||||||
|
|
||||||
class IStorage(ABC):
|
class IStorage(ABC):
|
||||||
"""Local storage for this node.
|
"""
|
||||||
|
Local storage for this node.
|
||||||
|
|
||||||
IStorage implementations of get must return the same type as put in
|
IStorage implementations of get must return the same type as put in
|
||||||
by set
|
by set
|
||||||
@ -18,14 +19,16 @@ class IStorage(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
"""Get the given key.
|
"""
|
||||||
|
Get the given key.
|
||||||
|
|
||||||
If item doesn't exist, raises C{KeyError}
|
If item doesn't exist, raises C{KeyError}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
"""Get given key.
|
"""
|
||||||
|
Get given key.
|
||||||
|
|
||||||
If not found, return default.
|
If not found, return default.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -17,7 +17,8 @@ def digest(string):
|
|||||||
|
|
||||||
|
|
||||||
class OrderedSet(list):
|
class OrderedSet(list):
|
||||||
"""Acts like a list in all ways, except in the behavior of the.
|
"""
|
||||||
|
Acts like a list in all ways, except in the behavior of the.
|
||||||
|
|
||||||
:meth:`push` method.
|
:meth:`push` method.
|
||||||
"""
|
"""
|
||||||
@ -33,7 +34,8 @@ class OrderedSet(list):
|
|||||||
|
|
||||||
|
|
||||||
def shared_prefix(args):
|
def shared_prefix(args):
|
||||||
"""Find the shared prefix between the strings.
|
"""
|
||||||
|
Find the shared prefix between the strings.
|
||||||
|
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,8 @@ class RawConnection(IRawConnection):
|
|||||||
raise RawConnError(error)
|
raise RawConnError(error)
|
||||||
|
|
||||||
async def read(self, n: int = -1) -> bytes:
|
async def read(self, n: int = -1) -> bytes:
|
||||||
"""Read up to ``n`` bytes from the underlying stream. This call is
|
"""
|
||||||
|
Read up to ``n`` bytes from the underlying stream. This call is
|
||||||
delegated directly to the underlying ``self.reader``.
|
delegated directly to the underlying ``self.reader``.
|
||||||
|
|
||||||
Raise `RawConnError` if the underlying connection breaks
|
Raise `RawConnError` if the underlying connection breaks
|
||||||
|
|||||||
@ -29,7 +29,8 @@ class INetwork(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def dial_peer(self, peer_id: ID) -> INetConn:
|
async def dial_peer(self, peer_id: ID) -> INetConn:
|
||||||
"""dial_peer try to create a connection to peer_id.
|
"""
|
||||||
|
dial_peer try to create a connection to peer_id.
|
||||||
|
|
||||||
:param peer_id: peer if we want to dial
|
:param peer_id: peer if we want to dial
|
||||||
:raises SwarmException: raised when an error occurs
|
:raises SwarmException: raised when an error occurs
|
||||||
|
|||||||
@ -38,7 +38,8 @@ class NetStream(INetStream):
|
|||||||
self.protocol_id = protocol_id
|
self.protocol_id = protocol_id
|
||||||
|
|
||||||
async def read(self, n: int = -1) -> bytes:
|
async def read(self, n: int = -1) -> bytes:
|
||||||
"""reads from stream.
|
"""
|
||||||
|
reads from stream.
|
||||||
|
|
||||||
:param n: number of bytes to read
|
:param n: number of bytes to read
|
||||||
:return: bytes of input
|
:return: bytes of input
|
||||||
@ -51,7 +52,8 @@ class NetStream(INetStream):
|
|||||||
raise StreamReset from error
|
raise StreamReset from error
|
||||||
|
|
||||||
async def write(self, data: bytes) -> int:
|
async def write(self, data: bytes) -> int:
|
||||||
"""write to stream.
|
"""
|
||||||
|
write to stream.
|
||||||
|
|
||||||
:return: number of bytes written
|
:return: number of bytes written
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -69,7 +69,8 @@ class Swarm(INetwork):
|
|||||||
self.common_stream_handler = stream_handler
|
self.common_stream_handler = stream_handler
|
||||||
|
|
||||||
async def dial_peer(self, peer_id: ID) -> INetConn:
|
async def dial_peer(self, peer_id: ID) -> INetConn:
|
||||||
"""dial_peer try to create a connection to peer_id.
|
"""
|
||||||
|
dial_peer try to create a connection to peer_id.
|
||||||
|
|
||||||
:param peer_id: peer if we want to dial
|
:param peer_id: peer if we want to dial
|
||||||
:raises SwarmException: raised when an error occurs
|
:raises SwarmException: raised when an error occurs
|
||||||
|
|||||||
@ -12,7 +12,8 @@ class IAddrBook(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None:
|
def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None:
|
||||||
"""Calls add_addrs(peer_id, [addr], ttl)
|
"""
|
||||||
|
Calls add_addrs(peer_id, [addr], ttl)
|
||||||
|
|
||||||
:param peer_id: the peer to add address for
|
:param peer_id: the peer to add address for
|
||||||
:param addr: multiaddress of the peer
|
:param addr: multiaddress of the peer
|
||||||
@ -21,9 +22,10 @@ class IAddrBook(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_addrs(self, peer_id: ID, addrs: Sequence[Multiaddr], ttl: int) -> None:
|
def add_addrs(self, peer_id: ID, addrs: Sequence[Multiaddr], ttl: int) -> None:
|
||||||
"""Adds addresses for a given peer all with the same time-to-live. If
|
"""
|
||||||
one of the addresses already exists for the peer and has a longer TTL,
|
Adds addresses for a given peer all with the same time-to-live. If one
|
||||||
no operation should take place. If one of the addresses exists with a
|
of the addresses already exists for the peer and has a longer TTL, no
|
||||||
|
operation should take place. If one of the addresses exists with a
|
||||||
shorter TTL, extend the TTL to equal param ttl.
|
shorter TTL, extend the TTL to equal param ttl.
|
||||||
|
|
||||||
:param peer_id: the peer to add address for
|
:param peer_id: the peer to add address for
|
||||||
@ -40,7 +42,8 @@ class IAddrBook(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def clear_addrs(self, peer_id: ID) -> None:
|
def clear_addrs(self, peer_id: ID) -> None:
|
||||||
"""Removes all previously stored addresses.
|
"""
|
||||||
|
Removes all previously stored addresses.
|
||||||
|
|
||||||
:param peer_id: peer to remove addresses of
|
:param peer_id: peer to remove addresses of
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -17,7 +17,8 @@ class PeerStore(IPeerStore):
|
|||||||
self.peer_map = {}
|
self.peer_map = {}
|
||||||
|
|
||||||
def __create_or_get_peer(self, peer_id: ID) -> PeerData:
|
def __create_or_get_peer(self, peer_id: ID) -> PeerData:
|
||||||
"""Returns the peer data for peer_id or creates a new peer data (and
|
"""
|
||||||
|
Returns the peer data for peer_id or creates a new peer data (and
|
||||||
stores it in peer_map) if peer data for peer_id does not yet exist.
|
stores it in peer_map) if peer data for peer_id does not yet exist.
|
||||||
|
|
||||||
:param peer_id: peer ID
|
:param peer_id: peer ID
|
||||||
|
|||||||
@ -21,7 +21,8 @@ class Multiselect(IMultiselectMuxer):
|
|||||||
self.handlers = {}
|
self.handlers = {}
|
||||||
|
|
||||||
def add_handler(self, protocol: TProtocol, handler: StreamHandlerFn) -> None:
|
def add_handler(self, protocol: TProtocol, handler: StreamHandlerFn) -> None:
|
||||||
"""Store the handler with the given protocol.
|
"""
|
||||||
|
Store the handler with the given protocol.
|
||||||
|
|
||||||
:param protocol: protocol name
|
:param protocol: protocol name
|
||||||
:param handler: handler function
|
:param handler: handler function
|
||||||
@ -31,7 +32,8 @@ class Multiselect(IMultiselectMuxer):
|
|||||||
async def negotiate(
|
async def negotiate(
|
||||||
self, communicator: IMultiselectCommunicator
|
self, communicator: IMultiselectCommunicator
|
||||||
) -> Tuple[TProtocol, StreamHandlerFn]:
|
) -> Tuple[TProtocol, StreamHandlerFn]:
|
||||||
"""Negotiate performs protocol selection.
|
"""
|
||||||
|
Negotiate performs protocol selection.
|
||||||
|
|
||||||
:param stream: stream to negotiate on
|
:param stream: stream to negotiate on
|
||||||
:return: selected protocol name, handler function
|
:return: selected protocol name, handler function
|
||||||
@ -63,7 +65,8 @@ class Multiselect(IMultiselectMuxer):
|
|||||||
raise MultiselectError(error)
|
raise MultiselectError(error)
|
||||||
|
|
||||||
async def handshake(self, communicator: IMultiselectCommunicator) -> None:
|
async def handshake(self, communicator: IMultiselectCommunicator) -> None:
|
||||||
"""Perform handshake to agree on multiselect protocol.
|
"""
|
||||||
|
Perform handshake to agree on multiselect protocol.
|
||||||
|
|
||||||
:param communicator: communicator to use
|
:param communicator: communicator to use
|
||||||
:raise MultiselectError: raised when handshake failed
|
:raise MultiselectError: raised when handshake failed
|
||||||
@ -86,7 +89,8 @@ class Multiselect(IMultiselectMuxer):
|
|||||||
|
|
||||||
|
|
||||||
def validate_handshake(handshake_contents: str) -> bool:
|
def validate_handshake(handshake_contents: str) -> bool:
|
||||||
"""Determine if handshake is valid and should be confirmed.
|
"""
|
||||||
|
Determine if handshake is valid and should be confirmed.
|
||||||
|
|
||||||
:param handshake_contents: contents of handshake message
|
:param handshake_contents: contents of handshake message
|
||||||
:return: true if handshake is complete, false otherwise
|
:return: true if handshake is complete, false otherwise
|
||||||
|
|||||||
@ -15,7 +15,8 @@ class MultiselectClient(IMultiselectClient):
|
|||||||
select a protocol id to communicate over."""
|
select a protocol id to communicate over."""
|
||||||
|
|
||||||
async def handshake(self, communicator: IMultiselectCommunicator) -> None:
|
async def handshake(self, communicator: IMultiselectCommunicator) -> None:
|
||||||
"""Ensure that the client and multiselect are both using the same
|
"""
|
||||||
|
Ensure that the client and multiselect are both using the same
|
||||||
multiselect protocol.
|
multiselect protocol.
|
||||||
|
|
||||||
:param stream: stream to communicate with multiselect over
|
:param stream: stream to communicate with multiselect over
|
||||||
@ -37,8 +38,9 @@ class MultiselectClient(IMultiselectClient):
|
|||||||
async def select_one_of(
|
async def select_one_of(
|
||||||
self, protocols: Sequence[TProtocol], communicator: IMultiselectCommunicator
|
self, protocols: Sequence[TProtocol], communicator: IMultiselectCommunicator
|
||||||
) -> TProtocol:
|
) -> TProtocol:
|
||||||
"""For each protocol, send message to multiselect selecting protocol
|
"""
|
||||||
and fail if multiselect does not return same protocol. Returns first
|
For each protocol, send message to multiselect selecting protocol and
|
||||||
|
fail if multiselect does not return same protocol. Returns first
|
||||||
protocol that multiselect agrees on (i.e. that multiselect selects)
|
protocol that multiselect agrees on (i.e. that multiselect selects)
|
||||||
|
|
||||||
:param protocol: protocol to select
|
:param protocol: protocol to select
|
||||||
@ -60,7 +62,8 @@ class MultiselectClient(IMultiselectClient):
|
|||||||
async def try_select(
|
async def try_select(
|
||||||
self, communicator: IMultiselectCommunicator, protocol: TProtocol
|
self, communicator: IMultiselectCommunicator, protocol: TProtocol
|
||||||
) -> TProtocol:
|
) -> TProtocol:
|
||||||
"""Try to select the given protocol or raise exception if fails.
|
"""
|
||||||
|
Try to select the given protocol or raise exception if fails.
|
||||||
|
|
||||||
:param communicator: communicator to use to communicate with counterparty
|
:param communicator: communicator to use to communicate with counterparty
|
||||||
:param protocol: protocol to select
|
:param protocol: protocol to select
|
||||||
@ -85,7 +88,8 @@ class MultiselectClient(IMultiselectClient):
|
|||||||
|
|
||||||
|
|
||||||
def validate_handshake(handshake_contents: str) -> bool:
|
def validate_handshake(handshake_contents: str) -> bool:
|
||||||
"""Determine if handshake is valid and should be confirmed.
|
"""
|
||||||
|
Determine if handshake is valid and should be confirmed.
|
||||||
|
|
||||||
:param handshake_contents: contents of handshake message
|
:param handshake_contents: contents of handshake message
|
||||||
:return: true if handshake is complete, false otherwise
|
:return: true if handshake is complete, false otherwise
|
||||||
|
|||||||
@ -12,7 +12,8 @@ class IMultiselectClient(ABC):
|
|||||||
select a protocol id to communicate over."""
|
select a protocol id to communicate over."""
|
||||||
|
|
||||||
async def handshake(self, communicator: IMultiselectCommunicator) -> None:
|
async def handshake(self, communicator: IMultiselectCommunicator) -> None:
|
||||||
"""Ensure that the client and multiselect are both using the same
|
"""
|
||||||
|
Ensure that the client and multiselect are both using the same
|
||||||
multiselect protocol.
|
multiselect protocol.
|
||||||
|
|
||||||
:param stream: stream to communicate with multiselect over
|
:param stream: stream to communicate with multiselect over
|
||||||
@ -23,8 +24,9 @@ class IMultiselectClient(ABC):
|
|||||||
async def select_one_of(
|
async def select_one_of(
|
||||||
self, protocols: Sequence[TProtocol], communicator: IMultiselectCommunicator
|
self, protocols: Sequence[TProtocol], communicator: IMultiselectCommunicator
|
||||||
) -> TProtocol:
|
) -> TProtocol:
|
||||||
"""For each protocol, send message to multiselect selecting protocol
|
"""
|
||||||
and fail if multiselect does not return same protocol. Returns first
|
For each protocol, send message to multiselect selecting protocol and
|
||||||
|
fail if multiselect does not return same protocol. Returns first
|
||||||
protocol that multiselect agrees on (i.e. that multiselect selects)
|
protocol that multiselect agrees on (i.e. that multiselect selects)
|
||||||
|
|
||||||
:param protocol: protocol to select
|
:param protocol: protocol to select
|
||||||
@ -35,7 +37,8 @@ class IMultiselectClient(ABC):
|
|||||||
async def try_select(
|
async def try_select(
|
||||||
self, communicator: IMultiselectCommunicator, protocol: TProtocol
|
self, communicator: IMultiselectCommunicator, protocol: TProtocol
|
||||||
) -> TProtocol:
|
) -> TProtocol:
|
||||||
"""Try to select the given protocol or raise exception if fails.
|
"""
|
||||||
|
Try to select the given protocol or raise exception if fails.
|
||||||
|
|
||||||
:param communicator: communicator to use to communicate with counterparty
|
:param communicator: communicator to use to communicate with counterparty
|
||||||
:param protocol: protocol to select
|
:param protocol: protocol to select
|
||||||
|
|||||||
@ -8,7 +8,8 @@ class IMultiselectCommunicator(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def write(self, msg_str: str) -> None:
|
async def write(self, msg_str: str) -> None:
|
||||||
"""Write message to stream.
|
"""
|
||||||
|
Write message to stream.
|
||||||
|
|
||||||
:param msg_str: message to write
|
:param msg_str: message to write
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -15,7 +15,8 @@ class IMultiselectMuxer(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_handler(self, protocol: TProtocol, handler: StreamHandlerFn) -> None:
|
def add_handler(self, protocol: TProtocol, handler: StreamHandlerFn) -> None:
|
||||||
"""Store the handler with the given protocol.
|
"""
|
||||||
|
Store the handler with the given protocol.
|
||||||
|
|
||||||
:param protocol: protocol name
|
:param protocol: protocol name
|
||||||
:param handler: handler function
|
:param handler: handler function
|
||||||
@ -25,7 +26,8 @@ class IMultiselectMuxer(ABC):
|
|||||||
async def negotiate(
|
async def negotiate(
|
||||||
self, communicator: IMultiselectCommunicator
|
self, communicator: IMultiselectCommunicator
|
||||||
) -> Tuple[TProtocol, StreamHandlerFn]:
|
) -> Tuple[TProtocol, StreamHandlerFn]:
|
||||||
"""Negotiate performs protocol selection.
|
"""
|
||||||
|
Negotiate performs protocol selection.
|
||||||
|
|
||||||
:param stream: stream to negotiate on
|
:param stream: stream to negotiate on
|
||||||
:return: selected protocol name, handler function
|
:return: selected protocol name, handler function
|
||||||
|
|||||||
@ -31,35 +31,40 @@ class FloodSub(IPubsubRouter):
|
|||||||
return self.protocols
|
return self.protocols
|
||||||
|
|
||||||
def attach(self, pubsub: Pubsub) -> None:
|
def attach(self, pubsub: Pubsub) -> None:
|
||||||
"""Attach is invoked by the PubSub constructor to attach the router to
|
"""
|
||||||
a freshly initialized PubSub instance.
|
Attach is invoked by the PubSub constructor to attach the router to a
|
||||||
|
freshly initialized PubSub instance.
|
||||||
|
|
||||||
:param pubsub: pubsub instance to attach to
|
:param pubsub: pubsub instance to attach to
|
||||||
"""
|
"""
|
||||||
self.pubsub = pubsub
|
self.pubsub = pubsub
|
||||||
|
|
||||||
def add_peer(self, peer_id: ID, protocol_id: TProtocol) -> None:
|
def add_peer(self, peer_id: ID, protocol_id: TProtocol) -> None:
|
||||||
"""Notifies the router that a new peer has been connected.
|
"""
|
||||||
|
Notifies the router that a new peer has been connected.
|
||||||
|
|
||||||
:param peer_id: id of peer to add
|
:param peer_id: id of peer to add
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def remove_peer(self, peer_id: ID) -> None:
|
def remove_peer(self, peer_id: ID) -> None:
|
||||||
"""Notifies the router that a peer has been disconnected.
|
"""
|
||||||
|
Notifies the router that a peer has been disconnected.
|
||||||
|
|
||||||
:param peer_id: id of peer to remove
|
:param peer_id: id of peer to remove
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def handle_rpc(self, rpc: rpc_pb2.RPC, sender_peer_id: ID) -> None:
|
async def handle_rpc(self, rpc: rpc_pb2.RPC, sender_peer_id: ID) -> None:
|
||||||
"""Invoked to process control messages in the RPC envelope. It is
|
"""
|
||||||
invoked after subscriptions and payload messages have been processed.
|
Invoked to process control messages in the RPC envelope. It is invoked
|
||||||
|
after subscriptions and payload messages have been processed.
|
||||||
|
|
||||||
:param rpc: rpc message
|
:param rpc: rpc message
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def publish(self, msg_forwarder: ID, pubsub_msg: rpc_pb2.Message) -> None:
|
async def publish(self, msg_forwarder: ID, pubsub_msg: rpc_pb2.Message) -> None:
|
||||||
"""Invoked to forward a new message that has been validated. This is
|
"""
|
||||||
where the "flooding" part of floodsub happens.
|
Invoked to forward a new message that has been validated. This is where
|
||||||
|
the "flooding" part of floodsub happens.
|
||||||
|
|
||||||
With flooding, routing is almost trivial: for each incoming message,
|
With flooding, routing is almost trivial: for each incoming message,
|
||||||
forward to all known peers in the topic. There is a bit of logic,
|
forward to all known peers in the topic. There is a bit of logic,
|
||||||
@ -87,15 +92,17 @@ class FloodSub(IPubsubRouter):
|
|||||||
await stream.write(encode_varint_prefixed(rpc_msg.SerializeToString()))
|
await stream.write(encode_varint_prefixed(rpc_msg.SerializeToString()))
|
||||||
|
|
||||||
async def join(self, topic: str) -> None:
|
async def join(self, topic: str) -> None:
|
||||||
"""Join notifies the router that we want to receive and forward
|
"""
|
||||||
messages in a topic. It is invoked after the subscription announcement.
|
Join notifies the router that we want to receive and forward messages
|
||||||
|
in a topic. It is invoked after the subscription announcement.
|
||||||
|
|
||||||
:param topic: topic to join
|
:param topic: topic to join
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def leave(self, topic: str) -> None:
|
async def leave(self, topic: str) -> None:
|
||||||
"""Leave notifies the router that we are no longer interested in a
|
"""
|
||||||
topic. It is invoked after the unsubscription announcement.
|
Leave notifies the router that we are no longer interested in a topic.
|
||||||
|
It is invoked after the unsubscription announcement.
|
||||||
|
|
||||||
:param topic: topic to leave
|
:param topic: topic to leave
|
||||||
"""
|
"""
|
||||||
@ -103,7 +110,8 @@ class FloodSub(IPubsubRouter):
|
|||||||
def _get_peers_to_send(
|
def _get_peers_to_send(
|
||||||
self, topic_ids: Iterable[str], msg_forwarder: ID, origin: ID
|
self, topic_ids: Iterable[str], msg_forwarder: ID, origin: ID
|
||||||
) -> Iterable[ID]:
|
) -> Iterable[ID]:
|
||||||
"""Get the eligible peers to send the data to.
|
"""
|
||||||
|
Get the eligible peers to send the data to.
|
||||||
|
|
||||||
:param msg_forwarder: peer ID of the peer who forwards the message to us.
|
:param msg_forwarder: peer ID of the peer who forwards the message to us.
|
||||||
:param origin: peer id of the peer the message originate from.
|
:param origin: peer id of the peer the message originate from.
|
||||||
|
|||||||
@ -94,8 +94,9 @@ class GossipSub(IPubsubRouter):
|
|||||||
return self.protocols
|
return self.protocols
|
||||||
|
|
||||||
def attach(self, pubsub: Pubsub) -> None:
|
def attach(self, pubsub: Pubsub) -> None:
|
||||||
"""Attach is invoked by the PubSub constructor to attach the router to
|
"""
|
||||||
a freshly initialized PubSub instance.
|
Attach is invoked by the PubSub constructor to attach the router to a
|
||||||
|
freshly initialized PubSub instance.
|
||||||
|
|
||||||
:param pubsub: pubsub instance to attach to
|
:param pubsub: pubsub instance to attach to
|
||||||
"""
|
"""
|
||||||
@ -108,7 +109,8 @@ class GossipSub(IPubsubRouter):
|
|||||||
asyncio.ensure_future(self.heartbeat())
|
asyncio.ensure_future(self.heartbeat())
|
||||||
|
|
||||||
def add_peer(self, peer_id: ID, protocol_id: TProtocol) -> None:
|
def add_peer(self, peer_id: ID, protocol_id: TProtocol) -> None:
|
||||||
"""Notifies the router that a new peer has been connected.
|
"""
|
||||||
|
Notifies the router that a new peer has been connected.
|
||||||
|
|
||||||
:param peer_id: id of peer to add
|
:param peer_id: id of peer to add
|
||||||
:param protocol_id: router protocol the peer speaks, e.g., floodsub, gossipsub
|
:param protocol_id: router protocol the peer speaks, e.g., floodsub, gossipsub
|
||||||
@ -129,7 +131,8 @@ class GossipSub(IPubsubRouter):
|
|||||||
self.peers_to_protocol[peer_id] = protocol_id
|
self.peers_to_protocol[peer_id] = protocol_id
|
||||||
|
|
||||||
def remove_peer(self, peer_id: ID) -> None:
|
def remove_peer(self, peer_id: ID) -> None:
|
||||||
"""Notifies the router that a peer has been disconnected.
|
"""
|
||||||
|
Notifies the router that a peer has been disconnected.
|
||||||
|
|
||||||
:param peer_id: id of peer to remove
|
:param peer_id: id of peer to remove
|
||||||
"""
|
"""
|
||||||
@ -144,8 +147,9 @@ class GossipSub(IPubsubRouter):
|
|||||||
del self.peers_to_protocol[peer_id]
|
del self.peers_to_protocol[peer_id]
|
||||||
|
|
||||||
async def handle_rpc(self, rpc: rpc_pb2.RPC, sender_peer_id: ID) -> None:
|
async def handle_rpc(self, rpc: rpc_pb2.RPC, sender_peer_id: ID) -> None:
|
||||||
"""Invoked to process control messages in the RPC envelope. It is
|
"""
|
||||||
invoked after subscriptions and payload messages have been processed.
|
Invoked to process control messages in the RPC envelope. It is invoked
|
||||||
|
after subscriptions and payload messages have been processed.
|
||||||
|
|
||||||
:param rpc: RPC message
|
:param rpc: RPC message
|
||||||
:param sender_peer_id: id of the peer who sent the message
|
:param sender_peer_id: id of the peer who sent the message
|
||||||
@ -189,7 +193,8 @@ class GossipSub(IPubsubRouter):
|
|||||||
def _get_peers_to_send(
|
def _get_peers_to_send(
|
||||||
self, topic_ids: Iterable[str], msg_forwarder: ID, origin: ID
|
self, topic_ids: Iterable[str], msg_forwarder: ID, origin: ID
|
||||||
) -> Iterable[ID]:
|
) -> Iterable[ID]:
|
||||||
"""Get the eligible peers to send the data to.
|
"""
|
||||||
|
Get the eligible peers to send the data to.
|
||||||
|
|
||||||
:param msg_forwarder: the peer id of the peer who forwards the message to me.
|
:param msg_forwarder: the peer id of the peer who forwards the message to me.
|
||||||
:param origin: peer id of the peer the message originate from.
|
:param origin: peer id of the peer the message originate from.
|
||||||
@ -231,8 +236,9 @@ class GossipSub(IPubsubRouter):
|
|||||||
|
|
||||||
async def join(self, topic: str) -> None:
|
async def join(self, topic: str) -> None:
|
||||||
# Note: the comments here are the near-exact algorithm description from the spec
|
# Note: the comments here are the near-exact algorithm description from the spec
|
||||||
"""Join notifies the router that we want to receive and forward
|
"""
|
||||||
messages in a topic. It is invoked after the subscription announcement.
|
Join notifies the router that we want to receive and forward messages
|
||||||
|
in a topic. It is invoked after the subscription announcement.
|
||||||
|
|
||||||
:param topic: topic to join
|
:param topic: topic to join
|
||||||
"""
|
"""
|
||||||
@ -268,8 +274,9 @@ class GossipSub(IPubsubRouter):
|
|||||||
|
|
||||||
async def leave(self, topic: str) -> None:
|
async def leave(self, topic: str) -> None:
|
||||||
# Note: the comments here are the near-exact algorithm description from the spec
|
# Note: the comments here are the near-exact algorithm description from the spec
|
||||||
"""Leave notifies the router that we are no longer interested in a
|
"""
|
||||||
topic. It is invoked after the unsubscription announcement.
|
Leave notifies the router that we are no longer interested in a topic.
|
||||||
|
It is invoked after the unsubscription announcement.
|
||||||
|
|
||||||
:param topic: topic to leave
|
:param topic: topic to leave
|
||||||
"""
|
"""
|
||||||
@ -286,7 +293,8 @@ class GossipSub(IPubsubRouter):
|
|||||||
|
|
||||||
# Heartbeat
|
# Heartbeat
|
||||||
async def heartbeat(self) -> None:
|
async def heartbeat(self) -> None:
|
||||||
"""Call individual heartbeats.
|
"""
|
||||||
|
Call individual heartbeats.
|
||||||
|
|
||||||
Note: the heartbeats are called with awaits because each heartbeat depends on the
|
Note: the heartbeats are called with awaits because each heartbeat depends on the
|
||||||
state changes in the preceding heartbeat
|
state changes in the preceding heartbeat
|
||||||
|
|||||||
@ -13,7 +13,8 @@ class CacheEntry:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, mid: Tuple[bytes, bytes], topics: Sequence[str]) -> None:
|
def __init__(self, mid: Tuple[bytes, bytes], topics: Sequence[str]) -> None:
|
||||||
"""Constructor.
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
:param mid: (seqno, from_id) of the msg
|
:param mid: (seqno, from_id) of the msg
|
||||||
:param topics: list of topics this message was sent on
|
:param topics: list of topics this message was sent on
|
||||||
@ -32,7 +33,8 @@ class MessageCache:
|
|||||||
history: List[List[CacheEntry]]
|
history: List[List[CacheEntry]]
|
||||||
|
|
||||||
def __init__(self, window_size: int, history_size: int) -> None:
|
def __init__(self, window_size: int, history_size: int) -> None:
|
||||||
"""Constructor.
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
:param window_size: Size of the window desired.
|
:param window_size: Size of the window desired.
|
||||||
:param history_size: Size of the history desired.
|
:param history_size: Size of the history desired.
|
||||||
@ -49,7 +51,8 @@ class MessageCache:
|
|||||||
self.history = [[] for _ in range(history_size)]
|
self.history = [[] for _ in range(history_size)]
|
||||||
|
|
||||||
def put(self, msg: rpc_pb2.Message) -> None:
|
def put(self, msg: rpc_pb2.Message) -> None:
|
||||||
"""Put a message into the mcache.
|
"""
|
||||||
|
Put a message into the mcache.
|
||||||
|
|
||||||
:param msg: The rpc message to put in. Should contain seqno and from_id
|
:param msg: The rpc message to put in. Should contain seqno and from_id
|
||||||
"""
|
"""
|
||||||
@ -59,7 +62,8 @@ class MessageCache:
|
|||||||
self.history[0].append(CacheEntry(mid, msg.topicIDs))
|
self.history[0].append(CacheEntry(mid, msg.topicIDs))
|
||||||
|
|
||||||
def get(self, mid: Tuple[bytes, bytes]) -> Optional[rpc_pb2.Message]:
|
def get(self, mid: Tuple[bytes, bytes]) -> Optional[rpc_pb2.Message]:
|
||||||
"""Get a message from the mcache.
|
"""
|
||||||
|
Get a message from the mcache.
|
||||||
|
|
||||||
:param mid: (seqno, from_id) of the message to get.
|
:param mid: (seqno, from_id) of the message to get.
|
||||||
:return: The rpc message associated with this mid
|
:return: The rpc message associated with this mid
|
||||||
@ -70,7 +74,8 @@ class MessageCache:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def window(self, topic: str) -> List[Tuple[bytes, bytes]]:
|
def window(self, topic: str) -> List[Tuple[bytes, bytes]]:
|
||||||
"""Get the window for this topic.
|
"""
|
||||||
|
Get the window for this topic.
|
||||||
|
|
||||||
:param topic: Topic whose message ids we desire.
|
:param topic: Topic whose message ids we desire.
|
||||||
:return: List of mids in the current window.
|
:return: List of mids in the current window.
|
||||||
|
|||||||
@ -81,7 +81,8 @@ class Pubsub:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self, host: IHost, router: "IPubsubRouter", my_id: ID, cache_size: int = None
|
self, host: IHost, router: "IPubsubRouter", my_id: ID, cache_size: int = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Construct a new Pubsub object, which is responsible for handling all
|
"""
|
||||||
|
Construct a new Pubsub object, which is responsible for handling all
|
||||||
Pubsub-related messages and relaying messages as appropriate to the
|
Pubsub-related messages and relaying messages as appropriate to the
|
||||||
Pubsub router (which is responsible for choosing who to send messages
|
Pubsub router (which is responsible for choosing who to send messages
|
||||||
to).
|
to).
|
||||||
@ -148,8 +149,9 @@ class Pubsub:
|
|||||||
return packet
|
return packet
|
||||||
|
|
||||||
async def continuously_read_stream(self, stream: INetStream) -> None:
|
async def continuously_read_stream(self, stream: INetStream) -> None:
|
||||||
"""Read from input stream in an infinite loop. Process messages from
|
"""
|
||||||
other nodes.
|
Read from input stream in an infinite loop. Process messages from other
|
||||||
|
nodes.
|
||||||
|
|
||||||
:param stream: stream to continously read from
|
:param stream: stream to continously read from
|
||||||
"""
|
"""
|
||||||
@ -207,8 +209,9 @@ class Pubsub:
|
|||||||
def set_topic_validator(
|
def set_topic_validator(
|
||||||
self, topic: str, validator: ValidatorFn, is_async_validator: bool
|
self, topic: str, validator: ValidatorFn, is_async_validator: bool
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Register a validator under the given topic. One topic can only have
|
"""
|
||||||
one validtor.
|
Register a validator under the given topic. One topic can only have one
|
||||||
|
validtor.
|
||||||
|
|
||||||
:param topic: the topic to register validator under
|
:param topic: the topic to register validator under
|
||||||
:param validator: the validator used to validate messages published to the topic
|
:param validator: the validator used to validate messages published to the topic
|
||||||
@ -217,7 +220,8 @@ class Pubsub:
|
|||||||
self.topic_validators[topic] = TopicValidator(validator, is_async_validator)
|
self.topic_validators[topic] = TopicValidator(validator, is_async_validator)
|
||||||
|
|
||||||
def remove_topic_validator(self, topic: str) -> None:
|
def remove_topic_validator(self, topic: str) -> None:
|
||||||
"""Remove the validator from the given topic.
|
"""
|
||||||
|
Remove the validator from the given topic.
|
||||||
|
|
||||||
:param topic: the topic to remove validator from
|
:param topic: the topic to remove validator from
|
||||||
"""
|
"""
|
||||||
@ -225,7 +229,8 @@ class Pubsub:
|
|||||||
del self.topic_validators[topic]
|
del self.topic_validators[topic]
|
||||||
|
|
||||||
def get_msg_validators(self, msg: rpc_pb2.Message) -> Tuple[TopicValidator, ...]:
|
def get_msg_validators(self, msg: rpc_pb2.Message) -> Tuple[TopicValidator, ...]:
|
||||||
"""Get all validators corresponding to the topics in the message.
|
"""
|
||||||
|
Get all validators corresponding to the topics in the message.
|
||||||
|
|
||||||
:param msg: the message published to the topic
|
:param msg: the message published to the topic
|
||||||
"""
|
"""
|
||||||
@ -236,7 +241,8 @@ class Pubsub:
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def stream_handler(self, stream: INetStream) -> None:
|
async def stream_handler(self, stream: INetStream) -> None:
|
||||||
"""Stream handler for pubsub. Gets invoked whenever a new stream is
|
"""
|
||||||
|
Stream handler for pubsub. Gets invoked whenever a new stream is
|
||||||
created on one of the supported pubsub protocols.
|
created on one of the supported pubsub protocols.
|
||||||
|
|
||||||
:param stream: newly created stream
|
:param stream: newly created stream
|
||||||
@ -291,7 +297,8 @@ class Pubsub:
|
|||||||
def handle_subscription(
|
def handle_subscription(
|
||||||
self, origin_id: ID, sub_message: rpc_pb2.RPC.SubOpts
|
self, origin_id: ID, sub_message: rpc_pb2.RPC.SubOpts
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle an incoming subscription message from a peer. Update internal
|
"""
|
||||||
|
Handle an incoming subscription message from a peer. Update internal
|
||||||
mapping to mark the peer as subscribed or unsubscribed to topics as
|
mapping to mark the peer as subscribed or unsubscribed to topics as
|
||||||
defined in the subscription message.
|
defined in the subscription message.
|
||||||
|
|
||||||
@ -311,7 +318,8 @@ class Pubsub:
|
|||||||
|
|
||||||
# FIXME(mhchia): Change the function name?
|
# FIXME(mhchia): Change the function name?
|
||||||
async def handle_talk(self, publish_message: rpc_pb2.Message) -> None:
|
async def handle_talk(self, publish_message: rpc_pb2.Message) -> None:
|
||||||
"""Put incoming message from a peer onto my blocking queue.
|
"""
|
||||||
|
Put incoming message from a peer onto my blocking queue.
|
||||||
|
|
||||||
:param publish_message: RPC.Message format
|
:param publish_message: RPC.Message format
|
||||||
"""
|
"""
|
||||||
@ -325,7 +333,8 @@ class Pubsub:
|
|||||||
await self.my_topics[topic].put(publish_message)
|
await self.my_topics[topic].put(publish_message)
|
||||||
|
|
||||||
async def subscribe(self, topic_id: str) -> "asyncio.Queue[rpc_pb2.Message]":
|
async def subscribe(self, topic_id: str) -> "asyncio.Queue[rpc_pb2.Message]":
|
||||||
"""Subscribe ourself to a topic.
|
"""
|
||||||
|
Subscribe ourself to a topic.
|
||||||
|
|
||||||
:param topic_id: topic_id to subscribe to
|
:param topic_id: topic_id to subscribe to
|
||||||
"""
|
"""
|
||||||
@ -355,7 +364,8 @@ class Pubsub:
|
|||||||
return self.my_topics[topic_id]
|
return self.my_topics[topic_id]
|
||||||
|
|
||||||
async def unsubscribe(self, topic_id: str) -> None:
|
async def unsubscribe(self, topic_id: str) -> None:
|
||||||
"""Unsubscribe ourself from a topic.
|
"""
|
||||||
|
Unsubscribe ourself from a topic.
|
||||||
|
|
||||||
:param topic_id: topic_id to unsubscribe from
|
:param topic_id: topic_id to unsubscribe from
|
||||||
"""
|
"""
|
||||||
@ -381,7 +391,8 @@ class Pubsub:
|
|||||||
await self.router.leave(topic_id)
|
await self.router.leave(topic_id)
|
||||||
|
|
||||||
async def message_all_peers(self, raw_msg: bytes) -> None:
|
async def message_all_peers(self, raw_msg: bytes) -> None:
|
||||||
"""Broadcast a message to peers.
|
"""
|
||||||
|
Broadcast a message to peers.
|
||||||
|
|
||||||
:param raw_msg: raw contents of the message to broadcast
|
:param raw_msg: raw contents of the message to broadcast
|
||||||
"""
|
"""
|
||||||
@ -392,7 +403,8 @@ class Pubsub:
|
|||||||
await stream.write(encode_varint_prefixed(raw_msg))
|
await stream.write(encode_varint_prefixed(raw_msg))
|
||||||
|
|
||||||
async def publish(self, topic_id: str, data: bytes) -> None:
|
async def publish(self, topic_id: str, data: bytes) -> None:
|
||||||
"""Publish data to a topic.
|
"""
|
||||||
|
Publish data to a topic.
|
||||||
|
|
||||||
:param topic_id: topic which we are going to publish the data to
|
:param topic_id: topic which we are going to publish the data to
|
||||||
:param data: data which we are publishing
|
:param data: data which we are publishing
|
||||||
@ -412,7 +424,8 @@ class Pubsub:
|
|||||||
logger.debug("successfully published message %s", msg)
|
logger.debug("successfully published message %s", msg)
|
||||||
|
|
||||||
async def validate_msg(self, msg_forwarder: ID, msg: rpc_pb2.Message) -> None:
|
async def validate_msg(self, msg_forwarder: ID, msg: rpc_pb2.Message) -> None:
|
||||||
"""Validate the received message.
|
"""
|
||||||
|
Validate the received message.
|
||||||
|
|
||||||
:param msg_forwarder: the peer who forward us the message.
|
:param msg_forwarder: the peer who forward us the message.
|
||||||
:param msg: the message.
|
:param msg: the message.
|
||||||
@ -441,7 +454,8 @@ class Pubsub:
|
|||||||
raise ValidationError(f"Validation failed for msg={msg}")
|
raise ValidationError(f"Validation failed for msg={msg}")
|
||||||
|
|
||||||
async def push_msg(self, msg_forwarder: ID, msg: rpc_pb2.Message) -> None:
|
async def push_msg(self, msg_forwarder: ID, msg: rpc_pb2.Message) -> None:
|
||||||
"""Push a pubsub message to others.
|
"""
|
||||||
|
Push a pubsub message to others.
|
||||||
|
|
||||||
:param msg_forwarder: the peer who forward us the message.
|
:param msg_forwarder: the peer who forward us the message.
|
||||||
:param msg: the message we are going to push out.
|
:param msg: the message we are going to push out.
|
||||||
|
|||||||
@ -30,9 +30,10 @@ class PubsubNotifee(INotifee):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
async def connected(self, network: INetwork, conn: INetConn) -> None:
|
async def connected(self, network: INetwork, conn: INetConn) -> None:
|
||||||
"""Add peer_id to initiator_peers_queue, so that this peer_id can be
|
"""
|
||||||
used to create a stream and we only want to have one pubsub stream with
|
Add peer_id to initiator_peers_queue, so that this peer_id can be used
|
||||||
each peer.
|
to create a stream and we only want to have one pubsub stream with each
|
||||||
|
peer.
|
||||||
|
|
||||||
:param network: network the connection was opened on
|
:param network: network the connection was opened on
|
||||||
:param conn: connection that was opened
|
:param conn: connection that was opened
|
||||||
|
|||||||
@ -19,22 +19,25 @@ class IPubsubRouter(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def attach(self, pubsub: "Pubsub") -> None:
|
def attach(self, pubsub: "Pubsub") -> None:
|
||||||
"""Attach is invoked by the PubSub constructor to attach the router to
|
"""
|
||||||
a freshly initialized PubSub instance.
|
Attach is invoked by the PubSub constructor to attach the router to a
|
||||||
|
freshly initialized PubSub instance.
|
||||||
|
|
||||||
:param pubsub: pubsub instance to attach to
|
:param pubsub: pubsub instance to attach to
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_peer(self, peer_id: ID, protocol_id: TProtocol) -> None:
|
def add_peer(self, peer_id: ID, protocol_id: TProtocol) -> None:
|
||||||
"""Notifies the router that a new peer has been connected.
|
"""
|
||||||
|
Notifies the router that a new peer has been connected.
|
||||||
|
|
||||||
:param peer_id: id of peer to add
|
:param peer_id: id of peer to add
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def remove_peer(self, peer_id: ID) -> None:
|
def remove_peer(self, peer_id: ID) -> None:
|
||||||
"""Notifies the router that a peer has been disconnected.
|
"""
|
||||||
|
Notifies the router that a peer has been disconnected.
|
||||||
|
|
||||||
:param peer_id: id of peer to remove
|
:param peer_id: id of peer to remove
|
||||||
"""
|
"""
|
||||||
@ -53,7 +56,8 @@ class IPubsubRouter(ABC):
|
|||||||
# FIXME: Should be changed to type 'peer.ID'
|
# FIXME: Should be changed to type 'peer.ID'
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def publish(self, msg_forwarder: ID, pubsub_msg: rpc_pb2.Message) -> None:
|
async def publish(self, msg_forwarder: ID, pubsub_msg: rpc_pb2.Message) -> None:
|
||||||
"""Invoked to forward a new message that has been validated.
|
"""
|
||||||
|
Invoked to forward a new message that has been validated.
|
||||||
|
|
||||||
:param msg_forwarder: peer_id of message sender
|
:param msg_forwarder: peer_id of message sender
|
||||||
:param pubsub_msg: pubsub message to forward
|
:param pubsub_msg: pubsub message to forward
|
||||||
@ -61,16 +65,18 @@ class IPubsubRouter(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def join(self, topic: str) -> None:
|
async def join(self, topic: str) -> None:
|
||||||
"""Join notifies the router that we want to receive and forward
|
"""
|
||||||
messages in a topic. It is invoked after the subscription announcement.
|
Join notifies the router that we want to receive and forward messages
|
||||||
|
in a topic. It is invoked after the subscription announcement.
|
||||||
|
|
||||||
:param topic: topic to join
|
:param topic: topic to join
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def leave(self, topic: str) -> None:
|
async def leave(self, topic: str) -> None:
|
||||||
"""Leave notifies the router that we are no longer interested in a
|
"""
|
||||||
topic. It is invoked after the unsubscription announcement.
|
Leave notifies the router that we are no longer interested in a topic.
|
||||||
|
It is invoked after the unsubscription announcement.
|
||||||
|
|
||||||
:param topic: topic to leave
|
:param topic: topic to leave
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# FIXME: Replace the type of `pubkey` with a custom type `Pubkey`
|
# FIXME: Replace the type of `pubkey` with a custom type `Pubkey`
|
||||||
def signature_validator(pubkey: bytes, msg: bytes) -> bool:
|
def signature_validator(pubkey: bytes, msg: bytes) -> bool:
|
||||||
"""Verify the message against the given public key.
|
"""
|
||||||
|
Verify the message against the given public key.
|
||||||
|
|
||||||
:param pubkey: the public key which signs the message.
|
:param pubkey: the public key which signs the message.
|
||||||
:param msg: the message signed.
|
:param msg: the message signed.
|
||||||
|
|||||||
@ -8,7 +8,8 @@ from libp2p.peer.peerinfo import PeerInfo
|
|||||||
class IContentRouting(ABC):
|
class IContentRouting(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def provide(self, cid: bytes, announce: bool = True) -> None:
|
def provide(self, cid: bytes, announce: bool = True) -> None:
|
||||||
"""Provide adds the given cid to the content routing system.
|
"""
|
||||||
|
Provide adds the given cid to the content routing system.
|
||||||
|
|
||||||
If announce is True, it also announces it, otherwise it is just
|
If announce is True, it also announces it, otherwise it is just
|
||||||
kept in the local accounting of which objects are being
|
kept in the local accounting of which objects are being
|
||||||
|
|||||||
@ -6,7 +6,8 @@ from libp2p.routing.interfaces import IContentRouting
|
|||||||
|
|
||||||
class KadmeliaContentRouter(IContentRouting):
|
class KadmeliaContentRouter(IContentRouting):
|
||||||
def provide(self, cid: bytes, announce: bool = True) -> None:
|
def provide(self, cid: bytes, announce: bool = True) -> None:
|
||||||
"""Provide adds the given cid to the content routing system.
|
"""
|
||||||
|
Provide adds the given cid to the content routing system.
|
||||||
|
|
||||||
If announce is True, it also announces it, otherwise it is just
|
If announce is True, it also announces it, otherwise it is just
|
||||||
kept in the local accounting of which objects are being
|
kept in the local accounting of which objects are being
|
||||||
|
|||||||
@ -15,7 +15,8 @@ class KadmeliaPeerRouter(IPeerRouting):
|
|||||||
self.server = dht_server
|
self.server = dht_server
|
||||||
|
|
||||||
async def find_peer(self, peer_id: ID) -> PeerInfo:
|
async def find_peer(self, peer_id: ID) -> PeerInfo:
|
||||||
"""Find a specific peer.
|
"""
|
||||||
|
Find a specific peer.
|
||||||
|
|
||||||
:param peer_id: peer to search for
|
:param peer_id: peer to search for
|
||||||
:return: PeerInfo of specified peer
|
:return: PeerInfo of specified peer
|
||||||
|
|||||||
@ -11,8 +11,9 @@ def default_secure_bytes_provider(n: int) -> bytes:
|
|||||||
|
|
||||||
|
|
||||||
class BaseSecureTransport(ISecureTransport):
|
class BaseSecureTransport(ISecureTransport):
|
||||||
"""``BaseSecureTransport`` is not fully instantiated from its abstract
|
"""
|
||||||
classes as it is only meant to be used in clases that derive from it.
|
``BaseSecureTransport`` is not fully instantiated from its abstract classes
|
||||||
|
as it is only meant to be used in clases that derive from it.
|
||||||
|
|
||||||
Clients can provide a strategy to get cryptographically secure bytes
|
Clients can provide a strategy to get cryptographically secure bytes
|
||||||
of a given length. A default implementation is provided using the
|
of a given length. A default implementation is provided using the
|
||||||
|
|||||||
@ -104,8 +104,9 @@ class InsecureTransport(BaseSecureTransport):
|
|||||||
security."""
|
security."""
|
||||||
|
|
||||||
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are not the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
|
node via conn, for an inbound connection (i.e. we are not the
|
||||||
initiator)
|
initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
@ -115,9 +116,9 @@ class InsecureTransport(BaseSecureTransport):
|
|||||||
return session
|
return session
|
||||||
|
|
||||||
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
initiator)
|
node via conn, for an inbound connection (i.e. we are the initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -394,7 +394,8 @@ async def create_secure_session(
|
|||||||
conn: IRawConnection,
|
conn: IRawConnection,
|
||||||
remote_peer: PeerID = None,
|
remote_peer: PeerID = None,
|
||||||
) -> ISecureConn:
|
) -> ISecureConn:
|
||||||
"""Attempt the initial `secio` handshake with the remote peer.
|
"""
|
||||||
|
Attempt the initial `secio` handshake with the remote peer.
|
||||||
|
|
||||||
If successful, return an object that provides secure communication
|
If successful, return an object that provides secure communication
|
||||||
to the ``remote_peer``. Raise `SecioException` when `conn` closed.
|
to the ``remote_peer``. Raise `SecioException` when `conn` closed.
|
||||||
@ -435,8 +436,9 @@ class Transport(BaseSecureTransport):
|
|||||||
return self.secure_bytes_provider(NONCE_SIZE)
|
return self.secure_bytes_provider(NONCE_SIZE)
|
||||||
|
|
||||||
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are not the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
|
node via conn, for an inbound connection (i.e. we are not the
|
||||||
initiator)
|
initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
@ -452,9 +454,9 @@ class Transport(BaseSecureTransport):
|
|||||||
async def secure_outbound(
|
async def secure_outbound(
|
||||||
self, conn: IRawConnection, peer_id: PeerID
|
self, conn: IRawConnection, peer_id: PeerID
|
||||||
) -> ISecureConn:
|
) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
initiator)
|
node via conn, for an inbound connection (i.e. we are the initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -16,8 +16,9 @@ Relevant go repo: https://github.com/libp2p/go-conn-security/blob/master/interfa
|
|||||||
class ISecureTransport(ABC):
|
class ISecureTransport(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are not the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
|
node via conn, for an inbound connection (i.e. we are not the
|
||||||
initiator)
|
initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
@ -25,9 +26,9 @@ class ISecureTransport(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
initiator)
|
node via conn, for an inbound connection (i.e. we are the initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -21,7 +21,8 @@ Relevant go repo: https://github.com/libp2p/go-conn-security/blob/master/interfa
|
|||||||
|
|
||||||
|
|
||||||
class SecurityMultistream(ABC):
|
class SecurityMultistream(ABC):
|
||||||
"""SSMuxer is a multistream stream security transport multiplexer.
|
"""
|
||||||
|
SSMuxer is a multistream stream security transport multiplexer.
|
||||||
|
|
||||||
Go implementation: github.com/libp2p/go-conn-security-multistream/ssms.go
|
Go implementation: github.com/libp2p/go-conn-security-multistream/ssms.go
|
||||||
"""
|
"""
|
||||||
@ -40,7 +41,8 @@ class SecurityMultistream(ABC):
|
|||||||
self.add_transport(protocol, transport)
|
self.add_transport(protocol, transport)
|
||||||
|
|
||||||
def add_transport(self, protocol: TProtocol, transport: ISecureTransport) -> None:
|
def add_transport(self, protocol: TProtocol, transport: ISecureTransport) -> None:
|
||||||
"""Add a protocol and its corresponding transport to multistream-
|
"""
|
||||||
|
Add a protocol and its corresponding transport to multistream-
|
||||||
select(multiselect). The order that a protocol is added is exactly the
|
select(multiselect). The order that a protocol is added is exactly the
|
||||||
precedence it is negotiated in multiselect.
|
precedence it is negotiated in multiselect.
|
||||||
|
|
||||||
@ -56,8 +58,9 @@ class SecurityMultistream(ABC):
|
|||||||
self.multiselect.add_handler(protocol, None)
|
self.multiselect.add_handler(protocol, None)
|
||||||
|
|
||||||
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are not the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
|
node via conn, for an inbound connection (i.e. we are not the
|
||||||
initiator)
|
initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
@ -67,9 +70,9 @@ class SecurityMultistream(ABC):
|
|||||||
return secure_conn
|
return secure_conn
|
||||||
|
|
||||||
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
||||||
"""Secure the connection, either locally or by communicating with
|
"""
|
||||||
opposing node via conn, for an inbound connection (i.e. we are the
|
Secure the connection, either locally or by communicating with opposing
|
||||||
initiator)
|
node via conn, for an inbound connection (i.e. we are the initiator)
|
||||||
|
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
"""
|
"""
|
||||||
@ -80,8 +83,9 @@ class SecurityMultistream(ABC):
|
|||||||
async def select_transport(
|
async def select_transport(
|
||||||
self, conn: IRawConnection, initiator: bool
|
self, conn: IRawConnection, initiator: bool
|
||||||
) -> ISecureTransport:
|
) -> ISecureTransport:
|
||||||
"""Select a transport that both us and the node on the other end of
|
"""
|
||||||
conn support and agree on.
|
Select a transport that both us and the node on the other end of conn
|
||||||
|
support and agree on.
|
||||||
|
|
||||||
:param conn: conn to choose a transport over
|
:param conn: conn to choose a transport over
|
||||||
:param initiator: true if we are the initiator, false otherwise
|
:param initiator: true if we are the initiator, false otherwise
|
||||||
|
|||||||
@ -14,7 +14,8 @@ class IMuxedConn(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self, conn: ISecureConn, peer_id: ID) -> None:
|
def __init__(self, conn: ISecureConn, peer_id: ID) -> None:
|
||||||
"""create a new muxed connection.
|
"""
|
||||||
|
create a new muxed connection.
|
||||||
|
|
||||||
:param conn: an instance of secured connection
|
:param conn: an instance of secured connection
|
||||||
for new muxed streams
|
for new muxed streams
|
||||||
@ -32,14 +33,16 @@ class IMuxedConn(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def is_closed(self) -> bool:
|
def is_closed(self) -> bool:
|
||||||
"""check connection is fully closed.
|
"""
|
||||||
|
check connection is fully closed.
|
||||||
|
|
||||||
:return: true if successful
|
:return: true if successful
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def open_stream(self) -> "IMuxedStream":
|
async def open_stream(self) -> "IMuxedStream":
|
||||||
"""creates a new muxed_stream.
|
"""
|
||||||
|
creates a new muxed_stream.
|
||||||
|
|
||||||
:return: a new ``IMuxedStream`` stream
|
:return: a new ``IMuxedStream`` stream
|
||||||
"""
|
"""
|
||||||
@ -59,7 +62,8 @@ class IMuxedStream(ReadWriteCloser):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def set_deadline(self, ttl: int) -> bool:
|
def set_deadline(self, ttl: int) -> bool:
|
||||||
"""set deadline for muxed stream.
|
"""
|
||||||
|
set deadline for muxed stream.
|
||||||
|
|
||||||
:return: a new stream
|
:return: a new stream
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -41,7 +41,8 @@ class Mplex(IMuxedConn):
|
|||||||
_tasks: List["asyncio.Future[Any]"]
|
_tasks: List["asyncio.Future[Any]"]
|
||||||
|
|
||||||
def __init__(self, secured_conn: ISecureConn, peer_id: ID) -> None:
|
def __init__(self, secured_conn: ISecureConn, peer_id: ID) -> None:
|
||||||
"""create a new muxed connection.
|
"""
|
||||||
|
create a new muxed connection.
|
||||||
|
|
||||||
:param secured_conn: an instance of ``ISecureConn``
|
:param secured_conn: an instance of ``ISecureConn``
|
||||||
:param generic_protocol_handler: generic protocol handler
|
:param generic_protocol_handler: generic protocol handler
|
||||||
@ -82,14 +83,16 @@ class Mplex(IMuxedConn):
|
|||||||
await self.event_closed.wait()
|
await self.event_closed.wait()
|
||||||
|
|
||||||
def is_closed(self) -> bool:
|
def is_closed(self) -> bool:
|
||||||
"""check connection is fully closed.
|
"""
|
||||||
|
check connection is fully closed.
|
||||||
|
|
||||||
:return: true if successful
|
:return: true if successful
|
||||||
"""
|
"""
|
||||||
return self.event_closed.is_set()
|
return self.event_closed.is_set()
|
||||||
|
|
||||||
def _get_next_channel_id(self) -> int:
|
def _get_next_channel_id(self) -> int:
|
||||||
"""Get next available stream id.
|
"""
|
||||||
|
Get next available stream id.
|
||||||
|
|
||||||
:return: next available stream id for the connection
|
:return: next available stream id for the connection
|
||||||
"""
|
"""
|
||||||
@ -104,7 +107,8 @@ class Mplex(IMuxedConn):
|
|||||||
return stream
|
return stream
|
||||||
|
|
||||||
async def open_stream(self) -> IMuxedStream:
|
async def open_stream(self) -> IMuxedStream:
|
||||||
"""creates a new muxed_stream.
|
"""
|
||||||
|
creates a new muxed_stream.
|
||||||
|
|
||||||
:return: a new ``MplexStream``
|
:return: a new ``MplexStream``
|
||||||
"""
|
"""
|
||||||
@ -141,7 +145,8 @@ class Mplex(IMuxedConn):
|
|||||||
async def send_message(
|
async def send_message(
|
||||||
self, flag: HeaderTags, data: Optional[bytes], stream_id: StreamID
|
self, flag: HeaderTags, data: Optional[bytes], stream_id: StreamID
|
||||||
) -> int:
|
) -> int:
|
||||||
"""sends a message over the connection.
|
"""
|
||||||
|
sends a message over the connection.
|
||||||
|
|
||||||
:param header: header to use
|
:param header: header to use
|
||||||
:param data: data to send in the message
|
:param data: data to send in the message
|
||||||
@ -160,7 +165,8 @@ class Mplex(IMuxedConn):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def write_to_stream(self, _bytes: bytes) -> int:
|
async def write_to_stream(self, _bytes: bytes) -> int:
|
||||||
"""writes a byte array to a secured connection.
|
"""
|
||||||
|
writes a byte array to a secured connection.
|
||||||
|
|
||||||
:param _bytes: byte array to write
|
:param _bytes: byte array to write
|
||||||
:return: length written
|
:return: length written
|
||||||
@ -184,7 +190,8 @@ class Mplex(IMuxedConn):
|
|||||||
await self._cleanup()
|
await self._cleanup()
|
||||||
|
|
||||||
async def read_message(self) -> Tuple[int, int, bytes]:
|
async def read_message(self) -> Tuple[int, int, bytes]:
|
||||||
"""Read a single message off of the secured connection.
|
"""
|
||||||
|
Read a single message off of the secured connection.
|
||||||
|
|
||||||
:return: stream_id, flag, message contents
|
:return: stream_id, flag, message contents
|
||||||
"""
|
"""
|
||||||
@ -210,7 +217,8 @@ class Mplex(IMuxedConn):
|
|||||||
return channel_id, flag, message
|
return channel_id, flag, message
|
||||||
|
|
||||||
async def _handle_incoming_message(self) -> None:
|
async def _handle_incoming_message(self) -> None:
|
||||||
"""Read and handle a new incoming message.
|
"""
|
||||||
|
Read and handle a new incoming message.
|
||||||
|
|
||||||
:raise MplexUnavailable: `Mplex` encounters fatal error or is shutting down.
|
:raise MplexUnavailable: `Mplex` encounters fatal error or is shutting down.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -34,7 +34,8 @@ class MplexStream(IMuxedStream):
|
|||||||
_buf: bytearray
|
_buf: bytearray
|
||||||
|
|
||||||
def __init__(self, name: str, stream_id: StreamID, muxed_conn: "Mplex") -> None:
|
def __init__(self, name: str, stream_id: StreamID, muxed_conn: "Mplex") -> None:
|
||||||
"""create new MuxedStream in muxer.
|
"""
|
||||||
|
create new MuxedStream in muxer.
|
||||||
|
|
||||||
:param stream_id: stream id of this stream
|
:param stream_id: stream id of this stream
|
||||||
:param muxed_conn: muxed connection of this muxed_stream
|
:param muxed_conn: muxed connection of this muxed_stream
|
||||||
@ -112,7 +113,8 @@ class MplexStream(IMuxedStream):
|
|||||||
return bytes(payload)
|
return bytes(payload)
|
||||||
|
|
||||||
async def read(self, n: int = -1) -> bytes:
|
async def read(self, n: int = -1) -> bytes:
|
||||||
"""Read up to n bytes. Read possibly returns fewer than `n` bytes, if
|
"""
|
||||||
|
Read up to n bytes. Read possibly returns fewer than `n` bytes, if
|
||||||
there are not enough bytes in the Mplex buffer. If `n == -1`, read
|
there are not enough bytes in the Mplex buffer. If `n == -1`, read
|
||||||
until EOF.
|
until EOF.
|
||||||
|
|
||||||
@ -141,7 +143,8 @@ class MplexStream(IMuxedStream):
|
|||||||
return bytes(payload)
|
return bytes(payload)
|
||||||
|
|
||||||
async def write(self, data: bytes) -> int:
|
async def write(self, data: bytes) -> int:
|
||||||
"""write to stream.
|
"""
|
||||||
|
write to stream.
|
||||||
|
|
||||||
:return: number of bytes written
|
:return: number of bytes written
|
||||||
"""
|
"""
|
||||||
@ -212,7 +215,8 @@ class MplexStream(IMuxedStream):
|
|||||||
|
|
||||||
# TODO deadline not in use
|
# TODO deadline not in use
|
||||||
def set_deadline(self, ttl: int) -> bool:
|
def set_deadline(self, ttl: int) -> bool:
|
||||||
"""set deadline for muxed stream.
|
"""
|
||||||
|
set deadline for muxed stream.
|
||||||
|
|
||||||
:return: True if successful
|
:return: True if successful
|
||||||
"""
|
"""
|
||||||
@ -221,7 +225,8 @@ class MplexStream(IMuxedStream):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def set_read_deadline(self, ttl: int) -> bool:
|
def set_read_deadline(self, ttl: int) -> bool:
|
||||||
"""set read deadline for muxed stream.
|
"""
|
||||||
|
set read deadline for muxed stream.
|
||||||
|
|
||||||
:return: True if successful
|
:return: True if successful
|
||||||
"""
|
"""
|
||||||
@ -229,7 +234,8 @@ class MplexStream(IMuxedStream):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def set_write_deadline(self, ttl: int) -> bool:
|
def set_write_deadline(self, ttl: int) -> bool:
|
||||||
"""set write deadline for muxed stream.
|
"""
|
||||||
|
set write deadline for muxed stream.
|
||||||
|
|
||||||
:return: True if successful
|
:return: True if successful
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -16,7 +16,8 @@ DEFAULT_NEGOTIATE_TIMEOUT = 60
|
|||||||
|
|
||||||
|
|
||||||
class MuxerMultistream:
|
class MuxerMultistream:
|
||||||
"""MuxerMultistream is a multistream stream muxed transport multiplexer.
|
"""
|
||||||
|
MuxerMultistream is a multistream stream muxed transport multiplexer.
|
||||||
|
|
||||||
go implementation: github.com/libp2p/go-stream-muxer-multistream/multistream.go
|
go implementation: github.com/libp2p/go-stream-muxer-multistream/multistream.go
|
||||||
"""
|
"""
|
||||||
@ -34,7 +35,8 @@ class MuxerMultistream:
|
|||||||
self.add_transport(protocol, transport)
|
self.add_transport(protocol, transport)
|
||||||
|
|
||||||
def add_transport(self, protocol: TProtocol, transport: TMuxerClass) -> None:
|
def add_transport(self, protocol: TProtocol, transport: TMuxerClass) -> None:
|
||||||
"""Add a protocol and its corresponding transport to multistream-
|
"""
|
||||||
|
Add a protocol and its corresponding transport to multistream-
|
||||||
select(multiselect). The order that a protocol is added is exactly the
|
select(multiselect). The order that a protocol is added is exactly the
|
||||||
precedence it is negotiated in multiselect.
|
precedence it is negotiated in multiselect.
|
||||||
|
|
||||||
@ -48,8 +50,9 @@ class MuxerMultistream:
|
|||||||
self.multiselect.add_handler(protocol, None)
|
self.multiselect.add_handler(protocol, None)
|
||||||
|
|
||||||
async def select_transport(self, conn: IRawConnection) -> TMuxerClass:
|
async def select_transport(self, conn: IRawConnection) -> TMuxerClass:
|
||||||
"""Select a transport that both us and the node on the other end of
|
"""
|
||||||
conn support and agree on.
|
Select a transport that both us and the node on the other end of conn
|
||||||
|
support and agree on.
|
||||||
|
|
||||||
:param conn: conn to choose a transport over
|
:param conn: conn to choose a transport over
|
||||||
:return: selected muxer transport
|
:return: selected muxer transport
|
||||||
|
|||||||
@ -7,7 +7,8 @@ from multiaddr import Multiaddr
|
|||||||
class IListener(ABC):
|
class IListener(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def listen(self, maddr: Multiaddr) -> bool:
|
async def listen(self, maddr: Multiaddr) -> bool:
|
||||||
"""put listener in listening mode and wait for incoming connections.
|
"""
|
||||||
|
put listener in listening mode and wait for incoming connections.
|
||||||
|
|
||||||
:param maddr: multiaddr of peer
|
:param maddr: multiaddr of peer
|
||||||
:return: return True if successful
|
:return: return True if successful
|
||||||
@ -15,7 +16,8 @@ class IListener(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_addrs(self) -> List[Multiaddr]:
|
def get_addrs(self) -> List[Multiaddr]:
|
||||||
"""retrieve list of addresses the listener is listening on.
|
"""
|
||||||
|
retrieve list of addresses the listener is listening on.
|
||||||
|
|
||||||
:return: return list of addrs
|
:return: return list of addrs
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -22,7 +22,8 @@ class TCPListener(IListener):
|
|||||||
self.handler = handler_function
|
self.handler = handler_function
|
||||||
|
|
||||||
async def listen(self, maddr: Multiaddr) -> bool:
|
async def listen(self, maddr: Multiaddr) -> bool:
|
||||||
"""put listener in listening mode and wait for incoming connections.
|
"""
|
||||||
|
put listener in listening mode and wait for incoming connections.
|
||||||
|
|
||||||
:param maddr: maddr of peer
|
:param maddr: maddr of peer
|
||||||
:return: return True if successful
|
:return: return True if successful
|
||||||
@ -38,7 +39,8 @@ class TCPListener(IListener):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_addrs(self) -> List[Multiaddr]:
|
def get_addrs(self) -> List[Multiaddr]:
|
||||||
"""retrieve list of addresses the listener is listening on.
|
"""
|
||||||
|
retrieve list of addresses the listener is listening on.
|
||||||
|
|
||||||
:return: return list of addrs
|
:return: return list of addrs
|
||||||
"""
|
"""
|
||||||
@ -57,7 +59,8 @@ class TCPListener(IListener):
|
|||||||
|
|
||||||
class TCP(ITransport):
|
class TCP(ITransport):
|
||||||
async def dial(self, maddr: Multiaddr) -> IRawConnection:
|
async def dial(self, maddr: Multiaddr) -> IRawConnection:
|
||||||
"""dial a transport to peer listening on multiaddr.
|
"""
|
||||||
|
dial a transport to peer listening on multiaddr.
|
||||||
|
|
||||||
:param maddr: multiaddr of peer
|
:param maddr: multiaddr of peer
|
||||||
:return: `RawConnection` if successful
|
:return: `RawConnection` if successful
|
||||||
@ -74,7 +77,8 @@ class TCP(ITransport):
|
|||||||
return RawConnection(reader, writer, True)
|
return RawConnection(reader, writer, True)
|
||||||
|
|
||||||
def create_listener(self, handler_function: THandler) -> TCPListener:
|
def create_listener(self, handler_function: THandler) -> TCPListener:
|
||||||
"""create listener on transport.
|
"""
|
||||||
|
create listener on transport.
|
||||||
|
|
||||||
:param handler_function: a function called when a new connection is received
|
:param handler_function: a function called when a new connection is received
|
||||||
that takes a connection as argument which implements interface-connection
|
that takes a connection as argument which implements interface-connection
|
||||||
|
|||||||
@ -11,7 +11,8 @@ from .typing import THandler
|
|||||||
class ITransport(ABC):
|
class ITransport(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def dial(self, maddr: Multiaddr) -> IRawConnection:
|
async def dial(self, maddr: Multiaddr) -> IRawConnection:
|
||||||
"""dial a transport to peer listening on multiaddr.
|
"""
|
||||||
|
dial a transport to peer listening on multiaddr.
|
||||||
|
|
||||||
:param multiaddr: multiaddr of peer
|
:param multiaddr: multiaddr of peer
|
||||||
:param self_id: peer_id of the dialer (to send to receiver)
|
:param self_id: peer_id of the dialer (to send to receiver)
|
||||||
@ -20,7 +21,8 @@ class ITransport(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def create_listener(self, handler_function: THandler) -> IListener:
|
def create_listener(self, handler_function: THandler) -> IListener:
|
||||||
"""create listener on transport.
|
"""
|
||||||
|
create listener on transport.
|
||||||
|
|
||||||
:param handler_function: a function called when a new conntion is received
|
:param handler_function: a function called when a new conntion is received
|
||||||
that takes a connection as argument which implements interface-connection
|
that takes a connection as argument which implements interface-connection
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
"""Test Notify and Notifee by ensuring that the proper events get called, and
|
"""
|
||||||
that the stream passed into opened_stream is correct.
|
Test Notify and Notifee by ensuring that the proper events get called, and that
|
||||||
|
the stream passed into opened_stream is correct.
|
||||||
|
|
||||||
Note: Listen event does not get hit because MyNotifee is passed
|
Note: Listen event does not get hit because MyNotifee is passed
|
||||||
into network after network has already started listening
|
into network after network has already started listening
|
||||||
|
|||||||
@ -20,7 +20,8 @@ CRYPTO_TOPIC = "ethereum"
|
|||||||
|
|
||||||
|
|
||||||
class DummyAccountNode:
|
class DummyAccountNode:
|
||||||
"""Node which has an internal balance mapping, meant to serve as a dummy
|
"""
|
||||||
|
Node which has an internal balance mapping, meant to serve as a dummy
|
||||||
crypto blockchain.
|
crypto blockchain.
|
||||||
|
|
||||||
There is no actual blockchain, just a simple map indicating how much
|
There is no actual blockchain, just a simple map indicating how much
|
||||||
@ -41,8 +42,9 @@ class DummyAccountNode:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls):
|
async def create(cls):
|
||||||
"""Create a new DummyAccountNode and attach a libp2p node, a floodsub,
|
"""
|
||||||
and a pubsub instance to this new node.
|
Create a new DummyAccountNode and attach a libp2p node, a floodsub, and
|
||||||
|
a pubsub instance to this new node.
|
||||||
|
|
||||||
We use create as this serves as a factory function and allows us
|
We use create as this serves as a factory function and allows us
|
||||||
to use async await, unlike the init function
|
to use async await, unlike the init function
|
||||||
@ -71,7 +73,8 @@ class DummyAccountNode:
|
|||||||
asyncio.ensure_future(self.handle_incoming_msgs())
|
asyncio.ensure_future(self.handle_incoming_msgs())
|
||||||
|
|
||||||
async def publish_send_crypto(self, source_user, dest_user, amount):
|
async def publish_send_crypto(self, source_user, dest_user, amount):
|
||||||
"""Create a send crypto message and publish that message to all other
|
"""
|
||||||
|
Create a send crypto message and publish that message to all other
|
||||||
nodes.
|
nodes.
|
||||||
|
|
||||||
:param source_user: user to send crypto from
|
:param source_user: user to send crypto from
|
||||||
@ -82,7 +85,8 @@ class DummyAccountNode:
|
|||||||
await self.pubsub.publish(CRYPTO_TOPIC, msg_contents.encode())
|
await self.pubsub.publish(CRYPTO_TOPIC, msg_contents.encode())
|
||||||
|
|
||||||
async def publish_set_crypto(self, user, amount):
|
async def publish_set_crypto(self, user, amount):
|
||||||
"""Create a set crypto message and publish that message to all other
|
"""
|
||||||
|
Create a set crypto message and publish that message to all other
|
||||||
nodes.
|
nodes.
|
||||||
|
|
||||||
:param user: user to set crypto for
|
:param user: user to set crypto for
|
||||||
@ -92,7 +96,8 @@ class DummyAccountNode:
|
|||||||
await self.pubsub.publish(CRYPTO_TOPIC, msg_contents.encode())
|
await self.pubsub.publish(CRYPTO_TOPIC, msg_contents.encode())
|
||||||
|
|
||||||
def handle_send_crypto(self, source_user, dest_user, amount):
|
def handle_send_crypto(self, source_user, dest_user, amount):
|
||||||
"""Handle incoming send_crypto message.
|
"""
|
||||||
|
Handle incoming send_crypto message.
|
||||||
|
|
||||||
:param source_user: user to send crypto from
|
:param source_user: user to send crypto from
|
||||||
:param dest_user: user to send crypto to
|
:param dest_user: user to send crypto to
|
||||||
@ -109,7 +114,8 @@ class DummyAccountNode:
|
|||||||
self.balances[dest_user] = amount
|
self.balances[dest_user] = amount
|
||||||
|
|
||||||
def handle_set_crypto(self, dest_user, amount):
|
def handle_set_crypto(self, dest_user, amount):
|
||||||
"""Handle incoming set_crypto message.
|
"""
|
||||||
|
Handle incoming set_crypto message.
|
||||||
|
|
||||||
:param dest_user: user to set crypto for
|
:param dest_user: user to set crypto for
|
||||||
:param amount: amount of crypto
|
:param amount: amount of crypto
|
||||||
@ -117,7 +123,8 @@ class DummyAccountNode:
|
|||||||
self.balances[dest_user] = amount
|
self.balances[dest_user] = amount
|
||||||
|
|
||||||
def get_balance(self, user):
|
def get_balance(self, user):
|
||||||
"""Get balance in crypto for a particular user.
|
"""
|
||||||
|
Get balance in crypto for a particular user.
|
||||||
|
|
||||||
:param user: user to get balance for
|
:param user: user to get balance for
|
||||||
:return: balance of user
|
:return: balance of user
|
||||||
|
|||||||
@ -16,7 +16,8 @@ def create_setup_in_new_thread_func(dummy_node):
|
|||||||
|
|
||||||
|
|
||||||
async def perform_test(num_nodes, adjacency_map, action_func, assertion_func):
|
async def perform_test(num_nodes, adjacency_map, action_func, assertion_func):
|
||||||
"""Helper function to allow for easy construction of custom tests for dummy
|
"""
|
||||||
|
Helper function to allow for easy construction of custom tests for dummy
|
||||||
account nodes in various network topologies.
|
account nodes in various network topologies.
|
||||||
|
|
||||||
:param num_nodes: number of nodes in the test
|
:param num_nodes: number of nodes in the test
|
||||||
|
|||||||
@ -7,7 +7,8 @@ from tests.utils import connect
|
|||||||
|
|
||||||
|
|
||||||
def message_id_generator(start_val):
|
def message_id_generator(start_val):
|
||||||
"""Generate a unique message id.
|
"""
|
||||||
|
Generate a unique message id.
|
||||||
|
|
||||||
:param start_val: value to start generating messages at
|
:param start_val: value to start generating messages at
|
||||||
:return: message id
|
:return: message id
|
||||||
|
|||||||
@ -19,7 +19,8 @@ TIMEOUT_DURATION = 30
|
|||||||
|
|
||||||
|
|
||||||
async def try_until_success(coro_func, timeout=TIMEOUT_DURATION):
|
async def try_until_success(coro_func, timeout=TIMEOUT_DURATION):
|
||||||
"""Keep running ``coro_func`` until either it succeed or time is up.
|
"""
|
||||||
|
Keep running ``coro_func`` until either it succeed or time is up.
|
||||||
|
|
||||||
All arguments of ``coro_func`` should be filled, i.e. it should be
|
All arguments of ``coro_func`` should be filled, i.e. it should be
|
||||||
called without arguments.
|
called without arguments.
|
||||||
|
|||||||
Reference in New Issue
Block a user