@@ -85,14 +85,16 @@ mod sync;
8585
8686pub use de:: { ParseError , ParseOrSemanticError } ;
8787
88- // TODO: fix before 2037 (see rust PR #55527)
89- /// Defines the maximum UNIX timestamp that can be represented as `SystemTime`. This is checked by
90- /// one of the unit tests, please run them.
91- const SYSTEM_TIME_MAX_UNIX_TIMESTAMP : u64 = core:: i32:: MAX as u64 ;
88+ /// The maximum timestamp that can be represented as a [`Duration`] since the UNIX epoch while
89+ /// allowing for adding an expiry without overflowing.
90+ const MAX_TIMESTAMP : u64 = core:: i64:: MAX as u64 ;
9291
93- /// Allow the expiry time to be up to one year. Since this reduces the range of possible timestamps
94- /// it should be rather low as long as we still have to support 32bit time representations
95- const MAX_EXPIRY_TIME : u64 = 60 * 60 * 24 * 356 ;
92+ /// The maximum expiry allowed, represented as a [`Duration`] since the invoice timestamp.
93+ const MAX_EXPIRY_TIME : u64 = ( core:: i64:: MAX ) as u64 + 1 ;
94+
95+ /// Assert that the maximum expiry represented as a [`Duration`] since the UNIX epoch does not
96+ /// exceed [`u64::MAX`].
97+ const _MAX_EXPIRY_TIMESTAMP: u64 = MAX_TIMESTAMP + MAX_EXPIRY_TIME ;
9698
9799/// Default expiry time as defined by [BOLT 11].
98100///
@@ -108,67 +110,6 @@ pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
108110/// [`MIN_FINAL_CLTV_EXPIRY`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY
109111pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY : u64 = 18 ;
110112
111- /// This function is used as a static assert for the size of `SystemTime`. If the crate fails to
112- /// compile due to it this indicates that your system uses unexpected bounds for `SystemTime`. You
113- /// can remove this functions and run the test `test_system_time_bounds_assumptions`. In any case,
114- /// please open an issue. If all tests pass you should be able to use this library safely by just
115- /// removing this function till we patch it accordingly.
116- #[ cfg( feature = "std" ) ]
117- fn __system_time_size_check ( ) {
118- // Use 2 * sizeof(u64) as expected size since the expected underlying implementation is storing
119- // a `Duration` since `SystemTime::UNIX_EPOCH`.
120- unsafe { let _ = core:: mem:: transmute_copy :: < SystemTime , [ u8 ; 16 ] > ( & SystemTime :: UNIX_EPOCH ) ; }
121- }
122-
123-
124- /// **Call this function on startup to ensure that all assumptions about the platform are valid.**
125- ///
126- /// Unfortunately we have to make assumptions about the upper bounds of the `SystemTime` type on
127- /// your platform which we can't fully verify at compile time and which isn't part of it's contract.
128- /// To our best knowledge our assumptions hold for all platforms officially supported by rust, but
129- /// since this check is fast we recommend to do it anyway.
130- ///
131- /// If this function fails this is considered a bug. Please open an issue describing your
132- /// platform and stating your current system time.
133- ///
134- /// Note that this currently does nothing in `no_std` environments, because they don't have
135- /// a `SystemTime` implementation.
136- ///
137- /// # Panics
138- /// If the check fails this function panics. By calling this function on startup you ensure that
139- /// this wont happen at an arbitrary later point in time.
140- pub fn check_platform ( ) {
141- #[ cfg( feature = "std" ) ]
142- check_system_time_bounds ( ) ;
143- }
144-
145- #[ cfg( feature = "std" ) ]
146- fn check_system_time_bounds ( ) {
147- // The upper and lower bounds of `SystemTime` are not part of its public contract and are
148- // platform specific. That's why we have to test if our assumptions regarding these bounds
149- // hold on the target platform.
150- //
151- // If this test fails on your platform, please don't use the library and open an issue
152- // instead so we can resolve the situation. Currently this library is tested on:
153- // * Linux (64bit)
154- let fail_date = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( SYSTEM_TIME_MAX_UNIX_TIMESTAMP ) ;
155- let year = Duration :: from_secs ( 60 * 60 * 24 * 365 ) ;
156-
157- // Make sure that the library will keep working for another year
158- assert ! ( fail_date. duration_since( SystemTime :: now( ) ) . unwrap( ) > year) ;
159-
160- let max_ts = PositiveTimestamp :: from_unix_timestamp (
161- SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME
162- ) . unwrap ( ) ;
163- let max_exp = :: ExpiryTime :: from_seconds ( MAX_EXPIRY_TIME ) . unwrap ( ) ;
164-
165- assert_eq ! (
166- ( max_ts. as_time( ) + * max_exp. as_duration( ) ) . duration_since( SystemTime :: UNIX_EPOCH ) . unwrap( ) . as_secs( ) ,
167- SYSTEM_TIME_MAX_UNIX_TIMESTAMP
168- ) ;
169- }
170-
171-
172113/// Builder for `Invoice`s. It's the most convenient and advised way to use this library. It ensures
173114/// that only a semantically and syntactically correct Invoice can be built using it.
174115///
@@ -447,8 +388,7 @@ pub struct PayeePubKey(pub PublicKey);
447388///
448389/// # Invariants
449390/// The number of seconds this expiry time represents has to be in the range
450- /// `0...(SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME)` to avoid overflows when adding it to a
451- /// timestamp
391+ /// `0...MAX_EXPIRY_TIME` to avoid overflows when adding it to a timestamp.
452392#[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
453393pub struct ExpiryTime ( Duration ) ;
454394
@@ -1003,32 +943,34 @@ impl RawInvoice {
1003943}
1004944
1005945impl PositiveTimestamp {
1006- /// Create a new `PositiveTimestamp` from a unix timestamp in the Range
1007- /// `0...SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME`, otherwise return a
1008- /// `CreationError::TimestampOutOfBounds`.
946+ /// Creates a `PositiveTimestamp` from a unix timestamp in the range `0...MAX_TIMESTAMP`.
947+ ///
948+ /// Otherwise, returns a [ `CreationError::TimestampOutOfBounds`] .
1009949 pub fn from_unix_timestamp ( unix_seconds : u64 ) -> Result < Self , CreationError > {
1010- if unix_seconds > SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME {
950+ if unix_seconds > MAX_TIMESTAMP {
1011951 Err ( CreationError :: TimestampOutOfBounds )
1012952 } else {
1013953 Ok ( PositiveTimestamp ( Duration :: from_secs ( unix_seconds) ) )
1014954 }
1015955 }
1016956
1017- /// Create a new `PositiveTimestamp` from a `SystemTime` with a corresponding unix timestamp in
1018- /// the range `0...SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME`, otherwise return a
1019- /// `CreationError::TimestampOutOfBounds`.
957+ /// Creates a `PositiveTimestamp` from a [`SystemTime`] with a corresponding unix timestamp in
958+ /// the range `0...MAX_TIMESTAMP`.
959+ ///
960+ /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
1020961 #[ cfg( feature = "std" ) ]
1021962 pub fn from_system_time ( time : SystemTime ) -> Result < Self , CreationError > {
1022963 time. duration_since ( SystemTime :: UNIX_EPOCH )
1023964 . map ( Self :: from_duration_since_epoch)
1024965 . unwrap_or ( Err ( CreationError :: TimestampOutOfBounds ) )
1025966 }
1026967
1027- /// Create a new `PositiveTimestamp` from a `Duration` since the UNIX epoch in
1028- /// the range `0...SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME`, otherwise return a
1029- /// `CreationError::TimestampOutOfBounds`.
968+ /// Creates a `PositiveTimestamp` from a [`Duration`] since the UNIX epoch in the range
969+ /// `0...MAX_TIMESTAMP`.
970+ ///
971+ /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
1030972 pub fn from_duration_since_epoch ( duration : Duration ) -> Result < Self , CreationError > {
1031- if duration. as_secs ( ) <= SYSTEM_TIME_MAX_UNIX_TIMESTAMP - MAX_EXPIRY_TIME {
973+ if duration. as_secs ( ) <= MAX_TIMESTAMP {
1032974 Ok ( PositiveTimestamp ( duration) )
1033975 } else {
1034976 Err ( CreationError :: TimestampOutOfBounds )
@@ -1399,7 +1341,7 @@ impl Deref for PayeePubKey {
13991341
14001342impl ExpiryTime {
14011343 /// Construct an `ExpiryTime` from seconds. If there exists a `PositiveTimestamp` which would
1402- /// overflow on adding the `EpiryTime ` to it then this function will return a
1344+ /// overflow on adding the `ExpiryTime ` to it then this function will return a
14031345 /// `CreationError::ExpiryTimeOutOfBounds`.
14041346 pub fn from_seconds ( seconds : u64 ) -> Result < ExpiryTime , CreationError > {
14051347 if seconds <= MAX_EXPIRY_TIME {
@@ -1410,7 +1352,7 @@ impl ExpiryTime {
14101352 }
14111353
14121354 /// Construct an `ExpiryTime` from a `Duration`. If there exists a `PositiveTimestamp` which
1413- /// would overflow on adding the `EpiryTime ` to it then this function will return a
1355+ /// would overflow on adding the `ExpiryTime ` to it then this function will return a
14141356 /// `CreationError::ExpiryTimeOutOfBounds`.
14151357 pub fn from_duration ( duration : Duration ) -> Result < ExpiryTime , CreationError > {
14161358 if duration. as_secs ( ) <= MAX_EXPIRY_TIME {
@@ -1594,10 +1536,8 @@ mod test {
15941536
15951537 #[ test]
15961538 fn test_system_time_bounds_assumptions ( ) {
1597- :: check_platform ( ) ;
1598-
15991539 assert_eq ! (
1600- :: PositiveTimestamp :: from_unix_timestamp( :: SYSTEM_TIME_MAX_UNIX_TIMESTAMP + 1 ) ,
1540+ :: PositiveTimestamp :: from_unix_timestamp( :: MAX_TIMESTAMP + 1 ) ,
16011541 Err ( :: CreationError :: TimestampOutOfBounds )
16021542 ) ;
16031543
0 commit comments