Skip to content

Commit edacd23

Browse files
committed
Avoid retrying over recently failed channels
In ProbabilisticScorer, the channel liquidity balance is reduced whenever a payment fails at the corresponding channel. The payment may still be retried through the channel, however, because the liquidity penalty is capped. Use u64::max_value instead in this situation to avoid retrying over the same path. This effectively makes u64::max_value the penalty for amounts exceeding the upper bound, as well. As an edge case, avoid using u64::max_value on attempts where the amount is equal to the effective capacity, which may be the HTLC maximum when the channel capacity is unknown.
1 parent 7671ae5 commit edacd23

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

lightning/src/routing/scoring.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,10 @@ pub struct ProbabilisticScoringParameters {
531531
///
532532
/// The penalty is based in part by the knowledge learned from prior successful and unsuccessful
533533
/// payments. This knowledge is decayed over time based on [`liquidity_offset_half_life`]. The
534-
/// penalty is effectively limited to `2 * liquidity_penalty_multiplier_msat`.
534+
/// penalty is effectively limited to `2 * liquidity_penalty_multiplier_msat` (corresponding to
535+
/// lower bounding the success probability to `0.01`) when the amount falls within the
536+
/// uncertainty bounds of the channel liquidity balance. Amounts above the upper bound will
537+
/// result in a `u64::max_value` penalty, however.
535538
///
536539
/// Default value: 40,000 msat
537540
///
@@ -669,10 +672,17 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
669672
let max_penalty_msat = liquidity_penalty_multiplier_msat.saturating_mul(2);
670673
let max_liquidity_msat = self.max_liquidity_msat();
671674
let min_liquidity_msat = core::cmp::min(self.min_liquidity_msat(), max_liquidity_msat);
672-
if amount_msat > max_liquidity_msat {
673-
max_penalty_msat
674-
} else if amount_msat <= min_liquidity_msat {
675+
if amount_msat <= min_liquidity_msat {
675676
0
677+
} else if amount_msat >= max_liquidity_msat {
678+
if amount_msat > max_liquidity_msat {
679+
u64::max_value()
680+
} else if max_liquidity_msat != self.capacity_msat {
681+
// Avoid using the failed channel on retry.
682+
u64::max_value()
683+
} else {
684+
max_penalty_msat
685+
}
676686
} else {
677687
let numerator = (max_liquidity_msat - amount_msat).saturating_add(1);
678688
let denominator = (max_liquidity_msat - min_liquidity_msat).saturating_add(1);
@@ -1774,8 +1784,8 @@ mod tests {
17741784

17751785
assert_eq!(scorer.channel_penalty_msat(42, 39, 100, &source, &target), 0);
17761786
assert_ne!(scorer.channel_penalty_msat(42, 50, 100, &source, &target), 0);
1777-
assert_ne!(scorer.channel_penalty_msat(42, 50, 100, &source, &target), 2_000);
1778-
assert_eq!(scorer.channel_penalty_msat(42, 61, 100, &source, &target), 2_000);
1787+
assert_ne!(scorer.channel_penalty_msat(42, 50, 100, &source, &target), u64::max_value());
1788+
assert_eq!(scorer.channel_penalty_msat(42, 61, 100, &source, &target), u64::max_value());
17791789
}
17801790

17811791
#[test]
@@ -1839,8 +1849,8 @@ mod tests {
18391849
scorer.payment_path_failed(&path.iter().collect::<Vec<_>>(), 42);
18401850

18411851
assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 300);
1842-
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 2_000);
1843-
assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 2_000);
1852+
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), u64::max_value());
1853+
assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), u64::max_value());
18441854
}
18451855

18461856
#[test]
@@ -1888,19 +1898,19 @@ mod tests {
18881898
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0);
18891899
assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 97);
18901900
assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_409);
1891-
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 2_000);
1901+
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), u64::max_value());
18921902

18931903
SinceEpoch::advance(Duration::from_secs(9));
18941904
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0);
18951905
assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 97);
18961906
assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_409);
1897-
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 2_000);
1907+
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), u64::max_value());
18981908

18991909
SinceEpoch::advance(Duration::from_secs(1));
19001910
assert_eq!(scorer.channel_penalty_msat(42, 64, 1_024, &source, &target), 0);
19011911
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 34);
19021912
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 1_773);
1903-
assert_eq!(scorer.channel_penalty_msat(42, 960, 1_024, &source, &target), 2_000);
1913+
assert_eq!(scorer.channel_penalty_msat(42, 960, 1_024, &source, &target), u64::max_value());
19041914

19051915
// Fully decay liquidity lower bound.
19061916
SinceEpoch::advance(Duration::from_secs(10 * 7));
@@ -1995,7 +2005,7 @@ mod tests {
19952005
let target = target_node_id();
19962006

19972007
scorer.payment_path_failed(&payment_path_for_amount(500).iter().collect::<Vec<_>>(), 42);
1998-
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 2_000);
2008+
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), u64::max_value());
19992009

20002010
SinceEpoch::advance(Duration::from_secs(10));
20012011
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 472);
@@ -2025,7 +2035,7 @@ mod tests {
20252035
let target = target_node_id();
20262036

20272037
scorer.payment_path_failed(&payment_path_for_amount(500).iter().collect::<Vec<_>>(), 42);
2028-
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 2_000);
2038+
assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), u64::max_value());
20292039

20302040
let mut serialized_scorer = Vec::new();
20312041
scorer.write(&mut serialized_scorer).unwrap();

0 commit comments

Comments
 (0)