@@ -8542,16 +8542,15 @@ where
8542
8542
8543
8543
macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
8544
8544
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
8545
- /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer will
8546
- /// not have an expiration unless otherwise set on the builder .
8545
+ /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer's
8546
+ /// expiration will be `absolute_expiry` if `Some`, otherwise it will not expire .
8547
8547
///
8548
8548
/// # Privacy
8549
8549
///
8550
- /// Uses [`MessageRouter::create_compact_blinded_paths`] to construct a [`BlindedPath`] for the
8551
- /// offer. However, if one is not found, uses a one-hop [`BlindedPath`] with
8552
- /// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
8553
- /// the node must be announced, otherwise, there is no way to find a path to the introduction in
8554
- /// order to send the [`InvoiceRequest`].
8550
+ /// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the offer. However, if one is not
8551
+ /// found, uses a one-hop [`BlindedPath`] with [`ChannelManager::get_our_node_id`] as the
8552
+ /// introduction node instead. In the latter case, the node must be announced, otherwise, there
8553
+ /// is no way to find a path to the introduction in order to send the [`InvoiceRequest`].
8555
8554
///
8556
8555
/// Also, uses a derived signing pubkey in the offer for recipient privacy.
8557
8556
///
@@ -8566,20 +8565,27 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
8566
8565
///
8567
8566
/// [`Offer`]: crate::offers::offer::Offer
8568
8567
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
8569
- pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> {
8568
+ pub fn create_offer_builder(
8569
+ &$self, absolute_expiry: Option<Duration>
8570
+ ) -> Result<$builder, Bolt12SemanticError> {
8570
8571
let node_id = $self.get_our_node_id();
8571
8572
let expanded_key = &$self.inbound_payment_key;
8572
8573
let entropy = &*$self.entropy_source;
8573
8574
let secp_ctx = &$self.secp_ctx;
8574
8575
8575
- let path = $self.create_compact_blinded_path( )
8576
+ let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry )
8576
8577
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8577
8578
let builder = OfferBuilder::deriving_signing_pubkey(
8578
8579
node_id, expanded_key, entropy, secp_ctx
8579
8580
)
8580
8581
.chain_hash($self.chain_hash)
8581
8582
.path(path);
8582
8583
8584
+ let builder = match absolute_expiry {
8585
+ None => builder,
8586
+ Some(absolute_expiry) => builder.absolute_expiry(absolute_expiry),
8587
+ };
8588
+
8583
8589
Ok(builder.into())
8584
8590
}
8585
8591
} }
@@ -8607,11 +8613,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
8607
8613
///
8608
8614
/// # Privacy
8609
8615
///
8610
- /// Uses [`MessageRouter::create_compact_blinded_paths`] to construct a [`BlindedPath`] for the
8611
- /// refund. However, if one is not found, uses a one-hop [`BlindedPath`] with
8612
- /// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
8613
- /// the node must be announced, otherwise, there is no way to find a path to the introduction in
8614
- /// order to send the [`Bolt12Invoice`].
8616
+ /// Uses [`MessageRouter`] to construct a [`BlindedPath`] for the refund. However, if one is not
8617
+ /// found, uses a one-hop [`BlindedPath`] with [`ChannelManager::get_our_node_id`] as the
8618
+ /// introduction node instead. In the latter case, the node must be announced, otherwise, there
8619
+ /// is no way to find a path to the introduction in order to send the [`Bolt12Invoice`].
8615
8620
///
8616
8621
/// Also, uses a derived payer id in the refund for payer privacy.
8617
8622
///
@@ -8640,7 +8645,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
8640
8645
let entropy = &*$self.entropy_source;
8641
8646
let secp_ctx = &$self.secp_ctx;
8642
8647
8643
- let path = $self.create_compact_blinded_path( )
8648
+ let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry) )
8644
8649
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8645
8650
let builder = RefundBuilder::deriving_payer_id(
8646
8651
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
@@ -8990,6 +8995,33 @@ where
8990
8995
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
8991
8996
}
8992
8997
8998
+ /// Creates a blinded path by delegating to [`MessageRouter`] based on the path's intended
8999
+ /// lifetime.
9000
+ ///
9001
+ /// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
9002
+ /// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch.
9003
+ fn create_blinded_path_using_absolute_expiry(
9004
+ &self, absolute_expiry: Option<Duration>
9005
+ ) -> Result<BlindedPath, ()> {
9006
+ const MAX_SHORT_LIVED_RELATIVE_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24);
9007
+
9008
+ #[cfg(not(feature = "std"))]
9009
+ let now = Duration::from_secs(
9010
+ self.highest_seen_timestamp.load(Ordering::Acquire) as u64
9011
+ );
9012
+ #[cfg(feature = "std")]
9013
+ let now = std::time::SystemTime::now()
9014
+ .duration_since(std::time::SystemTime::UNIX_EPOCH)
9015
+ .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
9016
+
9017
+ let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
9018
+ if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
9019
+ self.create_compact_blinded_path()
9020
+ } else {
9021
+ self.create_blinded_path()
9022
+ }
9023
+ }
9024
+
8993
9025
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
8994
9026
///
8995
9027
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
0 commit comments