Skip to content

Commit 3926df0

Browse files
Unify session_priv removal on PaymentSendFailure
When an outbound payment fails while paying to a route, we need to remove the session_privs for each failed path in the outbound payment. Previously we were sometimes removing in pay_route_internal and sometimes in handle_pay_route_err, so refactor this so we always remove in handle_pay_route_err.
1 parent 0758bd7 commit 3926df0

File tree

1 file changed

+19
-25
lines changed

1 file changed

+19
-25
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,10 +1467,22 @@ impl OutboundPayments {
14671467
{
14681468
match err {
14691469
PaymentSendFailure::AllFailedResendSafe(errs) => {
1470+
self.remove_session_privs(payment_id, route.paths.iter().zip(onion_session_privs.iter()));
14701471
Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, errs.into_iter().map(|e| Err(e)), logger, pending_events);
14711472
self.find_route_and_send_payment(payment_hash, payment_id, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
14721473
},
14731474
PaymentSendFailure::PartialFailure { failed_paths_retry: Some(mut retry), results, .. } => {
1475+
let filtered = results.iter().zip(route.paths.iter().zip(onion_session_privs.iter()))
1476+
.filter_map(|(path_res, (path, session_priv))| {
1477+
match path_res {
1478+
// While a MonitorUpdateInProgress is an Err(_), the payment is still
1479+
// considered "in flight" and we shouldn't remove it from the
1480+
// PendingOutboundPayment set.
1481+
Ok(_) | Err(APIError::MonitorUpdateInProgress) => None,
1482+
_ => Some((path, session_priv))
1483+
}
1484+
});
1485+
self.remove_session_privs(payment_id, filtered);
14741486
Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut retry, route.paths, results.into_iter(), logger, pending_events);
14751487
// Some paths were sent, even if we failed to send the full MPP value our recipient may
14761488
// misbehave and claim the funds, at which point we have to consider the payment sent, so
@@ -1484,13 +1496,13 @@ impl OutboundPayments {
14841496
},
14851497
PaymentSendFailure::PathParameterError(results) => {
14861498
log_error!(logger, "Failed to send to route due to parameter error in a single path. Your router is buggy");
1487-
self.remove_session_privs(payment_id, &route, onion_session_privs);
1499+
self.remove_session_privs(payment_id, route.paths.iter().zip(onion_session_privs.iter()));
14881500
Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, results.into_iter(), logger, pending_events);
14891501
self.abandon_payment(payment_id, PaymentFailureReason::UnexpectedError, pending_events);
14901502
},
14911503
PaymentSendFailure::ParameterError(e) => {
14921504
log_error!(logger, "Failed to send to route due to parameter error: {:?}. Your router is buggy", e);
1493-
self.remove_session_privs(payment_id, &route, onion_session_privs);
1505+
self.remove_session_privs(payment_id, route.paths.iter().zip(onion_session_privs.iter()));
14941506
self.abandon_payment(payment_id, PaymentFailureReason::UnexpectedError, pending_events);
14951507
},
14961508
PaymentSendFailure::DuplicatePayment => debug_assert!(false), // unreachable
@@ -1532,12 +1544,12 @@ impl OutboundPayments {
15321544

15331545
// If a payment fails after adding the pending payment but before any HTLCs are locked into
15341546
// channels, we need to clear the session_privs in order for abandoning the payment to succeed.
1535-
fn remove_session_privs(
1536-
&self, payment_id: PaymentId, route: &Route, onion_session_privs: Vec<[u8; 32]>
1547+
fn remove_session_privs<'a, I: Iterator<Item = (&'a Path, &'a [u8; 32])>>(
1548+
&self, payment_id: PaymentId, path_session_priv: I
15371549
) {
15381550
if let Some(payment) = self.pending_outbound_payments.lock().unwrap().get_mut(&payment_id) {
1539-
for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.into_iter()) {
1540-
let removed = payment.remove(&session_priv_bytes, Some(path));
1551+
for (path, session_priv_bytes) in path_session_priv {
1552+
let removed = payment.remove(session_priv_bytes, Some(path));
15411553
debug_assert!(removed, "This can't happen as the payment has an entry for this path added by callers");
15421554
}
15431555
} else {
@@ -1819,29 +1831,11 @@ impl OutboundPayments {
18191831
let mut results = Vec::new();
18201832
debug_assert_eq!(route.paths.len(), onion_session_privs.len());
18211833
for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.iter()) {
1822-
let mut path_res = send_payment_along_path(SendAlongPathArgs {
1834+
let path_res = send_payment_along_path(SendAlongPathArgs {
18231835
path: &path, payment_hash: &payment_hash, recipient_onion, total_value,
18241836
cur_height, payment_id, keysend_preimage: &keysend_preimage, invoice_request,
18251837
session_priv_bytes: *session_priv_bytes
18261838
});
1827-
match path_res {
1828-
Ok(_) => {},
1829-
Err(APIError::MonitorUpdateInProgress) => {
1830-
// While a MonitorUpdateInProgress is an Err(_), the payment is still
1831-
// considered "in flight" and we shouldn't remove it from the
1832-
// PendingOutboundPayment set.
1833-
},
1834-
Err(_) => {
1835-
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
1836-
if let Some(payment) = pending_outbounds.get_mut(&payment_id) {
1837-
let removed = payment.remove(&session_priv_bytes, Some(path));
1838-
debug_assert!(removed, "This can't happen as the payment has an entry for this path added by callers");
1839-
} else {
1840-
debug_assert!(false, "This can't happen as the payment was added by callers");
1841-
path_res = Err(APIError::APIMisuseError { err: "Internal error: payment disappeared during processing. Please report this bug!".to_owned() });
1842-
}
1843-
}
1844-
}
18451839
results.push(path_res);
18461840
}
18471841
let mut has_ok = false;

0 commit comments

Comments
 (0)