Skip to content

Commit 9543edb

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 <lightning/bolts#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 7f71532 commit 9543edb

File tree

1 file changed

+38
-16
lines changed

1 file changed

+38
-16
lines changed

lightning/src/ln/outbound_payment.rs

+38-16
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,36 @@ 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+
macro_rules! create_pending_payment {
953+
($invreq_opt: expr) => {
954+
self.create_pending_payment(
955+
payment_hash, recipient_onion.clone(), keysend_preimage, $invreq_opt, &route,
956+
Some(retry_strategy), payment_params, entropy_source, best_block_height
957+
)
958+
}
959+
}
960+
961+
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
962+
let onion_session_privs = match outbounds.entry(payment_id) {
956963
hash_map::Entry::Occupied(entry) => match entry.get() {
957-
PendingOutboundPayment::InvoiceReceived { .. }
958-
| PendingOutboundPayment::StaticInvoiceReceived { .. } => {
964+
PendingOutboundPayment::InvoiceReceived { .. } => {
965+
let (retryable_payment, onion_session_privs) = create_pending_payment!(None);
959966
*entry.into_mut() = retryable_payment;
967+
onion_session_privs
968+
},
969+
PendingOutboundPayment::StaticInvoiceReceived { .. } => {
970+
let invreq = if let PendingOutboundPayment::StaticInvoiceReceived { invoice_request, .. } = entry.remove() {
971+
invoice_request
972+
} else { unreachable!() };
973+
let (retryable_payment, onion_session_privs) = create_pending_payment!(Some(invreq));
974+
outbounds.insert(payment_id, retryable_payment);
975+
onion_session_privs
960976
},
961977
_ => return Err(Bolt12PaymentError::DuplicateInvoice),
962978
},
963979
hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice),
964-
}
980+
};
981+
core::mem::drop(outbounds);
965982

966983
let result = self.pay_route_internal(
967984
&route, payment_hash, &recipient_onion, keysend_preimage, invoice_request, payment_id,
@@ -1324,14 +1341,14 @@ impl OutboundPayments {
13241341
}
13251342
}
13261343
}
1327-
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs) = {
1344+
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request) = {
13281345
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
13291346
match outbounds.entry(payment_id) {
13301347
hash_map::Entry::Occupied(mut payment) => {
13311348
match payment.get() {
13321349
PendingOutboundPayment::Retryable {
13331350
total_msat, keysend_preimage, payment_secret, payment_metadata,
1334-
custom_tlvs, pending_amt_msat, ..
1351+
custom_tlvs, pending_amt_msat, invoice_request, ..
13351352
} => {
13361353
const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
13371354
let retry_amt_msat = route.get_total_amount();
@@ -1354,6 +1371,7 @@ impl OutboundPayments {
13541371
custom_tlvs: custom_tlvs.clone(),
13551372
};
13561373
let keysend_preimage = *keysend_preimage;
1374+
let invoice_request = invoice_request.clone();
13571375

13581376
let mut onion_session_privs = Vec::with_capacity(route.paths.len());
13591377
for _ in 0..route.paths.len() {
@@ -1366,7 +1384,7 @@ impl OutboundPayments {
13661384

13671385
payment.get_mut().increment_attempts();
13681386

1369-
(total_msat, recipient_onion, keysend_preimage, onion_session_privs)
1387+
(total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request)
13701388
},
13711389
PendingOutboundPayment::Legacy { .. } => {
13721390
log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
@@ -1404,8 +1422,8 @@ impl OutboundPayments {
14041422
}
14051423
};
14061424
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);
1425+
invoice_request.as_ref(), payment_id, Some(total_msat), onion_session_privs, node_signer,
1426+
best_block_height, &send_payment_along_path);
14091427
log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res);
14101428
if let Err(e) = res {
14111429
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 +1575,7 @@ impl OutboundPayments {
15571575
hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::DuplicatePayment),
15581576
hash_map::Entry::Vacant(entry) => {
15591577
let (payment, onion_session_privs) = self.create_pending_payment(
1560-
payment_hash, recipient_onion, keysend_preimage, route, retry_strategy,
1578+
payment_hash, recipient_onion, keysend_preimage, None, route, retry_strategy,
15611579
payment_params, entropy_source, best_block_height
15621580
);
15631581
entry.insert(payment);
@@ -1568,8 +1586,9 @@ impl OutboundPayments {
15681586

15691587
fn create_pending_payment<ES: Deref>(
15701588
&self, 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
1589+
keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<InvoiceRequest>,
1590+
route: &Route, retry_strategy: Option<Retry>, payment_params: Option<PaymentParameters>,
1591+
entropy_source: &ES, best_block_height: u32
15731592
) -> (PendingOutboundPayment, Vec<[u8; 32]>)
15741593
where
15751594
ES::Target: EntropySource,
@@ -1590,6 +1609,7 @@ impl OutboundPayments {
15901609
payment_secret: recipient_onion.payment_secret,
15911610
payment_metadata: recipient_onion.payment_metadata,
15921611
keysend_preimage,
1612+
invoice_request,
15931613
custom_tlvs: recipient_onion.custom_tlvs,
15941614
starting_block_height: best_block_height,
15951615
total_msat: route.get_total_amount(),
@@ -2151,6 +2171,7 @@ impl OutboundPayments {
21512171
payment_secret: None, // only used for retries, and we'll never retry on startup
21522172
payment_metadata: None, // only used for retries, and we'll never retry on startup
21532173
keysend_preimage: None, // only used for retries, and we'll never retry on startup
2174+
invoice_request: None, // only used for retries, and we'll never retry on startup
21542175
custom_tlvs: Vec::new(), // only used for retries, and we'll never retry on startup
21552176
pending_amt_msat: path_amt,
21562177
pending_fee_msat: Some(path_fee),
@@ -2237,6 +2258,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
22372258
(9, custom_tlvs, optional_vec),
22382259
(10, starting_block_height, required),
22392260
(11, remaining_max_total_routing_fee_msat, option),
2261+
(13, invoice_request, option),
22402262
(not_written, retry_strategy, (static_value, None)),
22412263
(not_written, attempts, (static_value, PaymentAttempts::new())),
22422264
},

0 commit comments

Comments
 (0)