hopr_transport_path/traits.rs
1use hopr_types::crypto::types::OffchainPublicKey;
2
3use crate::errors::Result;
4
5/// A candidate path paired with its accumulated traversal cost.
6///
7/// The cost is a multiplicative product of per-edge quality scores in
8/// `(0.0, 1.0]` — higher means better quality.
9#[derive(Debug, Clone)]
10pub struct PathWithCost {
11 /// The path nodes (excluding source): `[intermediates..., dest]`.
12 pub path: Vec<OffchainPublicKey>,
13 /// Accumulated traversal cost.
14 pub cost: f64,
15}
16
17/// Selects multi-hop paths through the network.
18///
19/// Implementors are responsible for determining how paths are found.
20/// The caller (e.g. [`crate::planner::PathPlanner`]) is responsible for caching,
21/// path selection strategy, and validation.
22///
23/// # Cycle-free invariant
24///
25/// Implementations **must** return only cycle-free (simple) paths — no node may
26/// appear more than once in any returned path. Cycles destroy path entropy and
27/// worsen anonymity. The built-in [`crate::selector::HoprGraphPathSelector`]
28/// guarantees this by using the `simple_paths` graph algorithm, which by
29/// definition never revisits a node. Alternative implementations must uphold
30/// the same invariant.
31pub trait PathSelector {
32 /// Return **all** candidate paths from `src` to `dest` using `hops` relays.
33 ///
34 /// Each returned [`PathWithCost`] contains a path `Vec<OffchainPublicKey>`
35 /// of length `hops + 1` (`[intermediates..., dest]`; `src` excluded) paired
36 /// with its accumulated traversal cost.
37 ///
38 /// Every returned path must be cycle-free (see trait-level docs).
39 ///
40 /// Returns `Err` when no paths can be found.
41 fn select_path(&self, src: OffchainPublicKey, dest: OffchainPublicKey, hops: usize) -> Result<Vec<PathWithCost>>;
42}
43
44/// A selector that can run a background path-cache refresh loop.
45///
46/// Implementors pre-warm their internal caches on a periodic schedule,
47/// so that steady-state traffic is always served without a blocking query.
48///
49/// The returned future is `'static` because it is intended to be
50/// spawned as a long-lived background task.
51pub trait BackgroundPathCacheRefreshable: Send + Sync {
52 /// Returns a future that runs the periodic cache-refresh loop.
53 ///
54 /// The future never completes under normal operation.
55 fn run_background_refresh(&self) -> impl std::future::Future<Output = ()> + Send + 'static;
56}