diff --git a/Makefile b/Makefile index d67aa1f2..0d8ca81a 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,8 @@ PYI = $(PB:.proto=_pb2.pyi) ## Set default to `protobufs`, otherwise `format` is called when typing only `make` all: protobufs +.PHONY: protobufs clean-proto + protobufs: $(PY) %_pb2.py: %.proto @@ -77,6 +79,11 @@ protobufs: $(PY) clean-proto: rm -f $(PY) $(PYI) +# Force protobuf regeneration by making them always out of date +$(PY): FORCE + +FORCE: + # docs commands docs: check-docs diff --git a/README.md b/README.md index 7df3589b..77166429 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,13 @@ [![Build Status](https://img.shields.io/github/actions/workflow/status/libp2p/py-libp2p/tox.yml?branch=main&label=build%20status)](https://github.com/libp2p/py-libp2p/actions/workflows/tox.yml) [![Docs build](https://readthedocs.org/projects/py-libp2p/badge/?version=latest)](http://py-libp2p.readthedocs.io/en/latest/?badge=latest) -> ⚠️ **Warning:** py-libp2p is an experimental and work-in-progress repo under development. We do not yet recommend using py-libp2p in production environments. +> py-libp2p has moved beyond its experimental roots and is steadily progressing toward production readiness. The core features are stable, and we’re focused on refining performance, expanding protocol support, and ensuring smooth interop with other libp2p implementations. We welcome contributions and real-world usage feedback to help us reach full production maturity. Read more in the [documentation on ReadTheDocs](https://py-libp2p.readthedocs.io/). [View the release notes](https://py-libp2p.readthedocs.io/en/latest/release_notes.html). ## Maintainers -Currently maintained by [@pacrob](https://github.com/pacrob), [@seetadev](https://github.com/seetadev) and [@dhuseby](https://github.com/dhuseby), looking for assistance! +Currently maintained by [@pacrob](https://github.com/pacrob), [@seetadev](https://github.com/seetadev) and [@dhuseby](https://github.com/dhuseby). Please reach out to us for collaboration or active feedback. If you have questions, feel free to open a new [discussion](https://github.com/libp2p/py-libp2p/discussions). We are also available on the libp2p Discord — join us at #py-libp2p [sub-channel](https://discord.gg/d92MEugb). ## Feature Breakdown @@ -34,19 +34,19 @@ ______________________________________________________________________ | -------------------------------------- | :--------: | :---------------------------------------------------------------------------------: | | **`libp2p-tcp`** | ✅ | [source](https://github.com/libp2p/py-libp2p/blob/main/libp2p/transport/tcp/tcp.py) | | **`libp2p-quic`** | 🌱 | | -| **`libp2p-websocket`** | ❌ | | -| **`libp2p-webrtc-browser-to-server`** | ❌ | | -| **`libp2p-webrtc-private-to-private`** | ❌ | | +| **`libp2p-websocket`** | 🌱 | | +| **`libp2p-webrtc-browser-to-server`** | 🌱 | | +| **`libp2p-webrtc-private-to-private`** | 🌱 | | ______________________________________________________________________ ### NAT Traversal -| **NAT Traversal** | **Status** | -| ----------------------------- | :--------: | -| **`libp2p-circuit-relay-v2`** | ❌ | -| **`libp2p-autonat`** | ❌ | -| **`libp2p-hole-punching`** | ❌ | +| **NAT Traversal** | **Status** | **Source** | +| ----------------------------- | :--------: | :-----------------------------------------------------------------------------: | +| **`libp2p-circuit-relay-v2`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/relay/circuit_v2) | +| **`libp2p-autonat`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/host/autonat) | +| **`libp2p-hole-punching`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/relay/circuit_v2) | ______________________________________________________________________ @@ -54,27 +54,27 @@ ______________________________________________________________________ | **Secure Communication** | **Status** | **Source** | | ------------------------ | :--------: | :---------------------------------------------------------------------------: | -| **`libp2p-noise`** | 🌱 | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/security/noise) | -| **`libp2p-tls`** | ❌ | | +| **`libp2p-noise`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/security/noise) | +| **`libp2p-tls`** | 🌱 | | ______________________________________________________________________ ### Discovery -| **Discovery** | **Status** | -| -------------------- | :--------: | -| **`bootstrap`** | ❌ | -| **`random-walk`** | ❌ | -| **`mdns-discovery`** | ❌ | -| **`rendezvous`** | ❌ | +| **Discovery** | **Status** | **Source** | +| -------------------- | :--------: | :--------------------------------------------------------------------------------: | +| **`bootstrap`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/discovery/bootstrap) | +| **`random-walk`** | 🌱 | | +| **`mdns-discovery`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/discovery/mdns) | +| **`rendezvous`** | 🌱 | | ______________________________________________________________________ ### Peer Routing -| **Peer Routing** | **Status** | -| -------------------- | :--------: | -| **`libp2p-kad-dht`** | ❌ | +| **Peer Routing** | **Status** | **Source** | +| -------------------- | :--------: | :--------------------------------------------------------------------: | +| **`libp2p-kad-dht`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/kad_dht) | ______________________________________________________________________ @@ -89,10 +89,10 @@ ______________________________________________________________________ ### Stream Muxers -| **Stream Muxers** | **Status** | **Status** | -| ------------------ | :--------: | :----------------------------------------------------------------------------------------: | -| **`libp2p-yamux`** | 🌱 | | -| **`libp2p-mplex`** | 🛠️ | [source](https://github.com/libp2p/py-libp2p/blob/main/libp2p/stream_muxer/mplex/mplex.py) | +| **Stream Muxers** | **Status** | **Source** | +| ------------------ | :--------: | :-------------------------------------------------------------------------------: | +| **`libp2p-yamux`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/stream_muxer/yamux) | +| **`libp2p-mplex`** | ✅ | [source](https://github.com/libp2p/py-libp2p/tree/main/libp2p/stream_muxer/mplex) | ______________________________________________________________________ @@ -100,7 +100,7 @@ ______________________________________________________________________ | **Storage** | **Status** | | ------------------- | :--------: | -| **`libp2p-record`** | ❌ | +| **`libp2p-record`** | 🌱 | ______________________________________________________________________ diff --git a/libp2p/crypto/pb/crypto_pb2.py b/libp2p/crypto/pb/crypto_pb2.py index 3ca19591..99d47202 100644 --- a/libp2p/crypto/pb/crypto_pb2.py +++ b/libp2p/crypto/pb/crypto_pb2.py @@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dlibp2p/crypto/pb/crypto.proto\x12\tcrypto.pb\"?\n\tPublicKey\x12$\n\x08key_type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"@\n\nPrivateKey\x12$\n\x08key_type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c*G\n\x07KeyType\x12\x07\n\x03RSA\x10\x00\x12\x0b\n\x07\x45\x64\x32\x35\x35\x31\x39\x10\x01\x12\r\n\tSecp256k1\x10\x02\x12\t\n\x05\x45\x43\x44SA\x10\x03\x12\x0c\n\x08\x45\x43\x43_P256\x10\x04') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dlibp2p/crypto/pb/crypto.proto\x12\tcrypto.pb\"?\n\tPublicKey\x12$\n\x08key_type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"@\n\nPrivateKey\x12$\n\x08key_type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c*S\n\x07KeyType\x12\x07\n\x03RSA\x10\x00\x12\x0b\n\x07\x45\x64\x32\x35\x35\x31\x39\x10\x01\x12\r\n\tSecp256k1\x10\x02\x12\t\n\x05\x45\x43\x44SA\x10\x03\x12\x0c\n\x08\x45\x43\x43_P256\x10\x04\x12\n\n\x06X25519\x10\x05') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.crypto.pb.crypto_pb2', globals()) @@ -21,7 +21,7 @@ if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None _KEYTYPE._serialized_start=175 - _KEYTYPE._serialized_end=246 + _KEYTYPE._serialized_end=258 _PUBLICKEY._serialized_start=44 _PUBLICKEY._serialized_end=107 _PRIVATEKEY._serialized_start=109 diff --git a/libp2p/crypto/pb/crypto_pb2.pyi b/libp2p/crypto/pb/crypto_pb2.pyi index 8c472474..578930c9 100644 --- a/libp2p/crypto/pb/crypto_pb2.pyi +++ b/libp2p/crypto/pb/crypto_pb2.pyi @@ -28,6 +28,7 @@ class _KeyTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy Secp256k1: _KeyType.ValueType # 2 ECDSA: _KeyType.ValueType # 3 ECC_P256: _KeyType.ValueType # 4 + X25519: _KeyType.ValueType # 5 class KeyType(_KeyType, metaclass=_KeyTypeEnumTypeWrapper): ... @@ -36,6 +37,7 @@ Ed25519: KeyType.ValueType # 1 Secp256k1: KeyType.ValueType # 2 ECDSA: KeyType.ValueType # 3 ECC_P256: KeyType.ValueType # 4 +X25519: KeyType.ValueType # 5 global___KeyType = KeyType @typing.final diff --git a/libp2p/identity/identify/pb/identify_pb2.py b/libp2p/identity/identify/pb/identify_pb2.py index 2db3c552..d582d68a 100644 --- a/libp2p/identity/identify/pb/identify_pb2.py +++ b/libp2p/identity/identify/pb/identify_pb2.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: libp2p/identity/identify/pb/identify.proto -# Protobuf Python Version: 4.25.3 """Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -16,11 +15,11 @@ _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n*libp2p/identity/identify/pb/identify.proto\x12\x0bidentify.pb\"\xa9\x01\n\x08Identify\x12\x18\n\x10protocol_version\x18\x05 \x01(\t\x12\x15\n\ragent_version\x18\x06 \x01(\t\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x14\n\x0clisten_addrs\x18\x02 \x03(\x0c\x12\x15\n\robserved_addr\x18\x04 \x01(\x0c\x12\x11\n\tprotocols\x18\x03 \x03(\t\x12\x18\n\x10signedPeerRecord\x18\x08 \x01(\x0c') -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.identity.identify.pb.identify_pb2', _globals) +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.identity.identify.pb.identify_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None - _globals['_IDENTIFY']._serialized_start=60 - _globals['_IDENTIFY']._serialized_end=229 + _IDENTIFY._serialized_start=60 + _IDENTIFY._serialized_end=229 # @@protoc_insertion_point(module_scope) diff --git a/libp2p/identity/identify/pb/identify_pb2.pyi b/libp2p/identity/identify/pb/identify_pb2.pyi index 428dcf35..9a0c75d5 100644 --- a/libp2p/identity/identify/pb/identify_pb2.pyi +++ b/libp2p/identity/identify/pb/identify_pb2.pyi @@ -1,24 +1,49 @@ -from google.protobuf.internal import containers as _containers -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from typing import ClassVar as _ClassVar, Iterable as _Iterable, Optional as _Optional +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" -DESCRIPTOR: _descriptor.FileDescriptor +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.message +import typing -class Identify(_message.Message): - __slots__ = ("protocol_version", "agent_version", "public_key", "listen_addrs", "observed_addr", "protocols", "signedPeerRecord") - PROTOCOL_VERSION_FIELD_NUMBER: _ClassVar[int] - AGENT_VERSION_FIELD_NUMBER: _ClassVar[int] - PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int] - LISTEN_ADDRS_FIELD_NUMBER: _ClassVar[int] - OBSERVED_ADDR_FIELD_NUMBER: _ClassVar[int] - PROTOCOLS_FIELD_NUMBER: _ClassVar[int] - SIGNEDPEERRECORD_FIELD_NUMBER: _ClassVar[int] - protocol_version: str - agent_version: str - public_key: bytes - listen_addrs: _containers.RepeatedScalarFieldContainer[bytes] - observed_addr: bytes - protocols: _containers.RepeatedScalarFieldContainer[str] - signedPeerRecord: bytes - def __init__(self, protocol_version: _Optional[str] = ..., agent_version: _Optional[str] = ..., public_key: _Optional[bytes] = ..., listen_addrs: _Optional[_Iterable[bytes]] = ..., observed_addr: _Optional[bytes] = ..., protocols: _Optional[_Iterable[str]] = ..., signedPeerRecord: _Optional[bytes] = ...) -> None: ... +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Identify(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PROTOCOL_VERSION_FIELD_NUMBER: builtins.int + AGENT_VERSION_FIELD_NUMBER: builtins.int + PUBLIC_KEY_FIELD_NUMBER: builtins.int + LISTEN_ADDRS_FIELD_NUMBER: builtins.int + OBSERVED_ADDR_FIELD_NUMBER: builtins.int + PROTOCOLS_FIELD_NUMBER: builtins.int + SIGNEDPEERRECORD_FIELD_NUMBER: builtins.int + protocol_version: builtins.str + agent_version: builtins.str + public_key: builtins.bytes + observed_addr: builtins.bytes + signedPeerRecord: builtins.bytes + @property + def listen_addrs(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... + @property + def protocols(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + def __init__( + self, + *, + protocol_version: builtins.str | None = ..., + agent_version: builtins.str | None = ..., + public_key: builtins.bytes | None = ..., + listen_addrs: collections.abc.Iterable[builtins.bytes] | None = ..., + observed_addr: builtins.bytes | None = ..., + protocols: collections.abc.Iterable[builtins.str] | None = ..., + signedPeerRecord: builtins.bytes | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["agent_version", b"agent_version", "observed_addr", b"observed_addr", "protocol_version", b"protocol_version", "public_key", b"public_key", "signedPeerRecord", b"signedPeerRecord"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["agent_version", b"agent_version", "listen_addrs", b"listen_addrs", "observed_addr", b"observed_addr", "protocol_version", b"protocol_version", "protocols", b"protocols", "public_key", b"public_key", "signedPeerRecord", b"signedPeerRecord"]) -> None: ... + +global___Identify = Identify diff --git a/libp2p/kad_dht/pb/kademlia_pb2.py b/libp2p/kad_dht/pb/kademlia_pb2.py index 1fe2c032..781333bf 100644 --- a/libp2p/kad_dht/pb/kademlia_pb2.py +++ b/libp2p/kad_dht/pb/kademlia_pb2.py @@ -2,10 +2,10 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: libp2p/kad_dht/pb/kademlia.proto """Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -15,19 +15,19 @@ _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n libp2p/kad_dht/pb/kademlia.proto\":\n\x06Record\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x14\n\x0ctimeReceived\x18\x05 \x01(\t\"\xca\x03\n\x07Message\x12\"\n\x04type\x18\x01 \x01(\x0e\x32\x14.Message.MessageType\x12\x17\n\x0f\x63lusterLevelRaw\x18\n \x01(\x05\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x17\n\x06record\x18\x03 \x01(\x0b\x32\x07.Record\x12\"\n\x0b\x63loserPeers\x18\x08 \x03(\x0b\x32\r.Message.Peer\x12$\n\rproviderPeers\x18\t \x03(\x0b\x32\r.Message.Peer\x1aN\n\x04Peer\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05\x61\x64\x64rs\x18\x02 \x03(\x0c\x12+\n\nconnection\x18\x03 \x01(\x0e\x32\x17.Message.ConnectionType\"i\n\x0bMessageType\x12\r\n\tPUT_VALUE\x10\x00\x12\r\n\tGET_VALUE\x10\x01\x12\x10\n\x0c\x41\x44\x44_PROVIDER\x10\x02\x12\x11\n\rGET_PROVIDERS\x10\x03\x12\r\n\tFIND_NODE\x10\x04\x12\x08\n\x04PING\x10\x05\"W\n\x0e\x43onnectionType\x12\x11\n\rNOT_CONNECTED\x10\x00\x12\r\n\tCONNECTED\x10\x01\x12\x0f\n\x0b\x43\x41N_CONNECT\x10\x02\x12\x12\n\x0e\x43\x41NNOT_CONNECT\x10\x03\x62\x06proto3') -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.kad_dht.pb.kademlia_pb2', _globals) +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.kad_dht.pb.kademlia_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None - _globals['_RECORD']._serialized_start=36 - _globals['_RECORD']._serialized_end=94 - _globals['_MESSAGE']._serialized_start=97 - _globals['_MESSAGE']._serialized_end=555 - _globals['_MESSAGE_PEER']._serialized_start=281 - _globals['_MESSAGE_PEER']._serialized_end=359 - _globals['_MESSAGE_MESSAGETYPE']._serialized_start=361 - _globals['_MESSAGE_MESSAGETYPE']._serialized_end=466 - _globals['_MESSAGE_CONNECTIONTYPE']._serialized_start=468 - _globals['_MESSAGE_CONNECTIONTYPE']._serialized_end=555 + _RECORD._serialized_start=36 + _RECORD._serialized_end=94 + _MESSAGE._serialized_start=97 + _MESSAGE._serialized_end=555 + _MESSAGE_PEER._serialized_start=281 + _MESSAGE_PEER._serialized_end=359 + _MESSAGE_MESSAGETYPE._serialized_start=361 + _MESSAGE_MESSAGETYPE._serialized_end=466 + _MESSAGE_CONNECTIONTYPE._serialized_start=468 + _MESSAGE_CONNECTIONTYPE._serialized_end=555 # @@protoc_insertion_point(module_scope) diff --git a/libp2p/network/connection/swarm_connection.py b/libp2p/network/connection/swarm_connection.py index c8919c23..c1b42c58 100644 --- a/libp2p/network/connection/swarm_connection.py +++ b/libp2p/network/connection/swarm_connection.py @@ -23,7 +23,8 @@ if TYPE_CHECKING: """ -Reference: https://github.com/libp2p/go-libp2p-swarm/blob/04c86bbdafd390651cb2ee14e334f7caeedad722/swarm_conn.go +Reference: https://github.com/libp2p/go-libp2p-swarm/blob/ +04c86bbdafd390651cb2ee14e334f7caeedad722/swarm_conn.go """ @@ -43,6 +44,21 @@ class SwarmConn(INetConn): self.streams = set() self.event_closed = trio.Event() self.event_started = trio.Event() + # Provide back-references/hooks expected by NetStream + try: + setattr(self.muxed_conn, "swarm", self.swarm) + + # NetStream expects an awaitable remove_stream hook + async def _remove_stream_hook(stream: NetStream) -> None: + self.remove_stream(stream) + + setattr(self.muxed_conn, "remove_stream", _remove_stream_hook) + except Exception as e: + logging.warning( + f"Failed to set optional conveniences on muxed_conn " + f"for peer {muxed_conn.peer_id}: {e}" + ) + # optional conveniences if hasattr(muxed_conn, "on_close"): logging.debug(f"Setting on_close for peer {muxed_conn.peer_id}") setattr(muxed_conn, "on_close", self._on_muxed_conn_closed) diff --git a/libp2p/network/swarm.py b/libp2p/network/swarm.py index 706d649a..0a1ae1cd 100644 --- a/libp2p/network/swarm.py +++ b/libp2p/network/swarm.py @@ -1,3 +1,7 @@ +from collections.abc import ( + Awaitable, + Callable, +) import logging from multiaddr import ( @@ -411,7 +415,15 @@ class Swarm(Service, INetworkService): nursery.start_soon(notifee.listen, self, multiaddr) async def notify_closed_stream(self, stream: INetStream) -> None: - raise NotImplementedError + async with trio.open_nursery() as nursery: + for notifee in self.notifees: + nursery.start_soon(notifee.closed_stream, self, stream) async def notify_listen_close(self, multiaddr: Multiaddr) -> None: raise NotImplementedError + + # Generic notifier used by NetStream._notify_closed + async def notify_all(self, notifier: Callable[[INotifee], Awaitable[None]]) -> None: + async with trio.open_nursery() as nursery: + for notifee in self.notifees: + nursery.start_soon(notifier, notifee) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 1f5ea36a..043aaf0d 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -39,8 +39,6 @@ from .peerinfo import ( PERMANENT_ADDR_TTL = 0 -# TODO: Set up an async task for periodic peer-store cleanup -# for expired addresses and records. class PeerRecordState: envelope: Envelope seq: int @@ -217,7 +215,6 @@ class PeerStore(IPeerStore): # -----CERT-ADDR-BOOK----- - # TODO: Make proper use of this function def maybe_delete_peer_record(self, peer_id: ID) -> None: """ Delete the signed peer record for a peer if it has no know diff --git a/libp2p/pubsub/pb/rpc_pb2.py b/libp2p/pubsub/pb/rpc_pb2.py index 7941d655..30f0281b 100644 --- a/libp2p/pubsub/pb/rpc_pb2.py +++ b/libp2p/pubsub/pb/rpc_pb2.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! -# source: rpc.proto +# source: libp2p/pubsub/pb/rpc.proto """Generated protocol buffer code.""" from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor @@ -13,39 +13,39 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\trpc.proto\x12\tpubsub.pb\"\xb4\x01\n\x03RPC\x12-\n\rsubscriptions\x18\x01 \x03(\x0b\x32\x16.pubsub.pb.RPC.SubOpts\x12#\n\x07publish\x18\x02 \x03(\x0b\x32\x12.pubsub.pb.Message\x12*\n\x07\x63ontrol\x18\x03 \x01(\x0b\x32\x19.pubsub.pb.ControlMessage\x1a-\n\x07SubOpts\x12\x11\n\tsubscribe\x18\x01 \x01(\x08\x12\x0f\n\x07topicid\x18\x02 \x01(\t\"i\n\x07Message\x12\x0f\n\x07\x66rom_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\r\n\x05seqno\x18\x03 \x01(\x0c\x12\x10\n\x08topicIDs\x18\x04 \x03(\t\x12\x11\n\tsignature\x18\x05 \x01(\x0c\x12\x0b\n\x03key\x18\x06 \x01(\x0c\"\xb0\x01\n\x0e\x43ontrolMessage\x12&\n\x05ihave\x18\x01 \x03(\x0b\x32\x17.pubsub.pb.ControlIHave\x12&\n\x05iwant\x18\x02 \x03(\x0b\x32\x17.pubsub.pb.ControlIWant\x12&\n\x05graft\x18\x03 \x03(\x0b\x32\x17.pubsub.pb.ControlGraft\x12&\n\x05prune\x18\x04 \x03(\x0b\x32\x17.pubsub.pb.ControlPrune\"3\n\x0c\x43ontrolIHave\x12\x0f\n\x07topicID\x18\x01 \x01(\t\x12\x12\n\nmessageIDs\x18\x02 \x03(\t\"\"\n\x0c\x43ontrolIWant\x12\x12\n\nmessageIDs\x18\x01 \x03(\t\"\x1f\n\x0c\x43ontrolGraft\x12\x0f\n\x07topicID\x18\x01 \x01(\t\"T\n\x0c\x43ontrolPrune\x12\x0f\n\x07topicID\x18\x01 \x01(\t\x12\"\n\x05peers\x18\x02 \x03(\x0b\x32\x13.pubsub.pb.PeerInfo\x12\x0f\n\x07\x62\x61\x63koff\x18\x03 \x01(\x04\"4\n\x08PeerInfo\x12\x0e\n\x06peerID\x18\x01 \x01(\x0c\x12\x18\n\x10signedPeerRecord\x18\x02 \x01(\x0c\"\x87\x03\n\x0fTopicDescriptor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x31\n\x04\x61uth\x18\x02 \x01(\x0b\x32#.pubsub.pb.TopicDescriptor.AuthOpts\x12/\n\x03\x65nc\x18\x03 \x01(\x0b\x32\".pubsub.pb.TopicDescriptor.EncOpts\x1a|\n\x08\x41uthOpts\x12:\n\x04mode\x18\x01 \x01(\x0e\x32,.pubsub.pb.TopicDescriptor.AuthOpts.AuthMode\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\"&\n\x08\x41uthMode\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03KEY\x10\x01\x12\x07\n\x03WOT\x10\x02\x1a\x83\x01\n\x07\x45ncOpts\x12\x38\n\x04mode\x18\x01 \x01(\x0e\x32*.pubsub.pb.TopicDescriptor.EncOpts.EncMode\x12\x11\n\tkeyHashes\x18\x02 \x03(\x0c\"+\n\x07\x45ncMode\x12\x08\n\x04NONE\x10\x00\x12\r\n\tSHAREDKEY\x10\x01\x12\x07\n\x03WOT\x10\x02') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1alibp2p/pubsub/pb/rpc.proto\x12\tpubsub.pb\"\xb4\x01\n\x03RPC\x12-\n\rsubscriptions\x18\x01 \x03(\x0b\x32\x16.pubsub.pb.RPC.SubOpts\x12#\n\x07publish\x18\x02 \x03(\x0b\x32\x12.pubsub.pb.Message\x12*\n\x07\x63ontrol\x18\x03 \x01(\x0b\x32\x19.pubsub.pb.ControlMessage\x1a-\n\x07SubOpts\x12\x11\n\tsubscribe\x18\x01 \x01(\x08\x12\x0f\n\x07topicid\x18\x02 \x01(\t\"i\n\x07Message\x12\x0f\n\x07\x66rom_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\r\n\x05seqno\x18\x03 \x01(\x0c\x12\x10\n\x08topicIDs\x18\x04 \x03(\t\x12\x11\n\tsignature\x18\x05 \x01(\x0c\x12\x0b\n\x03key\x18\x06 \x01(\x0c\"\xb0\x01\n\x0e\x43ontrolMessage\x12&\n\x05ihave\x18\x01 \x03(\x0b\x32\x17.pubsub.pb.ControlIHave\x12&\n\x05iwant\x18\x02 \x03(\x0b\x32\x17.pubsub.pb.ControlIWant\x12&\n\x05graft\x18\x03 \x03(\x0b\x32\x17.pubsub.pb.ControlGraft\x12&\n\x05prune\x18\x04 \x03(\x0b\x32\x17.pubsub.pb.ControlPrune\"3\n\x0c\x43ontrolIHave\x12\x0f\n\x07topicID\x18\x01 \x01(\t\x12\x12\n\nmessageIDs\x18\x02 \x03(\t\"\"\n\x0c\x43ontrolIWant\x12\x12\n\nmessageIDs\x18\x01 \x03(\t\"\x1f\n\x0c\x43ontrolGraft\x12\x0f\n\x07topicID\x18\x01 \x01(\t\"T\n\x0c\x43ontrolPrune\x12\x0f\n\x07topicID\x18\x01 \x01(\t\x12\"\n\x05peers\x18\x02 \x03(\x0b\x32\x13.pubsub.pb.PeerInfo\x12\x0f\n\x07\x62\x61\x63koff\x18\x03 \x01(\x04\"4\n\x08PeerInfo\x12\x0e\n\x06peerID\x18\x01 \x01(\x0c\x12\x18\n\x10signedPeerRecord\x18\x02 \x01(\x0c\"\x87\x03\n\x0fTopicDescriptor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x31\n\x04\x61uth\x18\x02 \x01(\x0b\x32#.pubsub.pb.TopicDescriptor.AuthOpts\x12/\n\x03\x65nc\x18\x03 \x01(\x0b\x32\".pubsub.pb.TopicDescriptor.EncOpts\x1a|\n\x08\x41uthOpts\x12:\n\x04mode\x18\x01 \x01(\x0e\x32,.pubsub.pb.TopicDescriptor.AuthOpts.AuthMode\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\"&\n\x08\x41uthMode\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03KEY\x10\x01\x12\x07\n\x03WOT\x10\x02\x1a\x83\x01\n\x07\x45ncOpts\x12\x38\n\x04mode\x18\x01 \x01(\x0e\x32*.pubsub.pb.TopicDescriptor.EncOpts.EncMode\x12\x11\n\tkeyHashes\x18\x02 \x03(\x0c\"+\n\x07\x45ncMode\x12\x08\n\x04NONE\x10\x00\x12\r\n\tSHAREDKEY\x10\x01\x12\x07\n\x03WOT\x10\x02') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'rpc_pb2', globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.pubsub.pb.rpc_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _RPC._serialized_start=25 - _RPC._serialized_end=205 - _RPC_SUBOPTS._serialized_start=160 - _RPC_SUBOPTS._serialized_end=205 - _MESSAGE._serialized_start=207 - _MESSAGE._serialized_end=312 - _CONTROLMESSAGE._serialized_start=315 - _CONTROLMESSAGE._serialized_end=491 - _CONTROLIHAVE._serialized_start=493 - _CONTROLIHAVE._serialized_end=544 - _CONTROLIWANT._serialized_start=546 - _CONTROLIWANT._serialized_end=580 - _CONTROLGRAFT._serialized_start=582 - _CONTROLGRAFT._serialized_end=613 - _CONTROLPRUNE._serialized_start=615 - _CONTROLPRUNE._serialized_end=699 - _PEERINFO._serialized_start=701 - _PEERINFO._serialized_end=753 - _TOPICDESCRIPTOR._serialized_start=756 - _TOPICDESCRIPTOR._serialized_end=1147 - _TOPICDESCRIPTOR_AUTHOPTS._serialized_start=889 - _TOPICDESCRIPTOR_AUTHOPTS._serialized_end=1013 - _TOPICDESCRIPTOR_AUTHOPTS_AUTHMODE._serialized_start=975 - _TOPICDESCRIPTOR_AUTHOPTS_AUTHMODE._serialized_end=1013 - _TOPICDESCRIPTOR_ENCOPTS._serialized_start=1016 - _TOPICDESCRIPTOR_ENCOPTS._serialized_end=1147 - _TOPICDESCRIPTOR_ENCOPTS_ENCMODE._serialized_start=1104 - _TOPICDESCRIPTOR_ENCOPTS_ENCMODE._serialized_end=1147 + _RPC._serialized_start=42 + _RPC._serialized_end=222 + _RPC_SUBOPTS._serialized_start=177 + _RPC_SUBOPTS._serialized_end=222 + _MESSAGE._serialized_start=224 + _MESSAGE._serialized_end=329 + _CONTROLMESSAGE._serialized_start=332 + _CONTROLMESSAGE._serialized_end=508 + _CONTROLIHAVE._serialized_start=510 + _CONTROLIHAVE._serialized_end=561 + _CONTROLIWANT._serialized_start=563 + _CONTROLIWANT._serialized_end=597 + _CONTROLGRAFT._serialized_start=599 + _CONTROLGRAFT._serialized_end=630 + _CONTROLPRUNE._serialized_start=632 + _CONTROLPRUNE._serialized_end=716 + _PEERINFO._serialized_start=718 + _PEERINFO._serialized_end=770 + _TOPICDESCRIPTOR._serialized_start=773 + _TOPICDESCRIPTOR._serialized_end=1164 + _TOPICDESCRIPTOR_AUTHOPTS._serialized_start=906 + _TOPICDESCRIPTOR_AUTHOPTS._serialized_end=1030 + _TOPICDESCRIPTOR_AUTHOPTS_AUTHMODE._serialized_start=992 + _TOPICDESCRIPTOR_AUTHOPTS_AUTHMODE._serialized_end=1030 + _TOPICDESCRIPTOR_ENCOPTS._serialized_start=1033 + _TOPICDESCRIPTOR_ENCOPTS._serialized_end=1164 + _TOPICDESCRIPTOR_ENCOPTS_ENCMODE._serialized_start=1121 + _TOPICDESCRIPTOR_ENCOPTS_ENCMODE._serialized_end=1164 # @@protoc_insertion_point(module_scope) diff --git a/libp2p/relay/circuit_v2/pb/circuit_pb2.py b/libp2p/relay/circuit_v2/pb/circuit_pb2.py index 9cdf16a2..946bff73 100644 --- a/libp2p/relay/circuit_v2/pb/circuit_pb2.py +++ b/libp2p/relay/circuit_v2/pb/circuit_pb2.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE # source: libp2p/relay/circuit_v2/pb/circuit.proto """Generated protocol buffer code.""" from google.protobuf.internal import builder as _builder @@ -12,11 +11,14 @@ from google.protobuf import symbol_database as _symbol_database _sym_db = _symbol_database.Default() + + DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(libp2p/relay/circuit_v2/pb/circuit.proto\x12\rcircuit.pb.v2\"\xf3\x01\n\nHopMessage\x12,\n\x04type\x18\x01 \x01(\x0e\x32\x1e.circuit.pb.v2.HopMessage.Type\x12\x0c\n\x04peer\x18\x02 \x01(\x0c\x12/\n\x0breservation\x18\x03 \x01(\x0b\x32\x1a.circuit.pb.v2.Reservation\x12#\n\x05limit\x18\x04 \x01(\x0b\x32\x14.circuit.pb.v2.Limit\x12%\n\x06status\x18\x05 \x01(\x0b\x32\x15.circuit.pb.v2.Status\",\n\x04Type\x12\x0b\n\x07RESERVE\x10\x00\x12\x0b\n\x07\x43ONNECT\x10\x01\x12\n\n\x06STATUS\x10\x02\"\x92\x01\n\x0bStopMessage\x12-\n\x04type\x18\x01 \x01(\x0e\x32\x1f.circuit.pb.v2.StopMessage.Type\x12\x0c\n\x04peer\x18\x02 \x01(\x0c\x12%\n\x06status\x18\x03 \x01(\x0b\x32\x15.circuit.pb.v2.Status\"\x1f\n\x04Type\x12\x0b\n\x07\x43ONNECT\x10\x00\x12\n\n\x06STATUS\x10\x01\"A\n\x0bReservation\x12\x0f\n\x07voucher\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\x12\x0e\n\x06\x65xpire\x18\x03 \x01(\x03\"\'\n\x05Limit\x12\x10\n\x08\x64uration\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x03\"\xf6\x01\n\x06Status\x12(\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1a.circuit.pb.v2.Status.Code\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xb0\x01\n\x04\x43ode\x12\x06\n\x02OK\x10\x00\x12\x17\n\x13RESERVATION_REFUSED\x10\x64\x12\x1b\n\x17RESOURCE_LIMIT_EXCEEDED\x10\x65\x12\x15\n\x11PERMISSION_DENIED\x10\x66\x12\x16\n\x11\x43ONNECTION_FAILED\x10\xc8\x01\x12\x11\n\x0c\x44IAL_REFUSED\x10\xc9\x01\x12\x10\n\x0bSTOP_FAILED\x10\xac\x02\x12\x16\n\x11MALFORMED_MESSAGE\x10\x90\x03\x62\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.relay.circuit_v2.pb.circuit_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None _HOPMESSAGE._serialized_start=60 _HOPMESSAGE._serialized_end=303 diff --git a/libp2p/relay/circuit_v2/pb/dcutr_pb2.py b/libp2p/relay/circuit_v2/pb/dcutr_pb2.py index 41807891..59e49a79 100644 --- a/libp2p/relay/circuit_v2/pb/dcutr_pb2.py +++ b/libp2p/relay/circuit_v2/pb/dcutr_pb2.py @@ -13,11 +13,12 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&libp2p/relay/circuit_v2/pb/dcutr.proto\x12\x0cholepunch.pb\"\x69\n\tHolePunch\x12*\n\x04type\x18\x01 \x02(\x0e\x32\x1c.holepunch.pb.HolePunch.Type\x12\x10\n\x08ObsAddrs\x18\x02 \x03(\x0c\"\x1e\n\x04Type\x12\x0b\n\x07CONNECT\x10\x64\x12\t\n\x04SYNC\x10\xac\x02') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&libp2p/relay/circuit_v2/pb/dcutr.proto\x12\x0cholepunch.pb\"i\n\tHolePunch\x12*\n\x04type\x18\x01 \x02(\x0e\x32\x1c.holepunch.pb.HolePunch.Type\x12\x10\n\x08ObsAddrs\x18\x02 \x03(\x0c\"\x1e\n\x04Type\x12\x0b\n\x07\x43ONNECT\x10\x64\x12\t\n\x04SYNC\x10\xac\x02') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'libp2p.relay.circuit_v2.pb.dcutr_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None _HOLEPUNCH._serialized_start=56 _HOLEPUNCH._serialized_end=161 diff --git a/libp2p/relay/circuit_v2/pb/dcutr_pb2.pyi b/libp2p/relay/circuit_v2/pb/dcutr_pb2.pyi index a314cbae..da6cf5dc 100644 --- a/libp2p/relay/circuit_v2/pb/dcutr_pb2.pyi +++ b/libp2p/relay/circuit_v2/pb/dcutr_pb2.pyi @@ -7,47 +7,46 @@ import builtins import collections.abc import google.protobuf.descriptor import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper import google.protobuf.message +import sys import typing +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + DESCRIPTOR: google.protobuf.descriptor.FileDescriptor @typing.final class HolePunch(google.protobuf.message.Message): - """HolePunch message for the DCUtR protocol.""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - class Type(builtins.int): - """Message types for HolePunch""" - @builtins.classmethod - def Name(cls, number: builtins.int) -> builtins.str: ... - @builtins.classmethod - def Value(cls, name: builtins.str) -> 'HolePunch.Type': ... - @builtins.classmethod - def keys(cls) -> typing.List[builtins.str]: ... - @builtins.classmethod - def values(cls) -> typing.List['HolePunch.Type']: ... - @builtins.classmethod - def items(cls) -> typing.List[typing.Tuple[builtins.str, 'HolePunch.Type']]: ... - - CONNECT: HolePunch.Type # 100 - SYNC: HolePunch.Type # 300 - + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[HolePunch._Type.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + CONNECT: HolePunch._Type.ValueType # 100 + SYNC: HolePunch._Type.ValueType # 300 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): ... + CONNECT: HolePunch.Type.ValueType # 100 + SYNC: HolePunch.Type.ValueType # 300 + TYPE_FIELD_NUMBER: builtins.int OBSADDRS_FIELD_NUMBER: builtins.int - type: HolePunch.Type - + type: global___HolePunch.Type.ValueType @property def ObsAddrs(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... - def __init__( self, *, - type: HolePunch.Type = ..., - ObsAddrs: collections.abc.Iterable[builtins.bytes] = ..., + type: global___HolePunch.Type.ValueType | None = ..., + ObsAddrs: collections.abc.Iterable[builtins.bytes] | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["type", b"type"]) -> builtins.bool: ... def ClearField(self, field_name: typing.Literal["ObsAddrs", b"ObsAddrs", "type", b"type"]) -> None: ... diff --git a/libp2p/security/noise/transport.py b/libp2p/security/noise/transport.py index 8fdd6b6e..b26e0644 100644 --- a/libp2p/security/noise/transport.py +++ b/libp2p/security/noise/transport.py @@ -29,11 +29,6 @@ class Transport(ISecureTransport): early_data: bytes | None with_noise_pipes: bool - # NOTE: Implementations that support Noise Pipes must decide whether to use - # an XX or IK handshake based on whether they possess a cached static - # Noise key for the remote peer. - # TODO: A storage of seen noise static keys for pattern IK? - def __init__( self, libp2p_keypair: KeyPair, diff --git a/newsfragments/816.internal.rst b/newsfragments/816.internal.rst new file mode 100644 index 00000000..ade49df8 --- /dev/null +++ b/newsfragments/816.internal.rst @@ -0,0 +1 @@ +The TODO IK patterns in Noise has been deprecated in specs: https://github.com/libp2p/specs/tree/master/noise#handshake-pattern diff --git a/newsfragments/818.bugfix.rst b/newsfragments/818.bugfix.rst new file mode 100644 index 00000000..985e3e33 --- /dev/null +++ b/newsfragments/818.bugfix.rst @@ -0,0 +1 @@ +Recompiled protobufs that were out of date and added a `make` rule so that protobufs are always up to date. diff --git a/newsfragments/819.internal.rst b/newsfragments/819.internal.rst new file mode 100644 index 00000000..65890f5e --- /dev/null +++ b/newsfragments/819.internal.rst @@ -0,0 +1,3 @@ +Remove the already completed TODO tasks in Peerstore: +TODO: Set up an async task for periodic peer-store cleanup for expired addresses and records. +TODO: Make proper use of this function diff --git a/newsfragments/826.feature.rst b/newsfragments/826.feature.rst new file mode 100644 index 00000000..face9786 --- /dev/null +++ b/newsfragments/826.feature.rst @@ -0,0 +1,6 @@ +Implement closed_stream notification in MyNotifee + +- Add notify_closed_stream method to swarm notification system for proper stream lifecycle management +- Integrate remove_stream hook in SwarmConn to enable stream closure notifications +- Add comprehensive tests for closed_stream functionality in test_notify.py +- Enable stream lifecycle integration for proper cleanup and resource management diff --git a/pyproject.toml b/pyproject.toml index 1718f226..c328f038 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,8 +10,10 @@ readme = "README.md" requires-python = ">=3.10, <4.0" license = { text = "MIT AND Apache-2.0" } keywords = ["libp2p", "p2p"] -authors = [ - { name = "The Ethereum Foundation", email = "snakecharmers@ethereum.org" }, +maintainers = [ + { name = "pacrob", email = "pacrob@protonmail.com" }, + { name = "Manu Sheel Gupta", email = "manu@seeta.in" }, + { name = "Dave Grantham", email = "dave@aviation.community" }, ] dependencies = [ "base58>=1.0.3", diff --git a/tests/core/network/test_notify.py b/tests/core/network/test_notify.py index 98caaf86..b19dd961 100644 --- a/tests/core/network/test_notify.py +++ b/tests/core/network/test_notify.py @@ -44,8 +44,11 @@ class MyNotifee(INotifee): self.events.append(Event.OpenedStream) async def closed_stream(self, network: INetwork, stream: INetStream) -> None: - # TODO: It is not implemented yet. - pass + if network is None: + raise ValueError("network parameter cannot be None") + if stream is None: + raise ValueError("stream parameter cannot be None") + self.events.append(Event.ClosedStream) async def connected(self, network: INetwork, conn: INetConn) -> None: self.events.append(Event.Connected) @@ -103,28 +106,20 @@ async def test_notify(security_protocol): # Wait for events assert await wait_for_event(events_0_0, Event.Connected, 1.0) assert await wait_for_event(events_0_0, Event.OpenedStream, 1.0) - # assert await wait_for_event( - # events_0_0, Event.ClosedStream, 1.0 - # ) # Not implemented + assert await wait_for_event(events_0_0, Event.ClosedStream, 1.0) assert await wait_for_event(events_0_0, Event.Disconnected, 1.0) assert await wait_for_event(events_0_1, Event.Connected, 1.0) assert await wait_for_event(events_0_1, Event.OpenedStream, 1.0) - # assert await wait_for_event( - # events_0_1, Event.ClosedStream, 1.0 - # ) # Not implemented + assert await wait_for_event(events_0_1, Event.ClosedStream, 1.0) assert await wait_for_event(events_0_1, Event.Disconnected, 1.0) assert await wait_for_event(events_1_0, Event.Connected, 1.0) assert await wait_for_event(events_1_0, Event.OpenedStream, 1.0) - # assert await wait_for_event( - # events_1_0, Event.ClosedStream, 1.0 - # ) # Not implemented + assert await wait_for_event(events_1_0, Event.ClosedStream, 1.0) assert await wait_for_event(events_1_0, Event.Disconnected, 1.0) assert await wait_for_event(events_1_1, Event.Connected, 1.0) assert await wait_for_event(events_1_1, Event.OpenedStream, 1.0) - # assert await wait_for_event( - # events_1_1, Event.ClosedStream, 1.0 - # ) # Not implemented + assert await wait_for_event(events_1_1, Event.ClosedStream, 1.0) assert await wait_for_event(events_1_1, Event.Disconnected, 1.0)