Skip to content

Commit feaed9b

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 d6321e6 commit feaed9b

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
@@ -997,10 +997,30 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
997997
}
998998

999999
fn decayed_offset_msat(&self, offset_msat: u64) -> u64 {
1000-
self.now.duration_since(*self.last_updated).as_secs()
1001-
.checked_div(self.params.liquidity_offset_half_life.as_secs())
1002-
.and_then(|decays| offset_msat.checked_shr(decays as u32))
1003-
.unwrap_or(0)
1000+
let elapsed_time = self.now.duration_since(*self.last_updated).as_secs();
1001+
let half_life = self.params.liquidity_offset_half_life.as_secs();
1002+
1003+
match elapsed_time.checked_div(half_life) {
1004+
None => 0,
1005+
Some(decays) => match elapsed_time.checked_div(half_life / 2) {
1006+
None => 0,
1007+
Some(half_decays) => {
1008+
// Decay the offset by the appropriate number of half lives. If half of the next
1009+
// half life has passed, approximate an additional three-quarter life by summing
1010+
// the results of taking both the *next two* half lives instead. This helps
1011+
// smooth out the decay.
1012+
if half_decays % 2 == 0 {
1013+
offset_msat.checked_shr(decays as u32).unwrap_or(0)
1014+
} else {
1015+
offset_msat
1016+
.checked_shr((decays + 1) as u32)
1017+
.map(|decayed_offset_msat| decayed_offset_msat
1018+
+ offset_msat.checked_shr((decays + 2) as u32).unwrap_or(0))
1019+
.unwrap_or(0)
1020+
}
1021+
}
1022+
},
1023+
}
10041024
}
10051025
}
10061026

@@ -2192,6 +2212,7 @@ mod tests {
21922212
scorer.payment_path_failed(&payment_path_for_amount(768).iter().collect::<Vec<_>>(), 42);
21932213
scorer.payment_path_failed(&payment_path_for_amount(128).iter().collect::<Vec<_>>(), 43);
21942214

2215+
// Initial penalties
21952216
let usage = ChannelUsage { amount_msat: 128, ..usage };
21962217
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), 0);
21972218
let usage = ChannelUsage { amount_msat: 256, ..usage };
@@ -2201,7 +2222,8 @@ mod tests {
22012222
let usage = ChannelUsage { amount_msat: 896, ..usage };
22022223
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), u64::max_value());
22032224

2204-
SinceEpoch::advance(Duration::from_secs(9));
2225+
// No decay
2226+
SinceEpoch::advance(Duration::from_secs(4));
22052227
let usage = ChannelUsage { amount_msat: 128, ..usage };
22062228
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), 0);
22072229
let usage = ChannelUsage { amount_msat: 256, ..usage };
@@ -2211,7 +2233,19 @@ mod tests {
22112233
let usage = ChannelUsage { amount_msat: 896, ..usage };
22122234
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), u64::max_value());
22132235

2236+
// Half decay (i.e., three-quarter life)
22142237
SinceEpoch::advance(Duration::from_secs(1));
2238+
let usage = ChannelUsage { amount_msat: 128, ..usage };
2239+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), 18);
2240+
let usage = ChannelUsage { amount_msat: 256, ..usage };
2241+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), 103);
2242+
let usage = ChannelUsage { amount_msat: 768, ..usage };
2243+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), 957);
2244+
let usage = ChannelUsage { amount_msat: 896, ..usage };
2245+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), u64::max_value());
2246+
2247+
// One decay (i.e., half life)
2248+
SinceEpoch::advance(Duration::from_secs(5));
22152249
let usage = ChannelUsage { amount_msat: 64, ..usage };
22162250
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage), 0);
22172251
let usage = ChannelUsage { amount_msat: 128, ..usage };

0 commit comments

Comments
 (0)