Skip to content

Commit 910ef35

Browse files
committed
Expand create_blinded_path Functionality for Enhanced Path Diversification
- Previously, the `create_blinded_path` function was limited to returning a single `BlindedPath`, which restricted the usage of `blinded_paths`. - This commit extends the `create_blinded_path` function to return the entire blinded path vector generated by the `MessageRouter`'s `create_blinded_paths`. - The updated functionality is integrated across the codebase, enabling the sending of Offers Response messages, such as `InvoiceRequest` (in `pay_for_offer`) and `Invoice` (in `request_refund_payment`), utilizing multiple reply paths.
1 parent 1d0c6c6 commit 910ef35

File tree

1 file changed

+60
-42
lines changed

1 file changed

+60
-42
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8285,8 +8285,10 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
82858285
let entropy = &*$self.entropy_source;
82868286
let secp_ctx = &$self.secp_ctx;
82878287

8288-
let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry)
8288+
let path = $self.create_blinded_paths_using_absolute_expiry(absolute_expiry)
8289+
.and_then(|paths| paths.into_iter().next().ok_or(()))
82898290
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8291+
82908292
let builder = OfferBuilder::deriving_signing_pubkey(
82918293
node_id, expanded_key, entropy, secp_ctx
82928294
)
@@ -8357,8 +8359,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
83578359
let entropy = &*$self.entropy_source;
83588360
let secp_ctx = &$self.secp_ctx;
83598361

8360-
let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry))
8362+
let path = $self.create_blinded_paths_using_absolute_expiry(Some(absolute_expiry))
8363+
.and_then(|paths| paths.into_iter().next().ok_or(()))
83618364
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8365+
83628366
let builder = RefundBuilder::deriving_payer_id(
83638367
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
83648368
)?
@@ -8379,6 +8383,12 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
83798383
}
83808384
} }
83818385

8386+
/// Defines the maximum number of [`OffersMessage`] to be sent along different reply paths.
8387+
/// Sending multiple requests increases the chances of successful delivery in case some
8388+
/// paths are unavailable. However, only one invoice for a given payment ID will be paid,
8389+
/// even if multiple requests are received.
8390+
const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
8391+
83828392
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, L>
83838393
where
83848394
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
@@ -8480,7 +8490,7 @@ where
84808490
Some(payer_note) => builder.payer_note(payer_note),
84818491
};
84828492
let invoice_request = builder.build_and_sign()?;
8483-
let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8493+
let reply_paths = self.create_blinded_paths().map_err(|_| Bolt12SemanticError::MissingPaths)?;
84848494

84858495
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
84868496

@@ -8493,25 +8503,27 @@ where
84938503

84948504
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
84958505
if !offer.paths().is_empty() {
8496-
// Send as many invoice requests as there are paths in the offer (with an upper bound).
8497-
// Using only one path could result in a failure if the path no longer exists. But only
8498-
// one invoice for a given payment id will be paid, even if more than one is received.
8499-
const REQUEST_LIMIT: usize = 10;
8500-
for path in offer.paths().into_iter().take(REQUEST_LIMIT) {
8506+
reply_paths
8507+
.iter()
8508+
.flat_map(|reply_path| offer.paths().iter().map(move |path| (path, reply_path)))
8509+
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
8510+
.for_each(|(path, reply_path)| {
8511+
let message = new_pending_onion_message(
8512+
OffersMessage::InvoiceRequest(invoice_request.clone()),
8513+
Destination::BlindedPath(path.clone()),
8514+
Some(reply_path.clone()),
8515+
);
8516+
pending_offers_messages.push(message);
8517+
});
8518+
} else if let Some(signing_pubkey) = offer.signing_pubkey() {
8519+
for reply_path in reply_paths {
85018520
let message = new_pending_onion_message(
85028521
OffersMessage::InvoiceRequest(invoice_request.clone()),
8503-
Destination::BlindedPath(path.clone()),
8504-
Some(reply_path.clone()),
8522+
Destination::Node(signing_pubkey),
8523+
Some(reply_path),
85058524
);
85068525
pending_offers_messages.push(message);
85078526
}
8508-
} else if let Some(signing_pubkey) = offer.signing_pubkey() {
8509-
let message = new_pending_onion_message(
8510-
OffersMessage::InvoiceRequest(invoice_request),
8511-
Destination::Node(signing_pubkey),
8512-
Some(reply_path),
8513-
);
8514-
pending_offers_messages.push(message);
85158527
} else {
85168528
debug_assert!(false);
85178529
return Err(Bolt12SemanticError::MissingSigningPubkey);
@@ -8580,26 +8592,32 @@ where
85808592
)?;
85818593
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
85828594
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
8583-
let reply_path = self.create_blinded_path()
8595+
let reply_paths = self.create_blinded_paths()
85848596
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
85858597

85868598
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
85878599
if refund.paths().is_empty() {
8588-
let message = new_pending_onion_message(
8589-
OffersMessage::Invoice(invoice.clone()),
8590-
Destination::Node(refund.payer_id()),
8591-
Some(reply_path),
8592-
);
8593-
pending_offers_messages.push(message);
8594-
} else {
8595-
for path in refund.paths() {
8600+
for reply_path in reply_paths {
85968601
let message = new_pending_onion_message(
85978602
OffersMessage::Invoice(invoice.clone()),
8598-
Destination::BlindedPath(path.clone()),
8599-
Some(reply_path.clone()),
8603+
Destination::Node(refund.payer_id()),
8604+
Some(reply_path),
86008605
);
86018606
pending_offers_messages.push(message);
86028607
}
8608+
} else {
8609+
reply_paths
8610+
.iter()
8611+
.flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
8612+
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
8613+
.for_each(|(path, reply_path)| {
8614+
let message = new_pending_onion_message(
8615+
OffersMessage::Invoice(invoice.clone()),
8616+
Destination::BlindedPath(path.clone()),
8617+
Some(reply_path.clone()),
8618+
);
8619+
pending_offers_messages.push(message);
8620+
});
86038621
}
86048622

86058623
Ok(invoice)
@@ -8706,22 +8724,22 @@ where
87068724
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
87078725
}
87088726

8709-
/// Creates a blinded path by delegating to [`MessageRouter`] based on the path's intended
8710-
/// lifetime.
8727+
/// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
8728+
/// the path's intended lifetime.
87118729
///
87128730
/// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
87138731
/// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
87148732
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
8715-
fn create_blinded_path_using_absolute_expiry(
8733+
fn create_blinded_paths_using_absolute_expiry(
87168734
&self, absolute_expiry: Option<Duration>
8717-
) -> Result<BlindedPath, ()> {
8735+
) -> Result<Vec<BlindedPath>, ()> {
87188736
let now = self.duration_since_epoch();
87198737
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
87208738

87218739
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
8722-
self.create_compact_blinded_path()
8740+
self.create_compact_blinded_paths()
87238741
} else {
8724-
self.create_blinded_path()
8742+
self.create_blinded_paths()
87258743
}
87268744
}
87278745

@@ -8738,10 +8756,11 @@ where
87388756
now
87398757
}
87408758

8741-
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
8759+
/// Creates a collection of blinded paths by delegating to
8760+
/// [`MessageRouter::create_blinded_paths`].
87428761
///
8743-
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
8744-
fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
8762+
/// Errors if the `MessageRouter` errors.
8763+
fn create_blinded_paths(&self) -> Result<Vec<BlindedPath>, ()> {
87458764
let recipient = self.get_our_node_id();
87468765
let secp_ctx = &self.secp_ctx;
87478766

@@ -8755,13 +8774,13 @@ where
87558774

87568775
self.router
87578776
.create_blinded_paths(recipient, peers, secp_ctx)
8758-
.and_then(|paths| paths.into_iter().next().ok_or(()))
87598777
}
87608778

8761-
/// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
8779+
/// Creates a collection of blinded paths by delegating to
8780+
/// [`MessageRouter::create_compact_blinded_paths`].
87628781
///
8763-
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
8764-
fn create_compact_blinded_path(&self) -> Result<BlindedPath, ()> {
8782+
/// Errors if the `MessageRouter` errors.
8783+
fn create_compact_blinded_paths(&self) -> Result<Vec<BlindedPath>, ()> {
87658784
let recipient = self.get_our_node_id();
87668785
let secp_ctx = &self.secp_ctx;
87678786

@@ -8782,7 +8801,6 @@ where
87828801

87838802
self.router
87848803
.create_compact_blinded_paths(recipient, peers, secp_ctx)
8785-
.and_then(|paths| paths.into_iter().next().ok_or(()))
87868804
}
87878805

87888806
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to

0 commit comments

Comments
 (0)