Skip to content

Drop the subsecond part of timestamps when constructing invoices #1760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions lightning-invoice/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,8 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBui
self
}

/// Sets the expiry time
/// Sets the expiry time, dropping the subsecond part (which is not representable in BOLT 11
/// invoices).
pub fn expiry_time(mut self, expiry_time: Duration) -> Self {
self.tagged_fields.push(TaggedField::ExpiryTime(ExpiryTime::from_duration(expiry_time)));
self
Expand Down Expand Up @@ -632,7 +633,8 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
self.set_flags()
}

/// Sets the timestamp to a duration since the Unix epoch.
/// Sets the timestamp to a duration since the Unix epoch, dropping the subsecond part (which
/// is not representable in BOLT 11 invoices).
pub fn duration_since_epoch(mut self, time: Duration) -> InvoiceBuilder<D, H, tb::True, C, S> {
match PositiveTimestamp::from_duration_since_epoch(time) {
Ok(t) => self.timestamp = Some(t),
Expand Down Expand Up @@ -960,12 +962,18 @@ impl PositiveTimestamp {
///
/// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
pub fn from_unix_timestamp(unix_seconds: u64) -> Result<Self, CreationError> {
Self::from_duration_since_epoch(Duration::from_secs(unix_seconds))
if unix_seconds <= MAX_TIMESTAMP {
Ok(Self(Duration::from_secs(unix_seconds)))
} else {
Err(CreationError::TimestampOutOfBounds)
}
}

/// Creates a `PositiveTimestamp` from a [`SystemTime`] with a corresponding Unix timestamp in
/// the range `0..=MAX_TIMESTAMP`.
///
/// Note that the subsecond part is dropped as it is not representable in BOLT 11 invoices.
///
/// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
#[cfg(feature = "std")]
pub fn from_system_time(time: SystemTime) -> Result<Self, CreationError> {
Expand All @@ -977,13 +985,11 @@ impl PositiveTimestamp {
/// Creates a `PositiveTimestamp` from a [`Duration`] since the Unix epoch in the range
/// `0..=MAX_TIMESTAMP`.
///
/// Note that the subsecond part is dropped as it is not representable in BOLT 11 invoices.
///
/// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
pub fn from_duration_since_epoch(duration: Duration) -> Result<Self, CreationError> {
if duration.as_secs() <= MAX_TIMESTAMP {
Ok(PositiveTimestamp(duration))
} else {
Err(CreationError::TimestampOutOfBounds)
}
Self::from_unix_timestamp(duration.as_secs())
}

/// Returns the Unix timestamp representing the stored time
Expand Down Expand Up @@ -1356,9 +1362,9 @@ impl ExpiryTime {
ExpiryTime(Duration::from_secs(seconds))
}

/// Construct an `ExpiryTime` from a `Duration`.
/// Construct an `ExpiryTime` from a `Duration`, dropping the sub-second part.
pub fn from_duration(duration: Duration) -> ExpiryTime {
ExpiryTime(duration)
Self::from_seconds(duration.as_secs())
}

/// Returns the expiry time in seconds
Expand Down