From 10f9795149cdfcd5160418d9cb5cee1ae310629d Mon Sep 17 00:00:00 2001 From: KaFai Choi Date: Mon, 18 Apr 2022 10:32:13 +0700 Subject: [PATCH] move Time trait from scoring mod to util::time and set it visibile within crate --- lightning/src/routing/scoring.rs | 154 ++----------------------------- lightning/src/util/mod.rs | 1 + lightning/src/util/time.rs | 152 ++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 147 deletions(-) create mode 100644 lightning/src/util/time.rs diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 4c47aac47..cffd2d905 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -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; @@ -262,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 @@ -1327,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}; @@ -1418,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::; diff --git a/lightning/src/util/mod.rs b/lightning/src/util/mod.rs index b7ee02d2c..c6181ab26 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -36,6 +36,7 @@ pub(crate) mod poly1305; pub(crate) mod chacha20poly1305rfc; pub(crate) mod transaction_utils; pub(crate) mod scid_utils; +pub(crate) mod time; /// Logging macro utilities. #[macro_use] diff --git a/lightning/src/util/time.rs b/lightning/src/util/time.rs new file mode 100644 index 000000000..d3768aa7c --- /dev/null +++ b/lightning/src/util/time.rs @@ -0,0 +1,152 @@ +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! [`Time`] trait and different implementations. Currently, it's mainly used in tests so we can +//! manually advance time. +//! Other crates may symlink this file to use it while [`Time`] trait is sealed here. + +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; + +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 + } +} + +#[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) + } +} + +#[cfg(test)] +pub mod tests { + use super::{Time, Eternity}; + + use core::time::Duration; + use core::ops::Sub; + use core::cell::Cell; + + /// Time that can be advanced manually in tests. + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + pub struct SinceEpoch(Duration); + + impl SinceEpoch { + thread_local! { + static ELAPSED: Cell = core::cell::Cell::new(Duration::from_secs(0)); + } + + pub 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); + } +} -- 2.39.5