hopr_transport/path/traits.rs
1use hopr_api::OffchainPublicKey;
2
3use super::errors::Result;
4
5/// A candidate path paired with its accumulated traversal cost and per-path quality metrics.
6///
7/// The `cost` is a multiplicative product of per-edge quality scores in
8/// `(0.0, 1.0]` — higher means better quality.
9///
10/// Aggregate fields are `Option<T>` with per-field `None` semantics documented on each
11/// field. Latency-measured paths are preferred during pruning; paths with `None` latency
12/// fill remaining slots up to the anonymity floor.
13#[derive(Debug, Clone)]
14pub struct PathWithMetrics {
15 /// The path nodes (excluding source): `[intermediates..., dest]`.
16 pub path: Vec<OffchainPublicKey>,
17 /// Accumulated traversal cost.
18 pub cost: f64,
19 /// Sum of per-edge EMA latencies in milliseconds.
20 /// `None` if any edge along the path has no measured latency.
21 pub total_latency_ms: Option<u32>,
22 /// Worst per-edge probe success rate along the path, taken as the minimum of
23 /// the available immediate (1-hop) and intermediate (multi-hop) probe rates per edge.
24 /// `None` if no edge has any probe data.
25 pub min_probe_success_rate: Option<f64>,
26 /// Worst per-edge acknowledgment rate along the path.
27 /// `None` if no edge has sent any messages yet.
28 pub min_ack_rate: Option<f64>,
29 /// Smallest known channel capacity along the path.
30 /// `None` if no edge carries channel-capacity data.
31 pub capacity_floor: Option<u128>,
32}
33
34/// Selects multi-hop paths through the network.
35///
36/// Implementors are responsible for determining how paths are found.
37/// The caller (e.g. [`crate::path::planner::PathPlanner`]) is responsible for caching,
38/// path selection strategy, and validation.
39///
40/// # Cycle-free invariant
41///
42/// Implementations **must** return only cycle-free (simple) paths — no node may
43/// appear more than once in any returned path. Cycles destroy path entropy and
44/// worsen anonymity. The built-in [`crate::path::selector::HoprGraphPathSelector`]
45/// guarantees this by using the `simple_paths` graph algorithm, which by
46/// definition never revisits a node. Alternative implementations must uphold
47/// the same invariant.
48pub trait PathSelector {
49 /// Return **all** candidate paths from `src` to `dest` using `hops` relays.
50 ///
51 /// Each returned [`PathWithMetrics`] contains a path `Vec<OffchainPublicKey>`
52 /// of length `hops + 1` (`[intermediates..., dest]`; `src` excluded) paired
53 /// with its accumulated traversal cost and optional per-path quality aggregates.
54 ///
55 /// Every returned path must be cycle-free (see trait-level docs).
56 ///
57 /// Returns `Err` when no paths can be found.
58 fn select_path(&self, src: OffchainPublicKey, dest: OffchainPublicKey, hops: usize)
59 -> Result<Vec<PathWithMetrics>>;
60}
61
62/// A selector that can run a background path-cache refresh loop.
63///
64/// Implementors pre-warm their internal caches on a periodic schedule,
65/// so that steady-state traffic is always served without a blocking query.
66///
67/// The returned future is `'static` because it is intended to be
68/// spawned as a long-lived background task.
69pub trait BackgroundPathCacheRefreshable: Send + Sync {
70 /// Returns a future that runs the periodic cache-refresh loop.
71 ///
72 /// The future never completes under normal operation.
73 fn run_background_refresh(&self) -> impl std::future::Future<Output = ()> + Send + 'static;
74}