Skip to content

Commit 7a8344a

Browse files
committed
Add test coverage for failure of inconsistent MPP parts
When we receive multiple HTLCs which claim to be a part of the same MPP but which are inconsistent for some reason, we should fail the inconsistent HTLCs but keep the first HTLCs up until the first inconsistency. This works, but it turns out there was no test coverage, so we add some here.
1 parent b9d097b commit 7a8344a

File tree

1 file changed

+143
-21
lines changed

1 file changed

+143
-21
lines changed

lightning/src/ln/functional_tests.rs

+143-21
Original file line numberDiff line numberDiff line change
@@ -9435,12 +9435,7 @@ fn test_forwardable_regen() {
94359435
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_2);
94369436
}
94379437

9438-
#[test]
9439-
fn test_dup_htlc_second_fail_panic() {
9440-
// Previously, if we received two HTLCs back-to-back, where the second overran the expected
9441-
// value for the payment, we'd fail back both HTLCs after generating a `PaymentReceived` event.
9442-
// Then, if the user failed the second payment, they'd hit a "tried to fail an already failed
9443-
// HTLC" debug panic. This tests for this behavior, checking that only one HTLC is auto-failed.
9438+
fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) {
94449439
let chanmon_cfgs = create_chanmon_cfgs(2);
94459440
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
94469441
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
@@ -9452,7 +9447,7 @@ fn test_dup_htlc_second_fail_panic() {
94529447
.with_features(InvoiceFeatures::known());
94539448
let route = get_route!(nodes[0], payment_params, 10_000, TEST_FINAL_CLTV).unwrap();
94549449

9455-
let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[1]);
9450+
let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[1]);
94569451

94579452
{
94589453
nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
@@ -9480,26 +9475,153 @@ fn test_dup_htlc_second_fail_panic() {
94809475
// the first HTLC delivered above.
94819476
}
94829477

9483-
// Now we go fail back the first HTLC from the user end.
94849478
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
94859479
nodes[1].node.process_pending_htlc_forwards();
9486-
nodes[1].node.fail_htlc_backwards(&our_payment_hash);
94879480

9488-
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
9489-
nodes[1].node.process_pending_htlc_forwards();
9481+
if test_for_second_fail_panic {
9482+
// Now we go fail back the first HTLC from the user end.
9483+
nodes[1].node.fail_htlc_backwards(&our_payment_hash);
94909484

9491-
check_added_monitors!(nodes[1], 1);
9492-
let fail_updates_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
9493-
assert_eq!(fail_updates_1.update_fail_htlcs.len(), 2);
9485+
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
9486+
nodes[1].node.process_pending_htlc_forwards();
9487+
9488+
check_added_monitors!(nodes[1], 1);
9489+
let fail_updates_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
9490+
assert_eq!(fail_updates_1.update_fail_htlcs.len(), 2);
9491+
9492+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]);
9493+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[1]);
9494+
commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false);
9495+
9496+
let failure_events = nodes[0].node.get_and_clear_pending_events();
9497+
assert_eq!(failure_events.len(), 2);
9498+
if let Event::PaymentPathFailed { .. } = failure_events[0] {} else { panic!(); }
9499+
if let Event::PaymentPathFailed { .. } = failure_events[1] {} else { panic!(); }
9500+
} else {
9501+
// Let the second HTLC fail and claim the first
9502+
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
9503+
nodes[1].node.process_pending_htlc_forwards();
9504+
9505+
check_added_monitors!(nodes[1], 1);
9506+
let fail_updates_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
9507+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]);
9508+
commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false);
9509+
9510+
expect_payment_failed_conditions!(nodes[0], our_payment_hash, true, PaymentFailedConditions::new().mpp_parts_remain());
9511+
9512+
claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage);
9513+
}
9514+
}
9515+
9516+
#[test]
9517+
fn test_dup_htlc_second_fail_panic() {
9518+
// Previously, if we received two HTLCs back-to-back, where the second overran the expected
9519+
// value for the payment, we'd fail back both HTLCs after generating a `PaymentReceived` event.
9520+
// Then, if the user failed the second payment, they'd hit a "tried to fail an already failed
9521+
// HTLC" debug panic. This tests for this behavior, checking that only one HTLC is auto-failed.
9522+
do_test_dup_htlc_second_rejected(true);
9523+
}
9524+
9525+
#[test]
9526+
fn test_dup_htlc_second_rejected() {
9527+
// Test that if we receive a second HTLC for an MPP payment that overruns the payment amount we
9528+
// simply reject the second HTLC but are still able to claim the first HTLC.
9529+
do_test_dup_htlc_second_rejected(false);
9530+
}
9531+
9532+
#[test]
9533+
fn test_inconsistent_mpp_params() {
9534+
// Test that if we recieve two HTLCs with different payment parameters we fail back the first
9535+
// such HTLC and allow the second to stay.
9536+
let chanmon_cfgs = create_chanmon_cfgs(4);
9537+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
9538+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
9539+
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
9540+
9541+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
9542+
create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0, InitFeatures::known(), InitFeatures::known());
9543+
create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
9544+
create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0, InitFeatures::known(), InitFeatures::known());
94949545

9495-
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]);
9496-
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[1]);
9497-
commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false);
9546+
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
9547+
.with_features(InvoiceFeatures::known());
9548+
let mut route = get_route!(nodes[0], payment_params, 15_000_000, TEST_FINAL_CLTV).unwrap();
9549+
assert_eq!(route.paths.len(), 2);
9550+
route.paths.sort_by(|path_a, _| {
9551+
// Sort the path so that the path through nodes[1] comes first
9552+
if path_a[0].pubkey == nodes[1].node.get_our_node_id() {
9553+
core::cmp::Ordering::Less } else { core::cmp::Ordering::Greater }
9554+
});
9555+
let payment_params_opt = Some(payment_params);
9556+
9557+
let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[3]);
9558+
9559+
let cur_height = nodes[0].best_block_info().1;
9560+
let payment_id = PaymentId([42; 32]);
9561+
{
9562+
nodes[0].node.send_payment_along_path(&route.paths[0], &payment_params_opt, &our_payment_hash, &Some(our_payment_secret), 15_000_000, cur_height, payment_id, &None).unwrap();
9563+
check_added_monitors!(nodes[0], 1);
9564+
9565+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
9566+
assert_eq!(events.len(), 1);
9567+
pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), false, None);
9568+
}
9569+
assert!(nodes[3].node.get_and_clear_pending_events().is_empty());
9570+
9571+
{
9572+
nodes[0].node.send_payment_along_path(&route.paths[1], &payment_params_opt, &our_payment_hash, &Some(our_payment_secret), 14_000_000, cur_height, payment_id, &None).unwrap();
9573+
check_added_monitors!(nodes[0], 1);
9574+
9575+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
9576+
assert_eq!(events.len(), 1);
9577+
let payment_event = SendEvent::from_event(events.pop().unwrap());
9578+
9579+
nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
9580+
commitment_signed_dance!(nodes[2], nodes[0], payment_event.commitment_msg, false);
9581+
9582+
expect_pending_htlcs_forwardable!(nodes[2]);
9583+
check_added_monitors!(nodes[2], 1);
9584+
9585+
let mut events = nodes[2].node.get_and_clear_pending_msg_events();
9586+
assert_eq!(events.len(), 1);
9587+
let payment_event = SendEvent::from_event(events.pop().unwrap());
9588+
9589+
nodes[3].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &payment_event.msgs[0]);
9590+
check_added_monitors!(nodes[3], 0);
9591+
commitment_signed_dance!(nodes[3], nodes[2], payment_event.commitment_msg, true, true);
9592+
9593+
// At this point, nodes[3] should notice the two HTLCs don't contain the same total payment
9594+
// amount. It will assume the second is a privacy attack (no longer particularly relevant
9595+
// post-payment_secrets) and fail back the new HTLC.
9596+
}
9597+
expect_pending_htlcs_forwardable_ignore!(nodes[3]);
9598+
nodes[3].node.process_pending_htlc_forwards();
9599+
expect_pending_htlcs_forwardable_ignore!(nodes[3]);
9600+
nodes[3].node.process_pending_htlc_forwards();
9601+
9602+
check_added_monitors!(nodes[3], 1);
9603+
9604+
let fail_updates_1 = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id());
9605+
nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]);
9606+
commitment_signed_dance!(nodes[2], nodes[3], fail_updates_1.commitment_signed, false);
9607+
9608+
expect_pending_htlcs_forwardable!(nodes[2]);
9609+
check_added_monitors!(nodes[2], 1);
9610+
9611+
let fail_updates_2 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id());
9612+
nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &fail_updates_2.update_fail_htlcs[0]);
9613+
commitment_signed_dance!(nodes[0], nodes[2], fail_updates_2.commitment_signed, false);
9614+
9615+
expect_payment_failed_conditions!(nodes[0], our_payment_hash, true, PaymentFailedConditions::new().mpp_parts_remain());
9616+
9617+
nodes[0].node.send_payment_along_path(&route.paths[1], &payment_params_opt, &our_payment_hash, &Some(our_payment_secret), 15_000_000, cur_height, payment_id, &None).unwrap();
9618+
check_added_monitors!(nodes[0], 1);
9619+
9620+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
9621+
assert_eq!(events.len(), 1);
9622+
pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), true, None);
94989623

9499-
let failure_events = nodes[0].node.get_and_clear_pending_events();
9500-
assert_eq!(failure_events.len(), 2);
9501-
if let Event::PaymentPathFailed { .. } = failure_events[0] {} else { panic!(); }
9502-
if let Event::PaymentPathFailed { .. } = failure_events[1] {} else { panic!(); }
9624+
claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
95039625
}
95049626

95059627
#[test]

0 commit comments

Comments
 (0)