@@ -8285,8 +8285,10 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
8285
8285
let entropy = &*$self.entropy_source;
8286
8286
let secp_ctx = &$self.secp_ctx;
8287
8287
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(()))
8289
8290
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8291
+
8290
8292
let builder = OfferBuilder::deriving_signing_pubkey(
8291
8293
node_id, expanded_key, entropy, secp_ctx
8292
8294
)
@@ -8357,8 +8359,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
8357
8359
let entropy = &*$self.entropy_source;
8358
8360
let secp_ctx = &$self.secp_ctx;
8359
8361
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(()))
8361
8364
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8365
+
8362
8366
let builder = RefundBuilder::deriving_payer_id(
8363
8367
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
8364
8368
)?
@@ -8379,6 +8383,12 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
8379
8383
}
8380
8384
} }
8381
8385
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
+
8382
8392
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>
8383
8393
where
8384
8394
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
@@ -8480,7 +8490,7 @@ where
8480
8490
Some(payer_note) => builder.payer_note(payer_note),
8481
8491
};
8482
8492
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)?;
8484
8494
8485
8495
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
8486
8496
@@ -8493,25 +8503,27 @@ where
8493
8503
8494
8504
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
8495
8505
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 {
8501
8520
let message = new_pending_onion_message(
8502
8521
OffersMessage::InvoiceRequest(invoice_request.clone()),
8503
- Destination::BlindedPath(path.clone() ),
8504
- Some(reply_path.clone() ),
8522
+ Destination::Node(signing_pubkey ),
8523
+ Some(reply_path),
8505
8524
);
8506
8525
pending_offers_messages.push(message);
8507
8526
}
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);
8515
8527
} else {
8516
8528
debug_assert!(false);
8517
8529
return Err(Bolt12SemanticError::MissingSigningPubkey);
@@ -8580,26 +8592,32 @@ where
8580
8592
)?;
8581
8593
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
8582
8594
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 ()
8584
8596
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8585
8597
8586
8598
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
8587
8599
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 {
8596
8601
let message = new_pending_onion_message(
8597
8602
OffersMessage::Invoice(invoice.clone()),
8598
- Destination::BlindedPath(path.clone ()),
8599
- Some(reply_path.clone() ),
8603
+ Destination::Node(refund.payer_id ()),
8604
+ Some(reply_path),
8600
8605
);
8601
8606
pending_offers_messages.push(message);
8602
8607
}
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
+ });
8603
8621
}
8604
8622
8605
8623
Ok(invoice)
@@ -8706,22 +8724,22 @@ where
8706
8724
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
8707
8725
}
8708
8726
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.
8711
8729
///
8712
8730
/// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
8713
8731
/// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
8714
8732
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
8715
- fn create_blinded_path_using_absolute_expiry (
8733
+ fn create_blinded_paths_using_absolute_expiry (
8716
8734
&self, absolute_expiry: Option<Duration>
8717
- ) -> Result<BlindedPath, ()> {
8735
+ ) -> Result<Vec< BlindedPath> , ()> {
8718
8736
let now = self.duration_since_epoch();
8719
8737
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
8720
8738
8721
8739
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
8722
- self.create_compact_blinded_path ()
8740
+ self.create_compact_blinded_paths ()
8723
8741
} else {
8724
- self.create_blinded_path ()
8742
+ self.create_blinded_paths ()
8725
8743
}
8726
8744
}
8727
8745
@@ -8738,10 +8756,11 @@ where
8738
8756
now
8739
8757
}
8740
8758
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`].
8742
8761
///
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> , ()> {
8745
8764
let recipient = self.get_our_node_id();
8746
8765
let secp_ctx = &self.secp_ctx;
8747
8766
@@ -8755,13 +8774,13 @@ where
8755
8774
8756
8775
self.router
8757
8776
.create_blinded_paths(recipient, peers, secp_ctx)
8758
- .and_then(|paths| paths.into_iter().next().ok_or(()))
8759
8777
}
8760
8778
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`].
8762
8781
///
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> , ()> {
8765
8784
let recipient = self.get_our_node_id();
8766
8785
let secp_ctx = &self.secp_ctx;
8767
8786
@@ -8782,7 +8801,6 @@ where
8782
8801
8783
8802
self.router
8784
8803
.create_compact_blinded_paths(recipient, peers, secp_ctx)
8785
- .and_then(|paths| paths.into_iter().next().ok_or(()))
8786
8804
}
8787
8805
8788
8806
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
0 commit comments