Skip to content

Commit 6e514a2

Browse files
committed
Smooth out channel liquidity bounds decay
Decaying the channel liquidity bounds by a half life can result in a large decrease, which may have an oscillating affect on whether a channel is retried. Approximate an additional three-quarter life when half of the next half life has passed to help smooth out the decay.
1 parent dba3e8f commit 6e514a2

File tree

1 file changed

+39
-5
lines changed

1 file changed

+39
-5
lines changed

lightning/src/routing/scoring.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,10 +1151,30 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
11511151
}
11521152

11531153
fn decayed_offset_msat(&self, offset_msat: u64) -> u64 {
1154-
self.now.duration_since(*self.last_updated).as_secs()
1155-
.checked_div(self.decay_params.liquidity_offset_half_life.as_secs())
1156-
.and_then(|decays| offset_msat.checked_shr(decays as u32))
1157-
.unwrap_or(0)
1154+
let elapsed_time = self.now.duration_since(*self.last_updated).as_secs();
1155+
let half_life = self.decay_params.liquidity_offset_half_life.as_secs();
1156+
1157+
match elapsed_time.checked_div(half_life) {
1158+
None => 0,
1159+
Some(decays) => match elapsed_time.checked_div(half_life / 2) {
1160+
None => 0,
1161+
Some(half_decays) => {
1162+
// Decay the offset by the appropriate number of half lives. If half of the next
1163+
// half life has passed, approximate an additional three-quarter life by summing
1164+
// the results of taking both the *next two* half lives instead. This helps
1165+
// smooth out the decay.
1166+
if half_decays % 2 == 0 {
1167+
offset_msat.checked_shr(decays as u32).unwrap_or(0)
1168+
} else {
1169+
offset_msat
1170+
.checked_shr((decays + 1) as u32)
1171+
.map(|decayed_offset_msat| decayed_offset_msat
1172+
+ offset_msat.checked_shr((decays + 2) as u32).unwrap_or(0))
1173+
.unwrap_or(0)
1174+
}
1175+
}
1176+
},
1177+
}
11581178
}
11591179
}
11601180

@@ -2405,6 +2425,7 @@ mod tests {
24052425
scorer.payment_path_failed(&payment_path_for_amount(768), 42);
24062426
scorer.payment_path_failed(&payment_path_for_amount(128), 43);
24072427

2428+
// Initial penalties
24082429
let usage = ChannelUsage { amount_msat: 128, ..usage };
24092430
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 0);
24102431
let usage = ChannelUsage { amount_msat: 256, ..usage };
@@ -2414,7 +2435,8 @@ mod tests {
24142435
let usage = ChannelUsage { amount_msat: 896, ..usage };
24152436
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), u64::max_value());
24162437

2417-
SinceEpoch::advance(Duration::from_secs(9));
2438+
// No decay
2439+
SinceEpoch::advance(Duration::from_secs(4));
24182440
let usage = ChannelUsage { amount_msat: 128, ..usage };
24192441
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 0);
24202442
let usage = ChannelUsage { amount_msat: 256, ..usage };
@@ -2424,7 +2446,19 @@ mod tests {
24242446
let usage = ChannelUsage { amount_msat: 896, ..usage };
24252447
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), u64::max_value());
24262448

2449+
// Half decay (i.e., three-quarter life)
24272450
SinceEpoch::advance(Duration::from_secs(1));
2451+
let usage = ChannelUsage { amount_msat: 128, ..usage };
2452+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 18);
2453+
let usage = ChannelUsage { amount_msat: 256, ..usage };
2454+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 103);
2455+
let usage = ChannelUsage { amount_msat: 768, ..usage };
2456+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 957);
2457+
let usage = ChannelUsage { amount_msat: 896, ..usage };
2458+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), u64::max_value());
2459+
2460+
// One decay (i.e., half life)
2461+
SinceEpoch::advance(Duration::from_secs(5));
24282462
let usage = ChannelUsage { amount_msat: 64, ..usage };
24292463
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 0);
24302464
let usage = ChannelUsage { amount_msat: 128, ..usage };

0 commit comments

Comments
 (0)