libp2p.relay.circuit_v2 package
Subpackages
Submodules
libp2p.relay.circuit_v2.protocol module
Circuit Relay v2 protocol implementation.
This module implements the Circuit Relay v2 protocol as specified in: https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md
- class libp2p.relay.circuit_v2.protocol.CircuitV2Protocol(host: IHost, limits: RelayLimits | None = None, allow_hop: bool = False, read_timeout: int = 15, write_timeout: int = 15, close_timeout: int = 10)
Bases:
ServiceCircuitV2Protocol implements the Circuit Relay v2 protocol.
This protocol allows peers to establish connections through relay nodes when direct connections are not possible (e.g., due to NAT).
libp2p.relay.circuit_v2.transport module
Transport implementation for Circuit Relay v2.
This module implements the transport layer for Circuit Relay v2, allowing peers to establish connections through relay nodes.
- class libp2p.relay.circuit_v2.transport.CircuitV2Listener(host: IHost, handler_function: Callable[[ReadWriteCloser], Awaitable[None]], protocol: CircuitV2Protocol, config: RelayConfig)
-
Listener for incoming relay connections.
- get_addrs() tuple[Multiaddr, ...]
Get the listening addresses.
Returns
- tuple[multiaddr.Multiaddr, …]
Tuple of listening multiaddresses
- async handle_incoming_connection(stream: INetStream) RawConnection
Handle an incoming relay connection.
Parameters
- streamINetStream
The incoming stream
- remote_peer_idID
The remote peer’s ID
Returns
- RawConnection
The established connection
Raises
- ConnectionError
If the connection cannot be established
- class libp2p.relay.circuit_v2.transport.CircuitV2Transport(host: IHost, protocol: CircuitV2Protocol, config: RelayConfig)
Bases:
ITransportCircuitV2Transport implements the transport interface for Circuit Relay v2.
This transport allows peers to establish connections through relay nodes when direct connections are not possible.
- create_listener(handler_function: Callable[[ReadWriteCloser], Awaitable[None]]) IListener
Create a listener on the transport.
Parameters
- handler_functionTHandler
A function that is called when a new connection is received. The function should accept a connection (that implements the connection interface) as its argument.
Returns
- IListener
A listener instance.
- async dial(maddr: Multiaddr) INetConn
Dial a peer using the multiaddr.
Parameters
- maddrmultiaddr.Multiaddr
The multiaddr to dial
Returns
- INetConn
The established connection
Raises
- ConnectionError
If the connection cannot be established
- async dial_peer_info(dest_info: PeerInfo, *, relay_info: PeerInfo | None = None) IRawConnection
Dial a destination peer using a relay.
Parameters
- dest_infoPeerInfo
The destination peer to dial.
- relay_infoOptional[PeerInfo], optional
An optional specific relay peer to use.
Returns
- RawConnection
The established raw connection to the destination peer through the relay.
Raises
- ConnectionError
If the connection cannot be established.
- parse_circuit_ma(ma: Multiaddr) tuple[Multiaddr, ID]
Parse a /p2p-circuit/p2p/<targetPeerID> path from a relay Multiaddr.
- Returns:
relay_ma: Multiaddr to the relay target_peer_id: ID of the target peer
- Raises:
ValueError: if the Multiaddr is not a valid circuit address
- async reserve(stream: INetStream, relay_peer_id: ID, nursery: Nursery) bool
Public method to create a reservation and start refresher if needed.
- class libp2p.relay.circuit_v2.transport.TrackedRawConnection(wrapped: RawConnection, relay_id: ID, tracker: RelayPerformanceTracker)
Bases:
IRawConnectionWrapper around RawConnection that tracks circuit closure.
Automatically calls record_circuit_closed() when the connection is closed. This ensures that active circuit counts are properly decremented when connections are closed, preventing unbounded growth of circuit counts.
libp2p.relay.circuit_v2.discovery module
Discovery module for Circuit Relay v2.
This module handles discovering and tracking relay nodes in the network.
- class libp2p.relay.circuit_v2.discovery.IHostWithMultiselect(*args, **kwargs)
Bases:
ProtocolExtended host interface with multiselect attribute.
- class libp2p.relay.circuit_v2.discovery.RelayDiscovery(host: IHost, auto_reserve: bool = False, discovery_interval: int = 300, max_relays: int = 10, stream_timeout: int = 10, peer_protocol_timeout: int = 5)
Bases:
ServiceDiscovery service for Circuit Relay v2 nodes.
This service discovers and keeps track of available relay nodes, and optionally makes reservations with them.
- async discover_relays() None
Discover relay nodes in the network.
This method queries the network for peers that support the Circuit Relay v2 protocol.
- get_relay() ID | None
Get a single relay peer ID for connection purposes. Prioritizes relays with active reservations.
Returns
- Optional[ID]
ID of a discovered relay, or None if no relays found
- get_relay_info(peer_id: ID) RelayInfo | None
Get information about a specific relay.
Parameters
- peer_idID
The ID of the relay to get information about
Returns
- Optional[RelayInfo]
Information about the relay, or None if not found
- get_relays() list[ID]
Get a list of discovered relay peer IDs.
Returns
- list[ID]
List of discovered relay peer IDs
libp2p.relay.circuit_v2.resources module
Resource management for Circuit Relay v2.
This module handles managing resources for relay operations, including reservations and connection limits.
- class libp2p.relay.circuit_v2.resources.RelayLimits(duration: int, data: int, max_circuit_conns: int, max_reservations: int)
Bases:
objectConfiguration for relay resource limits.
- class libp2p.relay.circuit_v2.resources.RelayResourceManager(limits: RelayLimits, host: IHost | None = None)
Bases:
objectManages resources and reservations for relay operations.
This class handles: - Tracking active reservations - Enforcing resource limits - Managing connection quotas
- can_accept_connection(peer_id: ID) bool
Check if a new connection can be accepted for the given peer.
Parameters
- peer_idID
The peer ID requesting the connection
Returns
- bool
True if the connection can be accepted
- can_accept_reservation(peer_id: ID) bool
Check if a new reservation can be accepted for the given peer.
Parameters
- peer_idID
The peer ID requesting the reservation
Returns
- bool
True if the reservation can be accepted
- create_reservation(peer_id: ID) Reservation
Create a new reservation for the given peer.
Parameters
- peer_idID
The peer ID to create the reservation for
Returns
- Reservation
The newly created reservation
- has_reservation(peer_id: ID) bool
Check if a reservation already exists for a peer
Parameters
- peer_idID
The peer ID to check for
Returns
- bool
True if reservation exists, False otherwise
- reserve(peer_id: ID) int
Create or update a reservation for a peer and return the TTL.
Parameters
- peer_idID
The peer ID to reserve for
Returns
- int
The TTL of the reservation in seconds
- class libp2p.relay.circuit_v2.resources.Reservation(peer_id: ID, limits: RelayLimits, host: IHost | None = None)
Bases:
objectRepresents a relay reservation.
- get_data_to_sign() bytes
Get the data that should be signed for this reservation.
Returns
- bytes
The data to sign, which includes the domain separator, voucher, and expiration
- property status: ReservationStatus
Return the current status as a
ReservationStatusenum.
- to_proto() Reservation
Convert the reservation to its protobuf representation.
Returns
- PbReservation
The protobuf representation of this reservation
- class libp2p.relay.circuit_v2.resources.ReservationStatus(value)
Bases:
EnumLifecycle status of a relay reservation.
- ACTIVE = 1
- EXPIRED = 2
- REJECTED = 3
libp2p.relay.circuit_v2.config module
Configuration management for Circuit Relay v2.
This module handles configuration for relay roles, resource limits, and discovery settings.
- class libp2p.relay.circuit_v2.config.ClientConfig(min_relay_score: float = 0.5, max_relay_latency: float = 1.0, enable_auto_relay: bool = True, auto_relay_timeout: int = 30, max_auto_relay_attempts: int = 3, reservation_refresh_threshold: float = 0.8, max_concurrent_reservations: int = 2)
Bases:
objectConfiguration specific to relay clients.
- class libp2p.relay.circuit_v2.config.HopConfig(max_reservations_per_ip: int = 8, max_circuits_per_ip: int = 16, reservation_rate_per_ip: int = 4, circuit_rate_per_ip: int = 8, max_circuits_total: int = 64, max_reservations_total: int = 32, max_bandwidth_per_circuit: int = 1048576, max_bandwidth_total: int = 10485760)
Bases:
objectConfiguration specific to relay (hop) nodes.
- class libp2p.relay.circuit_v2.config.RelayConfig(roles: ~libp2p.relay.circuit_v2.config.RelayRole = <RelayRole.CLIENT|STOP: 6>, limits: ~libp2p.relay.circuit_v2.resources.RelayLimits | None = None, bootstrap_relays: list[~libp2p.peer.peerinfo.PeerInfo] = <factory>, min_relays: int = 3, max_relays: int = 20, discovery_interval: int = 300, reservation_ttl: int = 3600, max_circuit_duration: int = 3600, max_circuit_bytes: int = 1073741824, timeouts: ~libp2p.relay.circuit_v2.config.TimeoutConfig = <factory>)
Bases:
objectConfiguration for Circuit Relay v2.
- limits: RelayLimits | None = None
- timeouts: TimeoutConfig
- class libp2p.relay.circuit_v2.config.RelayRole(value)
Bases:
FlagBit-flag enum that captures the three possible relay capabilities.
A node can combine multiple roles using bit-wise OR, for example:
RelayRole.HOP | RelayRole.STOP
- CLIENT = 4
- HOP = 1
- STOP = 2
- class libp2p.relay.circuit_v2.config.TimeoutConfig(discovery_stream_timeout: int = 10, peer_protocol_timeout: int = 5, protocol_read_timeout: int = 15, protocol_write_timeout: int = 15, protocol_close_timeout: int = 10, dcutr_read_timeout: int = 30, dcutr_write_timeout: int = 30, dial_timeout: int = 10)
Bases:
objectTimeout configuration for different Circuit Relay v2 components.
libp2p.relay.circuit_v2.protocol_buffer module
Protocol buffer wrapper classes for Circuit Relay v2.
This module provides wrapper classes for protocol buffer generated objects to make them easier to work with in type-checked code.
- class libp2p.relay.circuit_v2.protocol_buffer.StatusCode(value)
Bases:
IntEnumAn enumeration.
- CONNECTION_FAILED = 200
- DIAL_REFUSED = 201
- MALFORMED_MESSAGE = 400
- OK = 0
- PERMISSION_DENIED = 102
- RESERVATION_REFUSED = 100
- RESOURCE_LIMIT_EXCEEDED = 101
- STOP_FAILED = 300
- libp2p.relay.circuit_v2.protocol_buffer.create_status(code: int = StatusCode.OK, message: str = '') Status
Create a protocol buffer Status object.
Parameters
- codeint
The status code. Can be a StatusCode enum value or an integer.
- messagestr
The status message
Returns
- PbStatus
The protocol buffer Status object
libp2p.relay.circuit_v2.performance_tracker module
Relay performance tracker for intelligent relay selection.
This module provides per-relay performance tracking including latency, success rates, and active circuit counts to enable intelligent relay selection.
- class libp2p.relay.circuit_v2.performance_tracker.RelayPerformanceTracker(ema_alpha: float = 0.3, max_active_circuits: int = 100, latency_penalty_ms: float = 10.0, failure_penalty: float = 1000.0, min_success_rate: float = 0.5, circuit_penalty_multiplier: float = 5.0, success_bonus_multiplier: float = 100.0, unknown_relay_score: float = 1000.0)
Bases:
objectTracks performance metrics per relay for intelligent selection.
This tracker maintains per-relay statistics including: - Connection latency (exponential moving average) - Success/failure rates - Active circuit counts
It provides methods to score and select the best relay based on these metrics.
- export_metrics() dict[str, Any]
Export metrics for Prometheus/monitoring.
- Returns:
Dictionary with metrics data
- get_all_relay_stats() dict[ID, RelayStats]
Get statistics for all tracked relays.
- Returns:
Dictionary mapping relay IDs to their stats
- get_relay_score(relay_id: ID) float
Calculate a score for a relay (lower is better).
The score is based on: - Latency (lower is better) - Active circuits (fewer is better) - Success rate (higher is better)
- Args:
relay_id: The relay’s peer ID
- Returns:
Score for the relay (lower is better), or float(‘inf’) if unhealthy
- get_relay_stats(relay_id: ID) RelayStats | None
Get statistics for a specific relay.
- Args:
relay_id: The relay’s peer ID
- Returns:
RelayStats object, or None if relay not found
- record_circuit_closed(relay_id: ID) None
Record that a circuit was closed through a relay.
- Args:
relay_id: The relay’s peer ID
- record_circuit_opened(relay_id: ID) None
Record that a circuit was opened through a relay.
- Args:
relay_id: The relay’s peer ID
- record_connection_attempt(relay_id: ID, latency_ms: float, success: bool) None
Record a connection attempt to a relay.
- Args:
relay_id: The relay’s peer ID latency_ms: Connection latency in milliseconds success: Whether the connection succeeded
- select_best_relay(available_relays: list[ID], *, require_reservation: bool = False, relay_info_getter: Any | None = None) ID | None
Select the best relay from available options.
- Args:
available_relays: List of relay peer IDs to choose from require_reservation: If True, only consider relays with active reservations relay_info_getter: Optional callable to get relay info for reservation check
- Returns:
Selected relay ID, or None if no suitable relay found
Module contents
Circuit Relay v2 implementation for libp2p.
This package implements the Circuit Relay v2 protocol as specified in: https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md
- class libp2p.relay.circuit_v2.CircuitV2Protocol(host: IHost, limits: RelayLimits | None = None, allow_hop: bool = False, read_timeout: int = 15, write_timeout: int = 15, close_timeout: int = 10)
Bases:
ServiceCircuitV2Protocol implements the Circuit Relay v2 protocol.
This protocol allows peers to establish connections through relay nodes when direct connections are not possible (e.g., due to NAT).
- async handle_incoming_connection(stream: INetStream, remote_peer_id: bytes) None
Handle an incoming relay connection.
Parameters
- streamINetStream
The incoming stream
- remote_peer_idID
The remote peer’s ID
Raises
- ConnectionError
If the connection cannot be established
- class libp2p.relay.circuit_v2.CircuitV2Transport(host: IHost, protocol: CircuitV2Protocol, config: RelayConfig)
Bases:
ITransportCircuitV2Transport implements the transport interface for Circuit Relay v2.
This transport allows peers to establish connections through relay nodes when direct connections are not possible.
- create_listener(handler_function: Callable[[ReadWriteCloser], Awaitable[None]]) IListener
Create a listener on the transport.
Parameters
- handler_functionTHandler
A function that is called when a new connection is received. The function should accept a connection (that implements the connection interface) as its argument.
Returns
- IListener
A listener instance.
- async dial(maddr: Multiaddr) INetConn
Dial a peer using the multiaddr.
Parameters
- maddrmultiaddr.Multiaddr
The multiaddr to dial
Returns
- INetConn
The established connection
Raises
- ConnectionError
If the connection cannot be established
- async dial_peer_info(dest_info: PeerInfo, *, relay_info: PeerInfo | None = None) IRawConnection
Dial a destination peer using a relay.
Parameters
- dest_infoPeerInfo
The destination peer to dial.
- relay_infoOptional[PeerInfo], optional
An optional specific relay peer to use.
Returns
- RawConnection
The established raw connection to the destination peer through the relay.
Raises
- ConnectionError
If the connection cannot be established.
- parse_circuit_ma(ma: Multiaddr) tuple[Multiaddr, ID]
Parse a /p2p-circuit/p2p/<targetPeerID> path from a relay Multiaddr.
- Returns:
relay_ma: Multiaddr to the relay target_peer_id: ID of the target peer
- Raises:
ValueError: if the Multiaddr is not a valid circuit address
- async reserve(stream: INetStream, relay_peer_id: ID, nursery: Nursery) bool
Public method to create a reservation and start refresher if needed.
- class libp2p.relay.circuit_v2.DCUtRProtocol(host: IHost, read_timeout: int = 30, write_timeout: int = 30, dial_timeout: int = 10)
Bases:
ServiceDCUtRProtocol implements the Direct Connection Upgrade through Relay protocol.
This protocol allows two NATed peers to establish direct connections through hole punching, after they have established an initial connection through a relay.
- class libp2p.relay.circuit_v2.ReachabilityChecker(host: IHost)
Bases:
objectUtility class for checking peer reachability.
This class assesses whether a peer’s addresses are likely to be directly reachable or behind NAT.
- async check_peer_reachability(peer_id: ID) bool
Check if a peer is directly reachable.
Parameters
- peer_idID
The peer ID to check
Returns
- bool
True if peer is likely directly reachable
- async check_self_reachability() tuple[bool, list[Multiaddr]]
Check if this host is likely directly reachable.
Returns
- Tuple[bool, List[Multiaddr]]
Tuple of (is_reachable, public_addresses)
- class libp2p.relay.circuit_v2.RelayDiscovery(host: IHost, auto_reserve: bool = False, discovery_interval: int = 300, max_relays: int = 10, stream_timeout: int = 10, peer_protocol_timeout: int = 5)
Bases:
ServiceDiscovery service for Circuit Relay v2 nodes.
This service discovers and keeps track of available relay nodes, and optionally makes reservations with them.
- async discover_relays() None
Discover relay nodes in the network.
This method queries the network for peers that support the Circuit Relay v2 protocol.
- get_relay() ID | None
Get a single relay peer ID for connection purposes. Prioritizes relays with active reservations.
Returns
- Optional[ID]
ID of a discovered relay, or None if no relays found
- get_relay_info(peer_id: ID) RelayInfo | None
Get information about a specific relay.
Parameters
- peer_idID
The ID of the relay to get information about
Returns
- Optional[RelayInfo]
Information about the relay, or None if not found
- get_relays() list[ID]
Get a list of discovered relay peer IDs.
Returns
- list[ID]
List of discovered relay peer IDs
- class libp2p.relay.circuit_v2.RelayLimits(duration: int, data: int, max_circuit_conns: int, max_reservations: int)
Bases:
objectConfiguration for relay resource limits.
- data: int
- duration: int
- max_circuit_conns: int
- max_reservations: int
- class libp2p.relay.circuit_v2.RelayPerformanceTracker(ema_alpha: float = 0.3, max_active_circuits: int = 100, latency_penalty_ms: float = 10.0, failure_penalty: float = 1000.0, min_success_rate: float = 0.5, circuit_penalty_multiplier: float = 5.0, success_bonus_multiplier: float = 100.0, unknown_relay_score: float = 1000.0)
Bases:
objectTracks performance metrics per relay for intelligent selection.
This tracker maintains per-relay statistics including: - Connection latency (exponential moving average) - Success/failure rates - Active circuit counts
It provides methods to score and select the best relay based on these metrics.
- export_metrics() dict[str, Any]
Export metrics for Prometheus/monitoring.
- Returns:
Dictionary with metrics data
- get_all_relay_stats() dict[ID, RelayStats]
Get statistics for all tracked relays.
- Returns:
Dictionary mapping relay IDs to their stats
- get_relay_score(relay_id: ID) float
Calculate a score for a relay (lower is better).
The score is based on: - Latency (lower is better) - Active circuits (fewer is better) - Success rate (higher is better)
- Args:
relay_id: The relay’s peer ID
- Returns:
Score for the relay (lower is better), or float(‘inf’) if unhealthy
- get_relay_stats(relay_id: ID) RelayStats | None
Get statistics for a specific relay.
- Args:
relay_id: The relay’s peer ID
- Returns:
RelayStats object, or None if relay not found
- record_circuit_closed(relay_id: ID) None
Record that a circuit was closed through a relay.
- Args:
relay_id: The relay’s peer ID
- record_circuit_opened(relay_id: ID) None
Record that a circuit was opened through a relay.
- Args:
relay_id: The relay’s peer ID
- record_connection_attempt(relay_id: ID, latency_ms: float, success: bool) None
Record a connection attempt to a relay.
- Args:
relay_id: The relay’s peer ID latency_ms: Connection latency in milliseconds success: Whether the connection succeeded
- reset() None
Reset all tracking data.
- select_best_relay(available_relays: list[ID], *, require_reservation: bool = False, relay_info_getter: Any | None = None) ID | None
Select the best relay from available options.
- Args:
available_relays: List of relay peer IDs to choose from require_reservation: If True, only consider relays with active reservations relay_info_getter: Optional callable to get relay info for reservation check
- Returns:
Selected relay ID, or None if no suitable relay found
- class libp2p.relay.circuit_v2.RelayResourceManager(limits: RelayLimits, host: IHost | None = None)
Bases:
objectManages resources and reservations for relay operations.
This class handles: - Tracking active reservations - Enforcing resource limits - Managing connection quotas
- can_accept_connection(peer_id: ID) bool
Check if a new connection can be accepted for the given peer.
Parameters
- peer_idID
The peer ID requesting the connection
Returns
- bool
True if the connection can be accepted
- can_accept_reservation(peer_id: ID) bool
Check if a new reservation can be accepted for the given peer.
Parameters
- peer_idID
The peer ID requesting the reservation
Returns
- bool
True if the reservation can be accepted
- create_reservation(peer_id: ID) Reservation
Create a new reservation for the given peer.
Parameters
- peer_idID
The peer ID to create the reservation for
Returns
- Reservation
The newly created reservation
- has_reservation(peer_id: ID) bool
Check if a reservation already exists for a peer
Parameters
- peer_idID
The peer ID to check for
Returns
- bool
True if reservation exists, False otherwise
- reserve(peer_id: ID) int
Create or update a reservation for a peer and return the TTL.
Parameters
- peer_idID
The peer ID to reserve for
Returns
- int
The TTL of the reservation in seconds
- track_data_transfer(peer_id: ID, bytes_transferred: int) bool
Track data transferred for a peer’s reservation.
Parameters
- peer_idID
The peer ID
- bytes_transferredint
Number of bytes transferred
Returns
- bool
True if the data limit has not been exceeded, False otherwise
- verify_reservation(peer_id: ID, proto_res: Reservation) bool
Verify a reservation from a protobuf message.
Parameters
- peer_idID
The peer ID the reservation is for
- proto_resPbReservation
The protobuf reservation message
Returns
- bool
True if the reservation is valid
- class libp2p.relay.circuit_v2.RelayStats(relay_id: ~libp2p.peer.id.ID, latency_ema_ms: float = -1.0, success_count: int = 0, failure_count: int = 0, active_circuits: int = 0, last_updated: float = <factory>)
Bases:
objectPerformance statistics for a single relay.
- active_circuits: int = 0
- failure_count: int = 0
- last_updated: float
- latency_ema_ms: float = -1.0
- relay_id: ID
- success_count: int = 0
- property success_rate: float
Calculate success rate as a percentage.
- property total_attempts: int
Total connection attempts.
- class libp2p.relay.circuit_v2.Reservation(peer_id: ID, limits: RelayLimits, host: IHost | None = None)
Bases:
objectRepresents a relay reservation.
- can_accept_connection() bool
Check if a new connection can be accepted.
- get_data_to_sign() bytes
Get the data that should be signed for this reservation.
Returns
- bytes
The data to sign, which includes the domain separator, voucher, and expiration
- is_expired() bool
Check if the reservation has expired.
- property status: ReservationStatus
Return the current status as a
ReservationStatusenum.
- to_proto() Reservation
Convert the reservation to its protobuf representation.
Returns
- PbReservation
The protobuf representation of this reservation