Skip to content

Commit 1224dac

Browse files
On initial send retries, avoid previously failed scids
Previously, we could have tried the same failed channels over and over until retries are exhausted.
1 parent b826d17 commit 1224dac

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,8 @@ impl OutboundPayments {
735735

736736
fn handle_pay_route_err<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
737737
&self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, route: Route,
738-
route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>, inflight_htlcs: &IH,
739-
entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L,
738+
mut route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>,
739+
inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L,
740740
pending_events: &Mutex<Vec<events::Event>>, send_payment_along_path: &SP,
741741
)
742742
where
@@ -750,11 +750,11 @@ impl OutboundPayments {
750750
{
751751
match err {
752752
PaymentSendFailure::AllFailedResendSafe(errs) => {
753-
Self::push_payment_path_failed_evs(payment_id, payment_hash, route.paths, errs.into_iter().map(|e| Err(e)), pending_events);
753+
Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, errs.into_iter().map(|e| Err(e)), pending_events);
754754
self.retry_payment_internal(payment_id, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
755755
},
756-
PaymentSendFailure::PartialFailure { failed_paths_retry: Some(retry), results, .. } => {
757-
Self::push_payment_path_failed_evs(payment_id, payment_hash, route.paths, results.into_iter(), pending_events);
756+
PaymentSendFailure::PartialFailure { failed_paths_retry: Some(mut retry), results, .. } => {
757+
Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut retry, route.paths, results.into_iter(), pending_events);
758758
// Some paths were sent, even if we failed to send the full MPP value our recipient may
759759
// misbehave and claim the funds, at which point we have to consider the payment sent, so
760760
// return `Ok()` here, ignoring any retry errors.
@@ -766,7 +766,7 @@ impl OutboundPayments {
766766
// initial HTLC-Add messages yet.
767767
},
768768
PaymentSendFailure::PathParameterError(results) => {
769-
Self::push_payment_path_failed_evs(payment_id, payment_hash, route.paths, results.into_iter(), pending_events);
769+
Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, results.into_iter(), pending_events);
770770
self.abandon_payment(payment_id, pending_events);
771771
},
772772
PaymentSendFailure::ParameterError(e) => {
@@ -777,9 +777,9 @@ impl OutboundPayments {
777777
}
778778
}
779779

780-
fn push_payment_path_failed_evs<I: ExactSizeIterator + Iterator<Item = Result<(), APIError>>>(
781-
payment_id: PaymentId, payment_hash: PaymentHash, paths: Vec<Vec<RouteHop>>, path_results: I,
782-
pending_events: &Mutex<Vec<events::Event>>
780+
fn push_path_failed_evs_and_scids<I: ExactSizeIterator + Iterator<Item = Result<(), APIError>>>(
781+
payment_id: PaymentId, payment_hash: PaymentHash, route_params: &mut RouteParameters,
782+
paths: Vec<Vec<RouteHop>>, path_results: I, pending_events: &Mutex<Vec<events::Event>>
783783
) {
784784
let mut events = pending_events.lock().unwrap();
785785
debug_assert_eq!(paths.len(), path_results.len());
@@ -788,7 +788,9 @@ impl OutboundPayments {
788788
let failed_scid = if let APIError::InvalidRoute { .. } = e {
789789
None
790790
} else {
791-
Some(path[0].short_channel_id)
791+
let scid = path[0].short_channel_id;
792+
route_params.payment_params.previously_failed_channels.push(scid);
793+
Some(scid)
792794
};
793795
events.push(events::Event::PaymentPathFailed {
794796
payment_id: Some(payment_id),

lightning/src/ln/payment_tests.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,13 +1857,15 @@ fn auto_retry_partial_failure() {
18571857
payment_params: Some(route_params.payment_params.clone()),
18581858
};
18591859
nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route));
1860+
let mut payment_params = route_params.payment_params.clone();
1861+
payment_params.previously_failed_channels.push(chan_2_id);
18601862
nodes[0].router.expect_find_route(RouteParameters {
1861-
payment_params: route_params.payment_params.clone(),
1862-
final_value_msat: amt_msat / 2, final_cltv_expiry_delta: TEST_FINAL_CLTV
1863+
payment_params, final_value_msat: amt_msat / 2, final_cltv_expiry_delta: TEST_FINAL_CLTV
18631864
}, Ok(retry_1_route));
1865+
let mut payment_params = route_params.payment_params.clone();
1866+
payment_params.previously_failed_channels.push(chan_3_id);
18641867
nodes[0].router.expect_find_route(RouteParameters {
1865-
payment_params: route_params.payment_params.clone(),
1866-
final_value_msat: amt_msat / 4, final_cltv_expiry_delta: TEST_FINAL_CLTV
1868+
payment_params, final_value_msat: amt_msat / 4, final_cltv_expiry_delta: TEST_FINAL_CLTV
18671869
}, Ok(retry_2_route));
18681870

18691871
// Send a payment that will partially fail on send, then partially fail on retry, then succeed.
@@ -2113,8 +2115,10 @@ fn retry_multi_path_single_failed_payment() {
21132115
// On retry, split the payment across both channels.
21142116
route.paths[0][0].fee_msat = 50_000_001;
21152117
route.paths[1][0].fee_msat = 50_000_000;
2118+
let mut pay_params = route.payment_params.clone().unwrap();
2119+
pay_params.previously_failed_channels.push(chans[1].short_channel_id.unwrap());
21162120
nodes[0].router.expect_find_route(RouteParameters {
2117-
payment_params: route.payment_params.clone().unwrap(),
2121+
payment_params: pay_params,
21182122
// Note that the second request here requests the amount we originally failed to send,
21192123
// not the amount remaining on the full payment, which should be changed.
21202124
final_value_msat: 100_000_001, final_cltv_expiry_delta: TEST_FINAL_CLTV
@@ -2196,9 +2200,11 @@ fn immediate_retry_on_failure() {
21962200
route.paths[0][0].short_channel_id = chans[1].short_channel_id.unwrap();
21972201
route.paths[0][0].fee_msat = 50_000_000;
21982202
route.paths[1][0].fee_msat = 50_000_001;
2203+
let mut pay_params = route_params.payment_params.clone();
2204+
pay_params.previously_failed_channels.push(chans[0].short_channel_id.unwrap());
21992205
nodes[0].router.expect_find_route(RouteParameters {
2200-
payment_params: route_params.payment_params.clone(),
2201-
final_value_msat: amt_msat, final_cltv_expiry_delta: TEST_FINAL_CLTV
2206+
payment_params: pay_params, final_value_msat: amt_msat,
2207+
final_cltv_expiry_delta: TEST_FINAL_CLTV
22022208
}, Ok(route.clone()));
22032209

22042210
nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();

0 commit comments

Comments
 (0)