Skip to main content

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}