Skip to content

Commit 8acd55d

Browse files
committed
Update docs for background probing service
1 parent 935bd84 commit 8acd55d

2 files changed

Lines changed: 109 additions & 20 deletions

File tree

src/builder.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,14 +638,20 @@ impl NodeBuilder {
638638
/// Configures background probing.
639639
///
640640
/// Use [`ProbingConfigBuilder`] to build the configuration:
641-
/// ```ignore
641+
/// ```no_run
642+
/// # #[cfg(not(feature = "uniffi"))]
643+
/// # {
644+
/// use std::time::Duration;
645+
/// use ldk_node::Builder;
642646
/// use ldk_node::probing::ProbingConfigBuilder;
643647
///
648+
/// let mut builder = Builder::new();
644649
/// builder.set_probing_config(
645650
/// ProbingConfigBuilder::high_degree(100)
646651
/// .interval(Duration::from_secs(30))
647652
/// .build()
648653
/// );
654+
/// # }
649655
/// ```
650656
///
651657
/// [`ProbingConfigBuilder`]: crate::probing::ProbingConfigBuilder

src/probing.rs

Lines changed: 102 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,60 @@
55
// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
66
// accordance with one or both of these licenses.
77

8-
//! Background probing strategies for training the payment scorer.
8+
//! Background probing for training the payment scorer.
9+
//!
10+
//! Lightning Network nodes only know channels' capacities via their initially announced limits;
11+
//! the real values change unpredictably after payments have been sent, which makes some of
12+
//! the channels inoperable (capacity has been depleted). The only way to know about channel
13+
//! depletion is to attempt sending a payment through it. Thus, sending a live payment
14+
//! might involve a significant time delay for finding an appropriate channel with enough capacity,
15+
//! up to complete failure when a route with enough capacity cannot be found.
16+
//!
17+
//! The background probing service fires probes to learn about the live state of channels and
18+
//! their capacities, providing accurate data to the scorer and router.
19+
//!
20+
//! This module provides the configuration for such a service. There are two pre-built strategies,
21+
//! [`RandomStrategy`] and [`HighDegreeStrategy`], as well as a [`ProbingStrategy`] trait which
22+
//! allows defining a custom probing strategy (for example if there is an established payment
23+
//! pattern).
24+
//!
25+
//! # Configuration
26+
//!
27+
//! Probing is opt-in: a node only runs the service if a [`ProbingConfig`] has been registered
28+
//! on the [`Builder`] via [`Builder::set_probing_config`] before [`Builder::build`]. Without a
29+
//! config, no probes are sent.
30+
//!
31+
//! # Example
32+
//!
33+
//! ```no_run
34+
//! # #[cfg(not(feature = "uniffi"))]
35+
//! # {
36+
//! use std::time::Duration;
37+
//! use ldk_node::Builder;
38+
//! use ldk_node::probing::ProbingConfigBuilder;
39+
//!
40+
//! let probing_config = ProbingConfigBuilder::high_degree(100)
41+
//! .interval(Duration::from_secs(30))
42+
//! .max_locked_msat(500_000)
43+
//! .diversity_penalty_msat(250)
44+
//! .build();
45+
//!
46+
//! let mut builder = Builder::new();
47+
//! builder.set_probing_config(probing_config);
48+
//! # }
49+
//! ```
50+
//!
51+
//! # Caution
52+
//!
53+
//! Probes send real HTLCs along real paths. If an intermediate hop is offline or
54+
//! misbehaving, the probe HTLC can remain in-flight — locking outbound liquidity
55+
//! on the first-hop channel until the HTLC timeout elapses (potentially hours).
56+
//! `max_locked_msat` caps the total outbound capacity that in-flight probes may
57+
//! hold at any one time; tune it conservatively for nodes with tight liquidity.
58+
//!
59+
//! [`Builder`]: crate::Builder
60+
//! [`Builder::set_probing_config`]: crate::Builder::set_probing_config
61+
//! [`Builder::build`]: crate::Builder::build
962
1063
use std::collections::HashMap;
1164
use std::fmt;
@@ -58,27 +111,51 @@ impl fmt::Debug for ProbingStrategyKind {
58111

59112
/// Configuration for the background probing subsystem.
60113
///
61-
/// Construct via [`ProbingConfigBuilder`]. Pick a strategy with
62-
/// [`ProbingConfigBuilder::high_degree`], [`ProbingConfigBuilder::random_walk`], or
63-
/// [`ProbingConfigBuilder::custom`], chain optional setters, and finalize with
64-
/// [`ProbingConfigBuilder::build`].
114+
/// Instances are produced by [`ProbingConfigBuilder`], which exposes three strategy
115+
/// constructors: [`ProbingConfigBuilder::high_degree`], [`ProbingConfigBuilder::random_walk`],
116+
/// and [`ProbingConfigBuilder::custom`].
65117
///
66-
/// # Caution
118+
/// Optional setters on the builder tune timing and liquidity limits, and
119+
/// [`ProbingConfigBuilder::build`] finalizes the value.
67120
///
68-
/// Probes send real HTLCs along real paths. If an intermediate hop is offline or
69-
/// misbehaving, the probe HTLC can remain in-flight — locking outbound liquidity
70-
/// on the first-hop channel until the HTLC timeout elapses (potentially hours).
71-
/// `max_locked_msat` caps the total outbound capacity that in-flight probes may
72-
/// hold at any one time; tune it conservatively for nodes with tight liquidity.
121+
/// # Examples
122+
///
123+
/// Using pre-built strategy:
124+
/// ```no_run
125+
/// # #[cfg(not(feature = "uniffi"))]
126+
/// # {
127+
/// use std::time::Duration;
128+
/// use ldk_node::Builder;
129+
/// use ldk_node::probing::ProbingConfigBuilder;
73130
///
74-
/// # Example
75-
/// ```ignore
76131
/// let config = ProbingConfigBuilder::high_degree(100)
77132
/// .interval(Duration::from_secs(30))
78133
/// .max_locked_msat(500_000)
79134
/// .diversity_penalty_msat(250)
80135
/// .build();
136+
///
137+
/// let mut builder = Builder::new();
81138
/// builder.set_probing_config(config);
139+
/// # }
140+
/// ```
141+
///
142+
/// Creating a custom strategy that always probes the same path:
143+
/// ```
144+
/// use ldk_node::lightning::routing::router::Path;
145+
/// use ldk_node::probing::ProbingStrategy;
146+
///
147+
/// struct FixedPathStrategy {
148+
/// path: Path,
149+
/// }
150+
/// impl ProbingStrategy for FixedPathStrategy {
151+
/// fn next_probe(&self) -> Option<Path> {
152+
/// if self.path.hops.len() > 1 {
153+
/// Some(self.path.clone())
154+
/// } else {
155+
/// None
156+
/// }
157+
/// }
158+
/// }
82159
/// ```
83160
#[derive(Clone, Debug)]
84161
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
@@ -92,8 +169,9 @@ pub struct ProbingConfig {
92169

93170
/// Builder for [`ProbingConfig`].
94171
///
95-
/// Pick a strategy with [`high_degree`], [`random_walk`], or [`custom`], chain optional
96-
/// setters, and call [`build`] to finalize.
172+
/// A new instance starts from one of three strategy constructors — [`high_degree`],
173+
/// [`random_walk`], or [`custom`] — and is finalized through [`build`]. Optional setters
174+
/// in between override the timing and liquidity defaults.
97175
///
98176
/// [`high_degree`]: Self::high_degree
99177
/// [`random_walk`]: Self::random_walk
@@ -193,8 +271,9 @@ impl ProbingConfigBuilder {
193271
/// A UniFFI-compatible wrapper around [`ProbingConfigBuilder`] that uses interior mutability
194272
/// so it can be shared behind an `Arc` as required by the FFI object model.
195273
///
196-
/// Obtain one via the constructors [`new_high_degree`] or [`new_random_walk`], configure it
197-
/// with the `set_*` methods, then call [`build`] to produce a [`ProbingConfig`].
274+
/// Instances are produced by the constructors [`new_high_degree`] and [`new_random_walk`].
275+
/// The `set_*` methods override the defaults, and [`build`] yields the resulting
276+
/// [`ProbingConfig`].
198277
///
199278
/// [`new_high_degree`]: Self::new_high_degree
200279
/// [`new_random_walk`]: Self::new_random_walk
@@ -263,7 +342,7 @@ impl ArcedProbingConfigBuilder {
263342
}
264343
}
265344

266-
/// Strategy can be used for determining the next target and amount for probing.
345+
/// A strategy that decides which path the probing service should probe next.
267346
pub trait ProbingStrategy: Send + Sync + 'static {
268347
/// Returns the next probe path to run, or `None` to skip this tick.
269348
fn next_probe(&self) -> Option<Path>;
@@ -281,6 +360,8 @@ pub trait ProbingStrategy: Send + Sync + 'static {
281360
///
282361
/// The probe amount is chosen uniformly at random from
283362
/// `[min_amount_msat, max_amount_msat]`.
363+
///
364+
/// `HighDegreeStrategy` can only use publicly announced channels for probing.
284365
pub struct HighDegreeStrategy {
285366
network_graph: Arc<Graph>,
286367
channel_manager: Arc<ChannelManager>,
@@ -406,7 +487,7 @@ impl ProbingStrategy for HighDegreeStrategy {
406487
}
407488
}
408489

409-
/// Explores the graph by walking a random number of hops outward from one of our own
490+
/// Explores the graph by walking a random number (≥2) of hops outward from one of our own
410491
/// channels, constructing the [`Path`] explicitly.
411492
///
412493
/// On each tick:
@@ -418,6 +499,8 @@ impl ProbingStrategy for HighDegreeStrategy {
418499
///
419500
/// Because path selection ignores the scorer, this probes channels the router
420501
/// would never try on its own, teaching the scorer about previously unknown paths.
502+
///
503+
/// `RandomStrategy` can only use publicly announced channels for probing.
421504
pub struct RandomStrategy {
422505
network_graph: Arc<Graph>,
423506
channel_manager: Arc<ChannelManager>,

0 commit comments

Comments
 (0)