Skip to content

Commit d917dbc

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 a9a4126 commit d917dbc

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 24 additions & 12 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+.
@@ -947,12 +948,18 @@ impl OutboundPayments {
947948
};
948949

949950
let payment_params = Some(route_params.payment_params.clone());
951+
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
952+
let mut invoice_request_opt = outbounds.get(&payment_id).and_then(|pmt| {
953+
if let PendingOutboundPayment::StaticInvoiceReceived { invoice_request, .. } = pmt {
954+
Some(invoice_request.clone())
955+
} else {
956+
None
957+
}
958+
});
950959
let (retryable_payment, onion_session_privs) = self.create_pending_payment(
951-
payment_hash, recipient_onion.clone(), keysend_preimage, &route, Some(retry_strategy),
952-
payment_params, entropy_source, best_block_height
960+
payment_hash, recipient_onion.clone(), keysend_preimage, invoice_request_opt.take(), &route,
961+
Some(retry_strategy), payment_params, entropy_source, best_block_height
953962
);
954-
let mut invoice_request_opt = None;
955-
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
956963
match outbounds.entry(payment_id) {
957964
hash_map::Entry::Occupied(entry) => match entry.remove() {
958965
PendingOutboundPayment::InvoiceReceived { .. } => {
@@ -1328,14 +1335,14 @@ impl OutboundPayments {
13281335
}
13291336
}
13301337
}
1331-
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs) = {
1338+
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request) = {
13321339
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
13331340
match outbounds.entry(payment_id) {
13341341
hash_map::Entry::Occupied(mut payment) => {
13351342
match payment.get() {
13361343
PendingOutboundPayment::Retryable {
13371344
total_msat, keysend_preimage, payment_secret, payment_metadata,
1338-
custom_tlvs, pending_amt_msat, ..
1345+
custom_tlvs, pending_amt_msat, invoice_request, ..
13391346
} => {
13401347
const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
13411348
let retry_amt_msat = route.get_total_amount();
@@ -1358,6 +1365,7 @@ impl OutboundPayments {
13581365
custom_tlvs: custom_tlvs.clone(),
13591366
};
13601367
let keysend_preimage = *keysend_preimage;
1368+
let invoice_request = invoice_request.clone();
13611369

13621370
let mut onion_session_privs = Vec::with_capacity(route.paths.len());
13631371
for _ in 0..route.paths.len() {
@@ -1370,7 +1378,7 @@ impl OutboundPayments {
13701378

13711379
payment.get_mut().increment_attempts();
13721380

1373-
(total_msat, recipient_onion, keysend_preimage, onion_session_privs)
1381+
(total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request)
13741382
},
13751383
PendingOutboundPayment::Legacy { .. } => {
13761384
log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
@@ -1408,8 +1416,8 @@ impl OutboundPayments {
14081416
}
14091417
};
14101418
let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, keysend_preimage,
1411-
None, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height,
1412-
&send_payment_along_path);
1419+
invoice_request.as_ref(), payment_id, Some(total_msat), onion_session_privs, node_signer,
1420+
best_block_height, &send_payment_along_path);
14131421
log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res);
14141422
if let Err(e) = res {
14151423
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);
@@ -1561,7 +1569,7 @@ impl OutboundPayments {
15611569
hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::DuplicatePayment),
15621570
hash_map::Entry::Vacant(entry) => {
15631571
let (payment, onion_session_privs) = self.create_pending_payment(
1564-
payment_hash, recipient_onion, keysend_preimage, route, retry_strategy,
1572+
payment_hash, recipient_onion, keysend_preimage, None, route, retry_strategy,
15651573
payment_params, entropy_source, best_block_height
15661574
);
15671575
entry.insert(payment);
@@ -1572,8 +1580,9 @@ impl OutboundPayments {
15721580

15731581
fn create_pending_payment<ES: Deref>(
15741582
&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
1575-
keysend_preimage: Option<PaymentPreimage>, route: &Route, retry_strategy: Option<Retry>,
1576-
payment_params: Option<PaymentParameters>, entropy_source: &ES, best_block_height: u32
1583+
keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<InvoiceRequest>,
1584+
route: &Route, retry_strategy: Option<Retry>, payment_params: Option<PaymentParameters>,
1585+
entropy_source: &ES, best_block_height: u32
15771586
) -> (PendingOutboundPayment, Vec<[u8; 32]>)
15781587
where
15791588
ES::Target: EntropySource,
@@ -1594,6 +1603,7 @@ impl OutboundPayments {
15941603
payment_secret: recipient_onion.payment_secret,
15951604
payment_metadata: recipient_onion.payment_metadata,
15961605
keysend_preimage,
1606+
invoice_request,
15971607
custom_tlvs: recipient_onion.custom_tlvs,
15981608
starting_block_height: best_block_height,
15991609
total_msat: route.get_total_amount(),
@@ -2155,6 +2165,7 @@ impl OutboundPayments {
21552165
payment_secret: None, // only used for retries, and we'll never retry on startup
21562166
payment_metadata: None, // only used for retries, and we'll never retry on startup
21572167
keysend_preimage: None, // only used for retries, and we'll never retry on startup
2168+
invoice_request: None, // only used for retries, and we'll never retry on startup
21582169
custom_tlvs: Vec::new(), // only used for retries, and we'll never retry on startup
21592170
pending_amt_msat: path_amt,
21602171
pending_fee_msat: Some(path_fee),
@@ -2241,6 +2252,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
22412252
(9, custom_tlvs, optional_vec),
22422253
(10, starting_block_height, required),
22432254
(11, remaining_max_total_routing_fee_msat, option),
2255+
(13, invoice_request, option),
22442256
(not_written, retry_strategy, (static_value, None)),
22452257
(not_written, attempts, (static_value, PaymentAttempts::new())),
22462258
},

0 commit comments

Comments
 (0)