Skip to content
This repository was archived by the owner on Apr 13, 2021. It is now read-only.

Commit 84cfec7

Browse files
authored
Merge pull request #8 from rust-bitcoin/std-time
Use std::time API instead of u64s for timestamp and expiry time
2 parents 47ade71 + b2f9b12 commit 84cfec7

File tree

5 files changed

+264
-45
lines changed

5 files changed

+264
-45
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
This repo provides datastructures for BOLT 11 lightning invoices.
66
It provides functions to parse and serialize invoices from and to bech32.
77

8+
**Please be sure to run the test suite since we need to check assumptions
9+
regarding `SystemTime`'s bounds on your platform. You can also call `check_platform`
10+
on startup or in your test suite to do so.**
11+
812
## Contributing
913
* same coding style standard as [rust-bitcoin/rust-lightning](https://github.com/rust-bitcoin/rust-lightning)
1014
* use tabs and spaces (appropriately)

src/de.rs

+30-11
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,7 @@ impl FromBase32 for RawDataPart {
311311
return Err(ParseError::TooShortDataPart);
312312
}
313313

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])?;
316315
let tagged = parse_tagged_parts(&data[7..])?;
317316

318317
Ok(RawDataPart {
@@ -322,6 +321,23 @@ impl FromBase32 for RawDataPart {
322321
}
323322
}
324323

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+
325341
impl FromBase32 for Signature {
326342
type Err = ParseError;
327343
fn from_base32(signature: &[u5]) -> Result<Self, Self::Err> {
@@ -469,11 +485,11 @@ impl FromBase32 for ExpiryTime {
469485
type Err = ParseError;
470486

471487
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),
477493
}
478494
}
479495
}
@@ -589,7 +605,8 @@ pub enum ParseError {
589605
InvalidScriptHashLength,
590606
InvalidRecoveryId,
591607
InvalidSliceLength(String),
592-
Skip
608+
Skip,
609+
TimestampOverflow,
593610
}
594611

595612
#[derive(PartialEq, Debug, Clone)]
@@ -648,6 +665,7 @@ impl error::Error for ParseError {
648665
InvalidRecoveryId => "recovery id is out of range (should be in [0,3])",
649666
InvalidSliceLength(_) => "some slice had the wrong length",
650667
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",
651669
}
652670
}
653671
}
@@ -796,7 +814,7 @@ mod test {
796814
use bech32::FromBase32;
797815

798816
let input = from_bech32("pu".as_bytes());
799-
let expected = Ok(ExpiryTime{seconds: 60});
817+
let expected = Ok(ExpiryTime::from_seconds(60).unwrap());
800818
assert_eq!(ExpiryTime::from_base32(&input), expected);
801819

802820
let input_too_large = from_bech32("sqqqqqqqqqqqq".as_bytes());
@@ -924,7 +942,8 @@ mod test {
924942
fn test_raw_signed_invoice_deserialization() {
925943
use TaggedField::*;
926944
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};
928947

929948
assert_eq!(
930949
"lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmw\
@@ -938,7 +957,7 @@ mod test {
938957
si_prefix: None,
939958
},
940959
data: RawDataPart {
941-
timestamp: 1496314658,
960+
timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
942961
tagged_fields: vec ! [
943962
PaymentHash(Sha256(Sha256Hash::from_hex(
944963
"0001020304050607080900010203040506070809000102030405060708090102"

0 commit comments

Comments
 (0)