libp2p 0.2.6__tar.gz → 0.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {libp2p-0.2.6/libp2p.egg-info → libp2p-0.2.7}/PKG-INFO +1 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify_push/identify_push_demo.py +49 -0
- libp2p-0.2.7/libp2p/__init__.py +257 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/keys.py +23 -14
- libp2p-0.2.7/libp2p/crypto/x25519.py +69 -0
- libp2p-0.2.7/libp2p/exceptions.py +53 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/swarm_connection.py +42 -2
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/stream/net_stream.py +2 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/swarm.py +29 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/peerstore.py +3 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/gossipsub.py +58 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pubsub.py +41 -36
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/io.py +9 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/muxer_multistream.py +21 -2
- libp2p-0.2.7/libp2p/stream_muxer/yamux/__init__.py +5 -0
- libp2p-0.2.7/libp2p/stream_muxer/yamux/yamux.py +676 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/constants.py +9 -0
- libp2p-0.2.7/libp2p/tools/utils.py +154 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/tcp/tcp.py +8 -2
- libp2p-0.2.7/libp2p/utils/__init__.py +23 -0
- libp2p-0.2.7/libp2p/utils/logging.py +217 -0
- libp2p-0.2.6/libp2p/utils.py → libp2p-0.2.7/libp2p/utils/varint.py +2 -23
- libp2p-0.2.7/libp2p/utils/version.py +22 -0
- {libp2p-0.2.6 → libp2p-0.2.7/libp2p.egg-info}/PKG-INFO +1 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/SOURCES.txt +14 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/pyproject.toml +1 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/setup.py +1 -1
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/examples/test_examples.py +2 -2
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_connected_peers.py +2 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/test_net_stream.py +2 -2
- libp2p-0.2.7/tests/core/network/test_notify.py +208 -0
- libp2p-0.2.7/tests/core/pubsub/test_gossipsub_direct_peers.py +170 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_pubsub.py +8 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/test_security_multistream.py +23 -2
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/stream_muxer/conftest.py +20 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/stream_muxer/test_mplex_conn.py +3 -3
- libp2p-0.2.7/tests/core/stream_muxer/test_multiplexer_selection.py +256 -0
- libp2p-0.2.7/tests/core/stream_muxer/test_yamux.py +448 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/timed_cache/test_timed_cache.py +1 -1
- libp2p-0.2.7/tests/crypto/test_x25519.py +102 -0
- libp2p-0.2.7/tests/exceptions/test_exceptions.py +13 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/factories.py +62 -2
- libp2p-0.2.7/tests/utils/pubsub/__init__.py +0 -0
- libp2p-0.2.7/tests/utils/test_logging.py +257 -0
- libp2p-0.2.6/libp2p/__init__.py +0 -131
- libp2p-0.2.6/libp2p/exceptions.py +0 -16
- libp2p-0.2.6/libp2p/tools/utils.py +0 -63
- libp2p-0.2.6/tests/core/network/test_notify.py +0 -126
- {libp2p-0.2.6 → libp2p-0.2.7}/LICENSE-APACHE +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/LICENSE-MIT +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/MANIFEST.in +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/README.md +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/chat/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/chat/chat.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/echo/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/echo/echo.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify/identify.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify_push/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify_push/identify_push_listener_dialer.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/ping/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/examples/ping/ping.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/abc.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/authenticated_encryption.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/ecc.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/ed25519.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/key_exchange.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/pb/crypto_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/pb/crypto_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/rsa.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/secp256k1.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/serialization.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/custom_types.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/autonat.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2_grpc.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2_grpc.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/generate_proto.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/basic_host.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/defaults.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/ping.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/routed_host.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/identify.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/pb/identify_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/pb/identify_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify_push/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify_push/identify_push.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/abc.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/msgio.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/trio.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/utils.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/raw_connection.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/stream/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/stream/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/id.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/peerdata.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/peerinfo.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/multiselect.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/multiselect_client.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/multiselect_communicator.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/floodsub.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/mcache.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pb/rpc_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pb/rpc_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pubsub_notifee.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/subscription.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/validators.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/py.typed +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/base_session.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/base_transport.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/pb/plaintext_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/pb/plaintext_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/transport.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/messages.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/patterns.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/pb/noise_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/pb/noise_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/transport.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/pb/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/pb/spipe_pb2.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/pb/spipe_pb2.pyi +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/transport.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secure_session.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/security_multistream.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/constants.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/datastructures.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/mplex.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/mplex_stream.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/_utils.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/abc.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/base.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/stats.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/trio_service.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/typing.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/base_timed_cache.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/first_seen_cache.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/last_seen_cache.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/exceptions.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/tcp/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/upgrader.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/dependency_links.txt +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/entry_points.txt +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/not-zip-safe +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/requires.txt +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/top_level.txt +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/scripts/release/test_package.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/setup.cfg +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/conftest.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/crypto/test_ed25519.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/crypto/test_rsa.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/crypto/test_secp256k1.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_autonat.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_basic_host.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_live_peers.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_ping.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_routed_host.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/identity/identify/test_identify.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/identity/identify_push/test_identify_push.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/conftest.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/test_swarm.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/test_swarm_conn.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_addrbook.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_interop.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerdata.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerid.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerinfo.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peermetadata.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerstore.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/protocol_muxer/test_protocol_muxer.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_dummyaccount_demo.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_floodsub.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_gossipsub.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_gossipsub_backward_compatibility.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_mcache.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_subscription.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/noise/test_msg_read_writer.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/noise/test_noise.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/test_secio.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/stream_muxer/test_mplex_stream.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/test_import_and_version.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/test_libp2p/test_libp2p.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/async_service/test_trio_based_service.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/async_service/test_trio_external_api.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/async_service/test_trio_manager_stats.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/transport/test_tcp.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/go_libp2p/test_go_basic.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/js_libp2p/test_js_basic.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/rust_libp2p/test_rust_basic.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/zig_libp2p/test_zig_basic.py +0 -0
- {libp2p-0.2.6/tests/utils/interop → libp2p-0.2.7/tests/utils}/__init__.py +0 -0
- {libp2p-0.2.6/tests/utils/pubsub → libp2p-0.2.7/tests/utils/interop}/__init__.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/constants.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/daemon.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/envs.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/process.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/utils.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/pubsub/dummy_account_node.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/pubsub/floodsub_integration_test_settings.py +0 -0
- {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/pubsub/utils.py +0 -0
|
@@ -85,6 +85,52 @@ async def main() -> None:
|
|
|
85
85
|
logger.info("Host 2 connected to Host 1")
|
|
86
86
|
print("Host 2 successfully connected to Host 1")
|
|
87
87
|
|
|
88
|
+
# Run the identify protocol from host_2 to host_1
|
|
89
|
+
# (so Host 1 learns Host 2's address)
|
|
90
|
+
from libp2p.identity.identify.identify import ID as IDENTIFY_PROTOCOL_ID
|
|
91
|
+
|
|
92
|
+
stream = await host_2.new_stream(host_1.get_id(), (IDENTIFY_PROTOCOL_ID,))
|
|
93
|
+
response = await stream.read()
|
|
94
|
+
await stream.close()
|
|
95
|
+
|
|
96
|
+
# Run the identify protocol from host_1 to host_2
|
|
97
|
+
# (so Host 2 learns Host 1's address)
|
|
98
|
+
stream = await host_1.new_stream(host_2.get_id(), (IDENTIFY_PROTOCOL_ID,))
|
|
99
|
+
response = await stream.read()
|
|
100
|
+
await stream.close()
|
|
101
|
+
|
|
102
|
+
# --- NEW CODE: Update Host 1's peerstore with Host 2's addresses ---
|
|
103
|
+
from libp2p.identity.identify.pb.identify_pb2 import (
|
|
104
|
+
Identify,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
identify_msg = Identify()
|
|
108
|
+
identify_msg.ParseFromString(response)
|
|
109
|
+
peerstore_1 = host_1.get_peerstore()
|
|
110
|
+
peer_id_2 = host_2.get_id()
|
|
111
|
+
for addr_bytes in identify_msg.listen_addrs:
|
|
112
|
+
maddr = multiaddr.Multiaddr(addr_bytes)
|
|
113
|
+
# TTL can be any positive int
|
|
114
|
+
peerstore_1.add_addr(
|
|
115
|
+
peer_id_2,
|
|
116
|
+
maddr,
|
|
117
|
+
ttl=3600,
|
|
118
|
+
)
|
|
119
|
+
# --- END NEW CODE ---
|
|
120
|
+
|
|
121
|
+
# Now Host 1's peerstore should have Host 2's address
|
|
122
|
+
peerstore_1 = host_1.get_peerstore()
|
|
123
|
+
peer_id_2 = host_2.get_id()
|
|
124
|
+
addrs_1_for_2 = peerstore_1.addrs(peer_id_2)
|
|
125
|
+
logger.info(
|
|
126
|
+
f"[DEBUG] Host 1 peerstore addresses for Host 2 before push: "
|
|
127
|
+
f"{addrs_1_for_2}"
|
|
128
|
+
)
|
|
129
|
+
print(
|
|
130
|
+
f"[DEBUG] Host 1 peerstore addresses for Host 2 before push: "
|
|
131
|
+
f"{addrs_1_for_2}"
|
|
132
|
+
)
|
|
133
|
+
|
|
88
134
|
# Push identify information from host_1 to host_2
|
|
89
135
|
logger.info("Host 1 pushing identify information to Host 2")
|
|
90
136
|
print("\nHost 1 pushing identify information to Host 2...")
|
|
@@ -104,6 +150,9 @@ async def main() -> None:
|
|
|
104
150
|
logger.error(f"Error during identify push: {str(e)}")
|
|
105
151
|
print(f"\nError during identify push: {str(e)}")
|
|
106
152
|
|
|
153
|
+
# Add this at the end of your async with block:
|
|
154
|
+
await trio.sleep(0.5) # Give background tasks time to finish
|
|
155
|
+
|
|
107
156
|
|
|
108
157
|
if __name__ == "__main__":
|
|
109
158
|
trio.run(main)
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
from collections.abc import (
|
|
2
|
+
Mapping,
|
|
3
|
+
)
|
|
4
|
+
from importlib.metadata import version as __version
|
|
5
|
+
from typing import (
|
|
6
|
+
Literal,
|
|
7
|
+
Optional,
|
|
8
|
+
Type,
|
|
9
|
+
cast,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from libp2p.abc import (
|
|
13
|
+
IHost,
|
|
14
|
+
IMuxedConn,
|
|
15
|
+
INetworkService,
|
|
16
|
+
IPeerRouting,
|
|
17
|
+
IPeerStore,
|
|
18
|
+
ISecureTransport,
|
|
19
|
+
)
|
|
20
|
+
from libp2p.crypto.keys import (
|
|
21
|
+
KeyPair,
|
|
22
|
+
)
|
|
23
|
+
from libp2p.crypto.rsa import (
|
|
24
|
+
create_new_key_pair,
|
|
25
|
+
)
|
|
26
|
+
from libp2p.crypto.x25519 import create_new_key_pair as create_new_x25519_key_pair
|
|
27
|
+
from libp2p.custom_types import (
|
|
28
|
+
TMuxerOptions,
|
|
29
|
+
TProtocol,
|
|
30
|
+
TSecurityOptions,
|
|
31
|
+
)
|
|
32
|
+
from libp2p.host.basic_host import (
|
|
33
|
+
BasicHost,
|
|
34
|
+
)
|
|
35
|
+
from libp2p.host.routed_host import (
|
|
36
|
+
RoutedHost,
|
|
37
|
+
)
|
|
38
|
+
from libp2p.network.swarm import (
|
|
39
|
+
Swarm,
|
|
40
|
+
)
|
|
41
|
+
from libp2p.peer.id import (
|
|
42
|
+
ID,
|
|
43
|
+
)
|
|
44
|
+
from libp2p.peer.peerstore import (
|
|
45
|
+
PeerStore,
|
|
46
|
+
)
|
|
47
|
+
from libp2p.security.insecure.transport import (
|
|
48
|
+
PLAINTEXT_PROTOCOL_ID,
|
|
49
|
+
InsecureTransport,
|
|
50
|
+
)
|
|
51
|
+
from libp2p.security.noise.transport import PROTOCOL_ID as NOISE_PROTOCOL_ID
|
|
52
|
+
from libp2p.security.noise.transport import Transport as NoiseTransport
|
|
53
|
+
import libp2p.security.secio.transport as secio
|
|
54
|
+
from libp2p.stream_muxer.mplex.mplex import (
|
|
55
|
+
MPLEX_PROTOCOL_ID,
|
|
56
|
+
Mplex,
|
|
57
|
+
)
|
|
58
|
+
from libp2p.stream_muxer.yamux.yamux import (
|
|
59
|
+
Yamux,
|
|
60
|
+
)
|
|
61
|
+
from libp2p.stream_muxer.yamux.yamux import PROTOCOL_ID as YAMUX_PROTOCOL_ID
|
|
62
|
+
from libp2p.transport.tcp.tcp import (
|
|
63
|
+
TCP,
|
|
64
|
+
)
|
|
65
|
+
from libp2p.transport.upgrader import (
|
|
66
|
+
TransportUpgrader,
|
|
67
|
+
)
|
|
68
|
+
from libp2p.utils.logging import (
|
|
69
|
+
setup_logging,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Initialize logging configuration
|
|
73
|
+
setup_logging()
|
|
74
|
+
|
|
75
|
+
# Default multiplexer choice
|
|
76
|
+
DEFAULT_MUXER = "YAMUX"
|
|
77
|
+
|
|
78
|
+
# Multiplexer options
|
|
79
|
+
MUXER_YAMUX = "YAMUX"
|
|
80
|
+
MUXER_MPLEX = "MPLEX"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def set_default_muxer(muxer_name: Literal["YAMUX", "MPLEX"]) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Set the default multiplexer protocol to use.
|
|
86
|
+
|
|
87
|
+
:param muxer_name: Either "YAMUX" or "MPLEX"
|
|
88
|
+
:raise ValueError: If an unsupported muxer name is provided
|
|
89
|
+
"""
|
|
90
|
+
global DEFAULT_MUXER
|
|
91
|
+
muxer_upper = muxer_name.upper()
|
|
92
|
+
if muxer_upper not in [MUXER_YAMUX, MUXER_MPLEX]:
|
|
93
|
+
raise ValueError(f"Unknown muxer: {muxer_name}. Use 'YAMUX' or 'MPLEX'.")
|
|
94
|
+
DEFAULT_MUXER = muxer_upper
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def get_default_muxer() -> str:
|
|
98
|
+
"""
|
|
99
|
+
Returns the currently selected default muxer.
|
|
100
|
+
|
|
101
|
+
:return: Either "YAMUX" or "MPLEX"
|
|
102
|
+
"""
|
|
103
|
+
return DEFAULT_MUXER
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def create_yamux_muxer_option() -> TMuxerOptions:
|
|
107
|
+
"""
|
|
108
|
+
Returns muxer options with Yamux as the primary choice.
|
|
109
|
+
|
|
110
|
+
:return: Muxer options with Yamux first
|
|
111
|
+
"""
|
|
112
|
+
return {
|
|
113
|
+
TProtocol(YAMUX_PROTOCOL_ID): Yamux, # Primary choice
|
|
114
|
+
TProtocol(MPLEX_PROTOCOL_ID): Mplex, # Fallback for compatibility
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def create_mplex_muxer_option() -> TMuxerOptions:
|
|
119
|
+
"""
|
|
120
|
+
Returns muxer options with Mplex as the primary choice.
|
|
121
|
+
|
|
122
|
+
:return: Muxer options with Mplex first
|
|
123
|
+
"""
|
|
124
|
+
return {
|
|
125
|
+
TProtocol(MPLEX_PROTOCOL_ID): Mplex, # Primary choice
|
|
126
|
+
TProtocol(YAMUX_PROTOCOL_ID): Yamux, # Fallback
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def generate_new_rsa_identity() -> KeyPair:
|
|
131
|
+
return create_new_key_pair()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def generate_peer_id_from(key_pair: KeyPair) -> ID:
|
|
135
|
+
public_key = key_pair.public_key
|
|
136
|
+
return ID.from_pubkey(public_key)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def get_default_muxer_options() -> TMuxerOptions:
|
|
140
|
+
"""
|
|
141
|
+
Returns the default muxer options based on the current default muxer setting.
|
|
142
|
+
|
|
143
|
+
:return: Muxer options with the preferred muxer first
|
|
144
|
+
"""
|
|
145
|
+
if DEFAULT_MUXER == "MPLEX":
|
|
146
|
+
return create_mplex_muxer_option()
|
|
147
|
+
else: # YAMUX is default
|
|
148
|
+
return create_yamux_muxer_option()
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def new_swarm(
|
|
152
|
+
key_pair: Optional[KeyPair] = None,
|
|
153
|
+
muxer_opt: Optional[TMuxerOptions] = None,
|
|
154
|
+
sec_opt: Optional[TSecurityOptions] = None,
|
|
155
|
+
peerstore_opt: Optional[IPeerStore] = None,
|
|
156
|
+
muxer_preference: Optional[Literal["YAMUX", "MPLEX"]] = None,
|
|
157
|
+
) -> INetworkService:
|
|
158
|
+
"""
|
|
159
|
+
Create a swarm instance based on the parameters.
|
|
160
|
+
|
|
161
|
+
:param key_pair: optional choice of the ``KeyPair``
|
|
162
|
+
:param muxer_opt: optional choice of stream muxer
|
|
163
|
+
:param sec_opt: optional choice of security upgrade
|
|
164
|
+
:param peerstore_opt: optional peerstore
|
|
165
|
+
:param muxer_preference: optional explicit muxer preference
|
|
166
|
+
:return: return a default swarm instance
|
|
167
|
+
|
|
168
|
+
Note: Yamux (/yamux/1.0.0) is the preferred stream multiplexer
|
|
169
|
+
due to its improved performance and features.
|
|
170
|
+
Mplex (/mplex/6.7.0) is retained for backward compatibility
|
|
171
|
+
but may be deprecated in the future.
|
|
172
|
+
"""
|
|
173
|
+
if key_pair is None:
|
|
174
|
+
key_pair = generate_new_rsa_identity()
|
|
175
|
+
|
|
176
|
+
id_opt = generate_peer_id_from(key_pair)
|
|
177
|
+
|
|
178
|
+
# TODO: Parse `listen_addrs` to determine transport
|
|
179
|
+
transport = TCP()
|
|
180
|
+
|
|
181
|
+
# Generate X25519 keypair for Noise
|
|
182
|
+
noise_key_pair = create_new_x25519_key_pair()
|
|
183
|
+
|
|
184
|
+
# Default security transports (using Noise as primary)
|
|
185
|
+
secure_transports_by_protocol: Mapping[TProtocol, ISecureTransport] = sec_opt or {
|
|
186
|
+
NOISE_PROTOCOL_ID: NoiseTransport(
|
|
187
|
+
key_pair, noise_privkey=noise_key_pair.private_key
|
|
188
|
+
),
|
|
189
|
+
TProtocol(secio.ID): secio.Transport(key_pair),
|
|
190
|
+
TProtocol(PLAINTEXT_PROTOCOL_ID): InsecureTransport(key_pair),
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Use given muxer preference if provided, otherwise use global default
|
|
194
|
+
if muxer_preference is not None:
|
|
195
|
+
temp_pref = muxer_preference.upper()
|
|
196
|
+
if temp_pref not in [MUXER_YAMUX, MUXER_MPLEX]:
|
|
197
|
+
raise ValueError(
|
|
198
|
+
f"Unknown muxer: {muxer_preference}. Use 'YAMUX' or 'MPLEX'."
|
|
199
|
+
)
|
|
200
|
+
active_preference = temp_pref
|
|
201
|
+
else:
|
|
202
|
+
active_preference = DEFAULT_MUXER
|
|
203
|
+
|
|
204
|
+
# Use provided muxer options if given, otherwise create based on preference
|
|
205
|
+
if muxer_opt is not None:
|
|
206
|
+
muxer_transports_by_protocol = muxer_opt
|
|
207
|
+
else:
|
|
208
|
+
if active_preference == MUXER_MPLEX:
|
|
209
|
+
muxer_transports_by_protocol = create_mplex_muxer_option()
|
|
210
|
+
else: # YAMUX is default
|
|
211
|
+
muxer_transports_by_protocol = create_yamux_muxer_option()
|
|
212
|
+
|
|
213
|
+
upgrader = TransportUpgrader(
|
|
214
|
+
secure_transports_by_protocol=secure_transports_by_protocol,
|
|
215
|
+
muxer_transports_by_protocol=muxer_transports_by_protocol,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
peerstore = peerstore_opt or PeerStore()
|
|
219
|
+
# Store our key pair in peerstore
|
|
220
|
+
peerstore.add_key_pair(id_opt, key_pair)
|
|
221
|
+
|
|
222
|
+
return Swarm(id_opt, peerstore, upgrader, transport)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def new_host(
|
|
226
|
+
key_pair: Optional[KeyPair] = None,
|
|
227
|
+
muxer_opt: Optional[TMuxerOptions] = None,
|
|
228
|
+
sec_opt: Optional[TSecurityOptions] = None,
|
|
229
|
+
peerstore_opt: Optional[IPeerStore] = None,
|
|
230
|
+
disc_opt: Optional[IPeerRouting] = None,
|
|
231
|
+
muxer_preference: Optional[Literal["YAMUX", "MPLEX"]] = None,
|
|
232
|
+
) -> IHost:
|
|
233
|
+
"""
|
|
234
|
+
Create a new libp2p host based on the given parameters.
|
|
235
|
+
|
|
236
|
+
:param key_pair: optional choice of the ``KeyPair``
|
|
237
|
+
:param muxer_opt: optional choice of stream muxer
|
|
238
|
+
:param sec_opt: optional choice of security upgrade
|
|
239
|
+
:param peerstore_opt: optional peerstore
|
|
240
|
+
:param disc_opt: optional discovery
|
|
241
|
+
:param muxer_preference: optional explicit muxer preference
|
|
242
|
+
:return: return a host instance
|
|
243
|
+
"""
|
|
244
|
+
swarm = new_swarm(
|
|
245
|
+
key_pair=key_pair,
|
|
246
|
+
muxer_opt=muxer_opt,
|
|
247
|
+
sec_opt=sec_opt,
|
|
248
|
+
peerstore_opt=peerstore_opt,
|
|
249
|
+
muxer_preference=muxer_preference,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
if disc_opt is not None:
|
|
253
|
+
return RoutedHost(swarm, disc_opt)
|
|
254
|
+
return BasicHost(swarm)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
__version__ = __version("libp2p")
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Key types and interfaces."""
|
|
2
|
+
|
|
1
3
|
from abc import (
|
|
2
4
|
ABC,
|
|
3
5
|
abstractmethod,
|
|
@@ -9,17 +11,24 @@ from enum import (
|
|
|
9
11
|
Enum,
|
|
10
12
|
unique,
|
|
11
13
|
)
|
|
14
|
+
from typing import (
|
|
15
|
+
cast,
|
|
16
|
+
)
|
|
12
17
|
|
|
13
|
-
from .pb import
|
|
18
|
+
from libp2p.crypto.pb import (
|
|
19
|
+
crypto_pb2,
|
|
20
|
+
)
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
@unique
|
|
17
24
|
class KeyType(Enum):
|
|
18
|
-
RSA =
|
|
19
|
-
Ed25519 =
|
|
20
|
-
Secp256k1 =
|
|
21
|
-
ECDSA =
|
|
22
|
-
ECC_P256 =
|
|
25
|
+
RSA = crypto_pb2.KeyType.RSA
|
|
26
|
+
Ed25519 = crypto_pb2.KeyType.Ed25519
|
|
27
|
+
Secp256k1 = crypto_pb2.KeyType.Secp256k1
|
|
28
|
+
ECDSA = crypto_pb2.KeyType.ECDSA
|
|
29
|
+
ECC_P256 = crypto_pb2.KeyType.ECC_P256
|
|
30
|
+
# X25519 is added for Noise protocol
|
|
31
|
+
X25519 = cast(crypto_pb2.KeyType.ValueType, 5)
|
|
23
32
|
|
|
24
33
|
|
|
25
34
|
class Key(ABC):
|
|
@@ -52,11 +61,11 @@ class PublicKey(Key):
|
|
|
52
61
|
"""
|
|
53
62
|
...
|
|
54
63
|
|
|
55
|
-
def _serialize_to_protobuf(self) ->
|
|
64
|
+
def _serialize_to_protobuf(self) -> crypto_pb2.PublicKey:
|
|
56
65
|
"""Return the protobuf representation of this ``Key``."""
|
|
57
66
|
key_type = self.get_type().value
|
|
58
67
|
data = self.to_bytes()
|
|
59
|
-
protobuf_key =
|
|
68
|
+
protobuf_key = crypto_pb2.PublicKey(key_type=key_type, data=data)
|
|
60
69
|
return protobuf_key
|
|
61
70
|
|
|
62
71
|
def serialize(self) -> bytes:
|
|
@@ -64,8 +73,8 @@ class PublicKey(Key):
|
|
|
64
73
|
return self._serialize_to_protobuf().SerializeToString()
|
|
65
74
|
|
|
66
75
|
@classmethod
|
|
67
|
-
def deserialize_from_protobuf(cls, protobuf_data: bytes) ->
|
|
68
|
-
return
|
|
76
|
+
def deserialize_from_protobuf(cls, protobuf_data: bytes) -> crypto_pb2.PublicKey:
|
|
77
|
+
return crypto_pb2.PublicKey.FromString(protobuf_data)
|
|
69
78
|
|
|
70
79
|
|
|
71
80
|
class PrivateKey(Key):
|
|
@@ -79,11 +88,11 @@ class PrivateKey(Key):
|
|
|
79
88
|
def get_public_key(self) -> PublicKey:
|
|
80
89
|
...
|
|
81
90
|
|
|
82
|
-
def _serialize_to_protobuf(self) ->
|
|
91
|
+
def _serialize_to_protobuf(self) -> crypto_pb2.PrivateKey:
|
|
83
92
|
"""Return the protobuf representation of this ``Key``."""
|
|
84
93
|
key_type = self.get_type().value
|
|
85
94
|
data = self.to_bytes()
|
|
86
|
-
protobuf_key =
|
|
95
|
+
protobuf_key = crypto_pb2.PrivateKey(key_type=key_type, data=data)
|
|
87
96
|
return protobuf_key
|
|
88
97
|
|
|
89
98
|
def serialize(self) -> bytes:
|
|
@@ -91,8 +100,8 @@ class PrivateKey(Key):
|
|
|
91
100
|
return self._serialize_to_protobuf().SerializeToString()
|
|
92
101
|
|
|
93
102
|
@classmethod
|
|
94
|
-
def deserialize_from_protobuf(cls, protobuf_data: bytes) ->
|
|
95
|
-
return
|
|
103
|
+
def deserialize_from_protobuf(cls, protobuf_data: bytes) -> crypto_pb2.PrivateKey:
|
|
104
|
+
return crypto_pb2.PrivateKey.FromString(protobuf_data)
|
|
96
105
|
|
|
97
106
|
|
|
98
107
|
@dataclass(frozen=True)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from cryptography.hazmat.primitives import (
|
|
2
|
+
serialization,
|
|
3
|
+
)
|
|
4
|
+
from cryptography.hazmat.primitives.asymmetric import (
|
|
5
|
+
x25519,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
from libp2p.crypto.keys import (
|
|
9
|
+
KeyPair,
|
|
10
|
+
KeyType,
|
|
11
|
+
PrivateKey,
|
|
12
|
+
PublicKey,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class X25519PublicKey(PublicKey):
|
|
17
|
+
def __init__(self, impl: x25519.X25519PublicKey) -> None:
|
|
18
|
+
self.impl = impl
|
|
19
|
+
|
|
20
|
+
def to_bytes(self) -> bytes:
|
|
21
|
+
return self.impl.public_bytes(
|
|
22
|
+
encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_bytes(cls, data: bytes) -> "X25519PublicKey":
|
|
27
|
+
return cls(x25519.X25519PublicKey.from_public_bytes(data))
|
|
28
|
+
|
|
29
|
+
def get_type(self) -> KeyType:
|
|
30
|
+
# Not in protobuf, but for Noise use only
|
|
31
|
+
return KeyType.X25519 # Or define KeyType.X25519 if you want to extend
|
|
32
|
+
|
|
33
|
+
def verify(self, data: bytes, signature: bytes) -> bool:
|
|
34
|
+
raise NotImplementedError("X25519 does not support signatures.")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class X25519PrivateKey(PrivateKey):
|
|
38
|
+
def __init__(self, impl: x25519.X25519PrivateKey) -> None:
|
|
39
|
+
self.impl = impl
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def new(cls) -> "X25519PrivateKey":
|
|
43
|
+
return cls(x25519.X25519PrivateKey.generate())
|
|
44
|
+
|
|
45
|
+
def to_bytes(self) -> bytes:
|
|
46
|
+
return self.impl.private_bytes(
|
|
47
|
+
encoding=serialization.Encoding.Raw,
|
|
48
|
+
format=serialization.PrivateFormat.Raw,
|
|
49
|
+
encryption_algorithm=serialization.NoEncryption(),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def from_bytes(cls, data: bytes) -> "X25519PrivateKey":
|
|
54
|
+
return cls(x25519.X25519PrivateKey.from_private_bytes(data))
|
|
55
|
+
|
|
56
|
+
def get_type(self) -> KeyType:
|
|
57
|
+
return KeyType.X25519
|
|
58
|
+
|
|
59
|
+
def sign(self, data: bytes) -> bytes:
|
|
60
|
+
raise NotImplementedError("X25519 does not support signatures.")
|
|
61
|
+
|
|
62
|
+
def get_public_key(self) -> PublicKey:
|
|
63
|
+
return X25519PublicKey(self.impl.public_key())
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def create_new_key_pair() -> KeyPair:
|
|
67
|
+
priv = X25519PrivateKey.new()
|
|
68
|
+
pub = priv.get_public_key()
|
|
69
|
+
return KeyPair(priv, pub)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from collections.abc import (
|
|
2
|
+
Sequence,
|
|
3
|
+
)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseLibp2pError(Exception):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ValidationError(BaseLibp2pError):
|
|
11
|
+
"""Raised when something does not pass a validation check."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ParseError(BaseLibp2pError):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MultiError(BaseLibp2pError):
|
|
19
|
+
r"""
|
|
20
|
+
A combined error that wraps multiple exceptions into a single error object.
|
|
21
|
+
This error is raised when multiple exceptions need to be reported together,
|
|
22
|
+
typically in scenarios where parallel operations or multiple validations fail.
|
|
23
|
+
|
|
24
|
+
Example\:
|
|
25
|
+
---------
|
|
26
|
+
>>> from libp2p.exceptions import MultiError
|
|
27
|
+
>>> errors = [
|
|
28
|
+
... ValueError("Invalid input"),
|
|
29
|
+
... TypeError("Wrong type"),
|
|
30
|
+
... RuntimeError("Operation failed")
|
|
31
|
+
... ]
|
|
32
|
+
>>> multi_error = MultiError(errors)
|
|
33
|
+
>>> print(multi_error)
|
|
34
|
+
Error 1: Invalid input
|
|
35
|
+
Error 2: Wrong type
|
|
36
|
+
Error 3: Operation failed
|
|
37
|
+
|
|
38
|
+
Note\:
|
|
39
|
+
------
|
|
40
|
+
The string representation of this error will number and list all contained
|
|
41
|
+
errors sequentially, making it easier to identify individual issues in
|
|
42
|
+
complex error scenarios.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, errors: Sequence[Exception]) -> None:
|
|
47
|
+
super().__init__(errors)
|
|
48
|
+
self.errors = errors # Storing list of errors
|
|
49
|
+
|
|
50
|
+
def __str__(self) -> str:
|
|
51
|
+
return "\n".join(
|
|
52
|
+
f"Error {i + 1}: {error}" for i, error in enumerate(self.errors)
|
|
53
|
+
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from typing import (
|
|
2
3
|
TYPE_CHECKING,
|
|
3
4
|
)
|
|
@@ -37,30 +38,69 @@ class SwarmConn(INetConn):
|
|
|
37
38
|
self.streams = set()
|
|
38
39
|
self.event_closed = trio.Event()
|
|
39
40
|
self.event_started = trio.Event()
|
|
41
|
+
if hasattr(muxed_conn, "on_close"):
|
|
42
|
+
logging.debug(f"Setting on_close for peer {muxed_conn.peer_id}")
|
|
43
|
+
muxed_conn.on_close = self._on_muxed_conn_closed
|
|
44
|
+
else:
|
|
45
|
+
logging.error(
|
|
46
|
+
f"muxed_conn for peer {muxed_conn.peer_id} has no on_close attribute"
|
|
47
|
+
)
|
|
40
48
|
|
|
41
49
|
@property
|
|
42
50
|
def is_closed(self) -> bool:
|
|
43
51
|
return self.event_closed.is_set()
|
|
44
52
|
|
|
53
|
+
async def _on_muxed_conn_closed(self) -> None:
|
|
54
|
+
"""Handle closure of the underlying muxed connection."""
|
|
55
|
+
peer_id = self.muxed_conn.peer_id
|
|
56
|
+
logging.debug(f"SwarmConn closing for peer {peer_id} due to muxed_conn closure")
|
|
57
|
+
# Only call close if we're not already closing
|
|
58
|
+
if not self.event_closed.is_set():
|
|
59
|
+
await self.close()
|
|
60
|
+
|
|
45
61
|
async def close(self) -> None:
|
|
46
62
|
if self.event_closed.is_set():
|
|
47
63
|
return
|
|
64
|
+
logging.debug(f"Closing SwarmConn for peer {self.muxed_conn.peer_id}")
|
|
48
65
|
self.event_closed.set()
|
|
66
|
+
|
|
67
|
+
# Close the muxed connection
|
|
68
|
+
try:
|
|
69
|
+
await self.muxed_conn.close()
|
|
70
|
+
except Exception as e:
|
|
71
|
+
logging.warning(f"Error while closing muxed connection: {e}")
|
|
72
|
+
|
|
73
|
+
# Perform proper cleanup of resources
|
|
49
74
|
await self._cleanup()
|
|
50
75
|
|
|
51
76
|
async def _cleanup(self) -> None:
|
|
77
|
+
# Remove the connection from swarm
|
|
78
|
+
logging.debug(f"Removing connection for peer {self.muxed_conn.peer_id}")
|
|
52
79
|
self.swarm.remove_conn(self)
|
|
53
80
|
|
|
54
|
-
|
|
81
|
+
# Only close the connection if it's not already closed
|
|
82
|
+
# Be defensive here to avoid exceptions during cleanup
|
|
83
|
+
try:
|
|
84
|
+
if not self.muxed_conn.is_closed:
|
|
85
|
+
await self.muxed_conn.close()
|
|
86
|
+
except Exception as e:
|
|
87
|
+
logging.warning(f"Error closing muxed connection: {e}")
|
|
55
88
|
|
|
56
89
|
# This is just for cleaning up state. The connection has already been closed.
|
|
57
90
|
# We *could* optimize this but it really isn't worth it.
|
|
91
|
+
logging.debug(f"Resetting streams for peer {self.muxed_conn.peer_id}")
|
|
58
92
|
for stream in self.streams.copy():
|
|
59
|
-
|
|
93
|
+
try:
|
|
94
|
+
await stream.reset()
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logging.warning(f"Error resetting stream: {e}")
|
|
97
|
+
|
|
60
98
|
# Force context switch for stream handlers to process the stream reset event we
|
|
61
99
|
# just emit before we cancel the stream handler tasks.
|
|
62
100
|
await trio.sleep(0.1)
|
|
63
101
|
|
|
102
|
+
# Notify all listeners about the disconnection
|
|
103
|
+
logging.debug(f"Notifying disconnection for peer {self.muxed_conn.peer_id}")
|
|
64
104
|
await self._notify_disconnected()
|
|
65
105
|
|
|
66
106
|
async def _handle_new_streams(self) -> None:
|
|
@@ -12,6 +12,7 @@ from libp2p.custom_types import (
|
|
|
12
12
|
from libp2p.stream_muxer.exceptions import (
|
|
13
13
|
MuxedStreamClosed,
|
|
14
14
|
MuxedStreamEOF,
|
|
15
|
+
MuxedStreamError,
|
|
15
16
|
MuxedStreamReset,
|
|
16
17
|
)
|
|
17
18
|
|
|
@@ -68,7 +69,7 @@ class NetStream(INetStream):
|
|
|
68
69
|
"""
|
|
69
70
|
try:
|
|
70
71
|
await self.muxed_stream.write(data)
|
|
71
|
-
except MuxedStreamClosed as error:
|
|
72
|
+
except (MuxedStreamClosed, MuxedStreamError) as error:
|
|
72
73
|
raise StreamClosed() from error
|
|
73
74
|
|
|
74
75
|
async def close(self) -> None:
|
|
@@ -313,7 +313,35 @@ class Swarm(Service, INetworkService):
|
|
|
313
313
|
return False
|
|
314
314
|
|
|
315
315
|
async def close(self) -> None:
|
|
316
|
-
|
|
316
|
+
"""
|
|
317
|
+
Close the swarm instance and cleanup resources.
|
|
318
|
+
"""
|
|
319
|
+
# Check if manager exists before trying to stop it
|
|
320
|
+
if hasattr(self, "_manager") and self._manager is not None:
|
|
321
|
+
await self._manager.stop()
|
|
322
|
+
else:
|
|
323
|
+
# Perform alternative cleanup if the manager isn't initialized
|
|
324
|
+
# Close all connections manually
|
|
325
|
+
if hasattr(self, "connections"):
|
|
326
|
+
for conn_id in list(self.connections.keys()):
|
|
327
|
+
conn = self.connections[conn_id]
|
|
328
|
+
await conn.close()
|
|
329
|
+
|
|
330
|
+
# Clear connection tracking dictionary
|
|
331
|
+
self.connections.clear()
|
|
332
|
+
|
|
333
|
+
# Close all listeners
|
|
334
|
+
if hasattr(self, "listeners"):
|
|
335
|
+
for listener in self.listeners.values():
|
|
336
|
+
await listener.close()
|
|
337
|
+
self.listeners.clear()
|
|
338
|
+
|
|
339
|
+
# Close the transport if it exists and has a close method
|
|
340
|
+
if hasattr(self, "transport") and self.transport is not None:
|
|
341
|
+
# Check if transport has close method before calling it
|
|
342
|
+
if hasattr(self.transport, "close"):
|
|
343
|
+
await self.transport.close()
|
|
344
|
+
|
|
317
345
|
logger.debug("swarm successfully closed")
|
|
318
346
|
|
|
319
347
|
async def close_peer(self, peer_id: ID) -> None:
|
|
@@ -4,6 +4,7 @@ from collections import (
|
|
|
4
4
|
from collections.abc import (
|
|
5
5
|
Sequence,
|
|
6
6
|
)
|
|
7
|
+
import sys
|
|
7
8
|
from typing import (
|
|
8
9
|
Any,
|
|
9
10
|
)
|
|
@@ -32,6 +33,8 @@ from .peerinfo import (
|
|
|
32
33
|
PeerInfo,
|
|
33
34
|
)
|
|
34
35
|
|
|
36
|
+
PERMANENT_ADDR_TTL = sys.maxsize
|
|
37
|
+
|
|
35
38
|
|
|
36
39
|
class PeerStore(IPeerStore):
|
|
37
40
|
peer_data_map: dict[ID, PeerData]
|