@@ -8376,8 +8376,10 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
8376
8376
let entropy = &*$self.entropy_source;
8377
8377
let secp_ctx = &$self.secp_ctx;
8378
8378
8379
- let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry)
8379
+ let path = $self.create_blinded_paths_using_absolute_expiry(absolute_expiry)
8380
+ .and_then(|paths| paths.into_iter().next().ok_or(()))
8380
8381
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8382
+
8381
8383
let builder = OfferBuilder::deriving_signing_pubkey(
8382
8384
node_id, expanded_key, entropy, secp_ctx
8383
8385
)
@@ -8448,8 +8450,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
8448
8450
let entropy = &*$self.entropy_source;
8449
8451
let secp_ctx = &$self.secp_ctx;
8450
8452
8451
- let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry))
8453
+ let path = $self.create_blinded_paths_using_absolute_expiry(Some(absolute_expiry))
8454
+ .and_then(|paths| paths.into_iter().next().ok_or(()))
8452
8455
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8456
+
8453
8457
let builder = RefundBuilder::deriving_payer_id(
8454
8458
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
8455
8459
)?
@@ -8470,6 +8474,12 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
8470
8474
}
8471
8475
} }
8472
8476
8477
+ /// Defines the maximum number of [`OffersMessage`] to be sent along different reply paths.
8478
+ /// Sending multiple requests increases the chances of successful delivery in case some
8479
+ /// paths are unavailable. However, only one invoice for a given [`PaymentId`] will be paid,
8480
+ /// even if multiple invoices are received.
8481
+ const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
8482
+
8473
8483
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>
8474
8484
where
8475
8485
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
@@ -8571,7 +8581,7 @@ where
8571
8581
Some(payer_note) => builder.payer_note(payer_note),
8572
8582
};
8573
8583
let invoice_request = builder.build_and_sign()?;
8574
- let reply_path = self.create_blinded_path ().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8584
+ let reply_paths = self.create_blinded_paths ().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8575
8585
8576
8586
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
8577
8587
@@ -8584,25 +8594,27 @@ where
8584
8594
8585
8595
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
8586
8596
if !offer.paths().is_empty() {
8587
- // Send as many invoice requests as there are paths in the offer (with an upper bound).
8588
- // Using only one path could result in a failure if the path no longer exists. But only
8589
- // one invoice for a given payment id will be paid, even if more than one is received.
8590
- const REQUEST_LIMIT: usize = 10;
8591
- for path in offer.paths().into_iter().take(REQUEST_LIMIT) {
8597
+ reply_paths
8598
+ .iter()
8599
+ .flat_map(|reply_path| offer.paths().iter().map(move |path| (path, reply_path)))
8600
+ .take(OFFERS_MESSAGE_REQUEST_LIMIT)
8601
+ .for_each(|(path, reply_path)| {
8602
+ let message = new_pending_onion_message(
8603
+ OffersMessage::InvoiceRequest(invoice_request.clone()),
8604
+ Destination::BlindedPath(path.clone()),
8605
+ Some(reply_path.clone()),
8606
+ );
8607
+ pending_offers_messages.push(message);
8608
+ });
8609
+ } else if let Some(signing_pubkey) = offer.signing_pubkey() {
8610
+ for reply_path in reply_paths {
8592
8611
let message = new_pending_onion_message(
8593
8612
OffersMessage::InvoiceRequest(invoice_request.clone()),
8594
- Destination::BlindedPath(path.clone() ),
8595
- Some(reply_path.clone() ),
8613
+ Destination::Node(signing_pubkey ),
8614
+ Some(reply_path),
8596
8615
);
8597
8616
pending_offers_messages.push(message);
8598
8617
}
8599
- } else if let Some(signing_pubkey) = offer.signing_pubkey() {
8600
- let message = new_pending_onion_message(
8601
- OffersMessage::InvoiceRequest(invoice_request),
8602
- Destination::Node(signing_pubkey),
8603
- Some(reply_path),
8604
- );
8605
- pending_offers_messages.push(message);
8606
8618
} else {
8607
8619
debug_assert!(false);
8608
8620
return Err(Bolt12SemanticError::MissingSigningPubkey);
@@ -8671,26 +8683,32 @@ where
8671
8683
)?;
8672
8684
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
8673
8685
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
8674
- let reply_path = self.create_blinded_path ()
8686
+ let reply_paths = self.create_blinded_paths ()
8675
8687
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8676
8688
8677
8689
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
8678
8690
if refund.paths().is_empty() {
8679
- let message = new_pending_onion_message(
8680
- OffersMessage::Invoice(invoice.clone()),
8681
- Destination::Node(refund.payer_id()),
8682
- Some(reply_path),
8683
- );
8684
- pending_offers_messages.push(message);
8685
- } else {
8686
- for path in refund.paths() {
8691
+ for reply_path in reply_paths {
8687
8692
let message = new_pending_onion_message(
8688
8693
OffersMessage::Invoice(invoice.clone()),
8689
- Destination::BlindedPath(path.clone ()),
8690
- Some(reply_path.clone() ),
8694
+ Destination::Node(refund.payer_id ()),
8695
+ Some(reply_path),
8691
8696
);
8692
8697
pending_offers_messages.push(message);
8693
8698
}
8699
+ } else {
8700
+ reply_paths
8701
+ .iter()
8702
+ .flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
8703
+ .take(OFFERS_MESSAGE_REQUEST_LIMIT)
8704
+ .for_each(|(path, reply_path)| {
8705
+ let message = new_pending_onion_message(
8706
+ OffersMessage::Invoice(invoice.clone()),
8707
+ Destination::BlindedPath(path.clone()),
8708
+ Some(reply_path.clone()),
8709
+ );
8710
+ pending_offers_messages.push(message);
8711
+ });
8694
8712
}
8695
8713
8696
8714
Ok(invoice)
@@ -8797,22 +8815,22 @@ where
8797
8815
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
8798
8816
}
8799
8817
8800
- /// Creates a blinded path by delegating to [`MessageRouter`] based on the path's intended
8801
- /// lifetime.
8818
+ /// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
8819
+ /// the path's intended lifetime.
8802
8820
///
8803
8821
/// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
8804
8822
/// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
8805
8823
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
8806
- fn create_blinded_path_using_absolute_expiry (
8824
+ fn create_blinded_paths_using_absolute_expiry (
8807
8825
&self, absolute_expiry: Option<Duration>
8808
- ) -> Result<BlindedPath, ()> {
8826
+ ) -> Result<Vec< BlindedPath> , ()> {
8809
8827
let now = self.duration_since_epoch();
8810
8828
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
8811
8829
8812
8830
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
8813
- self.create_compact_blinded_path ()
8831
+ self.create_compact_blinded_paths ()
8814
8832
} else {
8815
- self.create_blinded_path ()
8833
+ self.create_blinded_paths ()
8816
8834
}
8817
8835
}
8818
8836
@@ -8829,10 +8847,11 @@ where
8829
8847
now
8830
8848
}
8831
8849
8832
- /// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
8850
+ /// Creates a collection of blinded paths by delegating to
8851
+ /// [`MessageRouter::create_blinded_paths`].
8833
8852
///
8834
- /// Errors if the `MessageRouter` errors or returns an empty `Vec` .
8835
- fn create_blinded_path (&self) -> Result<BlindedPath, ()> {
8853
+ /// Errors if the `MessageRouter` errors.
8854
+ fn create_blinded_paths (&self) -> Result<Vec< BlindedPath> , ()> {
8836
8855
let recipient = self.get_our_node_id();
8837
8856
let secp_ctx = &self.secp_ctx;
8838
8857
@@ -8846,13 +8865,14 @@ where
8846
8865
8847
8866
self.router
8848
8867
.create_blinded_paths(recipient, peers, secp_ctx)
8849
- .and_then(|paths| paths.into_iter().next( ).ok_or(()))
8868
+ .and_then(|paths| (! paths.is_empty()).then(|| paths ).ok_or(()))
8850
8869
}
8851
8870
8852
- /// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
8871
+ /// Creates a collection of blinded paths by delegating to
8872
+ /// [`MessageRouter::create_compact_blinded_paths`].
8853
8873
///
8854
- /// Errors if the `MessageRouter` errors or returns an empty `Vec` .
8855
- fn create_compact_blinded_path (&self) -> Result<BlindedPath, ()> {
8874
+ /// Errors if the `MessageRouter` errors.
8875
+ fn create_compact_blinded_paths (&self) -> Result<Vec< BlindedPath> , ()> {
8856
8876
let recipient = self.get_our_node_id();
8857
8877
let secp_ctx = &self.secp_ctx;
8858
8878
@@ -8873,7 +8893,7 @@ where
8873
8893
8874
8894
self.router
8875
8895
.create_compact_blinded_paths(recipient, peers, secp_ctx)
8876
- .and_then(|paths| paths.into_iter().next( ).ok_or(()))
8896
+ .and_then(|paths| (! paths.is_empty()).then(|| paths ).ok_or(()))
8877
8897
}
8878
8898
8879
8899
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
0 commit comments