use super::{ChannelLiquidity, HistoricalBucketRangeTracker, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters, ProbabilisticScorer};
use crate::blinded_path::{BlindedHop, BlindedPath};
use crate::util::config::UserConfig;
- use crate::util::time::tests::SinceEpoch;
use crate::ln::channelmanager;
use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, UnsignedChannelAnnouncement, UnsignedChannelUpdate};
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
// Half decay (i.e., three-quarter life)
- SinceEpoch::advance(Duration::from_secs(5));
scorer.decay_liquidity_certainty(Duration::from_secs(5));
let usage = ChannelUsage { amount_msat: 128, ..usage };
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 22);
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
// One decay (i.e., half life)
- SinceEpoch::advance(Duration::from_secs(5));
scorer.decay_liquidity_certainty(Duration::from_secs(10));
let usage = ChannelUsage { amount_msat: 64, ..usage };
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0);
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
// Fully decay liquidity lower bound.
- SinceEpoch::advance(Duration::from_secs(10 * 7));
scorer.decay_liquidity_certainty(Duration::from_secs(10 * 8));
let usage = ChannelUsage { amount_msat: 0, ..usage };
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0);
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
// Fully decay liquidity upper bound.
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(10 * 9));
let usage = ChannelUsage { amount_msat: 0, ..usage };
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0);
let usage = ChannelUsage { amount_msat: 1_024, ..usage };
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(10 * 10));
let usage = ChannelUsage { amount_msat: 0, ..usage };
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0);
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
}
- #[test]
- fn decays_liquidity_bounds_without_shift_overflow() {
- let logger = TestLogger::new();
- let network_graph = network_graph(&logger);
- let params = ProbabilisticScoringFeeParameters {
- liquidity_penalty_multiplier_msat: 1_000,
- ..ProbabilisticScoringFeeParameters::zero_penalty()
- };
- let decay_params = ProbabilisticScoringDecayParameters {
- liquidity_offset_half_life: Duration::from_secs(10),
- ..ProbabilisticScoringDecayParameters::default()
- };
- let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger);
- let source = source_node_id();
- let usage = ChannelUsage {
- amount_msat: 256,
- inflight_htlc_msat: 0,
- effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 },
- };
- let channel = network_graph.read_only().channel(42).unwrap().to_owned();
- let (info, _) = channel.as_directed_from(&source).unwrap();
- let candidate = CandidateRouteHop::PublicHop {
- info,
- short_channel_id: 42,
- };
- assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 125);
-
- scorer.payment_path_failed(&payment_path_for_amount(512), 42, Duration::ZERO);
- assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 281);
-
- // An unchecked right shift 64 bits or more in DirectedChannelLiquidity::decayed_offset_msat
- // would cause an overflow.
- SinceEpoch::advance(Duration::from_secs(10 * 64));
- scorer.decay_liquidity_certainty(Duration::from_secs(10 * 64));
- assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 125);
-
- SinceEpoch::advance(Duration::from_secs(10));
- scorer.decay_liquidity_certainty(Duration::from_secs(10 * 65));
- assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 125);
- }
-
#[test]
fn restricts_liquidity_bounds_after_decay() {
let logger = TestLogger::new();
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 281);
// Decaying knowledge gives less confidence (128, 896), meaning a higher penalty.
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(10));
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 291);
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 245);
// Further decaying affects the lower bound more than the upper bound (128, 928).
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(20));
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 280);
}
};
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(10));
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 473);
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value());
if decay_before_reload {
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(10));
}
let mut deserialized_scorer =
<ProbabilisticScorer<_, _>>::read(&mut serialized_scorer, (decay_params, &network_graph, &logger)).unwrap();
if !decay_before_reload {
- SinceEpoch::advance(Duration::from_secs(10));
scorer.decay_liquidity_certainty(Duration::from_secs(10));
deserialized_scorer.decay_liquidity_certainty(Duration::from_secs(10));
}
scorer.payment_path_failed(&payment_path_for_amount(250), 43, Duration::from_secs(10));
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300);
- SinceEpoch::advance(Duration::from_secs(10));
deserialized_scorer.decay_liquidity_certainty(Duration::from_secs(20));
assert_eq!(deserialized_scorer.channel_penalty_msat(&candidate, usage, ¶ms), 370);
}
// Advance the time forward 16 half-lives (which the docs claim will ensure all data is
// gone), and check that we're back to where we started.
- SinceEpoch::advance(Duration::from_secs(10 * 16));
scorer.decay_liquidity_certainty(Duration::from_secs(10 * 16));
{
let network_graph = network_graph.read_only();
}
// Advance to decay all liquidity offsets to zero.
- SinceEpoch::advance(Duration::from_secs(60 * 60 * 10));
scorer.decay_liquidity_certainty(Duration::from_secs(10 * (16 + 60 * 60)));
// Once even the bounds have decayed information about the channel should be removed