Skip to content

Commit d7a6d0d

Browse files
authored
Merge pull request #2661 from TheBlueMatt/2023-10-dup-claim-chan-hang
Immediately unblock channels on duplicate claims
2 parents 1852715 + f47270e commit d7a6d0d

File tree

2 files changed

+273
-43
lines changed

2 files changed

+273
-43
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

+69
Original file line numberDiff line numberDiff line change
@@ -3431,3 +3431,72 @@ fn test_reload_mon_update_completion_actions() {
34313431
do_test_reload_mon_update_completion_actions(true);
34323432
do_test_reload_mon_update_completion_actions(false);
34333433
}
3434+
3435+
fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) {
3436+
// Test that if a peer manages to send an `update_fulfill_htlc` message without a
3437+
// `commitment_signed`, disconnects, then replays the `update_fulfill_htlc` message it doesn't
3438+
// result in a channel hang. This was previously broken as the `DuplicateClaim` case wasn't
3439+
// handled when claiming an HTLC and handling wasn't added when completion actions were added
3440+
// (which must always complete at some point).
3441+
let chanmon_cfgs = create_chanmon_cfgs(3);
3442+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
3443+
3444+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
3445+
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
3446+
3447+
create_announced_chan_between_nodes(&nodes, 0, 1);
3448+
create_announced_chan_between_nodes(&nodes, 1, 2);
3449+
3450+
// Route a payment from A, through B, to C, then claim it on C. Replay the
3451+
// `update_fulfill_htlc` twice on B to check that B doesn't hang.
3452+
let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
3453+
3454+
nodes[2].node.claim_funds(payment_preimage);
3455+
check_added_monitors(&nodes[2], 1);
3456+
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
3457+
3458+
let cs_updates = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id());
3459+
if hold_chan_a {
3460+
// The first update will be on the A <-> B channel, which we allow to complete.
3461+
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
3462+
}
3463+
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]);
3464+
check_added_monitors(&nodes[1], 1);
3465+
3466+
if !hold_chan_a {
3467+
let bs_updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
3468+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]);
3469+
commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false);
3470+
expect_payment_sent!(&nodes[0], payment_preimage);
3471+
}
3472+
3473+
nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id());
3474+
nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id());
3475+
3476+
let mut reconnect = ReconnectArgs::new(&nodes[1], &nodes[2]);
3477+
reconnect.pending_htlc_claims = (1, 0);
3478+
reconnect_nodes(reconnect);
3479+
3480+
if !hold_chan_a {
3481+
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false);
3482+
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000);
3483+
} else {
3484+
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
3485+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3486+
3487+
let (route, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(&nodes[1], nodes[2], 1_000_000);
3488+
3489+
nodes[1].node.send_payment_with_route(&route, payment_hash_2,
3490+
RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap();
3491+
check_added_monitors(&nodes[1], 0);
3492+
3493+
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
3494+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3495+
}
3496+
}
3497+
3498+
#[test]
3499+
fn test_glacial_peer_cant_hang() {
3500+
do_test_glacial_peer_cant_hang(false);
3501+
do_test_glacial_peer_cant_hang(true);
3502+
}

0 commit comments

Comments
 (0)