You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
thread '<unnamed>' panicked at 'overflow when subtracting duration from instant', library/std/src/time.rs:424:33
Expected Behavior:
LDK does not panic, but reads the scorer.
Steps To Reproduce:
Build and run a node with LDK on iOS
Send coins (to have something to store for the scorer)
Store the scorer
Reboot the device
Read the scorer file
Environment
Device: iPhone8 and github MacOS builder.
What Happens
Usually std::time::Instant uses duration since the device boot time.
Seems that iOS uses u64 to store nanosecods, what means it cannot represent moments before the boot.
letmut duration_since_epoch = Duration::from_secs(0);// ...(4, duration_since_epoch, required),// ...let wall_clock_now = T::duration_since_epoch();let now = T::now();let last_updated = if wall_clock_now > duration_since_epoch {
now - (wall_clock_now - duration_since_epoch)// ^----- panics here}else{ now };
scorer writer writes the moment of the event as a duration since the Unix epoch let duration_since_epoch = T::duration_since_epoch() - self.last_updated.elapsed
scorer reader reads the moment of the event as a duration since the Unix epoch to duration_since_epoch
wall_clock_now is a SystemTime
wall_clock_now - duration_since_epoch is the duration since the event (till now)
now is Instant
if there was a reboot between the moment of the event and now then now will have number of nanosecods since the boot what is shorter than wall_clock_now - duration_since_epoch
now - (wall_clock_now - duration_since_epoch) panics
Simpler Test
#[test]fncheck_instant(){use std::time::{Duration,Instant};let now = Instant::now();let duration = Duration::from_secs(1);
std::thread::sleep(duration);let after = Instant::now();// Learn how Instant is represented.eprintln!("moment {now:?} after {duration:?} is {after:?}");// One of the statement will likely fail.
now.checked_sub(Duration::from_millis(1)).unwrap();
now.checked_sub(Duration::from_millis(10)).unwrap();
now.checked_sub(Duration::from_millis(100)).unwrap();
now.checked_sub(Duration::from_secs(1)).unwrap();
now.checked_sub(Duration::from_secs(10)).unwrap();
now.checked_sub(Duration::from_secs(60)).unwrap();
now.checked_sub(Duration::from_secs(10*60)).unwrap();
now.checked_sub(Duration::from_secs(30*60)).unwrap();
now.checked_sub(Duration::from_secs(60*60)).unwrap();
now.checked_sub(Duration::from_secs(2*60*60)).unwrap();
now.checked_sub(Duration::from_secs(4*60*60)).unwrap();
now.checked_sub(Duration::from_secs(8*60*60)).unwrap();
now.checked_sub(Duration::from_secs(12*60*60)).unwrap();
now.checked_sub(Duration::from_secs(24*60*60)).unwrap();
now.checked_sub(Duration::from_secs(10*24*60*60)).unwrap();
now.checked_sub(Duration::from_secs(100*24*60*60)).unwrap();}
Conclusion
Instant can be compared (or subtracted) only with other instances of Instant (such that they stay within the duration of the program runtime). It is not supposed to be stored or interpreted in any other way.
Instants are opaque types that can only be compared to one another. There is no method to get “the number of seconds” from an instant. Instead, it only allows measuring the duration between two instants (or comparing two instants).
The text was updated successfully, but these errors were encountered:
Grrrr, that leaves no simple "correct" option for us...SystemTime isn't a great fit either cause that can jump around quite a bit. We could store a Duration offset next to our Instants and always add that, but that's really annoying to deal with, not to mention increases the scorer's size and the complexity required per score fetch. We could also SystemTime and just deal with discontinuities, but that sucks too. Presumably Instant is also faster on some platforms (eg rtdsc vs a syscall to fetch the real time)?
Current Behavior:
On iOS LDK panics on reading scorer with:
Expected Behavior:
LDK does not panic, but reads the scorer.
Steps To Reproduce:
Environment
Device: iPhone8 and github MacOS builder.
What Happens
Usually
std::time::Instant
uses duration since the device boot time.Seems that iOS uses
u64
to store nanosecods, what means it cannot represent moments before the boot.It breaks code at https://github.com/lightningdevkit/rust-lightning/blob/main/lightning/src/routing/scoring.rs#L1727
let duration_since_epoch = T::duration_since_epoch() - self.last_updated.elapsed
duration_since_epoch
wall_clock_now
is aSystemTime
wall_clock_now - duration_since_epoch
is the duration since the event (till now)now
isInstant
now
will have number of nanosecods since the boot what is shorter thanwall_clock_now - duration_since_epoch
now - (wall_clock_now - duration_since_epoch)
panicsSimpler Test
Conclusion
Instant
can be compared (or subtracted) only with other instances ofInstant
(such that they stay within the duration of the program runtime). It is not supposed to be stored or interpreted in any other way.From https://doc.rust-lang.org/std/time/struct.Instant.html:
The text was updated successfully, but these errors were encountered: