Skip to content

Commit ebf220a

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 321f2a8 commit ebf220a

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
@@ -8408,7 +8408,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
84088408
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
84098409
$self.pending_outbound_payments
84108410
.add_new_awaiting_invoice(
8411-
payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
8411+
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, None
84128412
)
84138413
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
84148414

@@ -8524,7 +8524,7 @@ where
85248524
let expiration = StaleExpiration::TimerTicks(1);
85258525
self.pending_outbound_payments
85268526
.add_new_awaiting_invoice(
8527-
payment_id, expiration, retry_strategy, max_total_routing_fee_msat
8527+
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, Some(invoice_request.clone())
85288528
)
85298529
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
85308530

@@ -8554,6 +8554,8 @@ where
85548554
return Err(Bolt12SemanticError::MissingSigningPubkey);
85558555
}
85568556

8557+
self.pending_outbound_payments.awaiting_invoice_flag.store(true, Ordering::SeqCst);
8558+
85578559
Ok(())
85588560
}
85598561

@@ -11508,9 +11510,12 @@ where
1150811510
}
1150911511
let pending_outbounds = OutboundPayments {
1151011512
pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
11513+
awaiting_invoice_flag: AtomicBool::new(false),
1151111514
retry_lock: Mutex::new(())
1151211515
};
1151311516

11517+
pending_outbounds.set_awaiting_invoice_flag();
11518+
1151411519
// We have to replay (or skip, if they were completed after we wrote the `ChannelManager`)
1151511520
// each `ChannelMonitorUpdate` in `in_flight_monitor_updates`. After doing so, we have to
1151611521
// 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
@@ -22,6 +22,7 @@ use crate::ln::channelmanager::{EventCompletionAction, HTLCSource, PaymentId};
2222
use crate::ln::onion_utils;
2323
use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
2424
use crate::offers::invoice::Bolt12Invoice;
25+
use crate::offers::invoice_request::InvoiceRequest;
2526
use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router};
2627
use crate::sign::{EntropySource, NodeSigner, Recipient};
2728
use crate::util::errors::APIError;
@@ -33,6 +34,7 @@ use crate::util::ser::ReadableArgs;
3334

3435
use core::fmt::{self, Display, Formatter};
3536
use core::ops::Deref;
37+
use core::sync::atomic::{AtomicBool, Ordering};
3638
use core::time::Duration;
3739

3840
use crate::prelude::*;
@@ -54,6 +56,7 @@ pub(crate) enum PendingOutboundPayment {
5456
expiration: StaleExpiration,
5557
retry_strategy: Retry,
5658
max_total_routing_fee_msat: Option<u64>,
59+
invoice_request: Option<InvoiceRequest>,
5760
},
5861
InvoiceReceived {
5962
payment_hash: PaymentHash,
@@ -679,13 +682,15 @@ pub(super) struct SendAlongPathArgs<'a> {
679682

680683
pub(super) struct OutboundPayments {
681684
pub(super) pending_outbound_payments: Mutex<HashMap<PaymentId, PendingOutboundPayment>>,
685+
pub(super) awaiting_invoice_flag: AtomicBool,
682686
pub(super) retry_lock: Mutex<()>,
683687
}
684688

685689
impl OutboundPayments {
686690
pub(super) fn new() -> Self {
687691
Self {
688692
pending_outbound_payments: Mutex::new(new_hash_map()),
693+
awaiting_invoice_flag: AtomicBool::new(false),
689694
retry_lock: Mutex::new(()),
690695
}
691696
}
@@ -1337,7 +1342,7 @@ impl OutboundPayments {
13371342

13381343
pub(super) fn add_new_awaiting_invoice(
13391344
&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry,
1340-
max_total_routing_fee_msat: Option<u64>
1345+
max_total_routing_fee_msat: Option<u64>, invoice_request: Option<InvoiceRequest>
13411346
) -> Result<(), ()> {
13421347
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
13431348
match pending_outbounds.entry(payment_id) {
@@ -1347,6 +1352,7 @@ impl OutboundPayments {
13471352
expiration,
13481353
retry_strategy,
13491354
max_total_routing_fee_msat,
1355+
invoice_request,
13501356
});
13511357

13521358
Ok(())
@@ -1813,6 +1819,30 @@ impl OutboundPayments {
18131819
pub fn clear_pending_payments(&self) {
18141820
self.pending_outbound_payments.lock().unwrap().clear()
18151821
}
1822+
1823+
pub fn set_awaiting_invoice_flag(&self) {
1824+
let pending_outbound_payments = self.pending_outbound_payments.lock().unwrap();
1825+
let has_invoice_requests = pending_outbound_payments.values().any(|payment| {
1826+
matches!(payment, PendingOutboundPayment::AwaitingInvoice { invoice_request: Some(_), .. })
1827+
});
1828+
self.awaiting_invoice_flag.store(has_invoice_requests, Ordering::SeqCst);
1829+
}
1830+
1831+
pub fn get_invoice_request_awaiting_invoice(&self) -> Vec<InvoiceRequest> {
1832+
if !self.awaiting_invoice_flag.load(Ordering::SeqCst) {
1833+
return vec![];
1834+
}
1835+
let mut pending_outbound_payments = self.pending_outbound_payments.lock().unwrap();
1836+
let invoice_requests = pending_outbound_payments.values_mut()
1837+
.filter_map(|payment| match payment {
1838+
PendingOutboundPayment::AwaitingInvoice { invoice_request, .. } => invoice_request.take(),
1839+
_ => None,
1840+
})
1841+
.collect();
1842+
1843+
self.awaiting_invoice_flag.store(false, Ordering::SeqCst);
1844+
invoice_requests
1845+
}
18161846
}
18171847

18181848
/// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a
@@ -1868,6 +1898,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
18681898
(0, expiration, required),
18691899
(2, retry_strategy, required),
18701900
(4, max_total_routing_fee_msat, option),
1901+
(5, invoice_request, option),
18711902
},
18721903
(7, InvoiceReceived) => {
18731904
(0, payment_hash, required),
@@ -2106,7 +2137,7 @@ mod tests {
21062137
assert!(!outbound_payments.has_pending_payments());
21072138
assert!(
21082139
outbound_payments.add_new_awaiting_invoice(
2109-
payment_id, expiration, Retry::Attempts(0), None
2140+
payment_id, expiration, Retry::Attempts(0), None, None
21102141
).is_ok()
21112142
);
21122143
assert!(outbound_payments.has_pending_payments());
@@ -2132,14 +2163,14 @@ mod tests {
21322163

21332164
assert!(
21342165
outbound_payments.add_new_awaiting_invoice(
2135-
payment_id, expiration, Retry::Attempts(0), None
2166+
payment_id, expiration, Retry::Attempts(0), None, None
21362167
).is_ok()
21372168
);
21382169
assert!(outbound_payments.has_pending_payments());
21392170

21402171
assert!(
21412172
outbound_payments.add_new_awaiting_invoice(
2142-
payment_id, expiration, Retry::Attempts(0), None
2173+
payment_id, expiration, Retry::Attempts(0), None, None
21432174
).is_err()
21442175
);
21452176
}
@@ -2155,7 +2186,7 @@ mod tests {
21552186
assert!(!outbound_payments.has_pending_payments());
21562187
assert!(
21572188
outbound_payments.add_new_awaiting_invoice(
2158-
payment_id, expiration, Retry::Attempts(0), None
2189+
payment_id, expiration, Retry::Attempts(0), None, None
21592190
).is_ok()
21602191
);
21612192
assert!(outbound_payments.has_pending_payments());
@@ -2181,14 +2212,14 @@ mod tests {
21812212

21822213
assert!(
21832214
outbound_payments.add_new_awaiting_invoice(
2184-
payment_id, expiration, Retry::Attempts(0), None
2215+
payment_id, expiration, Retry::Attempts(0), None, None
21852216
).is_ok()
21862217
);
21872218
assert!(outbound_payments.has_pending_payments());
21882219

21892220
assert!(
21902221
outbound_payments.add_new_awaiting_invoice(
2191-
payment_id, expiration, Retry::Attempts(0), None
2222+
payment_id, expiration, Retry::Attempts(0), None, None
21922223
).is_err()
21932224
);
21942225
}
@@ -2203,7 +2234,7 @@ mod tests {
22032234
assert!(!outbound_payments.has_pending_payments());
22042235
assert!(
22052236
outbound_payments.add_new_awaiting_invoice(
2206-
payment_id, expiration, Retry::Attempts(0), None
2237+
payment_id, expiration, Retry::Attempts(0), None, None
22072238
).is_ok()
22082239
);
22092240
assert!(outbound_payments.has_pending_payments());
@@ -2237,7 +2268,7 @@ mod tests {
22372268

22382269
assert!(
22392270
outbound_payments.add_new_awaiting_invoice(
2240-
payment_id, expiration, Retry::Attempts(0), None
2271+
payment_id, expiration, Retry::Attempts(0), None, None
22412272
).is_ok()
22422273
);
22432274
assert!(outbound_payments.has_pending_payments());
@@ -2301,7 +2332,7 @@ mod tests {
23012332
assert!(
23022333
outbound_payments.add_new_awaiting_invoice(
23032334
payment_id, expiration, Retry::Attempts(0),
2304-
Some(invoice.amount_msats() / 100 + 50_000)
2335+
Some(invoice.amount_msats() / 100 + 50_000), None
23052336
).is_ok()
23062337
);
23072338
assert!(outbound_payments.has_pending_payments());
@@ -2401,7 +2432,7 @@ mod tests {
24012432

24022433
assert!(
24032434
outbound_payments.add_new_awaiting_invoice(
2404-
payment_id, expiration, Retry::Attempts(0), Some(1234)
2435+
payment_id, expiration, Retry::Attempts(0), Some(1234), None
24052436
).is_ok()
24062437
);
24072438
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)