@@ -311,8 +311,7 @@ impl FromBase32 for RawDataPart {
311
311
return Err ( ParseError :: TooShortDataPart ) ;
312
312
}
313
313
314
- let timestamp: u64 = parse_int_be ( & data[ 0 ..7 ] , 32 )
315
- . expect ( "7*5bit < 64bit, no overflow possible" ) ;
314
+ let timestamp = PositiveTimestamp :: from_base32 ( & data[ 0 ..7 ] ) ?;
316
315
let tagged = parse_tagged_parts ( & data[ 7 ..] ) ?;
317
316
318
317
Ok ( RawDataPart {
@@ -322,6 +321,23 @@ impl FromBase32 for RawDataPart {
322
321
}
323
322
}
324
323
324
+ impl FromBase32 for PositiveTimestamp {
325
+ type Err = ParseError ;
326
+
327
+ fn from_base32 ( b32 : & [ u5 ] ) -> Result < Self , Self :: Err > {
328
+ if b32. len ( ) != 7 {
329
+ return Err ( ParseError :: InvalidSliceLength ( "PositiveTimestamp::from_base32()" . into ( ) ) ) ;
330
+ }
331
+ let timestamp: u64 = parse_int_be ( b32, 32 )
332
+ . expect ( "7*5bit < 64bit, no overflow possible" ) ;
333
+ match PositiveTimestamp :: from_unix_timestamp ( timestamp) {
334
+ Ok ( t) => Ok ( t) ,
335
+ Err ( CreationError :: TimestampOutOfBounds ) => Err ( ParseError :: TimestampOverflow ) ,
336
+ Err ( _) => unreachable ! ( ) ,
337
+ }
338
+ }
339
+ }
340
+
325
341
impl FromBase32 for Signature {
326
342
type Err = ParseError ;
327
343
fn from_base32 ( signature : & [ u5 ] ) -> Result < Self , Self :: Err > {
@@ -469,11 +485,11 @@ impl FromBase32 for ExpiryTime {
469
485
type Err = ParseError ;
470
486
471
487
fn from_base32 ( field_data : & [ u5 ] ) -> Result < ExpiryTime , ParseError > {
472
- let expiry = parse_int_be :: < u64 , u5 > ( field_data, 32 ) ;
473
- if let Some ( expiry ) = expiry {
474
- Ok ( ExpiryTime { seconds : expiry } )
475
- } else {
476
- Err ( ParseError :: IntegerOverflowError )
488
+ match parse_int_be :: < u64 , u5 > ( field_data, 32 )
489
+ . and_then ( |t| ExpiryTime :: from_seconds ( t ) . ok ( ) ) // ok, since the only error is out of bounds
490
+ {
491
+ Some ( t ) => Ok ( t ) ,
492
+ None => Err ( ParseError :: IntegerOverflowError ) ,
477
493
}
478
494
}
479
495
}
@@ -589,7 +605,8 @@ pub enum ParseError {
589
605
InvalidScriptHashLength ,
590
606
InvalidRecoveryId ,
591
607
InvalidSliceLength ( String ) ,
592
- Skip
608
+ Skip ,
609
+ TimestampOverflow ,
593
610
}
594
611
595
612
#[ derive( PartialEq , Debug , Clone ) ]
@@ -648,6 +665,7 @@ impl error::Error for ParseError {
648
665
InvalidRecoveryId => "recovery id is out of range (should be in [0,3])" ,
649
666
InvalidSliceLength ( _) => "some slice had the wrong length" ,
650
667
Skip => "the tagged field has to be skipped because of an unexpected, but allowed property" ,
668
+ TimestampOverflow => "the invoice's timestamp could not be represented as SystemTime" ,
651
669
}
652
670
}
653
671
}
@@ -796,7 +814,7 @@ mod test {
796
814
use bech32:: FromBase32 ;
797
815
798
816
let input = from_bech32 ( "pu" . as_bytes ( ) ) ;
799
- let expected = Ok ( ExpiryTime { seconds : 60 } ) ;
817
+ let expected = Ok ( ExpiryTime :: from_seconds ( 60 ) . unwrap ( ) ) ;
800
818
assert_eq ! ( ExpiryTime :: from_base32( & input) , expected) ;
801
819
802
820
let input_too_large = from_bech32 ( "sqqqqqqqqqqqq" . as_bytes ( ) ) ;
@@ -924,7 +942,8 @@ mod test {
924
942
fn test_raw_signed_invoice_deserialization ( ) {
925
943
use TaggedField :: * ;
926
944
use secp256k1:: { RecoveryId , RecoverableSignature , Secp256k1 } ;
927
- use { SignedRawInvoice , Signature , RawInvoice , RawHrp , RawDataPart , Currency , Sha256 } ;
945
+ use { SignedRawInvoice , Signature , RawInvoice , RawHrp , RawDataPart , Currency , Sha256 ,
946
+ PositiveTimestamp } ;
928
947
929
948
assert_eq ! (
930
949
"lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmw\
@@ -938,7 +957,7 @@ mod test {
938
957
si_prefix: None ,
939
958
} ,
940
959
data: RawDataPart {
941
- timestamp: 1496314658 ,
960
+ timestamp: PositiveTimestamp :: from_unix_timestamp ( 1496314658 ) . unwrap ( ) ,
942
961
tagged_fields: vec ! [
943
962
PaymentHash ( Sha256 ( Sha256Hash :: from_hex(
944
963
"0001020304050607080900010203040506070809000102030405060708090102"
0 commit comments