Skip to content

Commit 6821187

Browse files
committed
Add unit tests for Scorer
Test basic and channel failure penalties, including after a (de-)serialization round trip.
1 parent 00789ab commit 6821187

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

lightning/src/routing/scorer.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,13 @@ mod tests {
328328

329329
use routing::Score;
330330
use routing::network_graph::NodeId;
331+
use util::ser::{Readable, Writeable};
331332

332333
use bitcoin::secp256k1::PublicKey;
333334
use core::cell::Cell;
334335
use core::ops::Sub;
335336
use core::time::Duration;
337+
use io;
336338

337339
/// Time that can be advanced manually in tests.
338340
#[derive(Debug, PartialEq, Eq)]
@@ -408,4 +410,157 @@ mod tests {
408410
assert!(elapsed > Duration::from_secs(0));
409411
assert!(later - elapsed > now);
410412
}
413+
414+
/// A scorer for testing with time that can be manually advanced.
415+
type Scorer = ScorerUsingTime::<SinceEpoch>;
416+
417+
fn source_node_id() -> NodeId {
418+
NodeId::from_pubkey(&PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap())
419+
}
420+
421+
fn target_node_id() -> NodeId {
422+
NodeId::from_pubkey(&PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap())
423+
}
424+
425+
#[test]
426+
fn penalizes_without_channel_failures() {
427+
let scorer = Scorer::new(ScoringParameters {
428+
base_penalty_msat: 1_000,
429+
failure_penalty_msat: 512,
430+
failure_penalty_half_life: Duration::from_secs(1),
431+
});
432+
let source = source_node_id();
433+
let target = target_node_id();
434+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
435+
436+
SinceEpoch::advance(Duration::from_secs(1));
437+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
438+
}
439+
440+
#[test]
441+
fn accumulates_channel_failure_penalties() {
442+
let mut scorer = Scorer::new(ScoringParameters {
443+
base_penalty_msat: 1_000,
444+
failure_penalty_msat: 64,
445+
failure_penalty_half_life: Duration::from_secs(10),
446+
});
447+
let source = source_node_id();
448+
let target = target_node_id();
449+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
450+
451+
scorer.payment_path_failed(&[], 42);
452+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_064);
453+
454+
scorer.payment_path_failed(&[], 42);
455+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_128);
456+
457+
scorer.payment_path_failed(&[], 42);
458+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_192);
459+
}
460+
461+
#[test]
462+
fn decays_channel_failure_penalties_over_time() {
463+
let mut scorer = Scorer::new(ScoringParameters {
464+
base_penalty_msat: 1_000,
465+
failure_penalty_msat: 512,
466+
failure_penalty_half_life: Duration::from_secs(10),
467+
});
468+
let source = source_node_id();
469+
let target = target_node_id();
470+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
471+
472+
scorer.payment_path_failed(&[], 42);
473+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_512);
474+
475+
SinceEpoch::advance(Duration::from_secs(9));
476+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_512);
477+
478+
SinceEpoch::advance(Duration::from_secs(1));
479+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_256);
480+
481+
SinceEpoch::advance(Duration::from_secs(10 * 8));
482+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_001);
483+
484+
SinceEpoch::advance(Duration::from_secs(10));
485+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
486+
487+
SinceEpoch::advance(Duration::from_secs(10));
488+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
489+
}
490+
491+
#[test]
492+
fn accumulates_channel_failure_penalties_after_decay() {
493+
let mut scorer = Scorer::new(ScoringParameters {
494+
base_penalty_msat: 1_000,
495+
failure_penalty_msat: 512,
496+
failure_penalty_half_life: Duration::from_secs(10),
497+
});
498+
let source = source_node_id();
499+
let target = target_node_id();
500+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_000);
501+
502+
scorer.payment_path_failed(&[], 42);
503+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_512);
504+
505+
SinceEpoch::advance(Duration::from_secs(10));
506+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_256);
507+
508+
scorer.payment_path_failed(&[], 42);
509+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_768);
510+
511+
SinceEpoch::advance(Duration::from_secs(10));
512+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_384);
513+
}
514+
515+
#[test]
516+
fn restores_persisted_channel_failure_penalties() {
517+
let mut scorer = Scorer::new(ScoringParameters {
518+
base_penalty_msat: 1_000,
519+
failure_penalty_msat: 512,
520+
failure_penalty_half_life: Duration::from_secs(10),
521+
});
522+
let source = source_node_id();
523+
let target = target_node_id();
524+
525+
scorer.payment_path_failed(&[], 42);
526+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_512);
527+
528+
SinceEpoch::advance(Duration::from_secs(10));
529+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_256);
530+
531+
scorer.payment_path_failed(&[], 43);
532+
assert_eq!(scorer.channel_penalty_msat(43, &source, &target), 1_512);
533+
534+
let mut serialized_scorer = Vec::new();
535+
scorer.write(&mut serialized_scorer).unwrap();
536+
537+
let deserialized_scorer = <Scorer>::read(&mut io::Cursor::new(&serialized_scorer)).unwrap();
538+
assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target), 1_256);
539+
assert_eq!(deserialized_scorer.channel_penalty_msat(43, &source, &target), 1_512);
540+
}
541+
542+
#[test]
543+
fn decays_persisted_channel_failure_penalties() {
544+
let mut scorer = Scorer::new(ScoringParameters {
545+
base_penalty_msat: 1_000,
546+
failure_penalty_msat: 512,
547+
failure_penalty_half_life: Duration::from_secs(10),
548+
});
549+
let source = source_node_id();
550+
let target = target_node_id();
551+
552+
scorer.payment_path_failed(&[], 42);
553+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target), 1_512);
554+
555+
let mut serialized_scorer = Vec::new();
556+
scorer.write(&mut serialized_scorer).unwrap();
557+
558+
SinceEpoch::advance(Duration::from_secs(10));
559+
560+
let deserialized_scorer = <Scorer>::read(&mut io::Cursor::new(&serialized_scorer)).unwrap();
561+
assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target), 1_256);
562+
563+
SinceEpoch::advance(Duration::from_secs(10));
564+
assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target), 1_128);
565+
}
411566
}

0 commit comments

Comments
 (0)