Skip to content

Commit c2d73cd

Browse files
committed
Drop return value from fail_htlc_backwards, clarify docs
`ChannelManager::fail_htlc_backwards`' bool return value is quite confusing - just because it returns false doesn't mean the payment wasn't (already) failed. Worse, in some race cases around shutdown where a payment was claimed before an unclean shutdown and then retried on startup, `fail_htlc_backwards` could return true even though (a duplicate copy of the same payment) was claimed, but the claim event has not been seen by the user yet. While its possible to use it correctly, its somewhat confusing to have a return value at all, and definitely lends itself to misuse. Instead, we should push users towards a model where they don't care if `fail_htlc_backwards` succeeds - either they've locally marked the payment as failed (prior to seeing any `PaymentReceived` events) and will fail any attempts to pay it, or they have not and the payment is still receivable until its timeout time is reached. We can revisit this decision based on user feedback, but will need to very carefully document the potential failure modes here if we do.
1 parent b7881fe commit c2d73cd

6 files changed

+30
-23
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
840840
events::Event::PaymentReceived { payment_hash, .. } => {
841841
if claim_set.insert(payment_hash.0) {
842842
if $fail {
843-
assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
843+
nodes[$node].fail_htlc_backwards(&payment_hash);
844844
} else {
845845
nodes[$node].claim_funds(PaymentPreimage(payment_hash.0));
846846
}

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
831831
let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
832832

833833
// Fail the payment backwards, failing the monitor update on nodes[1]'s receipt of the RAA
834-
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1));
834+
nodes[2].node.fail_htlc_backwards(&payment_hash_1);
835835
expect_pending_htlcs_forwardable!(nodes[2]);
836836
check_added_monitors!(nodes[2], 1);
837837

@@ -1696,7 +1696,7 @@ fn test_monitor_update_on_pending_forwards() {
16961696
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
16971697

16981698
let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
1699-
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1));
1699+
nodes[2].node.fail_htlc_backwards(&payment_hash_1);
17001700
expect_pending_htlcs_forwardable!(nodes[2]);
17011701
check_added_monitors!(nodes[2], 1);
17021702

@@ -2468,7 +2468,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
24682468
payment_preimage,
24692469
};
24702470
if second_fails {
2471-
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash));
2471+
nodes[2].node.fail_htlc_backwards(&payment_hash);
24722472
expect_pending_htlcs_forwardable!(nodes[2]);
24732473
check_added_monitors!(nodes[2], 1);
24742474
get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());

lightning/src/ln/channelmanager.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3506,9 +3506,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
35063506
/// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect
35073507
/// after a PaymentReceived event, failing the HTLC back to its origin and freeing resources
35083508
/// along the path (including in our own channel on which we received it).
3509-
/// Returns false if no payment was found to fail backwards, true if the process of failing the
3510-
/// HTLC backwards has been started.
3511-
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool {
3509+
///
3510+
/// Note that in some cases around unclean shutdown, it is possible the payment may have
3511+
/// already been claimed by you via [`ChannelManager::claim_funds`] prior to you seeing (a
3512+
/// second copy of) the [`events::Event::PaymentReceived`] event. Alternatively, the payment
3513+
/// may have already been failed automatically by LDK if it was nearing its expiration time.
3514+
///
3515+
/// While LDK will never claim a payment automatically on your behalf (i.e. without you calling
3516+
/// [`ChannelManager::claim_funds`]), you should still monitor for
3517+
/// [`events::Event::PaymentClaimed`] events even for payments you intend to fail, especially on
3518+
/// startup during which time claims which were in-progress at shutdown may be replayed.
3519+
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) {
35123520
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
35133521

35143522
let mut channel_state = Some(self.channel_state.lock().unwrap());
@@ -3523,8 +3531,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
35233531
HTLCSource::PreviousHopData(htlc.prev_hop), payment_hash,
35243532
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data });
35253533
}
3526-
true
3527-
} else { false }
3534+
}
35283535
}
35293536

35303537
/// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code

lightning/src/ln/functional_test_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,7 +1727,7 @@ pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe
17271727
for path in expected_paths.iter() {
17281728
assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id());
17291729
}
1730-
assert!(expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
1730+
expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash);
17311731
expect_pending_htlcs_forwardable!(expected_paths[0].last().unwrap());
17321732

17331733
pass_failed_payment_back(origin_node, expected_paths, skip_last, our_payment_hash);
@@ -1833,7 +1833,7 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe
18331833
}
18341834

18351835
// Ensure that fail_htlc_backwards is idempotent.
1836-
assert!(!expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
1836+
expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash);
18371837
assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_events().is_empty());
18381838
assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events().is_empty());
18391839
check_added_monitors!(expected_paths[0].last().unwrap(), 0);

lightning/src/ln/functional_tests.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,7 +3087,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
30873087
let (_, second_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
30883088
let (_, third_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
30893089

3090-
assert!(nodes[2].node.fail_htlc_backwards(&first_payment_hash));
3090+
nodes[2].node.fail_htlc_backwards(&first_payment_hash);
30913091
expect_pending_htlcs_forwardable!(nodes[2]);
30923092
check_added_monitors!(nodes[2], 1);
30933093
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -3100,7 +3100,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
31003100
let bs_raa = commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true, false, true);
31013101
// Drop the last RAA from 3 -> 2
31023102

3103-
assert!(nodes[2].node.fail_htlc_backwards(&second_payment_hash));
3103+
nodes[2].node.fail_htlc_backwards(&second_payment_hash);
31043104
expect_pending_htlcs_forwardable!(nodes[2]);
31053105
check_added_monitors!(nodes[2], 1);
31063106
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -3117,7 +3117,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
31173117
nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &as_raa);
31183118
check_added_monitors!(nodes[2], 1);
31193119

3120-
assert!(nodes[2].node.fail_htlc_backwards(&third_payment_hash));
3120+
nodes[2].node.fail_htlc_backwards(&third_payment_hash);
31213121
expect_pending_htlcs_forwardable!(nodes[2]);
31223122
check_added_monitors!(nodes[2], 1);
31233123
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -5474,10 +5474,10 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
54745474

54755475
// Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
54765476
// Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
5477-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_1));
5478-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_3));
5479-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_5));
5480-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_6));
5477+
nodes[4].node.fail_htlc_backwards(&payment_hash_1);
5478+
nodes[4].node.fail_htlc_backwards(&payment_hash_3);
5479+
nodes[4].node.fail_htlc_backwards(&payment_hash_5);
5480+
nodes[4].node.fail_htlc_backwards(&payment_hash_6);
54815481
check_added_monitors!(nodes[4], 0);
54825482
expect_pending_htlcs_forwardable!(nodes[4]);
54835483
check_added_monitors!(nodes[4], 1);
@@ -5490,8 +5490,8 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
54905490
commitment_signed_dance!(nodes[3], nodes[4], four_removes.commitment_signed, false);
54915491

54925492
// Fail 3rd below-dust and 7th above-dust HTLCs
5493-
assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_2));
5494-
assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_4));
5493+
nodes[5].node.fail_htlc_backwards(&payment_hash_2);
5494+
nodes[5].node.fail_htlc_backwards(&payment_hash_4);
54955495
check_added_monitors!(nodes[5], 0);
54965496
expect_pending_htlcs_forwardable!(nodes[5]);
54975497
check_added_monitors!(nodes[5], 1);
@@ -5916,7 +5916,7 @@ fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no
59165916
// actually revoked.
59175917
let htlc_value = if use_dust { 50000 } else { 3000000 };
59185918
let (_, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], htlc_value);
5919-
assert!(nodes[1].node.fail_htlc_backwards(&our_payment_hash));
5919+
nodes[1].node.fail_htlc_backwards(&our_payment_hash);
59205920
expect_pending_htlcs_forwardable!(nodes[1]);
59215921
check_added_monitors!(nodes[1], 1);
59225922

@@ -7092,7 +7092,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
70927092
let as_prev_commitment_tx = get_local_commitment_txn!(nodes[0], chan.2);
70937093

70947094
// Fail one HTLC to prune it in the will-be-latest-local commitment tx
7095-
assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2));
7095+
nodes[1].node.fail_htlc_backwards(&payment_hash_2);
70967096
check_added_monitors!(nodes[1], 0);
70977097
expect_pending_htlcs_forwardable!(nodes[1]);
70987098
check_added_monitors!(nodes[1], 1);

lightning/src/ln/onion_route_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ fn test_phantom_failure_reject_payment() {
11341134
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
11351135
nodes[1].node.process_pending_htlc_forwards();
11361136
expect_payment_received!(nodes[1], payment_hash, payment_secret, recv_amt_msat);
1137-
assert!(nodes[1].node.fail_htlc_backwards(&payment_hash));
1137+
nodes[1].node.fail_htlc_backwards(&payment_hash);
11381138
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
11391139
nodes[1].node.process_pending_htlc_forwards();
11401140

0 commit comments

Comments
 (0)