Skip to content

Commit a5d85bd

Browse files
Abandon payment if retry fails in process_pending_htlcs
1 parent f871210 commit a5d85bd

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3370,7 +3370,8 @@ where
33703370

33713371
let best_block_height = self.best_block.read().unwrap().height();
33723372
self.pending_outbound_payments.check_retry_payments(&self.router, || self.list_usable_channels(),
3373-
|| self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, &self.logger,
3373+
|| self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height,
3374+
&self.pending_events, &self.logger,
33743375
|path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv|
33753376
self.send_payment_along_path(path, payment_params, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv));
33763377

lightning/src/ln/outbound_payment.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,8 @@ impl OutboundPayments {
491491

492492
pub(super) fn check_retry_payments<R: Deref, ES: Deref, NS: Deref, SP, IH, FH, L: Deref>(
493493
&self, router: &R, first_hops: FH, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS,
494-
best_block_height: u32, logger: &L, send_payment_along_path: SP,
494+
best_block_height: u32, pending_events: &Mutex<Vec<events::Event>>, logger: &L,
495+
send_payment_along_path: SP,
495496
)
496497
where
497498
R::Target: Router,
@@ -525,10 +526,13 @@ impl OutboundPayments {
525526
}
526527
}
527528
}
529+
core::mem::drop(outbounds);
528530
if let Some((payment_id, route_params)) = retry_id_route_params {
529-
core::mem::drop(outbounds);
530531
if let Err(e) = self.pay_internal(payment_id, None, route_params, router, first_hops(), &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, &send_payment_along_path) {
531532
log_info!(logger, "Errored retrying payment: {:?}", e);
533+
// If we error on retry, there is no chance of the payment succeeding and no HTLCs have
534+
// been irrevocably committed to, so we can safely abandon.
535+
self.abandon_payment(payment_id, pending_events);
532536
}
533537
} else { break }
534538
}

lightning/src/ln/payment_tests.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,7 @@ enum AutoRetry {
16151615
FailAttempts,
16161616
FailTimeout,
16171617
FailOnRestart,
1618+
FailOnRetry,
16181619
}
16191620

16201621
#[test]
@@ -1624,6 +1625,7 @@ fn automatic_retries() {
16241625
do_automatic_retries(AutoRetry::FailAttempts);
16251626
do_automatic_retries(AutoRetry::FailTimeout);
16261627
do_automatic_retries(AutoRetry::FailOnRestart);
1628+
do_automatic_retries(AutoRetry::FailOnRetry);
16271629
}
16281630
fn do_automatic_retries(test: AutoRetry) {
16291631
// Test basic automatic payment retries in ChannelManager. See individual `test` variant comments
@@ -1812,6 +1814,25 @@ fn do_automatic_retries(test: AutoRetry) {
18121814
assert_eq!(msg_events.len(), 0);
18131815

18141816
nodes[0].node.abandon_payment(PaymentId(payment_hash.0));
1817+
let mut events = nodes[0].node.get_and_clear_pending_events();
1818+
assert_eq!(events.len(), 1);
1819+
match events[0] {
1820+
Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id } => {
1821+
assert_eq!(payment_hash, *ev_payment_hash);
1822+
assert_eq!(PaymentId(payment_hash.0), *ev_payment_id);
1823+
},
1824+
_ => panic!("Unexpected event"),
1825+
}
1826+
} else if test == AutoRetry::FailOnRetry {
1827+
nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
1828+
pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
1829+
1830+
// We retry payments in `process_pending_htlc_forwards`. Since our channel closed, we should
1831+
// fail to find a route.
1832+
nodes[0].node.process_pending_htlc_forwards();
1833+
let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
1834+
assert_eq!(msg_events.len(), 0);
1835+
18151836
let mut events = nodes[0].node.get_and_clear_pending_events();
18161837
assert_eq!(events.len(), 1);
18171838
match events[0] {

0 commit comments

Comments
 (0)