Skip to content

Commit c9e1453

Browse files
committed
Track a reference to scoring parameters in DirectedChannelLiquidity
This simplifies adding additional half lives in DirectedChannelLiquidity by simply storing a reference to the full parameter set rather than only the single current half-life.
1 parent d59d02e commit c9e1453

File tree

1 file changed

+45
-51
lines changed

1 file changed

+45
-51
lines changed

lightning/src/routing/scoring.rs

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -534,15 +534,15 @@ struct ChannelLiquidity<T: Time> {
534534

535535
/// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity and
536536
/// decayed with a given half life.
537-
struct DirectedChannelLiquidity<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>, T: Time, U: Deref<Target = T>> {
537+
struct DirectedChannelLiquidity<'a, L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>, T: Time, U: Deref<Target = T>> {
538538
min_liquidity_offset_msat: L,
539539
max_liquidity_offset_msat: L,
540540
min_liquidity_offset_history: BRT,
541541
max_liquidity_offset_history: BRT,
542542
capacity_msat: u64,
543543
last_updated: U,
544544
now: T,
545-
half_life: Duration,
545+
params: &'a ProbabilisticScoringParameters,
546546
}
547547

548548
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerUsingTime<G, L, T> where L::Target: Logger {
@@ -574,7 +574,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
574574
let log_direction = |source, target| {
575575
if let Some((directed_info, _)) = chan_debug.as_directed_to(target) {
576576
let amt = directed_info.effective_capacity().as_msat();
577-
let dir_liq = liq.as_directed(source, target, amt, self.params.liquidity_offset_half_life);
577+
let dir_liq = liq.as_directed(source, target, amt, &self.params);
578578
log_debug!(self.logger, "Liquidity from {:?} to {:?} via {} is in the range ({}, {})",
579579
source, target, scid, dir_liq.min_liquidity_msat(), dir_liq.max_liquidity_msat());
580580
} else {
@@ -599,7 +599,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
599599
if let Some(liq) = self.channel_liquidities.get(&scid) {
600600
if let Some((directed_info, source)) = chan.as_directed_to(target) {
601601
let amt = directed_info.effective_capacity().as_msat();
602-
let dir_liq = liq.as_directed(source, target, amt, self.params.liquidity_offset_half_life);
602+
let dir_liq = liq.as_directed(source, target, amt, &self.params);
603603
return Some((dir_liq.min_liquidity_msat(), dir_liq.max_liquidity_msat()));
604604
}
605605
}
@@ -691,9 +691,9 @@ impl<T: Time> ChannelLiquidity<T> {
691691

692692
/// Returns a view of the channel liquidity directed from `source` to `target` assuming
693693
/// `capacity_msat`.
694-
fn as_directed(
695-
&self, source: &NodeId, target: &NodeId, capacity_msat: u64, half_life: Duration
696-
) -> DirectedChannelLiquidity<&u64, &HistoricalBucketRangeTracker, T, &T> {
694+
fn as_directed<'a>(
695+
&self, source: &NodeId, target: &NodeId, capacity_msat: u64, params: &'a ProbabilisticScoringParameters
696+
) -> DirectedChannelLiquidity<'a, &u64, &HistoricalBucketRangeTracker, T, &T> {
697697
let (min_liquidity_offset_msat, max_liquidity_offset_msat, min_liquidity_offset_history, max_liquidity_offset_history) =
698698
if source < target {
699699
(&self.min_liquidity_offset_msat, &self.max_liquidity_offset_msat,
@@ -711,15 +711,15 @@ impl<T: Time> ChannelLiquidity<T> {
711711
capacity_msat,
712712
last_updated: &self.last_updated,
713713
now: T::now(),
714-
half_life,
714+
params,
715715
}
716716
}
717717

718718
/// Returns a mutable view of the channel liquidity directed from `source` to `target` assuming
719719
/// `capacity_msat`.
720-
fn as_directed_mut(
721-
&mut self, source: &NodeId, target: &NodeId, capacity_msat: u64, half_life: Duration
722-
) -> DirectedChannelLiquidity<&mut u64, &mut HistoricalBucketRangeTracker, T, &mut T> {
720+
fn as_directed_mut<'a>(
721+
&mut self, source: &NodeId, target: &NodeId, capacity_msat: u64, params: &'a ProbabilisticScoringParameters
722+
) -> DirectedChannelLiquidity<'a, &mut u64, &mut HistoricalBucketRangeTracker, T, &mut T> {
723723
let (min_liquidity_offset_msat, max_liquidity_offset_msat, min_liquidity_offset_history, max_liquidity_offset_history) =
724724
if source < target {
725725
(&mut self.min_liquidity_offset_msat, &mut self.max_liquidity_offset_msat,
@@ -737,7 +737,7 @@ impl<T: Time> ChannelLiquidity<T> {
737737
capacity_msat,
738738
last_updated: &mut self.last_updated,
739739
now: T::now(),
740-
half_life,
740+
params,
741741
}
742742
}
743743
}
@@ -754,7 +754,7 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
754754
const AMOUNT_PENALTY_DIVISOR: u64 = 1 << 20;
755755
const BASE_AMOUNT_PENALTY_DIVISOR: u64 = 1 << 30;
756756

757-
impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>, T: Time, U: Deref<Target = T>> DirectedChannelLiquidity<L, BRT, T, U> {
757+
impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>, T: Time, U: Deref<Target = T>> DirectedChannelLiquidity<'_, L, BRT, T, U> {
758758
/// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
759759
/// this direction.
760760
fn penalty_msat(&self, amount_msat: u64, params: &ProbabilisticScoringParameters) -> u64 {
@@ -890,13 +890,13 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
890890

891891
fn decayed_offset_msat(&self, offset_msat: u64) -> u64 {
892892
self.now.duration_since(*self.last_updated).as_secs()
893-
.checked_div(self.half_life.as_secs())
893+
.checked_div(self.params.liquidity_offset_half_life.as_secs())
894894
.and_then(|decays| offset_msat.checked_shr(decays as u32))
895895
.unwrap_or(0)
896896
}
897897
}
898898

899-
impl<L: DerefMut<Target = u64>, BRT: DerefMut<Target = HistoricalBucketRangeTracker>, T: Time, U: DerefMut<Target = T>> DirectedChannelLiquidity<L, BRT, T, U> {
899+
impl<L: DerefMut<Target = u64>, BRT: DerefMut<Target = HistoricalBucketRangeTracker>, T: Time, U: DerefMut<Target = T>> DirectedChannelLiquidity<'_, L, BRT, T, U> {
900900
/// Adjusts the channel liquidity balance bounds when failing to route `amount_msat`.
901901
fn failed_at_channel<Log: Deref>(&mut self, amount_msat: u64, chan_descr: fmt::Arguments, logger: &Log) where Log::Target: Logger {
902902
if amount_msat < self.max_liquidity_msat() {
@@ -989,22 +989,20 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
989989
_ => {},
990990
}
991991

992-
let liquidity_offset_half_life = self.params.liquidity_offset_half_life;
993992
let amount_msat = usage.amount_msat;
994993
let capacity_msat = usage.effective_capacity.as_msat()
995994
.saturating_sub(usage.inflight_htlc_msat);
996995
self.channel_liquidities
997996
.get(&short_channel_id)
998997
.unwrap_or(&ChannelLiquidity::new())
999-
.as_directed(source, target, capacity_msat, liquidity_offset_half_life)
998+
.as_directed(source, target, capacity_msat, &self.params)
1000999
.penalty_msat(amount_msat, &self.params)
10011000
.saturating_add(anti_probing_penalty_msat)
10021001
.saturating_add(base_penalty_msat)
10031002
}
10041003

10051004
fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
10061005
let amount_msat = path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0);
1007-
let liquidity_offset_half_life = self.params.liquidity_offset_half_life;
10081006
log_trace!(self.logger, "Scoring path through to SCID {} as having failed at {} msat", short_channel_id, amount_msat);
10091007
let network_graph = self.network_graph.read_only();
10101008
for (hop_idx, hop) in path.iter().enumerate() {
@@ -1024,15 +1022,15 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
10241022
self.channel_liquidities
10251023
.entry(hop.short_channel_id)
10261024
.or_insert_with(ChannelLiquidity::new)
1027-
.as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life)
1025+
.as_directed_mut(source, &target, capacity_msat, &self.params)
10281026
.failed_at_channel(amount_msat, format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger);
10291027
break;
10301028
}
10311029

10321030
self.channel_liquidities
10331031
.entry(hop.short_channel_id)
10341032
.or_insert_with(ChannelLiquidity::new)
1035-
.as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life)
1033+
.as_directed_mut(source, &target, capacity_msat, &self.params)
10361034
.failed_downstream(amount_msat, format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger);
10371035
} else {
10381036
log_debug!(self.logger, "Not able to penalize channel with SCID {} as we do not have graph info for it (likely a route-hint last-hop).",
@@ -1043,7 +1041,6 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
10431041

10441042
fn payment_path_successful(&mut self, path: &[&RouteHop]) {
10451043
let amount_msat = path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0);
1046-
let liquidity_offset_half_life = self.params.liquidity_offset_half_life;
10471044
log_trace!(self.logger, "Scoring path through SCID {} as having succeeded at {} msat.",
10481045
path.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), amount_msat);
10491046
let network_graph = self.network_graph.read_only();
@@ -1059,7 +1056,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
10591056
self.channel_liquidities
10601057
.entry(hop.short_channel_id)
10611058
.or_insert_with(ChannelLiquidity::new)
1062-
.as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life)
1059+
.as_directed_mut(source, &target, capacity_msat, &self.params)
10631060
.successful(amount_msat, format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger);
10641061
} else {
10651062
log_debug!(self.logger, "Not able to learn for channel with SCID {} as we do not have graph info for it (likely a route-hint last-hop).",
@@ -1672,54 +1669,53 @@ mod tests {
16721669

16731670
// Update minimum liquidity.
16741671

1675-
let liquidity_offset_half_life = scorer.params.liquidity_offset_half_life;
16761672
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1677-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1673+
.as_directed(&source, &target, 1_000, &scorer.params);
16781674
assert_eq!(liquidity.min_liquidity_msat(), 100);
16791675
assert_eq!(liquidity.max_liquidity_msat(), 300);
16801676

16811677
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1682-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1678+
.as_directed(&target, &source, 1_000, &scorer.params);
16831679
assert_eq!(liquidity.min_liquidity_msat(), 700);
16841680
assert_eq!(liquidity.max_liquidity_msat(), 900);
16851681

16861682
scorer.channel_liquidities.get_mut(&42).unwrap()
1687-
.as_directed_mut(&source, &target, 1_000, liquidity_offset_half_life)
1683+
.as_directed_mut(&source, &target, 1_000, &scorer.params)
16881684
.set_min_liquidity_msat(200);
16891685

16901686
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1691-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1687+
.as_directed(&source, &target, 1_000, &scorer.params);
16921688
assert_eq!(liquidity.min_liquidity_msat(), 200);
16931689
assert_eq!(liquidity.max_liquidity_msat(), 300);
16941690

16951691
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1696-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1692+
.as_directed(&target, &source, 1_000, &scorer.params);
16971693
assert_eq!(liquidity.min_liquidity_msat(), 700);
16981694
assert_eq!(liquidity.max_liquidity_msat(), 800);
16991695

17001696
// Update maximum liquidity.
17011697

17021698
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1703-
.as_directed(&target, &recipient, 1_000, liquidity_offset_half_life);
1699+
.as_directed(&target, &recipient, 1_000, &scorer.params);
17041700
assert_eq!(liquidity.min_liquidity_msat(), 700);
17051701
assert_eq!(liquidity.max_liquidity_msat(), 900);
17061702

17071703
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1708-
.as_directed(&recipient, &target, 1_000, liquidity_offset_half_life);
1704+
.as_directed(&recipient, &target, 1_000, &scorer.params);
17091705
assert_eq!(liquidity.min_liquidity_msat(), 100);
17101706
assert_eq!(liquidity.max_liquidity_msat(), 300);
17111707

17121708
scorer.channel_liquidities.get_mut(&43).unwrap()
1713-
.as_directed_mut(&target, &recipient, 1_000, liquidity_offset_half_life)
1709+
.as_directed_mut(&target, &recipient, 1_000, &scorer.params)
17141710
.set_max_liquidity_msat(200);
17151711

17161712
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1717-
.as_directed(&target, &recipient, 1_000, liquidity_offset_half_life);
1713+
.as_directed(&target, &recipient, 1_000, &scorer.params);
17181714
assert_eq!(liquidity.min_liquidity_msat(), 0);
17191715
assert_eq!(liquidity.max_liquidity_msat(), 200);
17201716

17211717
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1722-
.as_directed(&recipient, &target, 1_000, liquidity_offset_half_life);
1718+
.as_directed(&recipient, &target, 1_000, &scorer.params);
17231719
assert_eq!(liquidity.min_liquidity_msat(), 800);
17241720
assert_eq!(liquidity.max_liquidity_msat(), 1000);
17251721
}
@@ -1742,44 +1738,43 @@ mod tests {
17421738
assert!(source > target);
17431739

17441740
// Check initial bounds.
1745-
let liquidity_offset_half_life = scorer.params.liquidity_offset_half_life;
17461741
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1747-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1742+
.as_directed(&source, &target, 1_000, &scorer.params);
17481743
assert_eq!(liquidity.min_liquidity_msat(), 400);
17491744
assert_eq!(liquidity.max_liquidity_msat(), 800);
17501745

17511746
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1752-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1747+
.as_directed(&target, &source, 1_000, &scorer.params);
17531748
assert_eq!(liquidity.min_liquidity_msat(), 200);
17541749
assert_eq!(liquidity.max_liquidity_msat(), 600);
17551750

17561751
// Reset from source to target.
17571752
scorer.channel_liquidities.get_mut(&42).unwrap()
1758-
.as_directed_mut(&source, &target, 1_000, liquidity_offset_half_life)
1753+
.as_directed_mut(&source, &target, 1_000, &scorer.params)
17591754
.set_min_liquidity_msat(900);
17601755

17611756
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1762-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1757+
.as_directed(&source, &target, 1_000, &scorer.params);
17631758
assert_eq!(liquidity.min_liquidity_msat(), 900);
17641759
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
17651760

17661761
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1767-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1762+
.as_directed(&target, &source, 1_000, &scorer.params);
17681763
assert_eq!(liquidity.min_liquidity_msat(), 0);
17691764
assert_eq!(liquidity.max_liquidity_msat(), 100);
17701765

17711766
// Reset from target to source.
17721767
scorer.channel_liquidities.get_mut(&42).unwrap()
1773-
.as_directed_mut(&target, &source, 1_000, liquidity_offset_half_life)
1768+
.as_directed_mut(&target, &source, 1_000, &scorer.params)
17741769
.set_min_liquidity_msat(400);
17751770

17761771
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1777-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1772+
.as_directed(&source, &target, 1_000, &scorer.params);
17781773
assert_eq!(liquidity.min_liquidity_msat(), 0);
17791774
assert_eq!(liquidity.max_liquidity_msat(), 600);
17801775

17811776
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1782-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1777+
.as_directed(&target, &source, 1_000, &scorer.params);
17831778
assert_eq!(liquidity.min_liquidity_msat(), 400);
17841779
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
17851780
}
@@ -1802,44 +1797,43 @@ mod tests {
18021797
assert!(source > target);
18031798

18041799
// Check initial bounds.
1805-
let liquidity_offset_half_life = scorer.params.liquidity_offset_half_life;
18061800
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1807-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1801+
.as_directed(&source, &target, 1_000, &scorer.params);
18081802
assert_eq!(liquidity.min_liquidity_msat(), 400);
18091803
assert_eq!(liquidity.max_liquidity_msat(), 800);
18101804

18111805
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1812-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1806+
.as_directed(&target, &source, 1_000, &scorer.params);
18131807
assert_eq!(liquidity.min_liquidity_msat(), 200);
18141808
assert_eq!(liquidity.max_liquidity_msat(), 600);
18151809

18161810
// Reset from source to target.
18171811
scorer.channel_liquidities.get_mut(&42).unwrap()
1818-
.as_directed_mut(&source, &target, 1_000, liquidity_offset_half_life)
1812+
.as_directed_mut(&source, &target, 1_000, &scorer.params)
18191813
.set_max_liquidity_msat(300);
18201814

18211815
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1822-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1816+
.as_directed(&source, &target, 1_000, &scorer.params);
18231817
assert_eq!(liquidity.min_liquidity_msat(), 0);
18241818
assert_eq!(liquidity.max_liquidity_msat(), 300);
18251819

18261820
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1827-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1821+
.as_directed(&target, &source, 1_000, &scorer.params);
18281822
assert_eq!(liquidity.min_liquidity_msat(), 700);
18291823
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
18301824

18311825
// Reset from target to source.
18321826
scorer.channel_liquidities.get_mut(&42).unwrap()
1833-
.as_directed_mut(&target, &source, 1_000, liquidity_offset_half_life)
1827+
.as_directed_mut(&target, &source, 1_000, &scorer.params)
18341828
.set_max_liquidity_msat(600);
18351829

18361830
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1837-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1831+
.as_directed(&source, &target, 1_000, &scorer.params);
18381832
assert_eq!(liquidity.min_liquidity_msat(), 400);
18391833
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
18401834

18411835
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1842-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1836+
.as_directed(&target, &source, 1_000, &scorer.params);
18431837
assert_eq!(liquidity.min_liquidity_msat(), 0);
18441838
assert_eq!(liquidity.max_liquidity_msat(), 600);
18451839
}

0 commit comments

Comments
 (0)