Skip to content

Commit d574de9

Browse files
Include invreq in payment onion when retrying async payments
While in the last commit we began including invoice requests in async payment onions on initial send, further work is needed to include them on retry. Here we begin storing invreqs in our retry data, and pass them along for inclusion in the onion on payment retry. Per BOLTs PR 1149, when paying a static invoice we need to include our original invoice request in the HTLC onion since the recipient wouldn't have received it previously.
1 parent 925a0cb commit d574de9

File tree

1 file changed

+35
-16
lines changed

1 file changed

+35
-16
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ pub(crate) enum PendingOutboundPayment {
9494
payment_secret: Option<PaymentSecret>,
9595
payment_metadata: Option<Vec<u8>>,
9696
keysend_preimage: Option<PaymentPreimage>,
97+
invoice_request: Option<InvoiceRequest>,
9798
custom_tlvs: Vec<(u64, Vec<u8>)>,
9899
pending_amt_msat: u64,
99100
/// Used to track the fee paid. Present iff the payment was serialized on 0.0.103+.
@@ -948,20 +949,33 @@ impl OutboundPayments {
948949
};
949950

950951
let payment_params = Some(route_params.payment_params.clone());
951-
let (retryable_payment, onion_session_privs) = Self::create_pending_payment(
952-
payment_hash, recipient_onion.clone(), keysend_preimage, &route, Some(retry_strategy),
953-
payment_params, entropy_source, best_block_height
954-
);
955-
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
952+
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
953+
let onion_session_privs = match outbounds.entry(payment_id) {
956954
hash_map::Entry::Occupied(entry) => match entry.get() {
957-
PendingOutboundPayment::InvoiceReceived { .. }
958-
| PendingOutboundPayment::StaticInvoiceReceived { .. } => {
955+
PendingOutboundPayment::InvoiceReceived { .. } => {
956+
let (retryable_payment, onion_session_privs) = Self::create_pending_payment(
957+
payment_hash, recipient_onion.clone(), keysend_preimage, None, &route,
958+
Some(retry_strategy), payment_params, entropy_source, best_block_height
959+
);
959960
*entry.into_mut() = retryable_payment;
961+
onion_session_privs
962+
},
963+
PendingOutboundPayment::StaticInvoiceReceived { .. } => {
964+
let invreq = if let PendingOutboundPayment::StaticInvoiceReceived { invoice_request, .. } = entry.remove() {
965+
invoice_request
966+
} else { unreachable!() };
967+
let (retryable_payment, onion_session_privs) = Self::create_pending_payment(
968+
payment_hash, recipient_onion.clone(), keysend_preimage, Some(invreq), &route,
969+
Some(retry_strategy), payment_params, entropy_source, best_block_height
970+
);
971+
outbounds.insert(payment_id, retryable_payment);
972+
onion_session_privs
960973
},
961974
_ => return Err(Bolt12PaymentError::DuplicateInvoice),
962975
},
963976
hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice),
964-
}
977+
};
978+
core::mem::drop(outbounds);
965979

966980
let result = self.pay_route_internal(
967981
&route, payment_hash, &recipient_onion, keysend_preimage, invoice_request, payment_id,
@@ -1324,14 +1338,14 @@ impl OutboundPayments {
13241338
}
13251339
}
13261340
}
1327-
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs) = {
1341+
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request) = {
13281342
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
13291343
match outbounds.entry(payment_id) {
13301344
hash_map::Entry::Occupied(mut payment) => {
13311345
match payment.get() {
13321346
PendingOutboundPayment::Retryable {
13331347
total_msat, keysend_preimage, payment_secret, payment_metadata,
1334-
custom_tlvs, pending_amt_msat, ..
1348+
custom_tlvs, pending_amt_msat, invoice_request, ..
13351349
} => {
13361350
const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
13371351
let retry_amt_msat = route.get_total_amount();
@@ -1354,6 +1368,7 @@ impl OutboundPayments {
13541368
custom_tlvs: custom_tlvs.clone(),
13551369
};
13561370
let keysend_preimage = *keysend_preimage;
1371+
let invoice_request = invoice_request.clone();
13571372

13581373
let mut onion_session_privs = Vec::with_capacity(route.paths.len());
13591374
for _ in 0..route.paths.len() {
@@ -1366,7 +1381,7 @@ impl OutboundPayments {
13661381

13671382
payment.get_mut().increment_attempts();
13681383

1369-
(total_msat, recipient_onion, keysend_preimage, onion_session_privs)
1384+
(total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request)
13701385
},
13711386
PendingOutboundPayment::Legacy { .. } => {
13721387
log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
@@ -1404,8 +1419,8 @@ impl OutboundPayments {
14041419
}
14051420
};
14061421
let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, keysend_preimage,
1407-
None, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height,
1408-
&send_payment_along_path);
1422+
invoice_request.as_ref(), payment_id, Some(total_msat), onion_session_privs, node_signer,
1423+
best_block_height, &send_payment_along_path);
14091424
log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res);
14101425
if let Err(e) = res {
14111426
self.handle_pay_route_err(e, payment_id, payment_hash, route, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
@@ -1557,7 +1572,7 @@ impl OutboundPayments {
15571572
hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::DuplicatePayment),
15581573
hash_map::Entry::Vacant(entry) => {
15591574
let (payment, onion_session_privs) = Self::create_pending_payment(
1560-
payment_hash, recipient_onion, keysend_preimage, route, retry_strategy,
1575+
payment_hash, recipient_onion, keysend_preimage, None, route, retry_strategy,
15611576
payment_params, entropy_source, best_block_height
15621577
);
15631578
entry.insert(payment);
@@ -1568,8 +1583,9 @@ impl OutboundPayments {
15681583

15691584
fn create_pending_payment<ES: Deref>(
15701585
payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
1571-
keysend_preimage: Option<PaymentPreimage>, route: &Route, retry_strategy: Option<Retry>,
1572-
payment_params: Option<PaymentParameters>, entropy_source: &ES, best_block_height: u32
1586+
keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<InvoiceRequest>,
1587+
route: &Route, retry_strategy: Option<Retry>, payment_params: Option<PaymentParameters>,
1588+
entropy_source: &ES, best_block_height: u32
15731589
) -> (PendingOutboundPayment, Vec<[u8; 32]>)
15741590
where
15751591
ES::Target: EntropySource,
@@ -1590,6 +1606,7 @@ impl OutboundPayments {
15901606
payment_secret: recipient_onion.payment_secret,
15911607
payment_metadata: recipient_onion.payment_metadata,
15921608
keysend_preimage,
1609+
invoice_request,
15931610
custom_tlvs: recipient_onion.custom_tlvs,
15941611
starting_block_height: best_block_height,
15951612
total_msat: route.get_total_amount(),
@@ -2151,6 +2168,7 @@ impl OutboundPayments {
21512168
payment_secret: None, // only used for retries, and we'll never retry on startup
21522169
payment_metadata: None, // only used for retries, and we'll never retry on startup
21532170
keysend_preimage: None, // only used for retries, and we'll never retry on startup
2171+
invoice_request: None, // only used for retries, and we'll never retry on startup
21542172
custom_tlvs: Vec::new(), // only used for retries, and we'll never retry on startup
21552173
pending_amt_msat: path_amt,
21562174
pending_fee_msat: Some(path_fee),
@@ -2237,6 +2255,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
22372255
(9, custom_tlvs, optional_vec),
22382256
(10, starting_block_height, required),
22392257
(11, remaining_max_total_routing_fee_msat, option),
2258+
(13, invoice_request, option),
22402259
(not_written, retry_strategy, (static_value, None)),
22412260
(not_written, attempts, (static_value, PaymentAttempts::new())),
22422261
},

0 commit comments

Comments
 (0)