Skip to content

Commit c91c0a5

Browse files
authored
Merge branch 'main' into feat/920-add-gossipsub-2.0-support
2 parents a5889cc + 35889ad commit c91c0a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2563
-418
lines changed

docs/examples.nat.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
examples.nat package
2+
====================
3+
4+
Submodules
5+
----------
6+
7+
examples.nat.dialer module
8+
--------------------------
9+
10+
.. automodule:: examples.nat.dialer
11+
:members:
12+
:show-inheritance:
13+
:undoc-members:
14+
15+
examples.nat.listener module
16+
----------------------------
17+
18+
.. automodule:: examples.nat.listener
19+
:members:
20+
:show-inheritance:
21+
:undoc-members:
22+
23+
examples.nat.relay module
24+
-------------------------
25+
26+
.. automodule:: examples.nat.relay
27+
:members:
28+
:show-inheritance:
29+
:undoc-members:
30+
31+
Module contents
32+
---------------
33+
34+
.. automodule:: examples.nat
35+
:members:
36+
:show-inheritance:
37+
:undoc-members:

docs/examples.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Examples
1717
examples.circuit_relay
1818
examples.kademlia
1919
examples.mDNS
20+
examples.nat
2021
examples.rendezvous
2122
examples.random_walk
2223
examples.multiple_connections

docs/release_notes.rst

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,134 @@ Release Notes
33

44
.. towncrier release notes start
55
6+
py-libp2p v0.5.0 (2025-12-21)
7+
-----------------------------
8+
9+
Bugfixes
10+
~~~~~~~~
11+
12+
- Fixed pubsub service crashes when protocol negotiation fails by adding proper exception handling. (`#910 <https://github.com/libp2p/py-libp2p/issues/910>`__)
13+
- Fixed Yamux.accept_stream() hanging indefinitely when connection is closed. (`#930 <https://github.com/libp2p/py-libp2p/issues/930>`__)
14+
- Handle FLAG_FIN & FLAG_RST in TYPE_WINDOW_UPDATE frames (`#931 <https://github.com/libp2p/py-libp2p/issues/931>`__)
15+
- Added peer ID validation in identify_push protocol to prevent forged peer records.
16+
17+
This security enhancement ensures that the peer ID in signed peer records matches
18+
the sender's peer ID, preventing peer ID spoofing attacks. This addresses
19+
CVE-2023-40583 equivalent vulnerability. (`#958 <https://github.com/libp2p/py-libp2p/issues/958>`__)
20+
- Fixed resource scope cleanup in SwarmConn close method to properly release connection resources when connections are closed. (`#1020 <https://github.com/libp2p/py-libp2p/issues/1020>`__)
21+
- Fixed interoperability with rust-libp2p by switching default key generation to Ed25519 and enhancing Yamux to handle data with SYN/ACK frames. (`#1034 <https://github.com/libp2p/py-libp2p/issues/1034>`__)
22+
- Fixed Mplex connection cleanup to properly handle connection closure callbacks, resolving interop test failures with chromium-rust-v0.53. (`#1037 <https://github.com/libp2p/py-libp2p/issues/1037>`__)
23+
- Fixed QUIC interop issue where Go-to-Python ping would fail after identify stream closes. The listener now properly tracks new Connection IDs issued after connection establishment, enabling correct packet routing for subsequent streams. (`#1044 <https://github.com/libp2p/py-libp2p/issues/1044>`__)
24+
- Kademlia DHT API now accepts string keys instead of bytes (``put_value(key: str, ...)``). Fixes UnicodeDecodeError with binary multihash keys. (`#1059 <https://github.com/libp2p/py-libp2p/issues/1059>`__)
25+
- Fixed BasicHost.run() to accept task_status keyword argument for compatibility with modern pytest-trio (>=0.8.0) and trio (>=0.26.0). (`#1071 <https://github.com/libp2p/py-libp2p/issues/1071>`__)
26+
- Fixed QUIC stream direction misclassification that caused server-side errors when handling client-initiated streams. (`#1081 <https://github.com/libp2p/py-libp2p/issues/1081>`__)
27+
28+
29+
Features
30+
~~~~~~~~
31+
32+
- Noise protocol now uses spec-compliant X25519 keys for DH exchange while maintaining Ed25519 keys for libp2p identity signatures. This fixes signature verification failures and ensures compatibility with other libp2p implementations. Updated ``tests/utils/factories.py`` to use separate X25519 keys for Noise static keys and ``libp2p/security/noise/patterns.py`` to properly handle key separation during handshake.
33+
34+
Full Specification Compliance Achieved:
35+
Stream Muxers: Added stream_muxers field to NoiseExtensions (spec requirement)
36+
Legacy Cleanup: Removed non-spec data field from NoiseHandshakePayload
37+
Protobuf Schema: Updated to match official libp2p/specs/noise
38+
WebTransport Support: Certificate hash exchange fully implemented
39+
40+
Beyond Specification - Advanced Features:
41+
Early Data (0-RTT): Full implementation with handlers and callbacks
42+
Advanced Rekeying: Configurable policies and statistics
43+
Static Key Caching: Performance optimizations
44+
Comprehensive Management: Full handler system for early data (`#591 <https://github.com/libp2p/py-libp2p/issues/591>`__)
45+
- Added fallback mechanism in Kademlia DHT to use connected peers and peerstore when routing table has insufficient peers. (`#905 <https://github.com/libp2p/py-libp2p/issues/905>`__)
46+
- Enhanced WebSocket transport with advanced features including SOCKS proxy support,
47+
AutoTLS for browser integration, connection management, and comprehensive configuration
48+
options. The implementation adds production-ready features like connection pooling,
49+
statistics tracking, and advanced TLS configuration for improved reliability and
50+
monitoring capabilities. (`#938 <https://github.com/libp2p/py-libp2p/issues/938>`__)
51+
- Added persistent peer storage system with datastore-agnostic backend support.
52+
53+
The new PersistentPeerStore implementation provides persistent storage for peer data
54+
(addresses, keys, metadata, protocols, latency metrics) across application restarts.
55+
This addresses the limitation of the in-memory peerstore that loses all peer information
56+
when the process restarts.
57+
58+
Key features:
59+
- Datastore-agnostic interface supporting multiple backends (SQLite, LevelDB, RocksDB, Memory)
60+
- Full compatibility with existing IPeerStore interface
61+
- Automatic persistence of all PeerData fields including last_identified, ttl, and latmap
62+
- Factory functions for easy creation with different backends
63+
- Comprehensive test suite and usage examples
64+
65+
The implementation follows the same architectural pattern as go-libp2p's pstoreds package,
66+
providing a robust foundation for long-running libp2p applications that need to maintain
67+
peer information across restarts. (`#946 <https://github.com/libp2p/py-libp2p/issues/946>`__)
68+
- Enhances the `libp2p`` stack with improved peer connection, relay routing, and discovery for resilient networking.
69+
70+
**Voucher and Signature Verification**
71+
- Implements voucher and signature verification in ``resources.py``
72+
- Validates incoming relay vouchers and signatures to ensure proper authorization
73+
- Prevents misuse of relay resources through secure validation
74+
75+
**Relay Selection Logic**
76+
- Implements initial relay selection logic in ``transport.py``
77+
- Uses basic selection strategies (first-available or round-robin) for relay dialing
78+
- Introduces sophisticated relay selection with scoring, latency-based metrics, and retry strategies
79+
80+
**DHT-based Peer Discovery**
81+
- Implements DHT-based peer discovery using the libp2p DHT
82+
- Enables dynamic location and connection to peers across the network
83+
84+
**Relay Reservation and Maintenance**
85+
- Implements reservation storage and refresh mechanism
86+
- Tracks active relay reservations and refreshes them before expiry
87+
- Supports long-lived relayed connections
88+
89+
**Relay Multiaddr Handling**
90+
- Adds ``/p2p-circuit/...`` addresses to peerstore for reconnects and discovery
91+
- Implements proper parsing and handling of relayed multiaddrs
92+
- Ensures correct validation and usage of ``/p2p-circuit/p2p/...`` paths during dialing
93+
94+
**CircuitV2Listener Implementation**
95+
- Implements ``run()`` method in ``CircuitV2Listener``
96+
- Finalizes listener logic to support incoming relayed connections
97+
98+
**Testing and Quality**
99+
- Adds dedicated tests for voucher and signature verification
100+
- Includes tests for initial and advanced relay selection logic
101+
- Covers DHT-based peer discovery functionality
102+
- Tests reservation storage and refresh mechanisms
103+
- Validates relay multiaddr handling and parsing
104+
- Tests ``CircuitV2Listener`` functionality
105+
- Maintains 100% test coverage across all new features
106+
- Resolves all linting issues and adheres to code quality standards
107+
- Ensures no regressions in existing functionality (`#996 <https://github.com/libp2p/py-libp2p/issues/996>`__)
108+
- Introduced ``get_transport_addrs()`` method to ``BasicHost`` for retrieving raw transport addresses without the peer ID suffix.
109+
Refactored ``get_addrs()`` to utilize this new method, maintaining backward compatibility. (`#1073 <https://github.com/libp2p/py-libp2p/issues/1073>`__)
110+
- Adds custom validator support and quorum-based value retrieval to the Kademlia DHT. (`#1095 <https://github.com/libp2p/py-libp2p/issues/1095>`__)
111+
112+
113+
Internal Changes - for py-libp2p Contributors
114+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115+
116+
- Enhanced QUIC Connection ID management with quinn-inspired improvements:
117+
- Added sequence number tracking for proper CID retirement ordering
118+
- Separated initial vs. established CID lookups for better packet routing
119+
- Improved fallback routing from O(n) to O(1) using reverse address mapping
120+
- Refactored Connection ID management into a dedicated ConnectionIDRegistry class
121+
122+
These changes improve robustness, performance, and alignment with proven QUIC implementations. (`#1044 <https://github.com/libp2p/py-libp2p/issues/1044>`__)
123+
- Refactored QUIC Connection ID management into a dedicated ConnectionIDRegistry class, improving code organization and maintainability of the QUIC listener. (`#1046 <https://github.com/libp2p/py-libp2p/issues/1046>`__)
124+
- Upgraded py-libp2p transport ping test to the latest standard. (`#1086 <https://github.com/libp2p/py-libp2p/issues/1086>`__)
125+
- Updated py-multihash dependency from git repository to PyPI version 3.0.0. (`#1102 <https://github.com/libp2p/py-libp2p/issues/1102>`__)
126+
127+
128+
Miscellaneous Changes
129+
~~~~~~~~~~~~~~~~~~~~~
130+
131+
- `#926 <https://github.com/libp2p/py-libp2p/issues/926>`__, `#1039 <https://github.com/libp2p/py-libp2p/issues/1039>`__
132+
133+
6134
py-libp2p v0.4.0 (2025-11-05)
7135
-----------------------------
8136

examples/kademlia/kademlia.py

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
A basic example of using the Kademlia DHT implementation, with all setup logic inlined.
55
This example demonstrates both value storage/retrieval and content server
66
advertisement/discovery.
7+
It also shows how to use custom validators for namespaced keys.
78
"""
89

910
import argparse
@@ -31,6 +32,7 @@
3132
DHTMode,
3233
KadDHT,
3334
)
35+
from libp2p.records.validator import Validator
3436
from libp2p.tools.async_service import (
3537
background_trio_service,
3638
)
@@ -39,6 +41,46 @@
3941
)
4042
from libp2p.utils.paths import get_script_dir, join_paths
4143

44+
45+
# Custom validator for the "example" namespace
46+
class ExampleValidator(Validator):
47+
"""
48+
A simple validator for the 'example' namespace.
49+
50+
This validator accepts any value and always selects the first value
51+
when comparing multiple values.
52+
"""
53+
54+
def validate(self, key: str, value: bytes) -> None:
55+
"""
56+
Validate a key-value pair.
57+
58+
In a real application, you might check:
59+
- Value format/schema
60+
- Signatures
61+
- Size limits
62+
- etc.
63+
"""
64+
# For this example, we accept any value
65+
# You can add custom validation logic here
66+
if not value:
67+
raise ValueError("Value cannot be empty")
68+
69+
def select(self, key: str, values: list[bytes]) -> int:
70+
"""
71+
Select the best value from a list of values.
72+
73+
Returns the index of the selected value.
74+
In this example, we simply return the first value (index 0).
75+
76+
In a real application, you might:
77+
- Compare timestamps
78+
- Check version numbers
79+
- Verify signatures and pick the most recent valid one
80+
"""
81+
return 0
82+
83+
4284
# Configure logging
4385
logging.basicConfig(
4486
level=logging.INFO,
@@ -175,6 +217,12 @@ async def run_node(
175217

176218
await connect_to_bootstrap_nodes(host, bootstrap_nodes)
177219
dht = KadDHT(host, dht_mode)
220+
221+
# Register a custom validator for the "example" namespace
222+
# This allows us to store values with keys like "/example/my-key"
223+
dht.register_validator("example", ExampleValidator())
224+
logger.info("Registered custom 'example' namespace validator")
225+
178226
# take all peer ids from the host and add them to the dht
179227
for peer_id in host.get_peerstore().peer_ids():
180228
await dht.routing_table.add_peer(peer_id)
@@ -188,12 +236,15 @@ async def run_node(
188236
async with background_trio_service(dht):
189237
logger.info(f"DHT service started in {dht_mode.value} mode")
190238

191-
# Example 1: Simple Key-Value Storage
192-
# Just use a string key directly - DHT API accepts strings!
193-
key = "my-example-key"
239+
# Example 1: Simple Key-Value Storage with namespaced key
240+
# Keys MUST be namespaced (e.g., /namespace/key) for validation
241+
# The namespace must have a registered validator
242+
key = "/example/my-example-key"
194243
value = b"Hello from py-libp2p!"
195244

196245
# Example 2: Content Provider Advertisement
246+
# Provider keys use a different storage mechanism (provider store)
247+
# that doesn't go through the value validation path
197248
content_id = "my-content-identifier"
198249

199250
if dht_mode == DHTMode.SERVER:

examples/nat/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
NAT Traversal Examples for py-libp2p
3+
4+
This package contains examples demonstrating NAT traversal using:
5+
- Circuit Relay v2: Relay connections through publicly reachable nodes
6+
- DCUtR: Direct Connection Upgrade through Relay (hole punching)
7+
- AutoNAT: Automatic NAT detection and reachability assessment
8+
9+
Examples:
10+
- relay.py: Publicly reachable relay node
11+
- listener.py: NAT'd node that advertises via relay
12+
- dialer.py: NAT'd node that connects via relay and attempts hole punching
13+
"""

0 commit comments

Comments
 (0)