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.
Files changed (242) hide show
  1. {libp2p-0.2.6/libp2p.egg-info → libp2p-0.2.7}/PKG-INFO +1 -1
  2. {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify_push/identify_push_demo.py +49 -0
  3. libp2p-0.2.7/libp2p/__init__.py +257 -0
  4. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/keys.py +23 -14
  5. libp2p-0.2.7/libp2p/crypto/x25519.py +69 -0
  6. libp2p-0.2.7/libp2p/exceptions.py +53 -0
  7. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/swarm_connection.py +42 -2
  8. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/stream/net_stream.py +2 -1
  9. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/swarm.py +29 -1
  10. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/peerstore.py +3 -0
  11. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/gossipsub.py +58 -0
  12. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pubsub.py +41 -36
  13. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/io.py +9 -0
  14. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/muxer_multistream.py +21 -2
  15. libp2p-0.2.7/libp2p/stream_muxer/yamux/__init__.py +5 -0
  16. libp2p-0.2.7/libp2p/stream_muxer/yamux/yamux.py +676 -0
  17. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/constants.py +9 -0
  18. libp2p-0.2.7/libp2p/tools/utils.py +154 -0
  19. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/tcp/tcp.py +8 -2
  20. libp2p-0.2.7/libp2p/utils/__init__.py +23 -0
  21. libp2p-0.2.7/libp2p/utils/logging.py +217 -0
  22. libp2p-0.2.6/libp2p/utils.py → libp2p-0.2.7/libp2p/utils/varint.py +2 -23
  23. libp2p-0.2.7/libp2p/utils/version.py +22 -0
  24. {libp2p-0.2.6 → libp2p-0.2.7/libp2p.egg-info}/PKG-INFO +1 -1
  25. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/SOURCES.txt +14 -1
  26. {libp2p-0.2.6 → libp2p-0.2.7}/pyproject.toml +1 -1
  27. {libp2p-0.2.6 → libp2p-0.2.7}/setup.py +1 -1
  28. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/examples/test_examples.py +2 -2
  29. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_connected_peers.py +2 -0
  30. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/test_net_stream.py +2 -2
  31. libp2p-0.2.7/tests/core/network/test_notify.py +208 -0
  32. libp2p-0.2.7/tests/core/pubsub/test_gossipsub_direct_peers.py +170 -0
  33. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_pubsub.py +8 -0
  34. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/test_security_multistream.py +23 -2
  35. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/stream_muxer/conftest.py +20 -0
  36. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/stream_muxer/test_mplex_conn.py +3 -3
  37. libp2p-0.2.7/tests/core/stream_muxer/test_multiplexer_selection.py +256 -0
  38. libp2p-0.2.7/tests/core/stream_muxer/test_yamux.py +448 -0
  39. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/timed_cache/test_timed_cache.py +1 -1
  40. libp2p-0.2.7/tests/crypto/test_x25519.py +102 -0
  41. libp2p-0.2.7/tests/exceptions/test_exceptions.py +13 -0
  42. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/factories.py +62 -2
  43. libp2p-0.2.7/tests/utils/pubsub/__init__.py +0 -0
  44. libp2p-0.2.7/tests/utils/test_logging.py +257 -0
  45. libp2p-0.2.6/libp2p/__init__.py +0 -131
  46. libp2p-0.2.6/libp2p/exceptions.py +0 -16
  47. libp2p-0.2.6/libp2p/tools/utils.py +0 -63
  48. libp2p-0.2.6/tests/core/network/test_notify.py +0 -126
  49. {libp2p-0.2.6 → libp2p-0.2.7}/LICENSE-APACHE +0 -0
  50. {libp2p-0.2.6 → libp2p-0.2.7}/LICENSE-MIT +0 -0
  51. {libp2p-0.2.6 → libp2p-0.2.7}/MANIFEST.in +0 -0
  52. {libp2p-0.2.6 → libp2p-0.2.7}/README.md +0 -0
  53. {libp2p-0.2.6 → libp2p-0.2.7}/examples/__init__.py +0 -0
  54. {libp2p-0.2.6 → libp2p-0.2.7}/examples/chat/__init__.py +0 -0
  55. {libp2p-0.2.6 → libp2p-0.2.7}/examples/chat/chat.py +0 -0
  56. {libp2p-0.2.6 → libp2p-0.2.7}/examples/echo/__init__.py +0 -0
  57. {libp2p-0.2.6 → libp2p-0.2.7}/examples/echo/echo.py +0 -0
  58. {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify/__init__.py +0 -0
  59. {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify/identify.py +0 -0
  60. {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify_push/__init__.py +0 -0
  61. {libp2p-0.2.6 → libp2p-0.2.7}/examples/identify_push/identify_push_listener_dialer.py +0 -0
  62. {libp2p-0.2.6 → libp2p-0.2.7}/examples/ping/__init__.py +0 -0
  63. {libp2p-0.2.6 → libp2p-0.2.7}/examples/ping/ping.py +0 -0
  64. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/abc.py +0 -0
  65. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/__init__.py +0 -0
  66. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/authenticated_encryption.py +0 -0
  67. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/ecc.py +0 -0
  68. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/ed25519.py +0 -0
  69. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/exceptions.py +0 -0
  70. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/key_exchange.py +0 -0
  71. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/pb/__init__.py +0 -0
  72. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/pb/crypto_pb2.py +0 -0
  73. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/pb/crypto_pb2.pyi +0 -0
  74. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/rsa.py +0 -0
  75. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/secp256k1.py +0 -0
  76. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/crypto/serialization.py +0 -0
  77. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/custom_types.py +0 -0
  78. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/__init__.py +0 -0
  79. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/__init__.py +0 -0
  80. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/autonat.py +0 -0
  81. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/__init__.py +0 -0
  82. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2.py +0 -0
  83. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2.pyi +0 -0
  84. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2_grpc.py +0 -0
  85. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/autonat_pb2_grpc.pyi +0 -0
  86. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/autonat/pb/generate_proto.py +0 -0
  87. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/basic_host.py +0 -0
  88. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/defaults.py +0 -0
  89. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/exceptions.py +0 -0
  90. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/ping.py +0 -0
  91. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/host/routed_host.py +0 -0
  92. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/__init__.py +0 -0
  93. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/__init__.py +0 -0
  94. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/identify.py +0 -0
  95. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/pb/__init__.py +0 -0
  96. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/pb/identify_pb2.py +0 -0
  97. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify/pb/identify_pb2.pyi +0 -0
  98. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify_push/__init__.py +0 -0
  99. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/identity/identify_push/identify_push.py +0 -0
  100. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/__init__.py +0 -0
  101. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/abc.py +0 -0
  102. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/exceptions.py +0 -0
  103. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/msgio.py +0 -0
  104. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/trio.py +0 -0
  105. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/io/utils.py +0 -0
  106. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/__init__.py +0 -0
  107. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/__init__.py +0 -0
  108. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/exceptions.py +0 -0
  109. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/connection/raw_connection.py +0 -0
  110. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/exceptions.py +0 -0
  111. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/stream/__init__.py +0 -0
  112. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/network/stream/exceptions.py +0 -0
  113. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/__init__.py +0 -0
  114. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/id.py +0 -0
  115. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/peerdata.py +0 -0
  116. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/peer/peerinfo.py +0 -0
  117. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/__init__.py +0 -0
  118. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/exceptions.py +0 -0
  119. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/multiselect.py +0 -0
  120. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/multiselect_client.py +0 -0
  121. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/protocol_muxer/multiselect_communicator.py +0 -0
  122. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/__init__.py +0 -0
  123. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/exceptions.py +0 -0
  124. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/floodsub.py +0 -0
  125. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/mcache.py +0 -0
  126. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pb/__init__.py +0 -0
  127. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pb/rpc_pb2.py +0 -0
  128. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pb/rpc_pb2.pyi +0 -0
  129. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/pubsub_notifee.py +0 -0
  130. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/subscription.py +0 -0
  131. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/pubsub/validators.py +0 -0
  132. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/py.typed +0 -0
  133. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/__init__.py +0 -0
  134. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/base_session.py +0 -0
  135. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/base_transport.py +0 -0
  136. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/exceptions.py +0 -0
  137. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/__init__.py +0 -0
  138. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/pb/__init__.py +0 -0
  139. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/pb/plaintext_pb2.py +0 -0
  140. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/pb/plaintext_pb2.pyi +0 -0
  141. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/insecure/transport.py +0 -0
  142. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/__init__.py +0 -0
  143. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/exceptions.py +0 -0
  144. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/messages.py +0 -0
  145. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/patterns.py +0 -0
  146. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/pb/__init__.py +0 -0
  147. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/pb/noise_pb2.py +0 -0
  148. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/pb/noise_pb2.pyi +0 -0
  149. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/noise/transport.py +0 -0
  150. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/__init__.py +0 -0
  151. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/exceptions.py +0 -0
  152. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/pb/__init__.py +0 -0
  153. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/pb/spipe_pb2.py +0 -0
  154. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/pb/spipe_pb2.pyi +0 -0
  155. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secio/transport.py +0 -0
  156. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/secure_session.py +0 -0
  157. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/security/security_multistream.py +0 -0
  158. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/__init__.py +0 -0
  159. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/exceptions.py +0 -0
  160. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/__init__.py +0 -0
  161. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/constants.py +0 -0
  162. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/datastructures.py +0 -0
  163. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/exceptions.py +0 -0
  164. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/mplex.py +0 -0
  165. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/stream_muxer/mplex/mplex_stream.py +0 -0
  166. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/__init__.py +0 -0
  167. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/__init__.py +0 -0
  168. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/_utils.py +0 -0
  169. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/abc.py +0 -0
  170. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/base.py +0 -0
  171. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/exceptions.py +0 -0
  172. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/stats.py +0 -0
  173. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/trio_service.py +0 -0
  174. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/async_service/typing.py +0 -0
  175. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/__init__.py +0 -0
  176. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/base_timed_cache.py +0 -0
  177. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/first_seen_cache.py +0 -0
  178. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/tools/timed_cache/last_seen_cache.py +0 -0
  179. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/__init__.py +0 -0
  180. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/exceptions.py +0 -0
  181. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/tcp/__init__.py +0 -0
  182. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p/transport/upgrader.py +0 -0
  183. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/dependency_links.txt +0 -0
  184. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/entry_points.txt +0 -0
  185. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/not-zip-safe +0 -0
  186. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/requires.txt +0 -0
  187. {libp2p-0.2.6 → libp2p-0.2.7}/libp2p.egg-info/top_level.txt +0 -0
  188. {libp2p-0.2.6 → libp2p-0.2.7}/scripts/release/test_package.py +0 -0
  189. {libp2p-0.2.6 → libp2p-0.2.7}/setup.cfg +0 -0
  190. {libp2p-0.2.6 → libp2p-0.2.7}/tests/__init__.py +0 -0
  191. {libp2p-0.2.6 → libp2p-0.2.7}/tests/conftest.py +0 -0
  192. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/crypto/test_ed25519.py +0 -0
  193. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/crypto/test_rsa.py +0 -0
  194. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/crypto/test_secp256k1.py +0 -0
  195. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_autonat.py +0 -0
  196. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_basic_host.py +0 -0
  197. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_live_peers.py +0 -0
  198. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_ping.py +0 -0
  199. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/host/test_routed_host.py +0 -0
  200. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/identity/identify/test_identify.py +0 -0
  201. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/identity/identify_push/test_identify_push.py +0 -0
  202. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/conftest.py +0 -0
  203. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/test_swarm.py +0 -0
  204. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/network/test_swarm_conn.py +0 -0
  205. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_addrbook.py +0 -0
  206. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_interop.py +0 -0
  207. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerdata.py +0 -0
  208. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerid.py +0 -0
  209. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerinfo.py +0 -0
  210. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peermetadata.py +0 -0
  211. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/peer/test_peerstore.py +0 -0
  212. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/protocol_muxer/test_protocol_muxer.py +0 -0
  213. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_dummyaccount_demo.py +0 -0
  214. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_floodsub.py +0 -0
  215. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_gossipsub.py +0 -0
  216. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_gossipsub_backward_compatibility.py +0 -0
  217. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_mcache.py +0 -0
  218. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/pubsub/test_subscription.py +0 -0
  219. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/noise/test_msg_read_writer.py +0 -0
  220. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/noise/test_noise.py +0 -0
  221. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/security/test_secio.py +0 -0
  222. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/stream_muxer/test_mplex_stream.py +0 -0
  223. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/test_import_and_version.py +0 -0
  224. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/test_libp2p/test_libp2p.py +0 -0
  225. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/async_service/test_trio_based_service.py +0 -0
  226. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/async_service/test_trio_external_api.py +0 -0
  227. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/tools/async_service/test_trio_manager_stats.py +0 -0
  228. {libp2p-0.2.6 → libp2p-0.2.7}/tests/core/transport/test_tcp.py +0 -0
  229. {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/go_libp2p/test_go_basic.py +0 -0
  230. {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/js_libp2p/test_js_basic.py +0 -0
  231. {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/rust_libp2p/test_rust_basic.py +0 -0
  232. {libp2p-0.2.6 → libp2p-0.2.7}/tests/interop/zig_libp2p/test_zig_basic.py +0 -0
  233. {libp2p-0.2.6/tests/utils/interop → libp2p-0.2.7/tests/utils}/__init__.py +0 -0
  234. {libp2p-0.2.6/tests/utils/pubsub → libp2p-0.2.7/tests/utils/interop}/__init__.py +0 -0
  235. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/constants.py +0 -0
  236. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/daemon.py +0 -0
  237. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/envs.py +0 -0
  238. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/process.py +0 -0
  239. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/interop/utils.py +0 -0
  240. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/pubsub/dummy_account_node.py +0 -0
  241. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/pubsub/floodsub_integration_test_settings.py +0 -0
  242. {libp2p-0.2.6 → libp2p-0.2.7}/tests/utils/pubsub/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libp2p
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: libp2p: The Python implementation of the libp2p networking stack
5
5
  Home-page: https://github.com/libp2p/py-libp2p
6
6
  Author: The Ethereum Foundation
@@ -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 crypto_pb2 as protobuf
18
+ from libp2p.crypto.pb import (
19
+ crypto_pb2,
20
+ )
14
21
 
15
22
 
16
23
  @unique
17
24
  class KeyType(Enum):
18
- RSA = protobuf.KeyType.RSA
19
- Ed25519 = protobuf.KeyType.Ed25519
20
- Secp256k1 = protobuf.KeyType.Secp256k1
21
- ECDSA = protobuf.KeyType.ECDSA
22
- ECC_P256 = protobuf.KeyType.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) -> protobuf.PublicKey:
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 = protobuf.PublicKey(key_type=key_type, data=data)
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) -> protobuf.PublicKey:
68
- return protobuf.PublicKey.FromString(protobuf_data)
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) -> protobuf.PrivateKey:
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 = protobuf.PrivateKey(key_type=key_type, data=data)
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) -> protobuf.PrivateKey:
95
- return protobuf.PrivateKey.FromString(protobuf_data)
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
- await self.muxed_conn.close()
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
- await stream.reset()
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
- await self.manager.stop()
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]