mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 23:08:36 +01:00
Pass the current time through ScoreUpDate
methods
In the coming commits, we'll stop relying on fetching the time during routefetching, preferring to decay score data in the background instead. The first step towards this - passing the current time through into the scorer when updating.
This commit is contained in:
parent
6471eb050e
commit
6c366cf35f
4 changed files with 105 additions and 88 deletions
|
@ -244,30 +244,30 @@ fn handle_network_graph_update<L: Deref>(
|
|||
/// Updates scorer based on event and returns whether an update occurred so we can decide whether
|
||||
/// to persist.
|
||||
fn update_scorer<'a, S: 'static + Deref<Target = SC> + Send + Sync, SC: 'a + WriteableScore<'a>>(
|
||||
scorer: &'a S, event: &Event
|
||||
scorer: &'a S, event: &Event, duration_since_epoch: Duration,
|
||||
) -> bool {
|
||||
match event {
|
||||
Event::PaymentPathFailed { ref path, short_channel_id: Some(scid), .. } => {
|
||||
let mut score = scorer.write_lock();
|
||||
score.payment_path_failed(path, *scid);
|
||||
score.payment_path_failed(path, *scid, duration_since_epoch);
|
||||
},
|
||||
Event::PaymentPathFailed { ref path, payment_failed_permanently: true, .. } => {
|
||||
// Reached if the destination explicitly failed it back. We treat this as a successful probe
|
||||
// because the payment made it all the way to the destination with sufficient liquidity.
|
||||
let mut score = scorer.write_lock();
|
||||
score.probe_successful(path);
|
||||
score.probe_successful(path, duration_since_epoch);
|
||||
},
|
||||
Event::PaymentPathSuccessful { path, .. } => {
|
||||
let mut score = scorer.write_lock();
|
||||
score.payment_path_successful(path);
|
||||
score.payment_path_successful(path, duration_since_epoch);
|
||||
},
|
||||
Event::ProbeSuccessful { path, .. } => {
|
||||
let mut score = scorer.write_lock();
|
||||
score.probe_successful(path);
|
||||
score.probe_successful(path, duration_since_epoch);
|
||||
},
|
||||
Event::ProbeFailed { path, short_channel_id: Some(scid), .. } => {
|
||||
let mut score = scorer.write_lock();
|
||||
score.probe_failed(path, *scid);
|
||||
score.probe_failed(path, *scid, duration_since_epoch);
|
||||
},
|
||||
_ => return false,
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ macro_rules! define_run_body {
|
|||
$channel_manager: ident, $process_channel_manager_events: expr,
|
||||
$peer_manager: ident, $process_onion_message_handler_events: expr, $gossip_sync: ident,
|
||||
$logger: ident, $scorer: ident, $loop_exit_check: expr, $await: expr, $get_timer: expr,
|
||||
$timer_elapsed: expr, $check_slow_await: expr
|
||||
$timer_elapsed: expr, $check_slow_await: expr, $time_fetch: expr,
|
||||
) => { {
|
||||
log_trace!($logger, "Calling ChannelManager's timer_tick_occurred on startup");
|
||||
$channel_manager.timer_tick_occurred();
|
||||
|
@ -383,11 +383,10 @@ macro_rules! define_run_body {
|
|||
if should_prune {
|
||||
// The network graph must not be pruned while rapid sync completion is pending
|
||||
if let Some(network_graph) = $gossip_sync.prunable_network_graph() {
|
||||
#[cfg(feature = "std")] {
|
||||
if let Some(duration_since_epoch) = $time_fetch() {
|
||||
log_trace!($logger, "Pruning and persisting network graph.");
|
||||
network_graph.remove_stale_channels_and_tracking();
|
||||
}
|
||||
#[cfg(not(feature = "std"))] {
|
||||
network_graph.remove_stale_channels_and_tracking_with_time(duration_since_epoch.as_secs());
|
||||
} else {
|
||||
log_warn!($logger, "Not pruning network graph, consider enabling `std` or doing so manually with remove_stale_channels_and_tracking_with_time.");
|
||||
log_trace!($logger, "Persisting network graph.");
|
||||
}
|
||||
|
@ -510,12 +509,16 @@ use core::task;
|
|||
/// are unsure, you should set the flag, as the performance impact of it is minimal unless there
|
||||
/// are hundreds or thousands of simultaneous process calls running.
|
||||
///
|
||||
/// The `fetch_time` parameter should return the current wall clock time, if one is available. If
|
||||
/// no time is available, some features may be disabled, however the node will still operate fine.
|
||||
///
|
||||
/// For example, in order to process background events in a [Tokio](https://tokio.rs/) task, you
|
||||
/// could setup `process_events_async` like this:
|
||||
/// ```
|
||||
/// # use lightning::io;
|
||||
/// # use std::sync::{Arc, RwLock};
|
||||
/// # use std::sync::atomic::{AtomicBool, Ordering};
|
||||
/// # use std::time::SystemTime;
|
||||
/// # use lightning_background_processor::{process_events_async, GossipSync};
|
||||
/// # struct MyStore {}
|
||||
/// # impl lightning::util::persist::KVStore for MyStore {
|
||||
|
@ -584,6 +587,7 @@ use core::task;
|
|||
/// Some(background_scorer),
|
||||
/// sleeper,
|
||||
/// mobile_interruptable_platform,
|
||||
/// || Some(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap())
|
||||
/// )
|
||||
/// .await
|
||||
/// .expect("Failed to process events");
|
||||
|
@ -620,11 +624,12 @@ pub async fn process_events_async<
|
|||
S: 'static + Deref<Target = SC> + Send + Sync,
|
||||
SC: for<'b> WriteableScore<'b>,
|
||||
SleepFuture: core::future::Future<Output = bool> + core::marker::Unpin,
|
||||
Sleeper: Fn(Duration) -> SleepFuture
|
||||
Sleeper: Fn(Duration) -> SleepFuture,
|
||||
FetchTime: Fn() -> Option<Duration>,
|
||||
>(
|
||||
persister: PS, event_handler: EventHandler, chain_monitor: M, channel_manager: CM,
|
||||
gossip_sync: GossipSync<PGS, RGS, G, UL, L>, peer_manager: PM, logger: L, scorer: Option<S>,
|
||||
sleeper: Sleeper, mobile_interruptable_platform: bool,
|
||||
sleeper: Sleeper, mobile_interruptable_platform: bool, fetch_time: FetchTime,
|
||||
) -> Result<(), lightning::io::Error>
|
||||
where
|
||||
UL::Target: 'static + UtxoLookup,
|
||||
|
@ -648,15 +653,18 @@ where
|
|||
let scorer = &scorer;
|
||||
let logger = &logger;
|
||||
let persister = &persister;
|
||||
let fetch_time = &fetch_time;
|
||||
async move {
|
||||
if let Some(network_graph) = network_graph {
|
||||
handle_network_graph_update(network_graph, &event)
|
||||
}
|
||||
if let Some(ref scorer) = scorer {
|
||||
if update_scorer(scorer, &event) {
|
||||
log_trace!(logger, "Persisting scorer after update");
|
||||
if let Err(e) = persister.persist_scorer(&scorer) {
|
||||
log_error!(logger, "Error: Failed to persist scorer, check your disk and permissions {}", e)
|
||||
if let Some(duration_since_epoch) = fetch_time() {
|
||||
if update_scorer(scorer, &event, duration_since_epoch) {
|
||||
log_trace!(logger, "Persisting scorer after update");
|
||||
if let Err(e) = persister.persist_scorer(&scorer) {
|
||||
log_error!(logger, "Error: Failed to persist scorer, check your disk and permissions {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -688,7 +696,7 @@ where
|
|||
task::Poll::Ready(exit) => { should_break = exit; true },
|
||||
task::Poll::Pending => false,
|
||||
}
|
||||
}, mobile_interruptable_platform
|
||||
}, mobile_interruptable_platform, fetch_time,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -810,7 +818,10 @@ impl BackgroundProcessor {
|
|||
handle_network_graph_update(network_graph, &event)
|
||||
}
|
||||
if let Some(ref scorer) = scorer {
|
||||
if update_scorer(scorer, &event) {
|
||||
use std::time::SystemTime;
|
||||
let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
|
||||
.expect("Time should be sometime after 1970");
|
||||
if update_scorer(scorer, &event, duration_since_epoch) {
|
||||
log_trace!(logger, "Persisting scorer after update");
|
||||
if let Err(e) = persister.persist_scorer(&scorer) {
|
||||
log_error!(logger, "Error: Failed to persist scorer, check your disk and permissions {}", e)
|
||||
|
@ -829,7 +840,12 @@ impl BackgroundProcessor {
|
|||
channel_manager.get_event_or_persistence_needed_future(),
|
||||
chain_monitor.get_update_future()
|
||||
).wait_timeout(Duration::from_millis(100)); },
|
||||
|_| Instant::now(), |time: &Instant, dur| time.elapsed().as_secs() > dur, false
|
||||
|_| Instant::now(), |time: &Instant, dur| time.elapsed().as_secs() > dur, false,
|
||||
|| {
|
||||
use std::time::SystemTime;
|
||||
Some(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
|
||||
.expect("Time should be sometime after 1970"))
|
||||
},
|
||||
)
|
||||
});
|
||||
Self { stop_thread: stop_thread_clone, thread_handle: Some(handle) }
|
||||
|
@ -1117,7 +1133,7 @@ mod tests {
|
|||
}
|
||||
|
||||
impl ScoreUpdate for TestScorer {
|
||||
fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64) {
|
||||
fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64, _: Duration) {
|
||||
if let Some(expectations) = &mut self.event_expectations {
|
||||
match expectations.pop_front().unwrap() {
|
||||
TestResult::PaymentFailure { path, short_channel_id } => {
|
||||
|
@ -1137,7 +1153,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn payment_path_successful(&mut self, actual_path: &Path) {
|
||||
fn payment_path_successful(&mut self, actual_path: &Path, _: Duration) {
|
||||
if let Some(expectations) = &mut self.event_expectations {
|
||||
match expectations.pop_front().unwrap() {
|
||||
TestResult::PaymentFailure { path, .. } => {
|
||||
|
@ -1156,7 +1172,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn probe_failed(&mut self, actual_path: &Path, _: u64) {
|
||||
fn probe_failed(&mut self, actual_path: &Path, _: u64, _: Duration) {
|
||||
if let Some(expectations) = &mut self.event_expectations {
|
||||
match expectations.pop_front().unwrap() {
|
||||
TestResult::PaymentFailure { path, .. } => {
|
||||
|
@ -1174,7 +1190,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn probe_successful(&mut self, actual_path: &Path) {
|
||||
fn probe_successful(&mut self, actual_path: &Path, _: Duration) {
|
||||
if let Some(expectations) = &mut self.event_expectations {
|
||||
match expectations.pop_front().unwrap() {
|
||||
TestResult::PaymentFailure { path, .. } => {
|
||||
|
@ -1469,7 +1485,7 @@ mod tests {
|
|||
tokio::time::sleep(dur).await;
|
||||
false // Never exit
|
||||
})
|
||||
}, false,
|
||||
}, false, || Some(Duration::ZERO),
|
||||
);
|
||||
match bp_future.await {
|
||||
Ok(_) => panic!("Expected error persisting manager"),
|
||||
|
@ -1699,7 +1715,7 @@ mod tests {
|
|||
_ = exit_receiver.changed() => true,
|
||||
}
|
||||
})
|
||||
}, false,
|
||||
}, false, || Some(Duration::from_secs(1696300000)),
|
||||
);
|
||||
|
||||
let t1 = tokio::spawn(bp_future);
|
||||
|
@ -1874,7 +1890,7 @@ mod tests {
|
|||
_ = exit_receiver.changed() => true,
|
||||
}
|
||||
})
|
||||
}, false,
|
||||
}, false, || Some(Duration::ZERO),
|
||||
);
|
||||
let t1 = tokio::spawn(bp_future);
|
||||
let t2 = tokio::spawn(async move {
|
||||
|
|
|
@ -8160,6 +8160,7 @@ mod tests {
|
|||
pub(crate) mod bench_utils {
|
||||
use super::*;
|
||||
use std::fs::File;
|
||||
use std::time::Duration;
|
||||
|
||||
use bitcoin::hashes::Hash;
|
||||
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
|
||||
|
@ -8308,10 +8309,10 @@ pub(crate) mod bench_utils {
|
|||
if let Ok(route) = route_res {
|
||||
for path in route.paths {
|
||||
if seed & 0x80 == 0 {
|
||||
scorer.payment_path_successful(&path);
|
||||
scorer.payment_path_successful(&path, Duration::ZERO);
|
||||
} else {
|
||||
let short_channel_id = path.hops[path.hops.len() / 2].short_channel_id;
|
||||
scorer.payment_path_failed(&path, short_channel_id);
|
||||
scorer.payment_path_failed(&path, short_channel_id, Duration::ZERO);
|
||||
}
|
||||
seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
|
||||
}
|
||||
|
|
|
@ -110,16 +110,16 @@ pub trait ScoreLookUp {
|
|||
/// `ScoreUpdate` is used to update the scorer's internal state after a payment attempt.
|
||||
pub trait ScoreUpdate {
|
||||
/// Handles updating channel penalties after failing to route through a channel.
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64);
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration);
|
||||
|
||||
/// Handles updating channel penalties after successfully routing along a path.
|
||||
fn payment_path_successful(&mut self, path: &Path);
|
||||
fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration);
|
||||
|
||||
/// Handles updating channel penalties after a probe over the given path failed.
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64);
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration);
|
||||
|
||||
/// Handles updating channel penalties after a probe over the given path succeeded.
|
||||
fn probe_successful(&mut self, path: &Path);
|
||||
fn probe_successful(&mut self, path: &Path, duration_since_epoch: Duration);
|
||||
}
|
||||
|
||||
/// A trait which can both lookup and update routing channel penalty scores.
|
||||
|
@ -145,20 +145,20 @@ impl<S: ScoreLookUp, T: Deref<Target=S>> ScoreLookUp for T {
|
|||
|
||||
#[cfg(not(c_bindings))]
|
||||
impl<S: ScoreUpdate, T: DerefMut<Target=S>> ScoreUpdate for T {
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64) {
|
||||
self.deref_mut().payment_path_failed(path, short_channel_id)
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) {
|
||||
self.deref_mut().payment_path_failed(path, short_channel_id, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn payment_path_successful(&mut self, path: &Path) {
|
||||
self.deref_mut().payment_path_successful(path)
|
||||
fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration) {
|
||||
self.deref_mut().payment_path_successful(path, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64) {
|
||||
self.deref_mut().probe_failed(path, short_channel_id)
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) {
|
||||
self.deref_mut().probe_failed(path, short_channel_id, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn probe_successful(&mut self, path: &Path) {
|
||||
self.deref_mut().probe_successful(path)
|
||||
fn probe_successful(&mut self, path: &Path, duration_since_epoch: Duration) {
|
||||
self.deref_mut().probe_successful(path, duration_since_epoch)
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
@ -346,20 +346,20 @@ impl<'a, T: 'a + Score> DerefMut for MultiThreadedScoreLockWrite<'a, T> {
|
|||
|
||||
#[cfg(c_bindings)]
|
||||
impl<'a, T: Score> ScoreUpdate for MultiThreadedScoreLockWrite<'a, T> {
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64) {
|
||||
self.0.payment_path_failed(path, short_channel_id)
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) {
|
||||
self.0.payment_path_failed(path, short_channel_id, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn payment_path_successful(&mut self, path: &Path) {
|
||||
self.0.payment_path_successful(path)
|
||||
fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration) {
|
||||
self.0.payment_path_successful(path, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64) {
|
||||
self.0.probe_failed(path, short_channel_id)
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) {
|
||||
self.0.probe_failed(path, short_channel_id, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn probe_successful(&mut self, path: &Path) {
|
||||
self.0.probe_successful(path)
|
||||
fn probe_successful(&mut self, path: &Path, duration_since_epoch: Duration) {
|
||||
self.0.probe_successful(path, duration_since_epoch)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,13 +399,13 @@ impl ScoreLookUp for FixedPenaltyScorer {
|
|||
}
|
||||
|
||||
impl ScoreUpdate for FixedPenaltyScorer {
|
||||
fn payment_path_failed(&mut self, _path: &Path, _short_channel_id: u64) {}
|
||||
fn payment_path_failed(&mut self, _path: &Path, _short_channel_id: u64, _duration_since_epoch: Duration) {}
|
||||
|
||||
fn payment_path_successful(&mut self, _path: &Path) {}
|
||||
fn payment_path_successful(&mut self, _path: &Path, _duration_since_epoch: Duration) {}
|
||||
|
||||
fn probe_failed(&mut self, _path: &Path, _short_channel_id: u64) {}
|
||||
fn probe_failed(&mut self, _path: &Path, _short_channel_id: u64, _duration_since_epoch: Duration) {}
|
||||
|
||||
fn probe_successful(&mut self, _path: &Path) {}
|
||||
fn probe_successful(&mut self, _path: &Path, _duration_since_epoch: Duration) {}
|
||||
}
|
||||
|
||||
impl Writeable for FixedPenaltyScorer {
|
||||
|
@ -1391,7 +1391,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ScoreLookUp for Prob
|
|||
}
|
||||
|
||||
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ScoreUpdate for ProbabilisticScorerUsingTime<G, L, T> where L::Target: Logger {
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64) {
|
||||
fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, _duration_since_epoch: Duration) {
|
||||
let amount_msat = path.final_value_msat();
|
||||
log_trace!(self.logger, "Scoring path through to SCID {} as having failed at {} msat", short_channel_id, amount_msat);
|
||||
let network_graph = self.network_graph.read_only();
|
||||
|
@ -1430,7 +1430,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ScoreUpdate for Prob
|
|||
}
|
||||
}
|
||||
|
||||
fn payment_path_successful(&mut self, path: &Path) {
|
||||
fn payment_path_successful(&mut self, path: &Path, _duration_since_epoch: Duration) {
|
||||
let amount_msat = path.final_value_msat();
|
||||
log_trace!(self.logger, "Scoring path through SCID {} as having succeeded at {} msat.",
|
||||
path.hops.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), amount_msat);
|
||||
|
@ -1456,12 +1456,12 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ScoreUpdate for Prob
|
|||
}
|
||||
}
|
||||
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64) {
|
||||
self.payment_path_failed(path, short_channel_id)
|
||||
fn probe_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) {
|
||||
self.payment_path_failed(path, short_channel_id, duration_since_epoch)
|
||||
}
|
||||
|
||||
fn probe_successful(&mut self, path: &Path) {
|
||||
self.payment_path_failed(path, u64::max_value())
|
||||
fn probe_successful(&mut self, path: &Path, duration_since_epoch: Duration) {
|
||||
self.payment_path_failed(path, u64::max_value(), duration_since_epoch)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2661,10 +2661,10 @@ mod tests {
|
|||
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301);
|
||||
|
||||
scorer.payment_path_failed(&failed_path, 41);
|
||||
scorer.payment_path_failed(&failed_path, 41, Duration::ZERO);
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301);
|
||||
|
||||
scorer.payment_path_successful(&successful_path);
|
||||
scorer.payment_path_successful(&successful_path, Duration::ZERO);
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301);
|
||||
}
|
||||
|
||||
|
@ -2697,7 +2697,7 @@ mod tests {
|
|||
let usage = ChannelUsage { amount_msat: 750, ..usage };
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 602);
|
||||
|
||||
scorer.payment_path_failed(&path, 43);
|
||||
scorer.payment_path_failed(&path, 43, Duration::ZERO);
|
||||
|
||||
let usage = ChannelUsage { amount_msat: 250, ..usage };
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0);
|
||||
|
@ -2737,7 +2737,7 @@ mod tests {
|
|||
let usage = ChannelUsage { amount_msat: 750, ..usage };
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 602);
|
||||
|
||||
scorer.payment_path_failed(&path, 42);
|
||||
scorer.payment_path_failed(&path, 42, Duration::ZERO);
|
||||
|
||||
let usage = ChannelUsage { amount_msat: 250, ..usage };
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300);
|
||||
|
@ -2814,7 +2814,7 @@ mod tests {
|
|||
};
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128);
|
||||
|
||||
scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 43);
|
||||
scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 43, Duration::ZERO);
|
||||
|
||||
let channel = network_graph.read_only().channel(42).unwrap().to_owned();
|
||||
let (info, _) = channel.as_directed_from(&node_a).unwrap();
|
||||
|
@ -2877,7 +2877,7 @@ mod tests {
|
|||
assert_eq!(scorer.channel_penalty_msat(&candidate_42, usage, ¶ms), 128);
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate_43, usage, ¶ms), 128);
|
||||
|
||||
scorer.payment_path_successful(&payment_path_for_amount(500));
|
||||
scorer.payment_path_successful(&payment_path_for_amount(500), Duration::ZERO);
|
||||
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate_41, usage, ¶ms), 128);
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate_42, usage, ¶ms), 300);
|
||||
|
@ -2915,8 +2915,8 @@ mod tests {
|
|||
let usage = ChannelUsage { amount_msat: 1_023, ..usage };
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2_000);
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(768), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(128), 43);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(768), 42, Duration::ZERO);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(128), 43, Duration::ZERO);
|
||||
|
||||
// Initial penalties
|
||||
let usage = ChannelUsage { amount_msat: 128, ..usage };
|
||||
|
@ -3013,7 +3013,7 @@ mod tests {
|
|||
};
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 125);
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(512), 42);
|
||||
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
|
||||
|
@ -3054,8 +3054,8 @@ mod tests {
|
|||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300);
|
||||
|
||||
// More knowledge gives higher confidence (256, 768), meaning a lower penalty.
|
||||
scorer.payment_path_failed(&payment_path_for_amount(768), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(256), 43);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(768), 42, Duration::ZERO);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(256), 43, Duration::ZERO);
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 281);
|
||||
|
||||
// Decaying knowledge gives less confidence (128, 896), meaning a higher penalty.
|
||||
|
@ -3064,12 +3064,12 @@ mod tests {
|
|||
|
||||
// Reducing the upper bound gives more confidence (128, 832) that the payment amount (512)
|
||||
// is closer to the upper bound, meaning a higher penalty.
|
||||
scorer.payment_path_successful(&payment_path_for_amount(64));
|
||||
scorer.payment_path_successful(&payment_path_for_amount(64), Duration::from_secs(10));
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 331);
|
||||
|
||||
// Increasing the lower bound gives more confidence (256, 832) that the payment amount (512)
|
||||
// is closer to the lower bound, meaning a lower penalty.
|
||||
scorer.payment_path_failed(&payment_path_for_amount(256), 43);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(256), 43, Duration::from_secs(10));
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 245);
|
||||
|
||||
// Further decaying affects the lower bound more than the upper bound (128, 928).
|
||||
|
@ -3098,7 +3098,7 @@ mod tests {
|
|||
effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 },
|
||||
};
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(500), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(500), 42, Duration::ZERO);
|
||||
let channel = network_graph.read_only().channel(42).unwrap().to_owned();
|
||||
let (info, _) = channel.as_directed_from(&source).unwrap();
|
||||
let candidate = CandidateRouteHop::PublicHop {
|
||||
|
@ -3110,7 +3110,7 @@ mod tests {
|
|||
SinceEpoch::advance(Duration::from_secs(10));
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 473);
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(250), 43);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(250), 43, Duration::from_secs(10));
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300);
|
||||
|
||||
let mut serialized_scorer = Vec::new();
|
||||
|
@ -3143,7 +3143,7 @@ mod tests {
|
|||
effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 },
|
||||
};
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(500), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(500), 42, Duration::ZERO);
|
||||
let channel = network_graph.read_only().channel(42).unwrap().to_owned();
|
||||
let (info, _) = channel.as_directed_from(&source).unwrap();
|
||||
let candidate = CandidateRouteHop::PublicHop {
|
||||
|
@ -3162,7 +3162,7 @@ mod tests {
|
|||
<ProbabilisticScorer>::read(&mut serialized_scorer, (decay_params, &network_graph, &logger)).unwrap();
|
||||
assert_eq!(deserialized_scorer.channel_penalty_msat(&candidate, usage, ¶ms), 473);
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(250), 43);
|
||||
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));
|
||||
|
@ -3437,7 +3437,7 @@ mod tests {
|
|||
assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms),
|
||||
None);
|
||||
|
||||
scorer.payment_path_failed(&payment_path_for_amount(1), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(1), 42, Duration::ZERO);
|
||||
{
|
||||
let network_graph = network_graph.read_only();
|
||||
let channel = network_graph.channel(42).unwrap();
|
||||
|
@ -3462,7 +3462,7 @@ mod tests {
|
|||
|
||||
// Even after we tell the scorer we definitely have enough available liquidity, it will
|
||||
// still remember that there was some failure in the past, and assign a non-0 penalty.
|
||||
scorer.payment_path_failed(&payment_path_for_amount(1000), 43);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(1000), 43, Duration::ZERO);
|
||||
{
|
||||
let network_graph = network_graph.read_only();
|
||||
let channel = network_graph.channel(42).unwrap();
|
||||
|
@ -3515,7 +3515,7 @@ mod tests {
|
|||
inflight_htlc_msat: 1024,
|
||||
effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 },
|
||||
};
|
||||
scorer.payment_path_failed(&payment_path_for_amount(1), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(1), 42, Duration::from_secs(10 * 16));
|
||||
{
|
||||
let network_graph = network_graph.read_only();
|
||||
let channel = network_graph.channel(42).unwrap();
|
||||
|
@ -3547,7 +3547,7 @@ mod tests {
|
|||
path_hop(source_pubkey(), 42, 1),
|
||||
path_hop(sender_pubkey(), 41, 0),
|
||||
];
|
||||
scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 42);
|
||||
scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 42, Duration::from_secs(10 * (16 + 60 * 60)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -3646,9 +3646,9 @@ mod tests {
|
|||
// final value is taken into account.
|
||||
assert!(scorer.channel_liquidities.get(&42).is_none());
|
||||
|
||||
scorer.payment_path_failed(&path, 42);
|
||||
scorer.payment_path_failed(&path, 42, Duration::ZERO);
|
||||
path.blinded_tail.as_mut().unwrap().final_value_msat = 256;
|
||||
scorer.payment_path_failed(&path, 43);
|
||||
scorer.payment_path_failed(&path, 43, Duration::ZERO);
|
||||
|
||||
let liquidity = scorer.channel_liquidities.get(&42).unwrap()
|
||||
.as_directed(&source, &target, 1_000, decay_params);
|
||||
|
@ -3702,7 +3702,7 @@ mod tests {
|
|||
None);
|
||||
|
||||
// Fail to pay once, and then check the buckets and penalty.
|
||||
scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42, Duration::ZERO);
|
||||
// The penalty should be the maximum penalty, as the payment we're scoring is now in the
|
||||
// same bucket which is the only maximum datapoint.
|
||||
assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms),
|
||||
|
@ -3726,7 +3726,7 @@ mod tests {
|
|||
// ...but once we see a failure, we consider the payment to be substantially less likely,
|
||||
// even though not a probability of zero as we still look at the second max bucket which
|
||||
// now shows 31.
|
||||
scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42);
|
||||
scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42, Duration::ZERO);
|
||||
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
|
||||
Some(([63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[32, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])));
|
||||
|
|
|
@ -1350,13 +1350,13 @@ impl ScoreLookUp for TestScorer {
|
|||
}
|
||||
|
||||
impl ScoreUpdate for TestScorer {
|
||||
fn payment_path_failed(&mut self, _actual_path: &Path, _actual_short_channel_id: u64) {}
|
||||
fn payment_path_failed(&mut self, _actual_path: &Path, _actual_short_channel_id: u64, _duration_since_epoch: Duration) {}
|
||||
|
||||
fn payment_path_successful(&mut self, _actual_path: &Path) {}
|
||||
fn payment_path_successful(&mut self, _actual_path: &Path, _duration_since_epoch: Duration) {}
|
||||
|
||||
fn probe_failed(&mut self, _actual_path: &Path, _: u64) {}
|
||||
fn probe_failed(&mut self, _actual_path: &Path, _: u64, _duration_since_epoch: Duration) {}
|
||||
|
||||
fn probe_successful(&mut self, _actual_path: &Path) {}
|
||||
fn probe_successful(&mut self, _actual_path: &Path, _duration_since_epoch: Duration) {}
|
||||
}
|
||||
|
||||
impl Drop for TestScorer {
|
||||
|
|
Loading…
Add table
Reference in a new issue