Bootstrap: Spec Compliance and bug fixes - #1418
Conversation
- DNS addresses: decapsulate /p2p/ from resolved addresses (with ValueError handling) - Connection timeout: replace trio.move_on_after with trio.fail_after (TooSlowError now handled) - allow_ipv6: enforce IPv6 filtering in _is_supported_addr - Use ID.from_string instead of ID.from_base58 for DNS path peer ID parsing - Fix connection_timeout type: int -> float, constant 10 -> 10.0 - Remove redundant Exception from except clause (use TypeError) - Add type annotations on dns instance variables - Add newsfragment for changelog
- Fix _is_supported_addr to be @staticmethod with allow_ipv6 parameter - Add configurable connection_timeout parameter (float type) - Fix stop() to clear all state for clean restart - Make exception handling more specific (ValueError, TypeError, InvalidAddrError) - Add periodic reconnection loop (go-libp2p spec) - Add bootstrap peer removal after MAX_CONSECUTIVE_FAILURES (go-libp2p spec) - Fix _remove_bootstrap_peer to use exact /p2p/ match (not substring) - Import InvalidAddrError in bootstrap.py - Update newsfragment
|
@seetadev Ready for review. |
|
Excellent work, @sumanjeet0012! Thank you for taking the initiative to bring the bootstrap discovery implementation much closer to the libp2p specification while addressing several important correctness and reliability issues. This PR goes well beyond bug fixing. The addition of periodic reconnection, configurable connection timeouts, robust peer failure tracking, precise peer removal logic, improved exception handling, and proper cleanup during shutdown all make the bootstrap subsystem significantly more resilient for long-running deployments. I particularly appreciate the focus on aligning behavior with the go-libp2p reference implementation. Cross-language interoperability is one of the core strengths of the libp2p ecosystem, and improvements like these help ensure Python implementations behave consistently with the rest of the network. The refactoring also improves code quality through clearer type annotations, removal of broad exception handling, better state management, and more explicit APIs. These changes should make future maintenance and feature development much easier. As a follow-up, I would love to see us expand interoperability and resilience testing with long-running bootstrap scenarios, intermittent network failures, IPv4/IPv6 mixed environments, DNS-based bootstrap peers, and continuous cross-implementation testing across Go, Rust, JS, and Python. Integrating observability around bootstrap success rates, reconnect latency, peer churn, and connection health would also provide valuable operational insights for node operators. Overall, this is a thoughtful and impactful improvement to one of the most fundamental parts of peer discovery. Thanks again for the excellent contribution and for continuing to strengthen py-libp2p's interoperability and production readiness. CCing @johannamoran and @mishmosh on this PR. |
What was wrong?
Issue #1417
Multiple bugs in
libp2p/discovery/bootstrap/bootstrap.pyand missing spec compliance:InvalidAddrErrorcaught but never imported (NameError at runtime)_remove_bootstrap_peerused substring check instead of exact/p2p/match_periodic_reconnectcould crash system task ontrio.sleepcancel_is_supported_addrwas instance method with unusedselfconnection_timeouthardcoded, not configurablestop()didn't clear_failure_countsor restorebootstrap_addrsexcept Exceptionfor Multiaddr parse errors instead of specific typesHow was it fixed?
Refactored
BootstrapDiscoveryclass with targeted fixes:InvalidAddrErrorfromlibp2p.peer.peerinfo_remove_bootstrap_peerto useendswith(f"/p2p/{peer_id_str}")for exact matchtrio.sleepin_periodic_reconnectwithtry/except trio.Cancelled_is_supported_addrto@staticmethodwith explicitallow_ipv6parameterconnection_timeoutparameter to__init__(default10.0, typefloat)stop()clear all state and restorebootstrap_addrsfromoriginal_addrs(ValueError, TypeError)for Multiaddr parse errors_periodic_reconnect()loop viatrio.lowlevel.spawn_system_taskwith configurablereconnect_interval_record_failure()and_remove_bootstrap_peer()to track consecutive failures and remove peers afterMAX_CONSECUTIVE_FAILURES(3)To-Do