mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 23:08:36 +01:00
Fix shift overflow in Scorer::channel_penalty_msat
An unchecked shift of more than 64 bits on u64 values causes a shift overflow panic. This may happen if a channel is penalized only once and (1) is not successfully routed through and (2) after 64 or more half life decays. Use a checked shift to prevent this from happening.
This commit is contained in:
parent
d28d6a5403
commit
857b4c08a5
1 changed files with 29 additions and 5 deletions
|
@ -334,11 +334,10 @@ impl<T: Time> ChannelFailure<T> {
|
|||
}
|
||||
|
||||
fn decayed_penalty_msat(&self, half_life: Duration) -> u64 {
|
||||
let decays = self.last_updated.elapsed().as_secs().checked_div(half_life.as_secs());
|
||||
match decays {
|
||||
Some(decays) => self.undecayed_penalty_msat >> decays,
|
||||
None => 0,
|
||||
}
|
||||
self.last_updated.elapsed().as_secs()
|
||||
.checked_div(half_life.as_secs())
|
||||
.and_then(|decays| self.undecayed_penalty_msat.checked_shr(decays as u32))
|
||||
.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,6 +675,31 @@ mod tests {
|
|||
assert_eq!(scorer.channel_penalty_msat(42, 1, Some(1), &source, &target), 1_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decays_channel_failure_penalties_without_shift_overflow() {
|
||||
let mut scorer = Scorer::new(ScoringParameters {
|
||||
base_penalty_msat: 1_000,
|
||||
failure_penalty_msat: 512,
|
||||
failure_penalty_half_life: Duration::from_secs(10),
|
||||
overuse_penalty_start_1024th: 1024,
|
||||
overuse_penalty_msat_per_1024th: 0,
|
||||
});
|
||||
let source = source_node_id();
|
||||
let target = target_node_id();
|
||||
assert_eq!(scorer.channel_penalty_msat(42, 1, Some(1), &source, &target), 1_000);
|
||||
|
||||
scorer.payment_path_failed(&[], 42);
|
||||
assert_eq!(scorer.channel_penalty_msat(42, 1, Some(1), &source, &target), 1_512);
|
||||
|
||||
// An unchecked right shift 64 bits or more in ChannelFailure::decayed_penalty_msat would
|
||||
// cause an overflow.
|
||||
SinceEpoch::advance(Duration::from_secs(10 * 64));
|
||||
assert_eq!(scorer.channel_penalty_msat(42, 1, Some(1), &source, &target), 1_000);
|
||||
|
||||
SinceEpoch::advance(Duration::from_secs(10));
|
||||
assert_eq!(scorer.channel_penalty_msat(42, 1, Some(1), &source, &target), 1_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accumulates_channel_failure_penalties_after_decay() {
|
||||
let mut scorer = Scorer::new(ScoringParameters {
|
||||
|
|
Loading…
Add table
Reference in a new issue