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: Service

CircuitV2Protocol 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

async run(*, task_status: Any = TASK_STATUS_IGNORED) None

Run the protocol service.

class libp2p.relay.circuit_v2.protocol.IHostWithStreamHandlers(*args, **kwargs)

Bases: Protocol

Extended host interface with stream handler methods.

remove_stream_handler(protocol_id: TProtocol) None

Remove a stream handler for a protocol.

class libp2p.relay.circuit_v2.protocol.INetStreamWithExtras(*args, **kwargs)

Bases: Protocol

Extended net stream interface with additional methods.

get_remote_peer_id() ID

Get the remote peer ID.

is_closed() bool

Check if the stream is closed.

is_open() bool

Check if the stream is open.

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)

Bases: Service, IListener

Listener for incoming relay connections.

async close() None

Close the listener.

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

async listen(maddr: Multiaddr, nursery: Nursery) bool

Start listening on the given multiaddr.

Parameters

maddrmultiaddr.Multiaddr

The multiaddr to listen on

nurserytrio.Nursery

The nursery to run tasks in

Returns

bool

True if listening successfully started

async run() None

Run the listener service.

class libp2p.relay.circuit_v2.transport.CircuitV2Transport(host: IHost, protocol: CircuitV2Protocol, config: RelayConfig)

Bases: ITransport

CircuitV2Transport 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.

async discover_peers(key: bytes, max_results: int = 5) list[PeerInfo]
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: IRawConnection

Wrapper 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.

async close() None

Close the connection and record circuit closure.

get_remote_address() tuple[str, int] | None

Get remote address from the wrapped connection.

async read(n: int | None = None) bytes

Read data from the wrapped connection.

async write(data: bytes) None

Write data to the wrapped connection.

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: Protocol

Extended host interface with multiselect attribute.

property multiselect: Any

Get the multiselect component.

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: Service

Discovery 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

async make_reservation(peer_id: ID) bool

Make a reservation with a relay.

Parameters

peer_idID

The ID of the relay to make a reservation with

Returns

bool

True if reservation succeeded, False otherwise

async run(*, task_status: Any = TASK_STATUS_IGNORED) None

Run the discovery service.

class libp2p.relay.circuit_v2.discovery.RelayInfo(peer_id: ID, discovered_at: float, last_seen: float, has_reservation: bool = False, reservation_expires_at: float | None = None, reservation_data_limit: int | None = None)

Bases: object

Information about a discovered relay.

discovered_at: float
has_reservation: bool = False
last_seen: float
peer_id: ID
reservation_data_limit: int | None = None
reservation_expires_at: float | None = None

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: object

Configuration for relay resource limits.

data: int
duration: int
max_circuit_conns: int
max_reservations: int
class libp2p.relay.circuit_v2.resources.RelayResourceManager(limits: RelayLimits, host: IHost | None = None)

Bases: object

Manages 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

refresh_reservation(peer_id: ID) int
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.resources.Reservation(peer_id: ID, limits: RelayLimits, host: IHost | None = None)

Bases: object

Represents 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 ReservationStatus enum.

to_proto() Reservation

Convert the reservation to its protobuf representation.

Returns

PbReservation

The protobuf representation of this reservation

track_data_transfer(bytes_transferred: int) bool

Track data transferred for this reservation.

Parameters

bytes_transferredint

Number of bytes transferred

Returns

bool

True if the data limit has not been exceeded, False otherwise

class libp2p.relay.circuit_v2.resources.ReservationStatus(value)

Bases: Enum

Lifecycle status of a relay reservation.

ACTIVE = 1
EXPIRED = 2
REJECTED = 3
class libp2p.relay.circuit_v2.resources.ReservationVoucher(relay: ID, peer: ID, expiration: int, addrs: list[bytes] | None = None)

Bases: object

Represents a voucher for a relay reservation.

This is compatible with the Go implementation’s ReservationVoucher.

addrs: list[bytes] | None = None
expiration: int
peer: ID
relay: ID

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: object

Configuration specific to relay clients.

auto_relay_timeout: int = 30
enable_auto_relay: bool = True
max_auto_relay_attempts: int = 3
max_concurrent_reservations: int = 2
max_relay_latency: float = 1.0
min_relay_score: float = 0.5
reservation_refresh_threshold: float = 0.8
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: object

Configuration specific to relay (hop) nodes.

circuit_rate_per_ip: int = 8
max_bandwidth_per_circuit: int = 1048576
max_bandwidth_total: int = 10485760
max_circuits_per_ip: int = 16
max_circuits_total: int = 64
max_reservations_per_ip: int = 8
max_reservations_total: int = 32
reservation_rate_per_ip: int = 4
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: object

Configuration for Circuit Relay v2.

bootstrap_relays: list[PeerInfo]
discovery_interval: int = 300
property enable_client: bool
property enable_dht_discovery: bool
property enable_hop: bool
property enable_stop: bool
limits: RelayLimits | None = None
max_circuit_bytes: int = 1073741824
max_circuit_duration: int = 3600
max_relays: int = 20
min_relays: int = 3
reservation_ttl: int = 3600
roles: RelayRole = 6
timeouts: TimeoutConfig
class libp2p.relay.circuit_v2.config.RelayRole(value)

Bases: Flag

Bit-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: object

Timeout configuration for different Circuit Relay v2 components.

dcutr_read_timeout: int = 30
dcutr_write_timeout: int = 30
dial_timeout: int = 10
discovery_stream_timeout: int = 10
peer_protocol_timeout: int = 5
protocol_close_timeout: int = 10
protocol_read_timeout: int = 15
protocol_write_timeout: int = 15

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: IntEnum

An 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: object

Tracks 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.performance_tracker.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: object

Performance 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.

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: Service

CircuitV2Protocol 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

async run(*, task_status: Any = TASK_STATUS_IGNORED) None

Run the protocol service.

class libp2p.relay.circuit_v2.CircuitV2Transport(host: IHost, protocol: CircuitV2Protocol, config: RelayConfig)

Bases: ITransport

CircuitV2Transport 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.

async discover_peers(key: bytes, max_results: int = 5) list[PeerInfo]
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: Service

DCUtRProtocol 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.

async initiate_hole_punch(peer_id: ID) bool

Initiate a hole punch with a peer.

Parameters

peer_idID

The peer to hole punch with

Returns

bool

True if hole punch was successful, False otherwise

async run(*, task_status: Any = TASK_STATUS_IGNORED) None

Run the protocol service.

class libp2p.relay.circuit_v2.ReachabilityChecker(host: IHost)

Bases: object

Utility 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)

get_public_addrs(addrs: list[Multiaddr]) list[Multiaddr]

Filter a list of addresses to only include likely public ones.

Parameters

addrsList[Multiaddr]

List of addresses to filter

Returns

List[Multiaddr]

List of likely public addresses

is_addr_public(addr: Multiaddr) bool

Check if an address is likely to be publicly reachable.

Parameters

addrMultiaddr

The multiaddr to check

Returns

bool

True if address is likely public

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: Service

Discovery 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

async make_reservation(peer_id: ID) bool

Make a reservation with a relay.

Parameters

peer_idID

The ID of the relay to make a reservation with

Returns

bool

True if reservation succeeded, False otherwise

async run(*, task_status: Any = TASK_STATUS_IGNORED) None

Run the discovery service.

class libp2p.relay.circuit_v2.RelayLimits(duration: int, data: int, max_circuit_conns: int, max_reservations: int)

Bases: object

Configuration 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: object

Tracks 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: object

Manages 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

refresh_reservation(peer_id: ID) int
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: object

Performance 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: object

Represents 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 ReservationStatus enum.

to_proto() Reservation

Convert the reservation to its protobuf representation.

Returns

PbReservation

The protobuf representation of this reservation

track_data_transfer(bytes_transferred: int) bool

Track data transferred for this reservation.

Parameters

bytes_transferredint

Number of bytes transferred

Returns

bool

True if the data limit has not been exceeded, False otherwise

libp2p.relay.circuit_v2.is_private_ip(ip: str) bool

Check if an IP address is private.

Parameters

ipstr

IP address to check

Returns

bool

True if IP is private