1818from cryptography import x509
1919from cryptography .x509 .oid import ExtensionOID
2020import multiaddr
21+ from multiaddr .exceptions import ProtocolLookupError
2122import trio
2223
2324import libp2p
9394 background_trio_service ,
9495)
9596from libp2p .transport .quic .connection import QUICConnection
96- from libp2p .utils .multiaddr_utils import (
97- join_multiaddrs ,
98- )
9997import libp2p .utils .paths
10098from libp2p .utils .varint import (
10199 read_length_prefixed_protobuf ,
@@ -193,6 +191,7 @@ def __init__(
193191 bootstrap_allow_ipv6 : bool = False ,
194192 bootstrap_dns_timeout : float = 10.0 ,
195193 bootstrap_dns_max_retries : int = 3 ,
194+ announce_addrs : Sequence [multiaddr .Multiaddr ] | None = None ,
196195 ) -> None :
197196 """
198197 Initialize a BasicHost instance.
@@ -208,6 +207,9 @@ def __init__(
208207 :param bootstrap_allow_ipv6: If True, bootstrap uses IPv6+TCP when available.
209208 :param bootstrap_dns_timeout: DNS resolution timeout in seconds per attempt.
210209 :param bootstrap_dns_max_retries: Max DNS resolution retries (with backoff).
210+ :param announce_addrs: Optional addresses to advertise instead of
211+ listen addresses. ``None`` (default) uses listen addresses;
212+ an empty list advertises no addresses.
211213 """
212214 self ._network = network
213215 self ._network .set_stream_handler (self ._swarm_stream_handler )
@@ -253,6 +255,11 @@ def __init__(
253255 )
254256 self .psk = psk
255257
258+ # Address announcement configuration
259+ self ._announce_addrs = (
260+ list (announce_addrs ) if announce_addrs is not None else None
261+ )
262+
256263 # Cache a signed-record if the local-node in the PeerStore
257264 envelope = create_signed_peer_record (
258265 self .get_id (),
@@ -349,13 +356,34 @@ def get_transport_addrs(self) -> list[multiaddr.Multiaddr]:
349356
350357 def get_addrs (self ) -> list [multiaddr .Multiaddr ]:
351358 """
352- Return all the multiaddr addresses this host is listening to.
359+ Return the multiaddr addresses this host advertises to peers.
360+
361+ If ``announce_addrs`` was provided, those replace listen addresses
362+ entirely. Otherwise listen addresses are used.
353363
354364 Note: This method appends the /p2p/{peer_id} suffix to the addresses.
355365 Use get_transport_addrs() for raw transport addresses.
356366 """
357367 p2p_part = multiaddr .Multiaddr (f"/p2p/{ self .get_id ()!s} " )
358- return [join_multiaddrs (addr , p2p_part ) for addr in self .get_transport_addrs ()]
368+
369+ if self ._announce_addrs is not None :
370+ addrs = list (self ._announce_addrs )
371+ else :
372+ addrs = self .get_transport_addrs ()
373+
374+ result = []
375+ for addr in addrs :
376+ # Strip any existing /p2p/ component, then always append our own.
377+ # This avoids identity confusion when announce addrs contain a
378+ # mismatched peer ID (mirrors js-libp2p behaviour).
379+ try :
380+ p2p_value = addr .value_for_protocol ("p2p" )
381+ except ProtocolLookupError :
382+ p2p_value = None
383+ if p2p_value :
384+ addr = addr .decapsulate (multiaddr .Multiaddr (f"/p2p/{ p2p_value } " ))
385+ result .append (addr .encapsulate (p2p_part ))
386+ return result
359387
360388 def get_connected_peers (self ) -> list [ID ]:
361389 """
@@ -388,7 +416,7 @@ async def _run() -> AsyncIterator[None]:
388416 upnp_manager = self .upnp
389417 logger .debug ("Starting UPnP discovery and port mapping" )
390418 if await upnp_manager .discover ():
391- for addr in self .get_addrs ():
419+ for addr in self .get_transport_addrs ():
392420 if port := addr .value_for_protocol ("tcp" ):
393421 await upnp_manager .add_port_mapping (int (port ), "TCP" )
394422 if self .bootstrap is not None :
@@ -403,7 +431,7 @@ async def _run() -> AsyncIterator[None]:
403431 if self .upnp and self .upnp .get_external_ip ():
404432 upnp_manager = self .upnp
405433 logger .debug ("Removing UPnP port mappings" )
406- for addr in self .get_addrs ():
434+ for addr in self .get_transport_addrs ():
407435 if port := addr .value_for_protocol ("tcp" ):
408436 await upnp_manager .remove_port_mapping (int (port ), "TCP" )
409437 if self .bootstrap is not None :
0 commit comments