- #[test]
- fn penalizes_without_channel_failures() {
- let scorer = Scorer::new(ScoringParameters {
- base_penalty_msat: 1_000,
- failure_penalty_msat: 512,
- failure_penalty_half_life: Duration::from_secs(1),
- 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, 1, &source, &target), 1_000);
-
- SinceEpoch::advance(Duration::from_secs(1));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000);
- }
-
- #[test]
- fn accumulates_channel_failure_penalties() {
- let mut scorer = Scorer::new(ScoringParameters {
- base_penalty_msat: 1_000,
- failure_penalty_msat: 64,
- 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, 1, &source, &target), 1_000);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_064);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_128);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_192);
- }
-
- #[test]
- fn decays_channel_failure_penalties_over_time() {
- 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, 1, &source, &target), 1_000);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512);
-
- SinceEpoch::advance(Duration::from_secs(9));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512);
-
- SinceEpoch::advance(Duration::from_secs(1));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256);
-
- SinceEpoch::advance(Duration::from_secs(10 * 8));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_001);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 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, 1, &source, &target), 1_000);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 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, 1, &source, &target), 1_000);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000);
- }
-
- #[test]
- fn accumulates_channel_failure_penalties_after_decay() {
- 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, 1, &source, &target), 1_000);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_768);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_384);
- }
-
- #[test]
- fn reduces_channel_failure_penalties_after_success() {
- 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, 1, &source, &target), 1_000);
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256);
-
- let hop = RouteHop {
- pubkey: PublicKey::from_slice(target.as_slice()).unwrap(),
- node_features: NodeFeatures::known(),
- short_channel_id: 42,
- channel_features: ChannelFeatures::known(),
- fee_msat: 1,
- cltv_expiry_delta: 18,
- };
- scorer.payment_path_successful(&[&hop]);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_128);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_064);
- }
-
- #[test]
- fn restores_persisted_channel_failure_penalties() {
- 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();
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256);
-
- scorer.payment_path_failed(&[], 43);
- assert_eq!(scorer.channel_penalty_msat(43, 1, 1, &source, &target), 1_512);
-
- let mut serialized_scorer = Vec::new();
- scorer.write(&mut serialized_scorer).unwrap();
-
- let deserialized_scorer = <Scorer>::read(&mut io::Cursor::new(&serialized_scorer)).unwrap();
- assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256);
- assert_eq!(deserialized_scorer.channel_penalty_msat(43, 1, 1, &source, &target), 1_512);
- }
-
- #[test]
- fn decays_persisted_channel_failure_penalties() {
- 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();
-
- scorer.payment_path_failed(&[], 42);
- assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512);
-
- let mut serialized_scorer = Vec::new();
- scorer.write(&mut serialized_scorer).unwrap();
-
- SinceEpoch::advance(Duration::from_secs(10));
-
- let deserialized_scorer = <Scorer>::read(&mut io::Cursor::new(&serialized_scorer)).unwrap();
- assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256);
-
- SinceEpoch::advance(Duration::from_secs(10));
- assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_128);
- }
-
- #[test]
- fn charges_per_1024th_penalty() {
- let scorer = Scorer::new(ScoringParameters {
- base_penalty_msat: 0,
- failure_penalty_msat: 0,
- failure_penalty_half_life: Duration::from_secs(0),
- overuse_penalty_start_1024th: 256,
- overuse_penalty_msat_per_1024th: 100,
- });
- let source = source_node_id();
- let target = target_node_id();
-
- assert_eq!(scorer.channel_penalty_msat(42, 1_000, 1_024_000, &source, &target), 0);
- assert_eq!(scorer.channel_penalty_msat(42, 256_999, 1_024_000, &source, &target), 0);
- assert_eq!(scorer.channel_penalty_msat(42, 257_000, 1_024_000, &source, &target), 100);
- assert_eq!(scorer.channel_penalty_msat(42, 258_000, 1_024_000, &source, &target), 200);
- assert_eq!(scorer.channel_penalty_msat(42, 512_000, 1_024_000, &source, &target), 256 * 100);
- }
-