Skip to content

Commit 5d3e90b

Browse files
committed
Add a base penalty to ProbabilisticScorer
ProbabilisticScorer tends to prefer longer routes to shorter ones. Make the default scoring behavior include a customizable base penalty to avoid longer routes.
1 parent 472a02c commit 5d3e90b

File tree

1 file changed

+47
-15
lines changed

1 file changed

+47
-15
lines changed

lightning/src/routing/scoring.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -516,27 +516,32 @@ pub struct ProbabilisticScorerUsingTime<G: Deref<Target = NetworkGraph>, T: Time
516516
}
517517

518518
/// Parameters for configuring [`ProbabilisticScorer`].
519+
///
520+
/// Used to configure a base penalty and a liquidity penalty, the sum of which is the channel
521+
/// penalty (i.e., the amount in msats willing to be paid to avoid routing through the channel).
519522
#[derive(Clone, Copy)]
520523
pub struct ProbabilisticScoringParameters {
521-
/// The function calculating the cost of routing an amount through a channel.
524+
/// A fixed penalty in msats to apply to each channel.
522525
///
523-
/// The cost is multiplied by [`liquidity_penalty_multiplier_msat`] to determine the channel
524-
/// penalty (i.e., the amount msats willing to be paid to avoid routing through the channel).
525-
/// Penalties are limited to `2 * liquidity_penalty_multiplier_msat`.
526+
/// Default value: 500 msat
527+
pub base_penalty_msat: u64,
528+
529+
/// The function calculating the cost of routing an amount through a channel.
526530
///
527-
/// The cost is based in part by the knowledge learned from prior successful and unsuccessful
528-
/// payments. This knowledge is decayed over time based on [`liquidity_offset_half_life`].
531+
/// The cost is multiplied by [`liquidity_penalty_multiplier_msat`] to determine the liquidity
532+
/// penalty, which is limited to `2 * liquidity_penalty_multiplier_msat`. The cost is based in
533+
/// part by the knowledge learned from prior successful and unsuccessful payments. This
534+
/// knowledge is decayed over time based on [`liquidity_offset_half_life`].
529535
///
530536
/// Default value: [`ProbabilisticScoringCostFunction::NegativeLogSuccessProbability`]
531537
///
532538
/// [`liquidity_penalty_multiplier_msat`]: Self::liquidity_penalty_multiplier_msat
533539
/// [`liquidity_offset_half_life`]: Self::liquidity_offset_half_life
534540
pub cost_function: ProbabilisticScoringCostFunction,
535541

536-
/// A multiplier used in conjunction with [`cost_function`] to determine the channel penalty.
542+
/// A multiplier used in conjunction with [`cost_function`] to determine the liquidity penalty.
537543
///
538-
/// The channel penalty is the amount in msats willing to be paid to avoid routing through a
539-
/// channel. It is effectively limited to `2 * liquidity_penalty_multiplier_msat`.
544+
/// The liquidity penalty is effectively limited to `2 * liquidity_penalty_multiplier_msat`.
540545
///
541546
/// Default value: 10,000 msat
542547
///
@@ -633,6 +638,7 @@ impl Default for ProbabilisticScoringParameters {
633638
cost_function: ProbabilisticScoringCostFunction::NegativeLogSuccessProbability,
634639
liquidity_penalty_multiplier_msat: 10_000,
635640
liquidity_offset_half_life: Duration::from_secs(3600),
641+
base_penalty_msat: 500,
636642
}
637643
}
638644
}
@@ -795,6 +801,7 @@ impl<G: Deref<Target = NetworkGraph>, T: Time> Score for ProbabilisticScorerUsin
795801
.unwrap_or(&ChannelLiquidity::new())
796802
.as_directed(source, target, capacity_msat, self.params.liquidity_offset_half_life)
797803
.penalty_msat(amount_msat, &self.params)
804+
.saturating_add(self.params.base_penalty_msat)
798805
}
799806

800807
fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
@@ -1775,7 +1782,7 @@ mod tests {
17751782
fn increased_penalty_nearing_liquidity_upper_bound() {
17761783
let network_graph = network_graph();
17771784
let params = ProbabilisticScoringParameters {
1778-
liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
1785+
base_penalty_msat: 0, liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
17791786
};
17801787
let scorer = ProbabilisticScorer::new(params, &network_graph);
17811788
let source = source_node_id();
@@ -1799,6 +1806,7 @@ mod tests {
17991806
fn increased_penalty_linearly_nearing_liquidity_upper_bound() {
18001807
let network_graph = network_graph();
18011808
let params = ProbabilisticScoringParameters {
1809+
base_penalty_msat: 0,
18021810
cost_function: ProbabilisticScoringCostFunction::TwiceFailureProbability,
18031811
liquidity_penalty_multiplier_msat: 1_000,
18041812
..Default::default()
@@ -1826,7 +1834,7 @@ mod tests {
18261834
let last_updated = SinceEpoch::now();
18271835
let network_graph = network_graph();
18281836
let params = ProbabilisticScoringParameters {
1829-
liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
1837+
base_penalty_msat: 0, liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
18301838
};
18311839
let scorer = ProbabilisticScorer::new(params, &network_graph)
18321840
.with_channel(42,
@@ -1846,7 +1854,7 @@ mod tests {
18461854
fn does_not_further_penalize_own_channel() {
18471855
let network_graph = network_graph();
18481856
let params = ProbabilisticScoringParameters {
1849-
liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
1857+
base_penalty_msat: 0, liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
18501858
};
18511859
let mut scorer = ProbabilisticScorer::new(params, &network_graph);
18521860
let sender = sender_node_id();
@@ -1867,7 +1875,7 @@ mod tests {
18671875
fn sets_liquidity_lower_bound_on_downstream_failure() {
18681876
let network_graph = network_graph();
18691877
let params = ProbabilisticScoringParameters {
1870-
liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
1878+
base_penalty_msat: 0, liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
18711879
};
18721880
let mut scorer = ProbabilisticScorer::new(params, &network_graph);
18731881
let source = source_node_id();
@@ -1889,7 +1897,7 @@ mod tests {
18891897
fn sets_liquidity_upper_bound_on_failure() {
18901898
let network_graph = network_graph();
18911899
let params = ProbabilisticScoringParameters {
1892-
liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
1900+
base_penalty_msat: 0, liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
18931901
};
18941902
let mut scorer = ProbabilisticScorer::new(params, &network_graph);
18951903
let source = source_node_id();
@@ -1911,7 +1919,7 @@ mod tests {
19111919
fn reduces_liquidity_upper_bound_along_path_on_success() {
19121920
let network_graph = network_graph();
19131921
let params = ProbabilisticScoringParameters {
1914-
liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
1922+
base_penalty_msat: 0, liquidity_penalty_multiplier_msat: 1_000, ..Default::default()
19151923
};
19161924
let mut scorer = ProbabilisticScorer::new(params, &network_graph);
19171925
let sender = sender_node_id();
@@ -1935,6 +1943,7 @@ mod tests {
19351943
fn decays_liquidity_bounds_over_time() {
19361944
let network_graph = network_graph();
19371945
let params = ProbabilisticScoringParameters {
1946+
base_penalty_msat: 0,
19381947
liquidity_penalty_multiplier_msat: 1_000,
19391948
liquidity_offset_half_life: Duration::from_secs(10),
19401949
..Default::default()
@@ -1987,6 +1996,7 @@ mod tests {
19871996
fn decays_liquidity_bounds_without_shift_overflow() {
19881997
let network_graph = network_graph();
19891998
let params = ProbabilisticScoringParameters {
1999+
base_penalty_msat: 0,
19902000
liquidity_penalty_multiplier_msat: 1_000,
19912001
liquidity_offset_half_life: Duration::from_secs(10),
19922002
..Default::default()
@@ -2012,6 +2022,7 @@ mod tests {
20122022
fn restricts_liquidity_bounds_after_decay() {
20132023
let network_graph = network_graph();
20142024
let params = ProbabilisticScoringParameters {
2025+
base_penalty_msat: 0,
20152026
liquidity_penalty_multiplier_msat: 1_000,
20162027
liquidity_offset_half_life: Duration::from_secs(10),
20172028
..Default::default()
@@ -2050,6 +2061,7 @@ mod tests {
20502061
fn restores_persisted_liquidity_bounds() {
20512062
let network_graph = network_graph();
20522063
let params = ProbabilisticScoringParameters {
2064+
base_penalty_msat: 0,
20532065
liquidity_penalty_multiplier_msat: 1_000,
20542066
liquidity_offset_half_life: Duration::from_secs(10),
20552067
..Default::default()
@@ -2080,6 +2092,7 @@ mod tests {
20802092
fn decays_persisted_liquidity_bounds() {
20812093
let network_graph = network_graph();
20822094
let params = ProbabilisticScoringParameters {
2095+
base_penalty_msat: 0,
20832096
liquidity_penalty_multiplier_msat: 1_000,
20842097
liquidity_offset_half_life: Duration::from_secs(10),
20852098
..Default::default()
@@ -2107,4 +2120,23 @@ mod tests {
21072120
SinceEpoch::advance(Duration::from_secs(10));
21082121
assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 371);
21092122
}
2123+
2124+
#[test]
2125+
fn adds_base_penalty_to_liquidity_penalty() {
2126+
let network_graph = network_graph();
2127+
let source = source_node_id();
2128+
let target = target_node_id();
2129+
2130+
let params = ProbabilisticScoringParameters {
2131+
base_penalty_msat: 0, ..Default::default()
2132+
};
2133+
let scorer = ProbabilisticScorer::new(params, &network_graph);
2134+
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 585);
2135+
2136+
let params = ProbabilisticScoringParameters {
2137+
base_penalty_msat: 500, ..Default::default()
2138+
};
2139+
let scorer = ProbabilisticScorer::new(params, &network_graph);
2140+
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 1085);
2141+
}
21102142
}

0 commit comments

Comments
 (0)