From fe531c583db2739bee90a8a78096065c16d372d2 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 5 Oct 2022 19:10:06 +0000 Subject: [PATCH] Rewrite documentation some on `ProbabilisticScorer` We had some user confusion on how the probabilistic scorer works, especially in reference to the half-life parameter. This attempts to clarify how the bounds work, and how they are decayed. --- lightning/src/routing/scoring.rs | 56 ++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index d1195dc8d..8206a6b93 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -315,19 +315,28 @@ type ConfiguredTime = Eternity; /// [`Score`] implementation using channel success probability distributions. /// -/// Based on *Optimally Reliable & Cheap Payment Flows on the Lightning Network* by Rene Pickhardt -/// and Stefan Richter [[1]]. Given the uncertainty of channel liquidity balances, probability -/// distributions are defined based on knowledge learned from successful and unsuccessful attempts. -/// Then the negative `log10` of the success probability is used to determine the cost of routing a -/// specific HTLC amount through a channel. +/// Channels are tracked with upper and lower liquidity bounds - when an HTLC fails at a channel, +/// we learn that the upper-bound on the available liquidity is lower than the amount of the HTLC. +/// When a payment is forwarded through a channel (but fails later in the route), we learn the +/// lower-bound on the channel's available liquidity must be at least the value of the HTLC. /// -/// Knowledge about channel liquidity balances takes the form of upper and lower bounds on the -/// possible liquidity. Certainty of the bounds is decreased over time using a decay function. See -/// [`ProbabilisticScoringParameters`] for details. +/// These bounds are then used to determine a success probability using the formula from +/// *Optimally Reliable & Cheap Payment Flows on the Lightning Network* by Rene Pickhardt +/// and Stefan Richter [[1]] (i.e. `(upper_bound - payment_amount) / (upper_bound - lower_bound)`). /// -/// Since the scorer aims to learn the current channel liquidity balances, it works best for nodes -/// with high payment volume or that actively probe the [`NetworkGraph`]. Nodes with low payment -/// volume are more likely to experience failed payment paths, which would need to be retried. +/// This probability is combined with the [`liquidity_penalty_multiplier_msat`] and +/// [`liquidity_penalty_amount_multiplier_msat`] parameters to calculate a concrete penalty in +/// milli-satoshis. The penalties, when added across all hops, have the property of being linear in +/// terms of the entire path's success probability. This allows the router to directly compare +/// penalties for different paths. See the documentation of those parameters for the exact formulas. +/// +/// The liquidity bounds are decayed by halving them every [`liquidity_offset_half_life`]. +/// +/// Further, we track the history of our upper and lower liquidity bounds for each channel, +/// allowing us to assign a second penalty (using [`historical_liquidity_penalty_multiplier_msat`] +/// and [`historical_liquidity_penalty_amount_multiplier_msat`]) based on the same probability +/// formula, but using the history of a channel rather than our latest estimates for the liquidity +/// bounds. /// /// # Note /// @@ -335,6 +344,11 @@ type ConfiguredTime = Eternity; /// behavior. /// /// [1]: https://arxiv.org/abs/2107.05322 +/// [`liquidity_penalty_multiplier_msat`]: ProbabilisticScoringParameters::liquidity_penalty_multiplier_msat +/// [`liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::liquidity_penalty_amount_multiplier_msat +/// [`liquidity_offset_half_life`]: ProbabilisticScoringParameters::liquidity_offset_half_life +/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_multiplier_msat +/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_amount_multiplier_msat pub type ProbabilisticScorer = ProbabilisticScorerUsingTime::; /// Probabilistic [`Score`] implementation. @@ -388,19 +402,27 @@ pub struct ProbabilisticScoringParameters { /// uncertainty bounds of the channel liquidity balance. Amounts above the upper bound will /// result in a `u64::max_value` penalty, however. /// + /// `-log10(success_probability) * liquidity_penalty_multiplier_msat` + /// /// Default value: 30,000 msat /// /// [`liquidity_offset_half_life`]: Self::liquidity_offset_half_life pub liquidity_penalty_multiplier_msat: u64, - /// The time required to elapse before any knowledge learned about channel liquidity balances is - /// cut in half. + /// Whenever this amount of time elapses since the last update to a channel's liquidity bounds, + /// the distance from the bounds to "zero" is cut in half. In other words, the lower-bound on + /// the available liquidity is halved and the upper-bound moves half-way to the channel's total + /// capacity. + /// + /// Because halving the liquidity bounds grows the uncertainty on the channel's liquidity, + /// the penalty for an amount within the new bounds may change. See the [`ProbabilisticScorer`] + /// struct documentation for more info on the way the liquidity bounds are used. /// - /// The bounds are defined in terms of offsets and are initially zero. Increasing the offsets - /// gives tighter bounds on the channel liquidity balance. Thus, halving the offsets decreases - /// the certainty of the channel liquidity balance. + /// For example, if the channel's capacity is 1 million sats, and the current upper and lower + /// liquidity bounds are 200,000 sats and 600,000 sats, after this amount of time the upper + /// and lower liquidity bounds will be decayed to 100,000 and 800,000 sats. /// - /// Default value: 1 hour + /// Default value: hour /// /// # Note /// -- 2.39.5