Skip to content

Commit ec68f13

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 6852ea9 commit ec68f13

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 {
@@ -892,13 +892,13 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
892892

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

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

998-
let liquidity_offset_half_life = self.params.liquidity_offset_half_life;
999998
let amount_msat = usage.amount_msat;
1000999
let capacity_msat = usage.effective_capacity.as_msat()
10011000
.saturating_sub(usage.inflight_htlc_msat);
10021001
self.channel_liquidities
10031002
.get(&short_channel_id)
10041003
.unwrap_or(&ChannelLiquidity::new())
1005-
.as_directed(source, target, capacity_msat, liquidity_offset_half_life)
1004+
.as_directed(source, target, capacity_msat, &self.params)
10061005
.penalty_msat(amount_msat, &self.params)
10071006
.saturating_add(anti_probing_penalty_msat)
10081007
.saturating_add(base_penalty_msat)
10091008
}
10101009

10111010
fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
10121011
let amount_msat = path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0);
1013-
let liquidity_offset_half_life = self.params.liquidity_offset_half_life;
10141012
log_trace!(self.logger, "Scoring path through to SCID {} as having failed at {} msat", short_channel_id, amount_msat);
10151013
let network_graph = self.network_graph.read_only();
10161014
for (hop_idx, hop) in path.iter().enumerate() {
@@ -1030,15 +1028,15 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
10301028
self.channel_liquidities
10311029
.entry(hop.short_channel_id)
10321030
.or_insert_with(ChannelLiquidity::new)
1033-
.as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life)
1031+
.as_directed_mut(source, &target, capacity_msat, &self.params)
10341032
.failed_at_channel(amount_msat, format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger);
10351033
break;
10361034
}
10371035

10381036
self.channel_liquidities
10391037
.entry(hop.short_channel_id)
10401038
.or_insert_with(ChannelLiquidity::new)
1041-
.as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life)
1039+
.as_directed_mut(source, &target, capacity_msat, &self.params)
10421040
.failed_downstream(amount_msat, format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger);
10431041
} else {
10441042
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).",
@@ -1049,7 +1047,6 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
10491047

10501048
fn payment_path_successful(&mut self, path: &[&RouteHop]) {
10511049
let amount_msat = path.split_last().map(|(hop, _)| hop.fee_msat).unwrap_or(0);
1052-
let liquidity_offset_half_life = self.params.liquidity_offset_half_life;
10531050
log_trace!(self.logger, "Scoring path through SCID {} as having succeeded at {} msat.",
10541051
path.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), amount_msat);
10551052
let network_graph = self.network_graph.read_only();
@@ -1065,7 +1062,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
10651062
self.channel_liquidities
10661063
.entry(hop.short_channel_id)
10671064
.or_insert_with(ChannelLiquidity::new)
1068-
.as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life)
1065+
.as_directed_mut(source, &target, capacity_msat, &self.params)
10691066
.successful(amount_msat, format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger);
10701067
} else {
10711068
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).",
@@ -1678,54 +1675,53 @@ mod tests {
16781675

16791676
// Update minimum liquidity.
16801677

1681-
let liquidity_offset_half_life = scorer.params.liquidity_offset_half_life;
16821678
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1683-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1679+
.as_directed(&source, &target, 1_000, &scorer.params);
16841680
assert_eq!(liquidity.min_liquidity_msat(), 100);
16851681
assert_eq!(liquidity.max_liquidity_msat(), 300);
16861682

16871683
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1688-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1684+
.as_directed(&target, &source, 1_000, &scorer.params);
16891685
assert_eq!(liquidity.min_liquidity_msat(), 700);
16901686
assert_eq!(liquidity.max_liquidity_msat(), 900);
16911687

16921688
scorer.channel_liquidities.get_mut(&42).unwrap()
1693-
.as_directed_mut(&source, &target, 1_000, liquidity_offset_half_life)
1689+
.as_directed_mut(&source, &target, 1_000, &scorer.params)
16941690
.set_min_liquidity_msat(200);
16951691

16961692
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1697-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1693+
.as_directed(&source, &target, 1_000, &scorer.params);
16981694
assert_eq!(liquidity.min_liquidity_msat(), 200);
16991695
assert_eq!(liquidity.max_liquidity_msat(), 300);
17001696

17011697
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1702-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1698+
.as_directed(&target, &source, 1_000, &scorer.params);
17031699
assert_eq!(liquidity.min_liquidity_msat(), 700);
17041700
assert_eq!(liquidity.max_liquidity_msat(), 800);
17051701

17061702
// Update maximum liquidity.
17071703

17081704
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1709-
.as_directed(&target, &recipient, 1_000, liquidity_offset_half_life);
1705+
.as_directed(&target, &recipient, 1_000, &scorer.params);
17101706
assert_eq!(liquidity.min_liquidity_msat(), 700);
17111707
assert_eq!(liquidity.max_liquidity_msat(), 900);
17121708

17131709
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1714-
.as_directed(&recipient, &target, 1_000, liquidity_offset_half_life);
1710+
.as_directed(&recipient, &target, 1_000, &scorer.params);
17151711
assert_eq!(liquidity.min_liquidity_msat(), 100);
17161712
assert_eq!(liquidity.max_liquidity_msat(), 300);
17171713

17181714
scorer.channel_liquidities.get_mut(&43).unwrap()
1719-
.as_directed_mut(&target, &recipient, 1_000, liquidity_offset_half_life)
1715+
.as_directed_mut(&target, &recipient, 1_000, &scorer.params)
17201716
.set_max_liquidity_msat(200);
17211717

17221718
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1723-
.as_directed(&target, &recipient, 1_000, liquidity_offset_half_life);
1719+
.as_directed(&target, &recipient, 1_000, &scorer.params);
17241720
assert_eq!(liquidity.min_liquidity_msat(), 0);
17251721
assert_eq!(liquidity.max_liquidity_msat(), 200);
17261722

17271723
let liquidity = scorer.channel_liquidities.get(&43).unwrap()
1728-
.as_directed(&recipient, &target, 1_000, liquidity_offset_half_life);
1724+
.as_directed(&recipient, &target, 1_000, &scorer.params);
17291725
assert_eq!(liquidity.min_liquidity_msat(), 800);
17301726
assert_eq!(liquidity.max_liquidity_msat(), 1000);
17311727
}
@@ -1748,44 +1744,43 @@ mod tests {
17481744
assert!(source > target);
17491745

17501746
// Check initial bounds.
1751-
let liquidity_offset_half_life = scorer.params.liquidity_offset_half_life;
17521747
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1753-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1748+
.as_directed(&source, &target, 1_000, &scorer.params);
17541749
assert_eq!(liquidity.min_liquidity_msat(), 400);
17551750
assert_eq!(liquidity.max_liquidity_msat(), 800);
17561751

17571752
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1758-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1753+
.as_directed(&target, &source, 1_000, &scorer.params);
17591754
assert_eq!(liquidity.min_liquidity_msat(), 200);
17601755
assert_eq!(liquidity.max_liquidity_msat(), 600);
17611756

17621757
// Reset from source to target.
17631758
scorer.channel_liquidities.get_mut(&42).unwrap()
1764-
.as_directed_mut(&source, &target, 1_000, liquidity_offset_half_life)
1759+
.as_directed_mut(&source, &target, 1_000, &scorer.params)
17651760
.set_min_liquidity_msat(900);
17661761

17671762
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1768-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1763+
.as_directed(&source, &target, 1_000, &scorer.params);
17691764
assert_eq!(liquidity.min_liquidity_msat(), 900);
17701765
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
17711766

17721767
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1773-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1768+
.as_directed(&target, &source, 1_000, &scorer.params);
17741769
assert_eq!(liquidity.min_liquidity_msat(), 0);
17751770
assert_eq!(liquidity.max_liquidity_msat(), 100);
17761771

17771772
// Reset from target to source.
17781773
scorer.channel_liquidities.get_mut(&42).unwrap()
1779-
.as_directed_mut(&target, &source, 1_000, liquidity_offset_half_life)
1774+
.as_directed_mut(&target, &source, 1_000, &scorer.params)
17801775
.set_min_liquidity_msat(400);
17811776

17821777
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1783-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1778+
.as_directed(&source, &target, 1_000, &scorer.params);
17841779
assert_eq!(liquidity.min_liquidity_msat(), 0);
17851780
assert_eq!(liquidity.max_liquidity_msat(), 600);
17861781

17871782
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1788-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1783+
.as_directed(&target, &source, 1_000, &scorer.params);
17891784
assert_eq!(liquidity.min_liquidity_msat(), 400);
17901785
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
17911786
}
@@ -1808,44 +1803,43 @@ mod tests {
18081803
assert!(source > target);
18091804

18101805
// Check initial bounds.
1811-
let liquidity_offset_half_life = scorer.params.liquidity_offset_half_life;
18121806
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1813-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1807+
.as_directed(&source, &target, 1_000, &scorer.params);
18141808
assert_eq!(liquidity.min_liquidity_msat(), 400);
18151809
assert_eq!(liquidity.max_liquidity_msat(), 800);
18161810

18171811
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1818-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1812+
.as_directed(&target, &source, 1_000, &scorer.params);
18191813
assert_eq!(liquidity.min_liquidity_msat(), 200);
18201814
assert_eq!(liquidity.max_liquidity_msat(), 600);
18211815

18221816
// Reset from source to target.
18231817
scorer.channel_liquidities.get_mut(&42).unwrap()
1824-
.as_directed_mut(&source, &target, 1_000, liquidity_offset_half_life)
1818+
.as_directed_mut(&source, &target, 1_000, &scorer.params)
18251819
.set_max_liquidity_msat(300);
18261820

18271821
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1828-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1822+
.as_directed(&source, &target, 1_000, &scorer.params);
18291823
assert_eq!(liquidity.min_liquidity_msat(), 0);
18301824
assert_eq!(liquidity.max_liquidity_msat(), 300);
18311825

18321826
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1833-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1827+
.as_directed(&target, &source, 1_000, &scorer.params);
18341828
assert_eq!(liquidity.min_liquidity_msat(), 700);
18351829
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
18361830

18371831
// Reset from target to source.
18381832
scorer.channel_liquidities.get_mut(&42).unwrap()
1839-
.as_directed_mut(&target, &source, 1_000, liquidity_offset_half_life)
1833+
.as_directed_mut(&target, &source, 1_000, &scorer.params)
18401834
.set_max_liquidity_msat(600);
18411835

18421836
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1843-
.as_directed(&source, &target, 1_000, liquidity_offset_half_life);
1837+
.as_directed(&source, &target, 1_000, &scorer.params);
18441838
assert_eq!(liquidity.min_liquidity_msat(), 400);
18451839
assert_eq!(liquidity.max_liquidity_msat(), 1_000);
18461840

18471841
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
1848-
.as_directed(&target, &source, 1_000, liquidity_offset_half_life);
1842+
.as_directed(&target, &source, 1_000, &scorer.params);
18491843
assert_eq!(liquidity.min_liquidity_msat(), 0);
18501844
assert_eq!(liquidity.max_liquidity_msat(), 600);
18511845
}

0 commit comments

Comments
 (0)