Skip to content

Commit bc8a318

Browse files
committed
Add probing_diversity_penalty_msat to the scorer parameters
When doing background probing, its important to get a diverse view of the network graph to ensure you have as many options when pathfinding as possible. Sadly, the naive probing we currently recommend users do does not accomplish that - using the same success-optimized pathfinder when sending as when probing results in always testing the same (good) path over and over and over again. Instead, here, we add a `probing_diversity_penalty_msat` parameter to the scorer, allowing us to penalize channels for which we already have recent data. It applies a penalty which scales with the square of the inverse time since the channel was last updated, up to one day.
1 parent 2d6720e commit bc8a318

File tree

1 file changed

+41
-3
lines changed

1 file changed

+41
-3
lines changed

lightning/src/routing/scoring.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,9 @@ where L::Target: Logger {
475475
network_graph: G,
476476
logger: L,
477477
channel_liquidities: HashMap<u64, ChannelLiquidity>,
478+
/// The last time we were given via a [`ScoreUpdate`] method. This does not imply that we've
479+
/// decayed every liquidity bound up to that time.
480+
last_duration_since_epoch: Duration,
478481
}
479482

480483
/// Parameters for configuring [`ProbabilisticScorer`].
@@ -637,6 +640,22 @@ pub struct ProbabilisticScoringFeeParameters {
637640
///
638641
/// Default value: false
639642
pub linear_success_probability: bool,
643+
644+
/// In order to ensure we have knowledge for as many paths as possible, when probing it makes
645+
/// sense to bias away from channels for which we have very recent data.
646+
///
647+
/// This value is a penalty that is applied based on the last time that we updated the bounds
648+
/// on the available liquidity in a channel. The specified value is the maximum penalty that
649+
/// will be applied.
650+
///
651+
/// It obviously does not make sense to assign a non-0 value here unless you are using the
652+
/// pathfinding result for background probing.
653+
///
654+
/// Specifically, the following penalty is applied
655+
/// `probing_diversity_penalty_msat * max(0, (86400 - current time + last update))^2 / 86400^2` is
656+
///
657+
/// Default value: 0
658+
pub probing_diversity_penalty_msat: u64,
640659
}
641660

642661
impl Default for ProbabilisticScoringFeeParameters {
@@ -652,6 +671,7 @@ impl Default for ProbabilisticScoringFeeParameters {
652671
historical_liquidity_penalty_multiplier_msat: 10_000,
653672
historical_liquidity_penalty_amount_multiplier_msat: 64,
654673
linear_success_probability: false,
674+
probing_diversity_penalty_msat: 0,
655675
}
656676
}
657677
}
@@ -706,6 +726,7 @@ impl ProbabilisticScoringFeeParameters {
706726
anti_probing_penalty_msat: 0,
707727
considered_impossible_penalty_msat: 0,
708728
linear_success_probability: true,
729+
probing_diversity_penalty_msat: 0,
709730
}
710731
}
711732
}
@@ -823,6 +844,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
823844
network_graph,
824845
logger,
825846
channel_liquidities: new_hash_map(),
847+
last_duration_since_epoch: Duration::from_secs(0),
826848
}
827849
}
828850

@@ -1141,7 +1163,7 @@ DirectedChannelLiquidity< L, HT, T> {
11411163
/// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
11421164
/// this direction.
11431165
fn penalty_msat(
1144-
&self, amount_msat: u64, inflight_htlc_msat: u64,
1166+
&self, amount_msat: u64, inflight_htlc_msat: u64, last_duration_since_epoch: Duration,
11451167
score_params: &ProbabilisticScoringFeeParameters,
11461168
) -> u64 {
11471169
let total_inflight_amount_msat = amount_msat.saturating_add(inflight_htlc_msat);
@@ -1216,6 +1238,13 @@ DirectedChannelLiquidity< L, HT, T> {
12161238
}
12171239
}
12181240

1241+
if score_params.probing_diversity_penalty_msat != 0 {
1242+
let time_since_update = last_duration_since_epoch.saturating_sub(*self.last_updated);
1243+
let mul = Duration::from_secs(60 * 60 * 24).saturating_sub(time_since_update).as_secs();
1244+
let penalty = score_params.probing_diversity_penalty_msat.saturating_mul(mul * mul);
1245+
res = res.saturating_add(penalty / ((60 * 60 * 24) * (60 * 60 * 24)));
1246+
}
1247+
12191248
res
12201249
}
12211250

@@ -1365,11 +1394,12 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreLookUp for Probabilistic
13651394
}
13661395

13671396
let capacity_msat = usage.effective_capacity.as_msat();
1397+
let time = self.last_duration_since_epoch;
13681398
self.channel_liquidities
13691399
.get(scid)
13701400
.unwrap_or(&ChannelLiquidity::new(Duration::ZERO))
13711401
.as_directed(&source, &target, capacity_msat)
1372-
.penalty_msat(usage.amount_msat, usage.inflight_htlc_msat, score_params)
1402+
.penalty_msat(usage.amount_msat, usage.inflight_htlc_msat, time, score_params)
13731403
.saturating_add(anti_probing_penalty_msat)
13741404
.saturating_add(base_penalty_msat)
13751405
}
@@ -1415,6 +1445,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreUpdate for Probabilistic
14151445
}
14161446
if at_failed_channel { break; }
14171447
}
1448+
self.last_duration_since_epoch = duration_since_epoch;
14181449
}
14191450

14201451
fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration) {
@@ -1442,6 +1473,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreUpdate for Probabilistic
14421473
hop.short_channel_id);
14431474
}
14441475
}
1476+
self.last_duration_since_epoch = duration_since_epoch;
14451477
}
14461478

14471479
fn probe_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) {
@@ -1473,6 +1505,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreUpdate for Probabilistic
14731505
liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 ||
14741506
liquidity.liquidity_history.has_datapoints()
14751507
});
1508+
self.last_duration_since_epoch = duration_since_epoch;
14761509
}
14771510
}
14781511

@@ -1906,15 +1939,20 @@ ReadableArgs<(ProbabilisticScoringDecayParameters, G, L)> for ProbabilisticScore
19061939
r: &mut R, args: (ProbabilisticScoringDecayParameters, G, L)
19071940
) -> Result<Self, DecodeError> {
19081941
let (decay_params, network_graph, logger) = args;
1909-
let mut channel_liquidities = new_hash_map();
1942+
let mut channel_liquidities: HashMap<u64, ChannelLiquidity> = new_hash_map();
19101943
read_tlv_fields!(r, {
19111944
(0, channel_liquidities, required),
19121945
});
1946+
let mut last_duration_since_epoch = Duration::from_secs(0);
1947+
for (_, liq) in channel_liquidities.iter() {
1948+
last_duration_since_epoch = cmp::max(last_duration_since_epoch, liq.last_updated);
1949+
}
19131950
Ok(Self {
19141951
decay_params,
19151952
network_graph,
19161953
logger,
19171954
channel_liquidities,
1955+
last_duration_since_epoch,
19181956
})
19191957
}
19201958
}

0 commit comments

Comments
 (0)