Skip to content

Commit fdfd4f0

Browse files
authored
Merge pull request #1754 from TheBlueMatt/2022-10-better-liq-halflife-docs
Rewrite some documentation on `ProbabilisticScorer` and increase half-life to 6 hours.
2 parents 6738fd5 + 9e84966 commit fdfd4f0

File tree

1 file changed

+41
-19
lines changed

1 file changed

+41
-19
lines changed

lightning/src/routing/scoring.rs

+41-19
Original file line numberDiff line numberDiff line change
@@ -315,26 +315,40 @@ type ConfiguredTime = Eternity;
315315

316316
/// [`Score`] implementation using channel success probability distributions.
317317
///
318-
/// Based on *Optimally Reliable & Cheap Payment Flows on the Lightning Network* by Rene Pickhardt
319-
/// and Stefan Richter [[1]]. Given the uncertainty of channel liquidity balances, probability
320-
/// distributions are defined based on knowledge learned from successful and unsuccessful attempts.
321-
/// Then the negative `log10` of the success probability is used to determine the cost of routing a
322-
/// specific HTLC amount through a channel.
318+
/// Channels are tracked with upper and lower liquidity bounds - when an HTLC fails at a channel,
319+
/// we learn that the upper-bound on the available liquidity is lower than the amount of the HTLC.
320+
/// When a payment is forwarded through a channel (but fails later in the route), we learn the
321+
/// lower-bound on the channel's available liquidity must be at least the value of the HTLC.
323322
///
324-
/// Knowledge about channel liquidity balances takes the form of upper and lower bounds on the
325-
/// possible liquidity. Certainty of the bounds is decreased over time using a decay function. See
326-
/// [`ProbabilisticScoringParameters`] for details.
323+
/// These bounds are then used to determine a success probability using the formula from
324+
/// *Optimally Reliable & Cheap Payment Flows on the Lightning Network* by Rene Pickhardt
325+
/// and Stefan Richter [[1]] (i.e. `(upper_bound - payment_amount) / (upper_bound - lower_bound)`).
327326
///
328-
/// Since the scorer aims to learn the current channel liquidity balances, it works best for nodes
329-
/// with high payment volume or that actively probe the [`NetworkGraph`]. Nodes with low payment
330-
/// volume are more likely to experience failed payment paths, which would need to be retried.
327+
/// This probability is combined with the [`liquidity_penalty_multiplier_msat`] and
328+
/// [`liquidity_penalty_amount_multiplier_msat`] parameters to calculate a concrete penalty in
329+
/// milli-satoshis. The penalties, when added across all hops, have the property of being linear in
330+
/// terms of the entire path's success probability. This allows the router to directly compare
331+
/// penalties for different paths. See the documentation of those parameters for the exact formulas.
332+
///
333+
/// The liquidity bounds are decayed by halving them every [`liquidity_offset_half_life`].
334+
///
335+
/// Further, we track the history of our upper and lower liquidity bounds for each channel,
336+
/// allowing us to assign a second penalty (using [`historical_liquidity_penalty_multiplier_msat`]
337+
/// and [`historical_liquidity_penalty_amount_multiplier_msat`]) based on the same probability
338+
/// formula, but using the history of a channel rather than our latest estimates for the liquidity
339+
/// bounds.
331340
///
332341
/// # Note
333342
///
334343
/// Mixing the `no-std` feature between serialization and deserialization results in undefined
335344
/// behavior.
336345
///
337346
/// [1]: https://arxiv.org/abs/2107.05322
347+
/// [`liquidity_penalty_multiplier_msat`]: ProbabilisticScoringParameters::liquidity_penalty_multiplier_msat
348+
/// [`liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::liquidity_penalty_amount_multiplier_msat
349+
/// [`liquidity_offset_half_life`]: ProbabilisticScoringParameters::liquidity_offset_half_life
350+
/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_multiplier_msat
351+
/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_amount_multiplier_msat
338352
pub type ProbabilisticScorer<G, L> = ProbabilisticScorerUsingTime::<G, L, ConfiguredTime>;
339353

340354
/// Probabilistic [`Score`] implementation.
@@ -388,19 +402,27 @@ pub struct ProbabilisticScoringParameters {
388402
/// uncertainty bounds of the channel liquidity balance. Amounts above the upper bound will
389403
/// result in a `u64::max_value` penalty, however.
390404
///
405+
/// `-log10(success_probability) * liquidity_penalty_multiplier_msat`
406+
///
391407
/// Default value: 30,000 msat
392408
///
393409
/// [`liquidity_offset_half_life`]: Self::liquidity_offset_half_life
394410
pub liquidity_penalty_multiplier_msat: u64,
395411

396-
/// The time required to elapse before any knowledge learned about channel liquidity balances is
397-
/// cut in half.
412+
/// Whenever this amount of time elapses since the last update to a channel's liquidity bounds,
413+
/// the distance from the bounds to "zero" is cut in half. In other words, the lower-bound on
414+
/// the available liquidity is halved and the upper-bound moves half-way to the channel's total
415+
/// capacity.
416+
///
417+
/// Because halving the liquidity bounds grows the uncertainty on the channel's liquidity,
418+
/// the penalty for an amount within the new bounds may change. See the [`ProbabilisticScorer`]
419+
/// struct documentation for more info on the way the liquidity bounds are used.
398420
///
399-
/// The bounds are defined in terms of offsets and are initially zero. Increasing the offsets
400-
/// gives tighter bounds on the channel liquidity balance. Thus, halving the offsets decreases
401-
/// the certainty of the channel liquidity balance.
421+
/// For example, if the channel's capacity is 1 million sats, and the current upper and lower
422+
/// liquidity bounds are 200,000 sats and 600,000 sats, after this amount of time the upper
423+
/// and lower liquidity bounds will be decayed to 100,000 and 800,000 sats.
402424
///
403-
/// Default value: 1 hour
425+
/// Default value: 6 hours
404426
///
405427
/// # Note
406428
///
@@ -758,7 +780,7 @@ impl ProbabilisticScoringParameters {
758780
base_penalty_msat: 0,
759781
base_penalty_amount_multiplier_msat: 0,
760782
liquidity_penalty_multiplier_msat: 0,
761-
liquidity_offset_half_life: Duration::from_secs(3600),
783+
liquidity_offset_half_life: Duration::from_secs(6 * 60 * 60),
762784
liquidity_penalty_amount_multiplier_msat: 0,
763785
historical_liquidity_penalty_multiplier_msat: 0,
764786
historical_liquidity_penalty_amount_multiplier_msat: 0,
@@ -784,7 +806,7 @@ impl Default for ProbabilisticScoringParameters {
784806
base_penalty_msat: 500,
785807
base_penalty_amount_multiplier_msat: 8192,
786808
liquidity_penalty_multiplier_msat: 30_000,
787-
liquidity_offset_half_life: Duration::from_secs(3600),
809+
liquidity_offset_half_life: Duration::from_secs(6 * 60 * 60),
788810
liquidity_penalty_amount_multiplier_msat: 192,
789811
historical_liquidity_penalty_multiplier_msat: 10_000,
790812
historical_liquidity_penalty_amount_multiplier_msat: 64,

0 commit comments

Comments
 (0)