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