@@ -1551,8 +1551,9 @@ where
15511551/// #
15521552/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
15531553/// # let channel_manager = channel_manager.get_cm();
1554+ /// # let absolute_expiry = None;
15541555/// let offer = channel_manager
1555- ///     .create_offer_builder()?
1556+ ///     .create_offer_builder(absolute_expiry )?
15561557/// # ;
15571558/// # // Needed for compiling for c_bindings
15581559/// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into();
@@ -8542,16 +8543,15 @@ where
85428543
85438544macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
85448545	/// 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 .
85478548	///
85488549	/// # Privacy
85498550	///
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`].
85558555	///
85568556	/// Also, uses a derived signing pubkey in the offer for recipient privacy.
85578557	///
@@ -8566,20 +8566,27 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
85668566	///
85678567	/// [`Offer`]: crate::offers::offer::Offer
85688568	/// [`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> {
85708572		let node_id = $self.get_our_node_id();
85718573		let expanded_key = &$self.inbound_payment_key;
85728574		let entropy = &*$self.entropy_source;
85738575		let secp_ctx = &$self.secp_ctx;
85748576
8575- 		let path = $self.create_compact_blinded_path( )
8577+ 		let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry )
85768578			.map_err(|_| Bolt12SemanticError::MissingPaths)?;
85778579		let builder = OfferBuilder::deriving_signing_pubkey(
85788580			node_id, expanded_key, entropy, secp_ctx
85798581		)
85808582			.chain_hash($self.chain_hash)
85818583			.path(path);
85828584
8585+ 		let builder = match absolute_expiry {
8586+ 			None => builder,
8587+ 			Some(absolute_expiry) => builder.absolute_expiry(absolute_expiry),
8588+ 		};
8589+ 
85838590		Ok(builder.into())
85848591	}
85858592} }
@@ -8607,11 +8614,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
86078614	///
86088615	/// # Privacy
86098616	///
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`].
86158621	///
86168622	/// Also, uses a derived payer id in the refund for payer privacy.
86178623	///
@@ -8640,7 +8646,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
86408646		let entropy = &*$self.entropy_source;
86418647		let secp_ctx = &$self.secp_ctx;
86428648
8643- 		let path = $self.create_compact_blinded_path( )
8649+ 		let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry) )
86448650			.map_err(|_| Bolt12SemanticError::MissingPaths)?;
86458651		let builder = RefundBuilder::deriving_payer_id(
86468652			node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
@@ -8990,6 +8996,33 @@ where
89908996		inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
89918997	}
89928998
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+ 
89939026	/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
89949027	///
89959028	/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
0 commit comments