@@ -85,17 +85,6 @@ mod sync;
8585
8686pub use de:: { ParseError , ParseOrSemanticError } ;
8787
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 ;
91-
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 ;
98-
9988/// Default expiry time as defined by [BOLT 11].
10089///
10190/// [BOLT 11]: https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md
@@ -385,10 +374,6 @@ pub struct PayeePubKey(pub PublicKey);
385374
386375/// Positive duration that defines when (relatively to the timestamp) in the future the invoice
387376/// expires
388- ///
389- /// # Invariants
390- /// The number of seconds this expiry time represents has to be in the range
391- /// `0...MAX_EXPIRY_TIME` to avoid overflows when adding it to a timestamp.
392377#[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
393378pub struct ExpiryTime ( Duration ) ;
394379
@@ -496,10 +481,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBui
496481
497482 /// Sets the expiry time
498483 pub fn expiry_time ( mut self , expiry_time : Duration ) -> Self {
499- match ExpiryTime :: from_duration ( expiry_time) {
500- Ok ( t) => self . tagged_fields . push ( TaggedField :: ExpiryTime ( t) ) ,
501- Err ( e) => self . error = Some ( e) ,
502- } ;
484+ self . tagged_fields . push ( TaggedField :: ExpiryTime ( ExpiryTime :: from_duration ( expiry_time) ) ) ;
503485 self
504486 }
505487
@@ -591,19 +573,15 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
591573
592574 /// Sets the timestamp to a duration since the UNIX epoch.
593575 pub fn duration_since_epoch ( mut self , time : Duration ) -> InvoiceBuilder < D , H , tb:: True , C , S > {
594- match PositiveTimestamp :: from_duration_since_epoch ( time) {
595- Ok ( t) => self . timestamp = Some ( t) ,
596- Err ( e) => self . error = Some ( e) ,
597- }
598-
576+ self . timestamp = Some ( PositiveTimestamp :: from_duration_since_epoch ( time) ) ;
599577 self . set_flags ( )
600578 }
601579
602580 /// Sets the timestamp to the current system time.
603581 #[ cfg( feature = "std" ) ]
604582 pub fn current_timestamp ( mut self ) -> InvoiceBuilder < D , H , tb:: True , C , S > {
605583 let now = PositiveTimestamp :: from_system_time ( SystemTime :: now ( ) ) ;
606- self . timestamp = Some ( now. expect ( "for the foreseeable future this shouldn't happen" ) ) ;
584+ self . timestamp = Some ( now. expect ( "this shouldn't happen after the UNIX epoch " ) ) ;
607585 self . set_flags ( )
608586 }
609587}
@@ -946,35 +924,24 @@ impl PositiveTimestamp {
946924 /// Creates a `PositiveTimestamp` from a unix timestamp in the range `0...MAX_TIMESTAMP`.
947925 ///
948926 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
949- pub fn from_unix_timestamp ( unix_seconds : u64 ) -> Result < Self , CreationError > {
950- if unix_seconds > MAX_TIMESTAMP {
951- Err ( CreationError :: TimestampOutOfBounds )
952- } else {
953- Ok ( PositiveTimestamp ( Duration :: from_secs ( unix_seconds) ) )
954- }
927+ pub fn from_unix_timestamp ( unix_seconds : u64 ) -> Self {
928+ PositiveTimestamp ( Duration :: from_secs ( unix_seconds) )
955929 }
956930
957- /// Creates a `PositiveTimestamp` from a [`SystemTime`] with a corresponding unix timestamp in
958- /// the range `0...MAX_TIMESTAMP`.
931+ /// Creates a `PositiveTimestamp` from a [`SystemTime`] with a corresponding unix timestamp.
959932 ///
960- /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
933+ /// Returns a [`CreationError::TimestampOutOfBounds`] if `time` is before
934+ /// [`SystemTime::UNIX_EPOCH`].
961935 #[ cfg( feature = "std" ) ]
962936 pub fn from_system_time ( time : SystemTime ) -> Result < Self , CreationError > {
963937 time. duration_since ( SystemTime :: UNIX_EPOCH )
964938 . map ( Self :: from_duration_since_epoch)
965- . unwrap_or ( Err ( CreationError :: TimestampOutOfBounds ) )
939+ . map_err ( |_| CreationError :: TimestampOutOfBounds )
966940 }
967941
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`].
972- pub fn from_duration_since_epoch ( duration : Duration ) -> Result < Self , CreationError > {
973- if duration. as_secs ( ) <= MAX_TIMESTAMP {
974- Ok ( PositiveTimestamp ( duration) )
975- } else {
976- Err ( CreationError :: TimestampOutOfBounds )
977- }
942+ /// Creates a `PositiveTimestamp` from a [`Duration`] since the UNIX epoch.
943+ pub fn from_duration_since_epoch ( duration : Duration ) -> Self {
944+ PositiveTimestamp ( duration)
978945 }
979946
980947 /// Returns the UNIX timestamp representing the stored time
@@ -1219,7 +1186,7 @@ impl Invoice {
12191186 /// Returns whether the expiry time would pass at the given point in time.
12201187 /// `at_time` is the timestamp as a duration since the UNIX epoch.
12211188 pub fn would_expire ( & self , at_time : Duration ) -> bool {
1222- self . duration_since_epoch ( ) + self . expiry_time ( ) < at_time
1189+ self . duration_since_epoch ( ) . saturating_add ( self . expiry_time ( ) ) < at_time
12231190 }
12241191
12251192 /// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
@@ -1340,26 +1307,14 @@ impl Deref for PayeePubKey {
13401307}
13411308
13421309impl ExpiryTime {
1343- /// Construct an `ExpiryTime` from seconds. If there exists a `PositiveTimestamp` which would
1344- /// overflow on adding the `ExpiryTime` to it then this function will return a
1345- /// `CreationError::ExpiryTimeOutOfBounds`.
1346- pub fn from_seconds ( seconds : u64 ) -> Result < ExpiryTime , CreationError > {
1347- if seconds <= MAX_EXPIRY_TIME {
1348- Ok ( ExpiryTime ( Duration :: from_secs ( seconds) ) )
1349- } else {
1350- Err ( CreationError :: ExpiryTimeOutOfBounds )
1351- }
1310+ /// Construct an `ExpiryTime` from seconds.
1311+ pub fn from_seconds ( seconds : u64 ) -> ExpiryTime {
1312+ ExpiryTime ( Duration :: from_secs ( seconds) )
13521313 }
13531314
1354- /// Construct an `ExpiryTime` from a `Duration`. If there exists a `PositiveTimestamp` which
1355- /// would overflow on adding the `ExpiryTime` to it then this function will return a
1356- /// `CreationError::ExpiryTimeOutOfBounds`.
1357- pub fn from_duration ( duration : Duration ) -> Result < ExpiryTime , CreationError > {
1358- if duration. as_secs ( ) <= MAX_EXPIRY_TIME {
1359- Ok ( ExpiryTime ( duration) )
1360- } else {
1361- Err ( CreationError :: ExpiryTimeOutOfBounds )
1362- }
1315+ /// Construct an `ExpiryTime` from a `Duration`.
1316+ pub fn from_duration ( duration : Duration ) -> ExpiryTime {
1317+ ExpiryTime ( duration)
13631318 }
13641319
13651320 /// Returns the expiry time in seconds
@@ -1428,12 +1383,9 @@ pub enum CreationError {
14281383 /// The specified route has too many hops and can't be encoded
14291384 RouteTooLong ,
14301385
1431- /// The unix timestamp of the supplied date is <0 or can't be represented as `SystemTime`
1386+ /// The unix timestamp of the supplied date is less than zero
14321387 TimestampOutOfBounds ,
14331388
1434- /// The supplied expiry time could cause an overflow if added to a `PositiveTimestamp`
1435- ExpiryTimeOutOfBounds ,
1436-
14371389 /// The supplied millisatoshi amount was greater than the total bitcoin supply.
14381390 InvalidAmount ,
14391391}
@@ -1443,8 +1395,7 @@ impl Display for CreationError {
14431395 match self {
14441396 CreationError :: DescriptionTooLong => f. write_str ( "The supplied description string was longer than 639 bytes" ) ,
14451397 CreationError :: RouteTooLong => f. write_str ( "The specified route has too many hops and can't be encoded" ) ,
1446- CreationError :: TimestampOutOfBounds => f. write_str ( "The unix timestamp of the supplied date is <0 or can't be represented as `SystemTime`" ) ,
1447- CreationError :: ExpiryTimeOutOfBounds => f. write_str ( "The supplied expiry time could cause an overflow if added to a `PositiveTimestamp`" ) ,
1398+ CreationError :: TimestampOutOfBounds => f. write_str ( "The unix timestamp of the supplied date is less than zero" ) ,
14481399 CreationError :: InvalidAmount => f. write_str ( "The supplied millisatoshi amount was greater than the total bitcoin supply" ) ,
14491400 }
14501401 }
@@ -1534,19 +1485,6 @@ mod test {
15341485 use bitcoin_hashes:: hex:: FromHex ;
15351486 use bitcoin_hashes:: sha256;
15361487
1537- #[ test]
1538- fn test_system_time_bounds_assumptions ( ) {
1539- assert_eq ! (
1540- :: PositiveTimestamp :: from_unix_timestamp( :: MAX_TIMESTAMP + 1 ) ,
1541- Err ( :: CreationError :: TimestampOutOfBounds )
1542- ) ;
1543-
1544- assert_eq ! (
1545- :: ExpiryTime :: from_seconds( :: MAX_EXPIRY_TIME + 1 ) ,
1546- Err ( :: CreationError :: ExpiryTimeOutOfBounds )
1547- ) ;
1548- }
1549-
15501488 #[ test]
15511489 fn test_calc_invoice_hash ( ) {
15521490 use :: { RawInvoice , RawHrp , RawDataPart , Currency , PositiveTimestamp } ;
@@ -1559,7 +1497,7 @@ mod test {
15591497 si_prefix : None ,
15601498 } ,
15611499 data : RawDataPart {
1562- timestamp : PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) . unwrap ( ) ,
1500+ timestamp : PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) ,
15631501 tagged_fields : vec ! [
15641502 PaymentHash ( :: Sha256 ( sha256:: Hash :: from_hex(
15651503 "0001020304050607080900010203040506070809000102030405060708090102"
@@ -1597,7 +1535,7 @@ mod test {
15971535 si_prefix : None ,
15981536 } ,
15991537 data : RawDataPart {
1600- timestamp : PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) . unwrap ( ) ,
1538+ timestamp : PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) ,
16011539 tagged_fields : vec ! [
16021540 PaymentHash ( Sha256 ( sha256:: Hash :: from_hex(
16031541 "0001020304050607080900010203040506070809000102030405060708090102"
@@ -1667,7 +1605,7 @@ mod test {
16671605 si_prefix : None ,
16681606 } ,
16691607 data : RawDataPart {
1670- timestamp : PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) . unwrap ( ) ,
1608+ timestamp : PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) ,
16711609 tagged_fields : vec ! [
16721610 PaymentHash ( Sha256 ( sha256:: Hash :: from_hex(
16731611 "0001020304050607080900010203040506070809000102030405060708090102"
0 commit comments