Skip to content

Commit ab80fcf

Browse files
authored
Merge pull request #2322 from andrei-21/fix/instant-overflow
2 parents bd12067 + 189b070 commit ab80fcf

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

lightning/src/ln/outbound_payment.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ impl Retry {
239239
},
240240
#[cfg(all(not(feature = "no-std"), not(test)))]
241241
(Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) =>
242-
*max_duration >= std::time::Instant::now().duration_since(*first_attempted_at),
242+
*max_duration >= crate::util::time::MonotonicTime::now().duration_since(*first_attempted_at),
243243
#[cfg(all(not(feature = "no-std"), test))]
244244
(Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) =>
245245
*max_duration >= SinceEpoch::now().duration_since(*first_attempted_at),
@@ -274,7 +274,7 @@ pub(crate) struct PaymentAttemptsUsingTime<T: Time> {
274274
}
275275

276276
#[cfg(not(any(feature = "no-std", test)))]
277-
type ConfiguredTime = std::time::Instant;
277+
type ConfiguredTime = crate::util::time::MonotonicTime;
278278
#[cfg(feature = "no-std")]
279279
type ConfiguredTime = crate::util::time::Eternity;
280280
#[cfg(all(not(feature = "no-std"), test))]

lightning/src/routing/scoring.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ impl ReadableArgs<u64> for FixedPenaltyScorer {
325325
}
326326

327327
#[cfg(not(feature = "no-std"))]
328-
type ConfiguredTime = std::time::Instant;
328+
type ConfiguredTime = crate::util::time::MonotonicTime;
329329
#[cfg(feature = "no-std")]
330330
use crate::util::time::Eternity;
331331
#[cfg(feature = "no-std")]

lightning/src/util/time.rs

+36-4
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,20 @@ impl Sub<Duration> for Eternity {
5858
}
5959
}
6060

61+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62+
#[cfg(not(feature = "no-std"))]
63+
pub struct MonotonicTime(std::time::Instant);
64+
65+
/// The amount of time to shift `Instant` forward to prevent overflow when subtracting a `Duration`
66+
/// from `Instant::now` on some operating systems (e.g., iOS representing `Instance` as `u64`).
67+
#[cfg(not(feature = "no-std"))]
68+
const SHIFT: Duration = Duration::from_secs(10 * 365 * 24 * 60 * 60); // 10 years.
69+
6170
#[cfg(not(feature = "no-std"))]
62-
impl Time for std::time::Instant {
71+
impl Time for MonotonicTime {
6372
fn now() -> Self {
64-
std::time::Instant::now()
73+
let instant = std::time::Instant::now().checked_add(SHIFT).expect("Overflow on MonotonicTime instantiation");
74+
Self(instant)
6575
}
6676

6777
fn duration_since(&self, earlier: Self) -> Duration {
@@ -70,15 +80,26 @@ impl Time for std::time::Instant {
7080
// clocks" that go backwards in practice (likely relatively ancient kernels/etc). Thus, we
7181
// manually check for time going backwards here and return a duration of zero in that case.
7282
let now = Self::now();
73-
if now > earlier { now - earlier } else { Duration::from_secs(0) }
83+
if now.0 > earlier.0 { now.0 - earlier.0 } else { Duration::from_secs(0) }
7484
}
7585

7686
fn duration_since_epoch() -> Duration {
7787
use std::time::SystemTime;
7888
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap()
7989
}
90+
8091
fn elapsed(&self) -> Duration {
81-
std::time::Instant::elapsed(self)
92+
Self::now().0 - self.0
93+
}
94+
}
95+
96+
#[cfg(not(feature = "no-std"))]
97+
impl Sub<Duration> for MonotonicTime {
98+
type Output = Self;
99+
100+
fn sub(self, other: Duration) -> Self {
101+
let instant = self.0.checked_sub(other).expect("MonotonicTime is not supposed to go backward futher than 10 years");
102+
Self(instant)
82103
}
83104
}
84105

@@ -154,4 +175,15 @@ pub mod tests {
154175
assert_eq!(now.elapsed(), Duration::from_secs(0));
155176
assert_eq!(later - elapsed, now);
156177
}
178+
179+
#[test]
180+
#[cfg(not(feature = "no-std"))]
181+
fn monotonic_time_subtracts() {
182+
let now = super::MonotonicTime::now();
183+
assert!(now.elapsed() < Duration::from_secs(10));
184+
185+
let ten_years = Duration::from_secs(10 * 365 * 24 * 60 * 60);
186+
let past = now - ten_years;
187+
assert!(past.elapsed() >= ten_years);
188+
}
157189
}

0 commit comments

Comments
 (0)