X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Fscoring.rs;fp=lightning%2Fsrc%2Frouting%2Fscoring.rs;h=4ff6d9e69d54e7a47d3eb1cb328f1648a73e441c;hb=bdbe9c8925644d7891fadf5d31480df1be9d58d7;hp=d83adaf97f6603e321743a96f277e2bea6a10fac;hpb=dba3e8f2d975620f2edb1f6dc67f491d6a3cec6a;p=rust-lightning diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index d83adaf9..4ff6d9e6 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -1151,10 +1151,25 @@ impl, BRT: Deref, } fn decayed_offset_msat(&self, offset_msat: u64) -> u64 { - self.now.duration_since(*self.last_updated).as_secs() - .checked_div(self.decay_params.liquidity_offset_half_life.as_secs()) - .and_then(|decays| offset_msat.checked_shr(decays as u32)) - .unwrap_or(0) + let half_life = self.decay_params.liquidity_offset_half_life.as_secs(); + if half_life != 0 { + // Decay the offset by the appropriate number of half lives. If half of the next half + // life has passed, approximate an additional three-quarter life to help smooth out the + // decay. + let elapsed_time = self.now.duration_since(*self.last_updated).as_secs(); + let half_decays = elapsed_time / (half_life / 2); + let decays = half_decays / 2; + let decayed_offset_msat = offset_msat.checked_shr(decays as u32).unwrap_or(0); + if half_decays % 2 == 0 { + decayed_offset_msat + } else { + // 11_585 / 16_384 ~= core::f64::consts::FRAC_1_SQRT_2 + // 16_384 == 2^14 + (decayed_offset_msat as u128 * 11_585 / 16_384) as u64 + } + } else { + 0 + } } } @@ -2405,6 +2420,7 @@ mod tests { scorer.payment_path_failed(&payment_path_for_amount(768), 42); scorer.payment_path_failed(&payment_path_for_amount(128), 43); + // Initial penalties let usage = ChannelUsage { amount_msat: 128, ..usage }; assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); let usage = ChannelUsage { amount_msat: 256, ..usage }; @@ -2414,7 +2430,8 @@ mod tests { let usage = ChannelUsage { amount_msat: 896, ..usage }; assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); - SinceEpoch::advance(Duration::from_secs(9)); + // No decay + SinceEpoch::advance(Duration::from_secs(4)); let usage = ChannelUsage { amount_msat: 128, ..usage }; assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); let usage = ChannelUsage { amount_msat: 256, ..usage }; @@ -2424,7 +2441,19 @@ mod tests { let usage = ChannelUsage { amount_msat: 896, ..usage }; assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + // Half decay (i.e., three-quarter life) SinceEpoch::advance(Duration::from_secs(1)); + let usage = ChannelUsage { amount_msat: 128, ..usage }; + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 22); + let usage = ChannelUsage { amount_msat: 256, ..usage }; + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 106); + let usage = ChannelUsage { amount_msat: 768, ..usage }; + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 916); + let usage = ChannelUsage { amount_msat: 896, ..usage }; + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + + // One decay (i.e., half life) + SinceEpoch::advance(Duration::from_secs(5)); let usage = ChannelUsage { amount_msat: 64, ..usage }; assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); let usage = ChannelUsage { amount_msat: 128, ..usage };