Skip to content

Commit 102ffe4

Browse files
committed
Use compact blinded paths for short-lived offers
When an offer is short-lived, the likelihood of a channel used in a compact blinded path going away is low. Require passing the absolute expiry of an offer to ChannelManager::create_offer_builder so that it can be used to determine whether or not compact blinded path should be used. Use the same criteria for creating blinded paths for refunds as well.
1 parent 5c28c67 commit 102ffe4

File tree

3 files changed

+193
-39
lines changed

3 files changed

+193
-39
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

85438544
macro_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`.

lightning/src/ln/functional_test_utils.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use core::cell::RefCell;
5050
use core::iter::repeat;
5151
use core::mem;
5252
use core::ops::Deref;
53+
use core::time::Duration;
5354
use crate::io;
5455
use crate::prelude::*;
5556
use crate::sync::{Arc, Mutex, LockTestExt, RwLock};
@@ -464,6 +465,19 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
464465
self.override_init_features.borrow().clone()
465466
.unwrap_or_else(|| self.node.init_features() | self.onion_messenger.provided_init_features(peer_node_id))
466467
}
468+
469+
pub fn duration_since_epoch(&self) -> Duration {
470+
#[cfg(not(feature = "std"))]
471+
let now = Duration::from_secs(
472+
self.node.highest_seen_timestamp.load(Ordering::Acquire) as u64
473+
);
474+
#[cfg(feature = "std")]
475+
let now = std::time::SystemTime::now()
476+
.duration_since(std::time::SystemTime::UNIX_EPOCH)
477+
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
478+
479+
now
480+
}
467481
}
468482

469483
#[cfg(feature = "std")]

0 commit comments

Comments
 (0)