Skip to content

Commit 1daabbf

Browse files
Support expiring async payments blinded message paths
Store an absolute expiry in blinded message contexts for inbound async payments. Without this, anyone with the path corresponding to this context is able to trivially ask if we're online forever.
1 parent 1a51825 commit 1daabbf

File tree

3 files changed

+19
-7
lines changed

3 files changed

+19
-7
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,10 @@ pub enum AsyncPaymentsContext {
419419
///
420420
/// [`HeldHtlcAvailable`]: crate::onion_message::async_payments::HeldHtlcAvailable
421421
hmac: Hmac<Sha256>,
422+
/// The time as duration since the Unix epoch at which this path expires and messages sent over
423+
/// it should be ignored. Without this, anyone with the path corresponding to this context is
424+
/// able to trivially ask if we're online forever.
425+
path_absolute_expiry: core::time::Duration,
422426
},
423427
}
424428

@@ -454,6 +458,7 @@ impl_writeable_tlv_based_enum!(AsyncPaymentsContext,
454458
(1, InboundPayment) => {
455459
(0, nonce, required),
456460
(2, hmac, required),
461+
(4, path_absolute_expiry, required),
457462
},
458463
);
459464

lightning/src/ln/channelmanager.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9966,8 +9966,11 @@ where
99669966

99679967
let nonce = Nonce::from_entropy_source(entropy);
99689968
let hmac = signer::hmac_for_held_htlc_available_context(nonce, expanded_key);
9969+
let path_absolute_expiry = Duration::from_secs(
9970+
inbound_payment::calculate_absolute_expiry(created_at.as_secs(), relative_expiry_secs)
9971+
);
99699972
let context = MessageContext::AsyncPayments(
9970-
AsyncPaymentsContext::InboundPayment { nonce, hmac }
9973+
AsyncPaymentsContext::InboundPayment { nonce, hmac, path_absolute_expiry }
99719974
);
99729975
let async_receive_message_paths = self.create_blinded_paths(context)
99739976
.map_err(|()| Bolt12SemanticError::MissingPaths)?;

lightning/src/ln/inbound_payment.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ pub(super) fn create_for_spontaneous_payment(
213213
Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
214214
}
215215

216+
pub(super) fn calculate_absolute_expiry(highest_seen_timestamp: u64, invoice_expiry_delta_secs: u32) -> u64 {
217+
// We assume that highest_seen_timestamp is pretty close to the current time - it's updated when
218+
// we receive a new block with the maximum time we've seen in a header. It should never be more
219+
// than two hours in the future. Thus, we add two hours here as a buffer to ensure we
220+
// absolutely never fail a payment too early.
221+
// Note that we assume that received blocks have reasonably up-to-date timestamps.
222+
highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200
223+
}
224+
216225
fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method,
217226
invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64, min_final_cltv_expiry_delta: Option<u16>) -> Result<[u8; METADATA_LEN], ()> {
218227
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
@@ -225,12 +234,7 @@ fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method,
225234
};
226235
min_amt_msat_bytes[0] |= (payment_type as u8) << METHOD_TYPE_OFFSET;
227236

228-
// We assume that highest_seen_timestamp is pretty close to the current time - it's updated when
229-
// we receive a new block with the maximum time we've seen in a header. It should never be more
230-
// than two hours in the future. Thus, we add two hours here as a buffer to ensure we
231-
// absolutely never fail a payment too early.
232-
// Note that we assume that received blocks have reasonably up-to-date timestamps.
233-
let expiry_timestamp = highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200;
237+
let expiry_timestamp = calculate_absolute_expiry(highest_seen_timestamp, invoice_expiry_delta_secs);
234238
let mut expiry_bytes = expiry_timestamp.to_be_bytes();
235239

236240
// `min_value_msat` should fit in (64 bits - 3 payment type bits =) 61 bits as an unsigned integer.

0 commit comments

Comments
 (0)