X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Fscoring.rs;h=cffd2d90533b7290250b5a4886ad8c55fa5462fd;hb=bd1e20d49e5b67b55c22ee8927e546327d98e042;hp=0e04c63903392b8ccfc36d72c3fa87109b86c17b;hpb=df1c4ee1506061adf285c09638d401ec6e8397c3;p=rust-lightning diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 0e04c639..cffd2d90 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -15,14 +15,14 @@ //! # Example //! //! ``` -//! # extern crate secp256k1; +//! # extern crate bitcoin; //! # //! # use lightning::routing::network_graph::NetworkGraph; //! # use lightning::routing::router::{RouteParameters, find_route}; //! # use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters, Scorer, ScoringParameters}; //! # use lightning::chain::keysinterface::{KeysManager, KeysInterface}; //! # use lightning::util::logger::{Logger, Record}; -//! # use secp256k1::key::PublicKey; +//! # use bitcoin::secp256k1::PublicKey; //! # //! # struct FakeLogger {}; //! # impl Logger for FakeLogger { @@ -59,6 +59,7 @@ use routing::network_graph::{NetworkGraph, NodeId}; use routing::router::RouteHop; use util::ser::{Readable, ReadableArgs, Writeable, Writer}; use util::logger::Logger; +use util::time::Time; use prelude::*; use core::fmt; @@ -137,6 +138,14 @@ pub trait LockableScore<'a> { fn lock(&'a self) -> Self::Locked; } +/// Refers to a scorer that is accessible under lock and also writeable to disk +/// +/// We need this trait to be able to pass in a scorer to `lightning-background-processor` that will enable us to +/// use the Persister to persist it. +pub trait WriteableScore<'a>: LockableScore<'a> + Writeable {} + +impl<'a, T> WriteableScore<'a> for T where T: LockableScore<'a> + Writeable {} + /// (C-not exported) impl<'a, T: 'a + Score> LockableScore<'a> for Mutex { type Locked = MutexGuard<'a, T>; @@ -254,7 +263,9 @@ pub type Scorer = ScorerUsingTime::; #[cfg(not(feature = "no-std"))] type ConfiguredTime = std::time::Instant; #[cfg(feature = "no-std")] -type ConfiguredTime = time::Eternity; +use util::time::Eternity; +#[cfg(feature = "no-std")] +type ConfiguredTime = Eternity; // Note that ideally we'd hide ScorerUsingTime from public view by sealing it as well, but rustdoc // doesn't handle this well - instead exposing a `Scorer` which has no trait implementation(s) or @@ -623,6 +634,33 @@ impl, L: Deref, T: Time> ProbabilisticScorerUsin assert!(self.channel_liquidities.insert(short_channel_id, liquidity).is_none()); self } + + /// Dump the contents of this scorer into the configured logger. + /// + /// Note that this writes roughly one line per channel for which we have a liquidity estimate, + /// which may be a substantial amount of log output. + pub fn debug_log_liquidity_stats(&self) { + let graph = self.network_graph.read_only(); + for (scid, liq) in self.channel_liquidities.iter() { + if let Some(chan_debug) = graph.channels().get(scid) { + let log_direction = |source, target| { + if let Some((directed_info, _)) = chan_debug.as_directed_to(target) { + let amt = directed_info.effective_capacity().as_msat(); + let dir_liq = liq.as_directed(source, target, amt, self.params.liquidity_offset_half_life); + log_debug!(self.logger, "Liquidity from {:?} to {:?} via {} is in the range ({}, {})", + source, target, scid, dir_liq.min_liquidity_msat(), dir_liq.max_liquidity_msat()); + } else { + log_debug!(self.logger, "No amount known for SCID {} from {:?} to {:?}", scid, source, target); + } + }; + + log_direction(&chan_debug.node_one, &chan_debug.node_two); + log_direction(&chan_debug.node_two, &chan_debug.node_one); + } else { + log_debug!(self.logger, "No network graph entry for SCID {}", scid); + } + } + } } impl ProbabilisticScoringParameters { @@ -1292,83 +1330,11 @@ impl Readable for ChannelLiquidity { } } -pub(crate) mod time { - use core::ops::Sub; - use core::time::Duration; - /// A measurement of time. - pub trait Time: Copy + Sub where Self: Sized { - /// Returns an instance corresponding to the current moment. - fn now() -> Self; - - /// Returns the amount of time elapsed since `self` was created. - fn elapsed(&self) -> Duration; - - /// Returns the amount of time passed between `earlier` and `self`. - fn duration_since(&self, earlier: Self) -> Duration; - - /// Returns the amount of time passed since the beginning of [`Time`]. - /// - /// Used during (de-)serialization. - fn duration_since_epoch() -> Duration; - } - - /// A state in which time has no meaning. - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub struct Eternity; - - #[cfg(not(feature = "no-std"))] - impl Time for std::time::Instant { - fn now() -> Self { - std::time::Instant::now() - } - - fn duration_since(&self, earlier: Self) -> Duration { - self.duration_since(earlier) - } - - fn duration_since_epoch() -> Duration { - use std::time::SystemTime; - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap() - } - - fn elapsed(&self) -> Duration { - std::time::Instant::elapsed(self) - } - } - - impl Time for Eternity { - fn now() -> Self { - Self - } - - fn duration_since(&self, _earlier: Self) -> Duration { - Duration::from_secs(0) - } - - fn duration_since_epoch() -> Duration { - Duration::from_secs(0) - } - - fn elapsed(&self) -> Duration { - Duration::from_secs(0) - } - } - - impl Sub for Eternity { - type Output = Self; - - fn sub(self, _other: Duration) -> Self { - self - } - } -} - -pub(crate) use self::time::Time; - #[cfg(test)] mod tests { - use super::{ChannelLiquidity, ProbabilisticScoringParameters, ProbabilisticScorerUsingTime, ScoringParameters, ScorerUsingTime, Time}; - use super::time::Eternity; + use super::{ChannelLiquidity, ProbabilisticScoringParameters, ProbabilisticScorerUsingTime, ScoringParameters, ScorerUsingTime}; + use util::time::Time; + use util::time::tests::SinceEpoch; use ln::features::{ChannelFeatures, NodeFeatures}; use ln::msgs::{ChannelAnnouncement, ChannelUpdate, OptionalField, UnsignedChannelAnnouncement, UnsignedChannelUpdate}; @@ -1383,80 +1349,9 @@ mod tests { use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::network::constants::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; - use core::cell::Cell; - use core::ops::Sub; use core::time::Duration; use io; - // `Time` tests - - /// Time that can be advanced manually in tests. - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - struct SinceEpoch(Duration); - - impl SinceEpoch { - thread_local! { - static ELAPSED: Cell = core::cell::Cell::new(Duration::from_secs(0)); - } - - fn advance(duration: Duration) { - Self::ELAPSED.with(|elapsed| elapsed.set(elapsed.get() + duration)) - } - } - - impl Time for SinceEpoch { - fn now() -> Self { - Self(Self::duration_since_epoch()) - } - - fn duration_since(&self, earlier: Self) -> Duration { - self.0 - earlier.0 - } - - fn duration_since_epoch() -> Duration { - Self::ELAPSED.with(|elapsed| elapsed.get()) - } - - fn elapsed(&self) -> Duration { - Self::duration_since_epoch() - self.0 - } - } - - impl Sub for SinceEpoch { - type Output = Self; - - fn sub(self, other: Duration) -> Self { - Self(self.0 - other) - } - } - - #[test] - fn time_passes_when_advanced() { - let now = SinceEpoch::now(); - assert_eq!(now.elapsed(), Duration::from_secs(0)); - - SinceEpoch::advance(Duration::from_secs(1)); - SinceEpoch::advance(Duration::from_secs(1)); - - let elapsed = now.elapsed(); - let later = SinceEpoch::now(); - - assert_eq!(elapsed, Duration::from_secs(2)); - assert_eq!(later - elapsed, now); - } - - #[test] - fn time_never_passes_in_an_eternity() { - let now = Eternity::now(); - let elapsed = now.elapsed(); - let later = Eternity::now(); - - assert_eq!(now.elapsed(), Duration::from_secs(0)); - assert_eq!(later - elapsed, now); - } - - // `Scorer` tests - /// A scorer for testing with time that can be manually advanced. type Scorer = ScorerUsingTime::; @@ -1778,10 +1673,10 @@ mod tests { }; let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); let signed_announcement = ChannelAnnouncement { - node_signature_1: secp_ctx.sign(&msghash, &node_1_key), - node_signature_2: secp_ctx.sign(&msghash, &node_2_key), - bitcoin_signature_1: secp_ctx.sign(&msghash, &node_1_secret), - bitcoin_signature_2: secp_ctx.sign(&msghash, &node_2_secret), + node_signature_1: secp_ctx.sign_ecdsa(&msghash, &node_1_key), + node_signature_2: secp_ctx.sign_ecdsa(&msghash, &node_2_key), + bitcoin_signature_1: secp_ctx.sign_ecdsa(&msghash, &node_1_secret), + bitcoin_signature_2: secp_ctx.sign_ecdsa(&msghash, &node_2_secret), contents: unsigned_announcement, }; let chain_source: Option<&::util::test_utils::TestChainSource> = None; @@ -1810,7 +1705,7 @@ mod tests { }; let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_update.encode()[..])[..]); let signed_update = ChannelUpdate { - signature: secp_ctx.sign(&msghash, &node_key), + signature: secp_ctx.sign_ecdsa(&msghash, &node_key), contents: unsigned_update, }; network_graph.update_channel(&signed_update, &secp_ctx).unwrap();