Skip to content

Commit ba45b1f

Browse files
committed
f: test blinded path failure scenarios
1 parent a36ef3d commit ba45b1f

File tree

2 files changed

+230
-37
lines changed

2 files changed

+230
-37
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 226 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,18 +2698,18 @@ fn do_test_unblinded_trampoline_forward(failure_scenario: Option<TrampolineForwa
26982698
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
26992699
}
27002700
}
2701-
Some(TrampolineForwardFailureScenario::InvalidRecipientOnion) => {
2702-
let route_alice_t0: &[&Node] = &[&nodes[1], &nodes[2], &nodes[4]];
2703-
pass_along_path(&nodes[0], route_alice_t0, amt_msat, payment_hash.clone(),
2701+
Some(TrampolineForwardFailureScenario::InvalidInterTrampolineOnion) => {
2702+
let route_alice_carol: &[&Node] = &[&nodes[1], &nodes[2]];
2703+
pass_along_path(&nodes[0], route_alice_carol, amt_msat, payment_hash.clone(),
27042704
None, first_message_event.clone(), false, Some(payment_preimage));
27052705

2706-
check_added_monitors!(&nodes[4], 1);
2707-
let mut events = nodes[4].node.get_and_clear_pending_msg_events();
2706+
check_added_monitors!(&nodes[2], 1);
2707+
let mut events = nodes[2].node.get_and_clear_pending_msg_events();
27082708
assert_eq!(events.len(), 1);
27092709

2710-
let mut update_message_t0_dave = remove_first_msg_event_to_node(&nodes[3].node.get_our_node_id(), &mut events);
2710+
let mut update_message_carol_t0 = remove_first_msg_event_to_node(&nodes[4].node.get_our_node_id(), &mut events);
27112711
{
2712-
let mut update_message = match update_message_t0_dave {
2712+
let mut update_message = match update_message_carol_t0 {
27132713
MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => {
27142714
assert_eq!(updates.update_add_htlcs.len(), 1);
27152715
updates.update_add_htlcs.get_mut(0)
@@ -2722,25 +2722,16 @@ fn do_test_unblinded_trampoline_forward(failure_scenario: Option<TrampolineForwa
27222722
});
27232723
}
27242724

2725-
let route_to_dave: &[&Node] = &[&nodes[3]];
2726-
let args = PassAlongPathArgs::new(&nodes[4], route_to_dave, amt_msat, payment_hash, update_message_t0_dave.clone()).expect_failure(HTLCDestination::InvalidOnion);
2725+
let route_carol_t0: &[&Node] = &[&nodes[4]];
2726+
let args = PassAlongPathArgs::new(&nodes[2], route_carol_t0, amt_msat, payment_hash, update_message_carol_t0.clone()).expect_failure(HTLCDestination::InvalidOnion);
27272727
do_pass_along_path(args);
27282728

2729-
{
2730-
let downstream_id = 3;
2731-
let upstream_id = 4;
2732-
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
2733-
nodes[upstream_id].node.handle_update_fail_malformed_htlc(
2734-
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_malformed_htlcs[0]
2735-
);
2736-
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
2737-
}
27382729
{
27392730
let downstream_id = 4;
27402731
let upstream_id = 2;
27412732
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
2742-
nodes[upstream_id].node.handle_update_fail_htlc(
2743-
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2733+
nodes[upstream_id].node.handle_update_fail_malformed_htlc(
2734+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_malformed_htlcs[0]
27442735
);
27452736
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
27462737
}
@@ -2768,18 +2759,18 @@ fn do_test_unblinded_trampoline_forward(failure_scenario: Option<TrampolineForwa
27682759
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
27692760
}
27702761
}
2771-
Some(TrampolineForwardFailureScenario::InvalidInterTrampolineOnion) => {
2772-
let route_alice_carol: &[&Node] = &[&nodes[1], &nodes[2]];
2773-
pass_along_path(&nodes[0], route_alice_carol, amt_msat, payment_hash.clone(),
2762+
Some(TrampolineForwardFailureScenario::InvalidRecipientOnion) => {
2763+
let route_alice_t0: &[&Node] = &[&nodes[1], &nodes[2], &nodes[4]];
2764+
pass_along_path(&nodes[0], route_alice_t0, amt_msat, payment_hash.clone(),
27742765
None, first_message_event.clone(), false, Some(payment_preimage));
27752766

2776-
check_added_monitors!(&nodes[2], 1);
2777-
let mut events = nodes[2].node.get_and_clear_pending_msg_events();
2767+
check_added_monitors!(&nodes[4], 1);
2768+
let mut events = nodes[4].node.get_and_clear_pending_msg_events();
27782769
assert_eq!(events.len(), 1);
27792770

2780-
let mut update_message_carol_t0 = remove_first_msg_event_to_node(&nodes[4].node.get_our_node_id(), &mut events);
2771+
let mut update_message_t0_dave = remove_first_msg_event_to_node(&nodes[3].node.get_our_node_id(), &mut events);
27812772
{
2782-
let mut update_message = match update_message_carol_t0 {
2773+
let mut update_message = match update_message_t0_dave {
27832774
MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => {
27842775
assert_eq!(updates.update_add_htlcs.len(), 1);
27852776
updates.update_add_htlcs.get_mut(0)
@@ -2792,19 +2783,28 @@ fn do_test_unblinded_trampoline_forward(failure_scenario: Option<TrampolineForwa
27922783
});
27932784
}
27942785

2795-
let route_carol_t0: &[&Node] = &[&nodes[4]];
2796-
let args = PassAlongPathArgs::new(&nodes[2], route_carol_t0, amt_msat, payment_hash, update_message_carol_t0.clone()).expect_failure(HTLCDestination::InvalidOnion);
2786+
let route_to_dave: &[&Node] = &[&nodes[3]];
2787+
let args = PassAlongPathArgs::new(&nodes[4], route_to_dave, amt_msat, payment_hash, update_message_t0_dave.clone()).expect_failure(HTLCDestination::InvalidOnion);
27972788
do_pass_along_path(args);
27982789

27992790
{
2800-
let downstream_id = 4;
2801-
let upstream_id = 2;
2791+
let downstream_id = 3;
2792+
let upstream_id = 4;
28022793
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
28032794
nodes[upstream_id].node.handle_update_fail_malformed_htlc(
28042795
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_malformed_htlcs[0]
28052796
);
28062797
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
28072798
}
2799+
{
2800+
let downstream_id = 4;
2801+
let upstream_id = 2;
2802+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
2803+
nodes[upstream_id].node.handle_update_fail_htlc(
2804+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2805+
);
2806+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
2807+
}
28082808
{
28092809
let downstream_id = 2;
28102810
let upstream_id = 1;
@@ -2840,8 +2840,7 @@ fn test_unblinded_trampoline_forward() {
28402840
do_test_unblinded_trampoline_forward(Some(TrampolineForwardFailureScenario::InvalidRecipientOnion));
28412841
}
28422842

2843-
#[test]
2844-
fn test_blinded_trampoline_forward() {
2843+
fn do_test_blinded_trampoline_forward(failure_scenario: Option<TrampolineForwardFailureScenario>) {
28452844
// Simulate a payment of A (0) -> B (1) -> C(Trampoline (blinded forward)) (2) -> D(Trampoline(blinded receive)) (3)
28462845
// trampoline hops C -> T0 (4) -> D
28472846
// make it fail at B, then at C's outer onion, then at C's inner onion
@@ -2855,7 +2854,9 @@ fn test_blinded_trampoline_forward() {
28552854

28562855
let (_, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
28572856
let (_, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
2858-
let (_, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 1_000_000, 0);
2857+
if failure_scenario != Some(TrampolineForwardFailureScenario::NoRoute) {
2858+
let (_, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 1_000_000, 0);
2859+
}
28592860
let (_, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 4, 3, 1_000_000, 0);
28602861

28612862
for i in 0..TOTAL_NODE_COUNT { // connect all nodes' blocks
@@ -2957,6 +2958,195 @@ fn test_blinded_trampoline_forward() {
29572958
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
29582959
check_added_monitors!(&nodes[0], 1);
29592960

2960-
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[4], &nodes[3]]], amt_msat, payment_hash, payment_secret);
2961-
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[4], &nodes[3]], payment_preimage);
2961+
match failure_scenario {
2962+
None => {
2963+
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[4], &nodes[3]]], amt_msat, payment_hash, payment_secret);
2964+
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[4], &nodes[3]], payment_preimage);
2965+
},
2966+
Some(TrampolineForwardFailureScenario::NoRoute) => {
2967+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
2968+
assert_eq!(events.len(), 1);
2969+
let first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
2970+
2971+
let route = &[&nodes[1], &nodes[2]];
2972+
let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event)
2973+
.with_payment_preimage(payment_preimage)
2974+
.without_claimable_event()
2975+
.expect_failure(HTLCDestination::FailedTrampolineForward { requested_next_node_id: dave_node_id, forward_scid: None });
2976+
do_pass_along_path(args);
2977+
2978+
{
2979+
let downstream_id = 2;
2980+
let upstream_id = 1;
2981+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
2982+
nodes[upstream_id].node.handle_update_fail_htlc(
2983+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2984+
);
2985+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
2986+
}
2987+
{
2988+
let downstream_id = 1;
2989+
let upstream_id = 0;
2990+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
2991+
nodes[upstream_id].node.handle_update_fail_htlc(
2992+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2993+
);
2994+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, false, false);
2995+
}
2996+
{
2997+
let payment_failed_conditions = PaymentFailedConditions::new()
2998+
.expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]);
2999+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
3000+
}
3001+
}
3002+
Some(TrampolineForwardFailureScenario::InvalidInterTrampolineOnion) => {
3003+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
3004+
assert_eq!(events.len(), 1);
3005+
let first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
3006+
3007+
let route_alice_carol: &[&Node] = &[&nodes[1], &nodes[2]];
3008+
pass_along_path(&nodes[0], route_alice_carol, amt_msat, payment_hash.clone(),
3009+
None, first_message_event.clone(), false, Some(payment_preimage));
3010+
3011+
check_added_monitors!(&nodes[2], 1);
3012+
let mut events = nodes[2].node.get_and_clear_pending_msg_events();
3013+
assert_eq!(events.len(), 1);
3014+
3015+
let mut update_message_carol_t0 = remove_first_msg_event_to_node(&nodes[4].node.get_our_node_id(), &mut events);
3016+
{
3017+
let mut update_message = match update_message_carol_t0 {
3018+
MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => {
3019+
assert_eq!(updates.update_add_htlcs.len(), 1);
3020+
updates.update_add_htlcs.get_mut(0)
3021+
}
3022+
_ => panic!()
3023+
};
3024+
update_message.map(|msg| {
3025+
// corrupt the onion packet
3026+
msg.onion_routing_packet.hmac = [1; 32];
3027+
});
3028+
}
3029+
3030+
let route_carol_t0: &[&Node] = &[&nodes[4]];
3031+
let args = PassAlongPathArgs::new(&nodes[2], route_carol_t0, amt_msat, payment_hash, update_message_carol_t0.clone()).expect_failure(HTLCDestination::InvalidOnion);
3032+
do_pass_along_path(args);
3033+
3034+
{
3035+
let downstream_id = 4;
3036+
let upstream_id = 2;
3037+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3038+
nodes[upstream_id].node.handle_update_fail_malformed_htlc(
3039+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_malformed_htlcs[0]
3040+
);
3041+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
3042+
}
3043+
{
3044+
let downstream_id = 2;
3045+
let upstream_id = 1;
3046+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3047+
nodes[upstream_id].node.handle_update_fail_htlc(
3048+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
3049+
);
3050+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
3051+
}
3052+
{
3053+
let downstream_id = 1;
3054+
let upstream_id = 0;
3055+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3056+
nodes[upstream_id].node.handle_update_fail_htlc(
3057+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
3058+
);
3059+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, false, false);
3060+
}
3061+
{
3062+
let payment_failed_conditions = PaymentFailedConditions::new()
3063+
.expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]);
3064+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
3065+
}
3066+
}
3067+
Some(TrampolineForwardFailureScenario::InvalidRecipientOnion) => {
3068+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
3069+
assert_eq!(events.len(), 1);
3070+
let first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
3071+
3072+
let route_alice_t0: &[&Node] = &[&nodes[1], &nodes[2], &nodes[4]];
3073+
pass_along_path(&nodes[0], route_alice_t0, amt_msat, payment_hash.clone(),
3074+
None, first_message_event.clone(), false, Some(payment_preimage));
3075+
3076+
check_added_monitors!(&nodes[4], 1);
3077+
let mut events = nodes[4].node.get_and_clear_pending_msg_events();
3078+
assert_eq!(events.len(), 1);
3079+
3080+
let mut update_message_t0_dave = remove_first_msg_event_to_node(&nodes[3].node.get_our_node_id(), &mut events);
3081+
{
3082+
let mut update_message = match update_message_t0_dave {
3083+
MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => {
3084+
assert_eq!(updates.update_add_htlcs.len(), 1);
3085+
updates.update_add_htlcs.get_mut(0)
3086+
}
3087+
_ => panic!()
3088+
};
3089+
update_message.map(|msg| {
3090+
// corrupt the onion packet
3091+
msg.onion_routing_packet.hmac = [1; 32];
3092+
});
3093+
}
3094+
3095+
let route_to_dave: &[&Node] = &[&nodes[3]];
3096+
let args = PassAlongPathArgs::new(&nodes[4], route_to_dave, amt_msat, payment_hash, update_message_t0_dave.clone()).expect_failure(HTLCDestination::InvalidOnion);
3097+
do_pass_along_path(args);
3098+
3099+
{
3100+
let downstream_id = 3;
3101+
let upstream_id = 4;
3102+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3103+
nodes[upstream_id].node.handle_update_fail_malformed_htlc(
3104+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_malformed_htlcs[0]
3105+
);
3106+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
3107+
}
3108+
{
3109+
let downstream_id = 4;
3110+
let upstream_id = 2;
3111+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3112+
nodes[upstream_id].node.handle_update_fail_htlc(
3113+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
3114+
);
3115+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
3116+
}
3117+
{
3118+
let downstream_id = 2;
3119+
let upstream_id = 1;
3120+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3121+
nodes[upstream_id].node.handle_update_fail_htlc(
3122+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
3123+
);
3124+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, true, false);
3125+
}
3126+
{
3127+
let downstream_id = 1;
3128+
let upstream_id = 0;
3129+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[downstream_id], nodes[upstream_id].node.get_our_node_id());
3130+
nodes[upstream_id].node.handle_update_fail_htlc(
3131+
nodes[downstream_id].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
3132+
);
3133+
do_commitment_signed_dance(&nodes[upstream_id], &nodes[downstream_id], &unblinded_node_updates.commitment_signed, false, false);
3134+
}
3135+
{
3136+
let payment_failed_conditions = PaymentFailedConditions::new()
3137+
.expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]);
3138+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
3139+
}
3140+
}
3141+
}
3142+
3143+
3144+
}
3145+
3146+
#[test]
3147+
fn test_blinded_trampoline_forward() {
3148+
do_test_blinded_trampoline_forward(None);
3149+
do_test_blinded_trampoline_forward(Some(TrampolineForwardFailureScenario::NoRoute));
3150+
do_test_blinded_trampoline_forward(Some(TrampolineForwardFailureScenario::InvalidInterTrampolineOnion));
3151+
do_test_blinded_trampoline_forward(Some(TrampolineForwardFailureScenario::InvalidRecipientOnion));
29623152
}

lightning/src/routing/router.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,10 @@ impl PaymentParameters {
10681068
found_blinded_tail = true;
10691069
}
10701070
}
1071-
debug_assert!(found_blinded_tail);
1071+
if failed_blinded_tail.trampoline_hops.is_empty() {
1072+
// do not mandate path hints when paying using blinded Trampoline hops
1073+
debug_assert!(found_blinded_tail);
1074+
}
10721075
}
10731076
}
10741077

0 commit comments

Comments
 (0)