Skip to content

Commit 3f02374

Browse files
committed
f - fail back non-matching even custom tlvs
Adds logic + refactors test to more easily test different cases of non-matching vs. missing tlvs. Also adds modifying the second parameter in `check_merge` to match documentation, although this isn't used currently.
1 parent 1763fb7 commit 3f02374

File tree

2 files changed

+91
-32
lines changed

2 files changed

+91
-32
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,13 @@ impl RecipientOnionFields {
505505
if self.payment_secret != further_htlc_fields.payment_secret { return Err(()); }
506506
if self.payment_metadata != further_htlc_fields.payment_metadata { return Err(()); }
507507

508-
if let (Some(tlvs), Some(further_tlvs)) = (&mut self.custom_tlvs, &further_htlc_fields.custom_tlvs) {
508+
if let (Some(tlvs), Some(further_tlvs)) = (&mut self.custom_tlvs, &mut further_htlc_fields.custom_tlvs) {
509+
let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();
510+
let further_even_tlvs: Vec<&(u64, Vec<u8>)> = further_tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();
511+
if even_tlvs != further_even_tlvs { return Err(()) }
512+
509513
tlvs.retain(|tlv| further_tlvs.iter().any(|further_tlv| tlv == further_tlv));
514+
further_tlvs.retain(|further_tlv| tlvs.iter().any(|tlv| tlv == further_tlv));
510515
}
511516
Ok(())
512517
}

lightning/src/ln/payment_tests.rs

Lines changed: 85 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,7 +3262,43 @@ fn do_test_custom_tlvs(spontaneous: bool) {
32623262

32633263
#[test]
32643264
fn test_custom_tlvs_consistency() {
3265-
// Test that if we recieve two HTLCs with different custom TLVs we drop the non-matching TLVs
3265+
let even_type_1 = 1 << 16;
3266+
let odd_type_1 = (1 << 16)+ 1;
3267+
let even_type_2 = (1 << 16) + 2;
3268+
let odd_type_2 = (1 << 16) + 3;
3269+
let value_1 = || vec![1, 2, 3, 4];
3270+
let differing_value_1 = || vec![1, 2, 3, 5];
3271+
let value_2 = || vec![42u8; 16];
3272+
3273+
// Drop missing odd tlvs
3274+
do_test_custom_tlvs_consistency(
3275+
vec![(odd_type_1, value_1()), (odd_type_2, value_2())],
3276+
vec![(odd_type_1, value_1())],
3277+
Some(vec![(odd_type_1, value_1())]),
3278+
);
3279+
// Drop non-matching odd tlvs
3280+
do_test_custom_tlvs_consistency(
3281+
vec![(odd_type_1, value_1()), (odd_type_2, value_2())],
3282+
vec![(odd_type_1, differing_value_1()), (odd_type_2, value_2())],
3283+
Some(vec![(odd_type_2, value_2())]),
3284+
);
3285+
// Fail missing even tlvs
3286+
do_test_custom_tlvs_consistency(
3287+
vec![(odd_type_1, value_1()), (even_type_2, value_2())],
3288+
vec![(odd_type_1, value_1())],
3289+
None,
3290+
);
3291+
// Fail non-matching even tlvs
3292+
do_test_custom_tlvs_consistency(
3293+
vec![(even_type_1, value_1()), (odd_type_2, value_2())],
3294+
vec![(even_type_1, differing_value_1()), (odd_type_2, value_2())],
3295+
None,
3296+
);
3297+
}
3298+
3299+
fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec<u8>)>, second_tlvs: Vec<(u64, Vec<u8>)>,
3300+
expected_receive_tlvs: Option<Vec<(u64, Vec<u8>)>>) {
3301+
32663302
let chanmon_cfgs = create_chanmon_cfgs(4);
32673303
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
32683304
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
@@ -3271,7 +3307,7 @@ fn test_custom_tlvs_consistency() {
32713307
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0);
32723308
create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0);
32733309
create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0);
3274-
create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0);
3310+
let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0);
32753311

32763312
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
32773313
.with_bolt11_features(nodes[3].node.invoice_features()).unwrap();
@@ -3286,14 +3322,12 @@ fn test_custom_tlvs_consistency() {
32863322
let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[3]);
32873323
let payment_id = PaymentId([42; 32]);
32883324
let amt_msat = 15_000_000;
3289-
let custom_tlvs = vec![
3290-
(5482373483, vec![1, 2, 3, 4]),
3291-
(5482373487, vec![0x42u8; 16]),
3292-
];
3325+
3326+
// Send first part
32933327
let onion_fields = RecipientOnionFields {
32943328
payment_secret: Some(our_payment_secret),
32953329
payment_metadata: None,
3296-
custom_tlvs: Some(custom_tlvs.clone())
3330+
custom_tlvs: Some(first_tlvs)
32973331
};
32983332
let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash,
32993333
onion_fields.clone(), payment_id, &route).unwrap();
@@ -3310,13 +3344,11 @@ fn test_custom_tlvs_consistency() {
33103344
}
33113345
assert!(nodes[3].node.get_and_clear_pending_events().is_empty());
33123346

3313-
let custom_tlvs = vec![
3314-
(5482373483, vec![1, 2, 3, 4]),
3315-
];
3347+
// Send second part
33163348
let onion_fields = RecipientOnionFields {
33173349
payment_secret: Some(our_payment_secret),
33183350
payment_metadata: None,
3319-
custom_tlvs: Some(custom_tlvs.clone())
3351+
custom_tlvs: Some(second_tlvs)
33203352
};
33213353
nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash,
33223354
onion_fields.clone(), amt_msat, cur_height, payment_id, &None, session_privs[1]).unwrap();
@@ -3344,27 +3376,49 @@ fn test_custom_tlvs_consistency() {
33443376
expect_pending_htlcs_forwardable_ignore!(nodes[3]);
33453377
nodes[3].node.process_pending_htlc_forwards();
33463378

3347-
let events = nodes[3].node.get_and_clear_pending_events();
3348-
assert_eq!(events.len(), 1);
3349-
match events[0] {
3350-
Event::PaymentClaimable { ref purpose, amount_msat, ref onion_fields, .. } => {
3351-
match &purpose {
3352-
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
3353-
assert_eq!(our_payment_secret, *payment_secret);
3354-
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);
3355-
},
3356-
PaymentPurpose::SpontaneousPayment(payment_preimage) => {
3357-
assert_eq!(our_payment_preimage, *payment_preimage);
3358-
},
3359-
}
3360-
assert_eq!(amount_msat, amt_msat);
3361-
assert_eq!(onion_fields.clone().unwrap().custom_tlvs.unwrap(), custom_tlvs);
3362-
},
3363-
_ => panic!("Unexpected event"),
3364-
}
3379+
if let Some(expected_tlvs) = expected_receive_tlvs {
3380+
// Claim and match expected
3381+
let events = nodes[3].node.get_and_clear_pending_events();
3382+
println!("events: {:?}", events);
3383+
assert_eq!(events.len(), 1);
3384+
match events[0] {
3385+
Event::PaymentClaimable { ref purpose, amount_msat, ref onion_fields, .. } => {
3386+
match &purpose {
3387+
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
3388+
assert_eq!(our_payment_secret, *payment_secret);
3389+
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);
3390+
},
3391+
PaymentPurpose::SpontaneousPayment(payment_preimage) => {
3392+
assert_eq!(our_payment_preimage, *payment_preimage);
3393+
},
3394+
}
3395+
assert_eq!(amount_msat, amt_msat);
3396+
assert_eq!(onion_fields.clone().unwrap().custom_tlvs.unwrap(), expected_tlvs);
3397+
},
3398+
_ => panic!("Unexpected event"),
3399+
}
3400+
3401+
do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
3402+
expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true);
3403+
} else {
3404+
// Expect fail back
3405+
let expected_destinations = vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }];
3406+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], expected_destinations);
3407+
check_added_monitors!(nodes[3], 1);
3408+
3409+
let fail_updates_1 = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id());
3410+
nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]);
3411+
commitment_signed_dance!(nodes[2], nodes[3], fail_updates_1.commitment_signed, false);
3412+
3413+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }]);
3414+
check_added_monitors!(nodes[2], 1);
3415+
3416+
let fail_updates_2 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id());
3417+
nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &fail_updates_2.update_fail_htlcs[0]);
3418+
commitment_signed_dance!(nodes[0], nodes[2], fail_updates_2.commitment_signed, false);
33653419

3366-
do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
3367-
expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true);
3420+
expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, PaymentFailedConditions::new().mpp_parts_remain());
3421+
}
33683422
}
33693423

33703424
fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) {

0 commit comments

Comments
 (0)