From fe531c583db2739bee90a8a78096065c16d372d2 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 5 Oct 2022 19:10:06 +0000 Subject: [PATCH 1/2] 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 d1195dc8d67..8206a6b93cc 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 /// From 9e8496659f5ae0bf6f29c08b16d7ab18df3e37b4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 5 Oct 2022 19:23:56 +0000 Subject: [PATCH 2/2] Increase the default `liquidity_offset_half_life` to six hours Even at relatively high payment volumes, decaying knowledge of each individual channel every hour causes aggressive retrying of channels as we quickly forget the state of a channel. Even with the historical tracker, this isn't fully remedied, as we'll track the history bounds with the decayed value. Instead, we decay every six hours here, reducing how often we'll retry a channel due to decay. In addition to this, the decay likely needs to be substantially more linear, as tracked in #1752. --- lightning/src/routing/scoring.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 8206a6b93cc..fefdebfccd3 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -422,7 +422,7 @@ pub struct ProbabilisticScoringParameters { /// 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: hour + /// Default value: 6 hours /// /// # Note /// @@ -780,7 +780,7 @@ impl ProbabilisticScoringParameters { base_penalty_msat: 0, base_penalty_amount_multiplier_msat: 0, liquidity_penalty_multiplier_msat: 0, - liquidity_offset_half_life: Duration::from_secs(3600), + liquidity_offset_half_life: Duration::from_secs(6 * 60 * 60), liquidity_penalty_amount_multiplier_msat: 0, historical_liquidity_penalty_multiplier_msat: 0, historical_liquidity_penalty_amount_multiplier_msat: 0, @@ -806,7 +806,7 @@ impl Default for ProbabilisticScoringParameters { base_penalty_msat: 500, base_penalty_amount_multiplier_msat: 8192, liquidity_penalty_multiplier_msat: 30_000, - liquidity_offset_half_life: Duration::from_secs(3600), + liquidity_offset_half_life: Duration::from_secs(6 * 60 * 60), liquidity_penalty_amount_multiplier_msat: 192, historical_liquidity_penalty_multiplier_msat: 10_000, historical_liquidity_penalty_amount_multiplier_msat: 64,