@@ -8621,8 +8621,10 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
86218621 let entropy = &*$self.entropy_source;
86228622 let secp_ctx = &$self.secp_ctx;
86238623
8624- let path = $self.create_blinded_path_using_absolute_expiry(OffersContext::Unknown {}, absolute_expiry)
8624+ let path = $self.create_blinded_paths_using_absolute_expiry(OffersContext::Unknown {}, absolute_expiry)
8625+ .and_then(|paths| paths.into_iter().next().ok_or(()))
86258626 .map_err(|_| Bolt12SemanticError::MissingPaths)?;
8627+
86268628 let builder = OfferBuilder::deriving_signing_pubkey(
86278629 node_id, expanded_key, entropy, secp_ctx
86288630 )
@@ -8694,8 +8696,10 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
86948696 let secp_ctx = &$self.secp_ctx;
86958697
86968698 let context = OffersContext::OutboundPayment { payment_id };
8697- let path = $self.create_blinded_path_using_absolute_expiry(context, Some(absolute_expiry))
8699+ let path = $self.create_blinded_paths_using_absolute_expiry(context, Some(absolute_expiry))
8700+ .and_then(|paths| paths.into_iter().next().ok_or(()))
86988701 .map_err(|_| Bolt12SemanticError::MissingPaths)?;
8702+
86998703 let builder = RefundBuilder::deriving_payer_id(
87008704 node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
87018705 )?
@@ -8716,6 +8720,13 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
87168720 }
87178721} }
87188722
8723+ /// Defines the maximum number of [`OffersMessage`] including different reply paths to be sent
8724+ /// along different paths.
8725+ /// Sending multiple requests increases the chances of successful delivery in case some
8726+ /// paths are unavailable. However, only one invoice for a given [`PaymentId`] will be paid,
8727+ /// even if multiple invoices are received.
8728+ const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
8729+
87198730impl<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>
87208731where
87218732 M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
@@ -8819,7 +8830,7 @@ where
88198830 let invoice_request = builder.build_and_sign()?;
88208831
88218832 let context = OffersContext::OutboundPayment { payment_id };
8822- let reply_path = self.create_blinded_path (context).map_err(|_| Bolt12SemanticError::MissingPaths)?;
8833+ let reply_paths = self.create_blinded_paths (context).map_err(|_| Bolt12SemanticError::MissingPaths)?;
88238834
88248835 let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
88258836
@@ -8832,25 +8843,27 @@ where
88328843
88338844 let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
88348845 if !offer.paths().is_empty() {
8835- // Send as many invoice requests as there are paths in the offer (with an upper bound).
8836- // Using only one path could result in a failure if the path no longer exists. But only
8837- // one invoice for a given payment id will be paid, even if more than one is received.
8838- const REQUEST_LIMIT: usize = 10;
8839- for path in offer.paths().into_iter().take(REQUEST_LIMIT) {
8846+ reply_paths
8847+ .iter()
8848+ .flat_map(|reply_path| offer.paths().iter().map(move |path| (path, reply_path)))
8849+ .take(OFFERS_MESSAGE_REQUEST_LIMIT)
8850+ .for_each(|(path, reply_path)| {
8851+ let message = new_pending_onion_message(
8852+ OffersMessage::InvoiceRequest(invoice_request.clone()),
8853+ Destination::BlindedPath(path.clone()),
8854+ Some(reply_path.clone()),
8855+ );
8856+ pending_offers_messages.push(message);
8857+ });
8858+ } else if let Some(signing_pubkey) = offer.signing_pubkey() {
8859+ for reply_path in reply_paths {
88408860 let message = new_pending_onion_message(
88418861 OffersMessage::InvoiceRequest(invoice_request.clone()),
8842- Destination::BlindedPath(path.clone() ),
8843- Some(reply_path.clone() ),
8862+ Destination::Node(signing_pubkey ),
8863+ Some(reply_path),
88448864 );
88458865 pending_offers_messages.push(message);
88468866 }
8847- } else if let Some(signing_pubkey) = offer.signing_pubkey() {
8848- let message = new_pending_onion_message(
8849- OffersMessage::InvoiceRequest(invoice_request),
8850- Destination::Node(signing_pubkey),
8851- Some(reply_path),
8852- );
8853- pending_offers_messages.push(message);
88548867 } else {
88558868 debug_assert!(false);
88568869 return Err(Bolt12SemanticError::MissingSigningPubkey);
@@ -8919,26 +8932,32 @@ where
89198932 )?;
89208933 let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
89218934 let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
8922- let reply_path = self.create_blinded_path (OffersContext::Unknown {})
8935+ let reply_paths = self.create_blinded_paths (OffersContext::Unknown {})
89238936 .map_err(|_| Bolt12SemanticError::MissingPaths)?;
89248937
89258938 let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
89268939 if refund.paths().is_empty() {
8927- let message = new_pending_onion_message(
8928- OffersMessage::Invoice(invoice.clone()),
8929- Destination::Node(refund.payer_id()),
8930- Some(reply_path),
8931- );
8932- pending_offers_messages.push(message);
8933- } else {
8934- for path in refund.paths() {
8940+ for reply_path in reply_paths {
89358941 let message = new_pending_onion_message(
89368942 OffersMessage::Invoice(invoice.clone()),
8937- Destination::BlindedPath(path.clone ()),
8938- Some(reply_path.clone() ),
8943+ Destination::Node(refund.payer_id ()),
8944+ Some(reply_path),
89398945 );
89408946 pending_offers_messages.push(message);
89418947 }
8948+ } else {
8949+ reply_paths
8950+ .iter()
8951+ .flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
8952+ .take(OFFERS_MESSAGE_REQUEST_LIMIT)
8953+ .for_each(|(path, reply_path)| {
8954+ let message = new_pending_onion_message(
8955+ OffersMessage::Invoice(invoice.clone()),
8956+ Destination::BlindedPath(path.clone()),
8957+ Some(reply_path.clone()),
8958+ );
8959+ pending_offers_messages.push(message);
8960+ });
89428961 }
89438962
89448963 Ok(invoice)
@@ -9045,22 +9064,22 @@ where
90459064 inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
90469065 }
90479066
9048- /// Creates a blinded path by delegating to [`MessageRouter`] based on the path's intended
9049- /// lifetime.
9067+ /// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
9068+ /// the path's intended lifetime.
90509069 ///
90519070 /// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
90529071 /// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
90539072 /// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
9054- fn create_blinded_path_using_absolute_expiry (
9073+ fn create_blinded_paths_using_absolute_expiry (
90559074 &self, context: OffersContext, absolute_expiry: Option<Duration>,
9056- ) -> Result<BlindedPath, ()> {
9075+ ) -> Result<Vec< BlindedPath> , ()> {
90579076 let now = self.duration_since_epoch();
90589077 let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
90599078
90609079 if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
9061- self.create_compact_blinded_path (context)
9080+ self.create_compact_blinded_paths (context)
90629081 } else {
9063- self.create_blinded_path (context)
9082+ self.create_blinded_paths (context)
90649083 }
90659084 }
90669085
@@ -9077,10 +9096,11 @@ where
90779096 now
90789097 }
90799098
9080- /// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
9099+ /// Creates a collection of blinded paths by delegating to
9100+ /// [`MessageRouter::create_blinded_paths`].
90819101 ///
9082- /// Errors if the `MessageRouter` errors or returns an empty `Vec` .
9083- fn create_blinded_path (&self, context: OffersContext) -> Result<BlindedPath, ()> {
9102+ /// Errors if the `MessageRouter` errors.
9103+ fn create_blinded_paths (&self, context: OffersContext) -> Result<Vec< BlindedPath> , ()> {
90849104 let recipient = self.get_our_node_id();
90859105 let secp_ctx = &self.secp_ctx;
90869106
@@ -9094,13 +9114,14 @@ where
90949114
90959115 self.router
90969116 .create_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
9097- .and_then(|paths| paths.into_iter().next( ).ok_or(()))
9117+ .and_then(|paths| (! paths.is_empty()).then(|| paths ).ok_or(()))
90989118 }
90999119
9100- /// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
9120+ /// Creates a collection of blinded paths by delegating to
9121+ /// [`MessageRouter::create_compact_blinded_paths`].
91019122 ///
9102- /// Errors if the `MessageRouter` errors or returns an empty `Vec` .
9103- fn create_compact_blinded_path (&self, context: OffersContext) -> Result<BlindedPath, ()> {
9123+ /// Errors if the `MessageRouter` errors.
9124+ fn create_compact_blinded_paths (&self, context: OffersContext) -> Result<Vec< BlindedPath> , ()> {
91049125 let recipient = self.get_our_node_id();
91059126 let secp_ctx = &self.secp_ctx;
91069127
@@ -9121,7 +9142,7 @@ where
91219142
91229143 self.router
91239144 .create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
9124- .and_then(|paths| paths.into_iter().next( ).ok_or(()))
9145+ .and_then(|paths| (! paths.is_empty()).then(|| paths ).ok_or(()))
91259146 }
91269147
91279148 /// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
0 commit comments