Skip to content

Commit 88abc24

Browse files
committed
Add InvoiceRequest field and awaiting_invoice_flag
- Introduce InvoiceRequest as a field in AwaitingInvoice. - Use this field to recreate InvoiceRequest messages for retrying payments still awaiting an invoice. - Introduce awaiting_invoice_flag to track if there are any PendingOutboundPayments::AwaitingInvoice with the corresponding InvoiceRequest. - This flag helps determine the state of pending_outbound_payments without explicitly locking its mutex.
1 parent 1d0c6c6 commit 88abc24

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8371,7 +8371,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
83718371
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
83728372
$self.pending_outbound_payments
83738373
.add_new_awaiting_invoice(
8374-
payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
8374+
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, None
83758375
)
83768376
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
83778377

@@ -8487,7 +8487,7 @@ where
84878487
let expiration = StaleExpiration::TimerTicks(1);
84888488
self.pending_outbound_payments
84898489
.add_new_awaiting_invoice(
8490-
payment_id, expiration, retry_strategy, max_total_routing_fee_msat
8490+
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, Some(invoice_request.clone())
84918491
)
84928492
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
84938493

@@ -8517,6 +8517,8 @@ where
85178517
return Err(Bolt12SemanticError::MissingSigningPubkey);
85188518
}
85198519

8520+
self.pending_outbound_payments.awaiting_invoice_flag.store(true, Ordering::SeqCst);
8521+
85208522
Ok(())
85218523
}
85228524

@@ -11437,9 +11439,12 @@ where
1143711439
}
1143811440
let pending_outbounds = OutboundPayments {
1143911441
pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
11442+
awaiting_invoice_flag: AtomicBool::new(false),
1144011443
retry_lock: Mutex::new(())
1144111444
};
1144211445

11446+
pending_outbounds.set_awaiting_invoice_flag();
11447+
1144311448
// We have to replay (or skip, if they were completed after we wrote the `ChannelManager`)
1144411449
// each `ChannelMonitorUpdate` in `in_flight_monitor_updates`. After doing so, we have to
1144511450
// check that each channel we have isn't newer than the latest `ChannelMonitorUpdate`(s) we

lightning/src/ln/outbound_payment.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use bitcoin::hashes::Hash;
1313
use bitcoin::hashes::sha256::Hash as Sha256;
1414
use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
1515

16+
use crate::offers::invoice_request::InvoiceRequest;
1617
use crate::sign::{EntropySource, NodeSigner, Recipient};
1718
use crate::events::{self, PaymentFailureReason};
1819
use crate::ln::types::{PaymentHash, PaymentPreimage, PaymentSecret};
@@ -31,6 +32,7 @@ use crate::util::ser::ReadableArgs;
3132

3233
use core::fmt::{self, Display, Formatter};
3334
use core::ops::Deref;
35+
use core::sync::atomic::{AtomicBool, Ordering};
3436
use core::time::Duration;
3537

3638
use crate::prelude::*;
@@ -52,6 +54,7 @@ pub(crate) enum PendingOutboundPayment {
5254
expiration: StaleExpiration,
5355
retry_strategy: Retry,
5456
max_total_routing_fee_msat: Option<u64>,
57+
invoice_request: Option<InvoiceRequest>,
5558
},
5659
InvoiceReceived {
5760
payment_hash: PaymentHash,
@@ -677,13 +680,15 @@ pub(super) struct SendAlongPathArgs<'a> {
677680

678681
pub(super) struct OutboundPayments {
679682
pub(super) pending_outbound_payments: Mutex<HashMap<PaymentId, PendingOutboundPayment>>,
683+
pub(super) awaiting_invoice_flag: AtomicBool,
680684
pub(super) retry_lock: Mutex<()>,
681685
}
682686

683687
impl OutboundPayments {
684688
pub(super) fn new() -> Self {
685689
Self {
686690
pending_outbound_payments: Mutex::new(new_hash_map()),
691+
awaiting_invoice_flag: AtomicBool::new(false),
687692
retry_lock: Mutex::new(()),
688693
}
689694
}
@@ -1310,7 +1315,7 @@ impl OutboundPayments {
13101315

13111316
pub(super) fn add_new_awaiting_invoice(
13121317
&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry,
1313-
max_total_routing_fee_msat: Option<u64>
1318+
max_total_routing_fee_msat: Option<u64>, invoice_request: Option<InvoiceRequest>
13141319
) -> Result<(), ()> {
13151320
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
13161321
match pending_outbounds.entry(payment_id) {
@@ -1320,6 +1325,7 @@ impl OutboundPayments {
13201325
expiration,
13211326
retry_strategy,
13221327
max_total_routing_fee_msat,
1328+
invoice_request,
13231329
});
13241330

13251331
Ok(())
@@ -1786,6 +1792,30 @@ impl OutboundPayments {
17861792
pub fn clear_pending_payments(&self) {
17871793
self.pending_outbound_payments.lock().unwrap().clear()
17881794
}
1795+
1796+
pub fn set_awaiting_invoice_flag(&self) {
1797+
let pending_outbound_payments = self.pending_outbound_payments.lock().unwrap();
1798+
let has_invoice_requests = pending_outbound_payments.values().any(|payment| {
1799+
matches!(payment, PendingOutboundPayment::AwaitingInvoice { invoice_request: Some(_), .. })
1800+
});
1801+
self.awaiting_invoice_flag.store(has_invoice_requests, Ordering::SeqCst);
1802+
}
1803+
1804+
pub fn get_invoice_request_awaiting_invoice(&self) -> Vec<InvoiceRequest> {
1805+
if !self.awaiting_invoice_flag.load(Ordering::SeqCst) {
1806+
return vec![];
1807+
}
1808+
let mut pending_outbound_payments = self.pending_outbound_payments.lock().unwrap();
1809+
let invoice_requests = pending_outbound_payments.values_mut()
1810+
.filter_map(|payment| match payment {
1811+
PendingOutboundPayment::AwaitingInvoice { invoice_request, .. } => invoice_request.take(),
1812+
_ => None,
1813+
})
1814+
.collect();
1815+
1816+
self.awaiting_invoice_flag.store(false, Ordering::SeqCst);
1817+
invoice_requests
1818+
}
17891819
}
17901820

17911821
/// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a
@@ -1841,6 +1871,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
18411871
(0, expiration, required),
18421872
(2, retry_strategy, required),
18431873
(4, max_total_routing_fee_msat, option),
1874+
(6, invoice_request, option),
18441875
},
18451876
(7, InvoiceReceived) => {
18461877
(0, payment_hash, required),
@@ -2078,7 +2109,7 @@ mod tests {
20782109
assert!(!outbound_payments.has_pending_payments());
20792110
assert!(
20802111
outbound_payments.add_new_awaiting_invoice(
2081-
payment_id, expiration, Retry::Attempts(0), None
2112+
payment_id, expiration, Retry::Attempts(0), None, None
20822113
).is_ok()
20832114
);
20842115
assert!(outbound_payments.has_pending_payments());
@@ -2104,14 +2135,14 @@ mod tests {
21042135

21052136
assert!(
21062137
outbound_payments.add_new_awaiting_invoice(
2107-
payment_id, expiration, Retry::Attempts(0), None
2138+
payment_id, expiration, Retry::Attempts(0), None, None
21082139
).is_ok()
21092140
);
21102141
assert!(outbound_payments.has_pending_payments());
21112142

21122143
assert!(
21132144
outbound_payments.add_new_awaiting_invoice(
2114-
payment_id, expiration, Retry::Attempts(0), None
2145+
payment_id, expiration, Retry::Attempts(0), None, None
21152146
).is_err()
21162147
);
21172148
}
@@ -2127,7 +2158,7 @@ mod tests {
21272158
assert!(!outbound_payments.has_pending_payments());
21282159
assert!(
21292160
outbound_payments.add_new_awaiting_invoice(
2130-
payment_id, expiration, Retry::Attempts(0), None
2161+
payment_id, expiration, Retry::Attempts(0), None, None
21312162
).is_ok()
21322163
);
21332164
assert!(outbound_payments.has_pending_payments());
@@ -2153,14 +2184,14 @@ mod tests {
21532184

21542185
assert!(
21552186
outbound_payments.add_new_awaiting_invoice(
2156-
payment_id, expiration, Retry::Attempts(0), None
2187+
payment_id, expiration, Retry::Attempts(0), None, None
21572188
).is_ok()
21582189
);
21592190
assert!(outbound_payments.has_pending_payments());
21602191

21612192
assert!(
21622193
outbound_payments.add_new_awaiting_invoice(
2163-
payment_id, expiration, Retry::Attempts(0), None
2194+
payment_id, expiration, Retry::Attempts(0), None, None
21642195
).is_err()
21652196
);
21662197
}
@@ -2175,7 +2206,7 @@ mod tests {
21752206
assert!(!outbound_payments.has_pending_payments());
21762207
assert!(
21772208
outbound_payments.add_new_awaiting_invoice(
2178-
payment_id, expiration, Retry::Attempts(0), None
2209+
payment_id, expiration, Retry::Attempts(0), None, None
21792210
).is_ok()
21802211
);
21812212
assert!(outbound_payments.has_pending_payments());
@@ -2208,7 +2239,7 @@ mod tests {
22082239

22092240
assert!(
22102241
outbound_payments.add_new_awaiting_invoice(
2211-
payment_id, expiration, Retry::Attempts(0), None
2242+
payment_id, expiration, Retry::Attempts(0), None, None
22122243
).is_ok()
22132244
);
22142245
assert!(outbound_payments.has_pending_payments());
@@ -2270,7 +2301,7 @@ mod tests {
22702301
assert!(
22712302
outbound_payments.add_new_awaiting_invoice(
22722303
payment_id, expiration, Retry::Attempts(0),
2273-
Some(invoice.amount_msats() / 100 + 50_000)
2304+
Some(invoice.amount_msats() / 100 + 50_000), None
22742305
).is_ok()
22752306
);
22762307
assert!(outbound_payments.has_pending_payments());
@@ -2367,7 +2398,7 @@ mod tests {
23672398

23682399
assert!(
23692400
outbound_payments.add_new_awaiting_invoice(
2370-
payment_id, expiration, Retry::Attempts(0), Some(1234)
2401+
payment_id, expiration, Retry::Attempts(0), Some(1234), None
23712402
).is_ok()
23722403
);
23732404
assert!(outbound_payments.has_pending_payments());

lightning/src/offers/invoice_request.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,13 @@ impl Writeable for InvoiceRequestContents {
10101010
}
10111011
}
10121012

1013+
impl Readable for InvoiceRequest<> {
1014+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1015+
let bytes: WithoutLength<Vec<u8>> = Readable::read(reader)?;
1016+
Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue)
1017+
}
1018+
}
1019+
10131020
/// Valid type range for invoice_request TLV records.
10141021
pub(super) const INVOICE_REQUEST_TYPES: core::ops::Range<u64> = 80..160;
10151022

0 commit comments

Comments
 (0)