@@ -61,11 +61,11 @@ use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
61
61
use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
62
62
#[cfg(test)]
63
63
use crate::ln::outbound_payment;
64
- use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration};
64
+ use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, RetryableInvoiceRequest, SendAlongPathArgs, StaleExpiration};
65
65
use crate::ln::wire::Encode;
66
66
use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
67
67
use crate::offers::invoice_error::InvoiceError;
68
- use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
68
+ use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequest, InvoiceRequestBuilder};
69
69
use crate::offers::nonce::Nonce;
70
70
use crate::offers::offer::{Offer, OfferBuilder};
71
71
use crate::offers::parse::Bolt12SemanticError;
@@ -3105,7 +3105,7 @@ where
3105
3105
3106
3106
outbound_scid_aliases: Mutex::new(new_hash_set()),
3107
3107
pending_inbound_payments: Mutex::new(new_hash_map()),
3108
- pending_outbound_payments: OutboundPayments::new(),
3108
+ pending_outbound_payments: OutboundPayments::new(new_hash_map() ),
3109
3109
forward_htlcs: Mutex::new(new_hash_map()),
3110
3110
decode_update_add_htlcs: Mutex::new(new_hash_map()),
3111
3111
claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: new_hash_map(), pending_claiming_payments: new_hash_map() }),
@@ -9005,7 +9005,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
9005
9005
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
9006
9006
$self.pending_outbound_payments
9007
9007
.add_new_awaiting_invoice(
9008
- payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
9008
+ payment_id, expiration, retry_strategy, max_total_routing_fee_msat, None,
9009
9009
)
9010
9010
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
9011
9011
@@ -9131,17 +9131,30 @@ where
9131
9131
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
9132
9132
9133
9133
let expiration = StaleExpiration::TimerTicks(1);
9134
+ let retryable_invoice_request = RetryableInvoiceRequest {
9135
+ invoice_request: invoice_request.clone(),
9136
+ nonce,
9137
+ };
9134
9138
self.pending_outbound_payments
9135
9139
.add_new_awaiting_invoice(
9136
- payment_id, expiration, retry_strategy, max_total_routing_fee_msat
9140
+ payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
9141
+ Some(retryable_invoice_request)
9137
9142
)
9138
9143
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
9139
9144
9145
+ self.enqueue_invoice_request(invoice_request, reply_paths)
9146
+ }
9147
+
9148
+ fn enqueue_invoice_request(
9149
+ &self,
9150
+ invoice_request: InvoiceRequest,
9151
+ reply_paths: Vec<BlindedMessagePath>,
9152
+ ) -> Result<(), Bolt12SemanticError> {
9140
9153
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
9141
- if !offer .paths().is_empty() {
9154
+ if !invoice_request .paths().is_empty() {
9142
9155
reply_paths
9143
9156
.iter()
9144
- .flat_map(|reply_path| offer .paths().iter().map(move |path| (path, reply_path)))
9157
+ .flat_map(|reply_path| invoice_request .paths().iter().map(move |path| (path, reply_path)))
9145
9158
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
9146
9159
.for_each(|(path, reply_path)| {
9147
9160
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
@@ -9151,7 +9164,7 @@ where
9151
9164
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
9152
9165
pending_offers_messages.push((message, instructions));
9153
9166
});
9154
- } else if let Some(signing_pubkey) = offer .signing_pubkey() {
9167
+ } else if let Some(signing_pubkey) = invoice_request .signing_pubkey() {
9155
9168
for reply_path in reply_paths {
9156
9169
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
9157
9170
destination: Destination::Node(signing_pubkey),
@@ -10811,6 +10824,39 @@ where
10811
10824
"Dual-funded channels not supported".to_owned(),
10812
10825
msg.channel_id.clone())), counterparty_node_id);
10813
10826
}
10827
+
10828
+ fn message_received(&self) {
10829
+ for (payment_id, retryable_invoice_request) in self
10830
+ .pending_outbound_payments
10831
+ .release_invoice_requests_awaiting_invoice()
10832
+ {
10833
+ let RetryableInvoiceRequest { invoice_request, nonce } = retryable_invoice_request;
10834
+ let hmac = payment_id.hmac_for_offer_payment(nonce, &self.inbound_payment_key);
10835
+ let context = OffersContext::OutboundPayment {
10836
+ payment_id,
10837
+ nonce,
10838
+ hmac: Some(hmac)
10839
+ };
10840
+ match self.create_blinded_paths(context) {
10841
+ Ok(reply_paths) => match self.enqueue_invoice_request(invoice_request, reply_paths) {
10842
+ Ok(_) => {}
10843
+ Err(_) => {
10844
+ log_warn!(self.logger,
10845
+ "Retry failed for an invoice request with payment_id: {}",
10846
+ payment_id
10847
+ );
10848
+ }
10849
+ },
10850
+ Err(_) => {
10851
+ log_warn!(self.logger,
10852
+ "Retry failed for an invoice request with payment_id: {}. \
10853
+ Reason: router could not find a blinded path to include as the reply path",
10854
+ payment_id
10855
+ );
10856
+ }
10857
+ }
10858
+ }
10859
+ }
10814
10860
}
10815
10861
10816
10862
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
@@ -12227,10 +12273,7 @@ where
12227
12273
}
12228
12274
pending_outbound_payments = Some(outbounds);
12229
12275
}
12230
- let pending_outbounds = OutboundPayments {
12231
- pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
12232
- retry_lock: Mutex::new(())
12233
- };
12276
+ let pending_outbounds = OutboundPayments::new(pending_outbound_payments.unwrap());
12234
12277
12235
12278
// We have to replay (or skip, if they were completed after we wrote the `ChannelManager`)
12236
12279
// each `ChannelMonitorUpdate` in `in_flight_monitor_updates`. After doing so, we have to
0 commit comments