77// You may not use this file except in accordance with one or both of these
88// licenses.
99
10+ use std:: cmp:: PartialEq ;
1011use bitcoin:: hashes:: hex:: FromHex ;
1112use bitcoin:: hex:: DisplayHex ;
1213use bitcoin:: secp256k1:: { PublicKey , Scalar , Secp256k1 , SecretKey , schnorr} ;
@@ -2497,7 +2498,14 @@ fn test_trampoline_constraint_enforcement() {
24972498 }
24982499}
24992500
2500- fn do_test_unblinded_trampoline_forward ( success : bool ) {
2501+ #[ derive( PartialEq ) ]
2502+ enum TrampolineForwardFailureScenario {
2503+ NoRoute ,
2504+ InvalidRecipientOnion ,
2505+ InvalidInterTrampolineOnion ,
2506+ }
2507+
2508+ fn do_test_unblinded_trampoline_forward ( failure_scenario : Option < TrampolineForwardFailureScenario > ) {
25012509 // Simulate a payment of A (0) -> B (1) -> C(Trampoline) (2) -> D(Trampoline(receive)) (3)
25022510 // trampoline hops C -> T0 (4) -> D
25032511 // make it fail at B, then at C's outer onion, then at C's inner onion
@@ -2511,7 +2519,7 @@ fn do_test_unblinded_trampoline_forward(success: bool) {
25112519
25122520 let ( _, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
25132521 let ( _, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) ;
2514- if success {
2522+ if failure_scenario != Some ( TrampolineForwardFailureScenario :: NoRoute ) {
25152523 let ( _, _, _, _) = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 1_000_000 , 0 ) ;
25162524 }
25172525 let ( _, _, _, _) = create_announced_chan_between_nodes_with_value ( & nodes, 4 , 3 , 1_000_000 , 0 ) ;
@@ -2641,59 +2649,195 @@ fn do_test_unblinded_trampoline_forward(success: bool) {
26412649 let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
26422650 assert_eq ! ( events. len( ) , 1 ) ;
26432651 let mut first_message_event = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
2644- let mut update_message = match first_message_event {
2645- MessageSendEvent :: UpdateHTLCs { ref mut updates, .. } => {
2646- assert_eq ! ( updates. update_add_htlcs. len( ) , 1 ) ;
2647- updates. update_add_htlcs . get_mut ( 0 )
2648- } ,
2649- _ => panic ! ( )
2650- } ;
2651- update_message. map ( |msg| {
2652- msg. onion_routing_packet = replacement_onion. clone ( ) ;
2653- } ) ;
2654-
2655- let success_route = [ & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 4 ] , & nodes[ 3 ] ] ;
2656- let failure_route = [ & nodes[ 1 ] , & nodes[ 2 ] ] ;
2657- let route: & [ & Node ] = if success { & success_route } else { & failure_route } ;
2658- let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , route, amt_msat, payment_hash, first_message_event) ;
2659- let args = if success {
2660- args. with_payment_secret ( payment_secret)
2661- } else {
2662- args. with_payment_preimage ( payment_preimage)
2663- . without_claimable_event ( )
2664- . expect_failure ( HTLCDestination :: FailedTrampolineForward { requested_next_node_id : dave_node_id, forward_scid : None } )
2665- } ;
2666- do_pass_along_path ( args) ;
2652+ {
2653+ let mut update_message_alice_bob = match first_message_event {
2654+ MessageSendEvent :: UpdateHTLCs { ref mut updates, .. } => {
2655+ assert_eq ! ( updates. update_add_htlcs. len( ) , 1 ) ;
2656+ updates. update_add_htlcs . get_mut ( 0 )
2657+ }
2658+ _ => panic ! ( )
2659+ } ;
2660+ update_message_alice_bob. map ( |msg| {
2661+ msg. onion_routing_packet = replacement_onion. clone ( ) ;
2662+ } ) ;
2663+ }
26672664
2668- if success {
2669- claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 4 ] , & nodes[ 3 ] ] , payment_preimage) ;
2670- } else {
2671- {
2672- let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ 2 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2673- nodes[ 1 ] . node . handle_update_fail_htlc (
2674- nodes[ 2 ] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2675- ) ;
2676- do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 2 ] , & unblinded_node_updates. commitment_signed , true , false ) ;
2665+ match failure_scenario {
2666+ None => {
2667+ let route: & [ & Node ] = & [ & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 4 ] , & nodes[ 3 ] ] ;
2668+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , route, amt_msat, payment_hash, first_message_event)
2669+ . with_payment_secret ( payment_secret) ;
2670+ do_pass_along_path ( args) ;
2671+ claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 4 ] , & nodes[ 3 ] ] , payment_preimage) ;
26772672 }
2678- {
2679- let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2680- nodes[ 0 ] . node . handle_update_fail_htlc (
2681- nodes[ 1 ] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2682- ) ;
2683- do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 1 ] , & unblinded_node_updates. commitment_signed , false , false ) ;
2673+ Some ( TrampolineForwardFailureScenario :: NoRoute ) => {
2674+ let route = & [ & nodes[ 1 ] , & nodes[ 2 ] ] ;
2675+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , route, amt_msat, payment_hash, first_message_event)
2676+ . with_payment_preimage ( payment_preimage)
2677+ . without_claimable_event ( )
2678+ . expect_failure ( HTLCDestination :: FailedTrampolineForward { requested_next_node_id : dave_node_id, forward_scid : None } ) ;
2679+ do_pass_along_path ( args) ;
2680+
2681+ {
2682+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ 2 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2683+ nodes[ 1 ] . node . handle_update_fail_htlc (
2684+ nodes[ 2 ] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ] ,
2685+ ) ;
2686+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 2 ] , & unblinded_node_updates. commitment_signed , true , false ) ;
2687+ }
2688+ {
2689+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2690+ nodes[ 0 ] . node . handle_update_fail_htlc (
2691+ nodes[ 1 ] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ] ,
2692+ ) ;
2693+ do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 1 ] , & unblinded_node_updates. commitment_signed , false , false ) ;
2694+ }
2695+ {
2696+ let payment_failed_conditions = PaymentFailedConditions :: new ( )
2697+ . expected_htlc_error_data ( 0x2000 | 25 , & [ 0 ; 0 ] ) ;
2698+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false , payment_failed_conditions) ;
2699+ }
26842700 }
2685- {
2686- let payment_failed_conditions = PaymentFailedConditions :: new ( )
2687- . expected_htlc_error_data ( 0x2000 | 25 , & [ 0 ; 0 ] ) ;
2688- expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false , payment_failed_conditions) ;
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 ( ) ,
2704+ None , first_message_event. clone ( ) , false , Some ( payment_preimage) ) ;
2705+
2706+ check_added_monitors ! ( & nodes[ 4 ] , 1 ) ;
2707+ let mut events = nodes[ 4 ] . node . get_and_clear_pending_msg_events ( ) ;
2708+ assert_eq ! ( events. len( ) , 1 ) ;
2709+
2710+ let mut update_message_t0_dave = remove_first_msg_event_to_node ( & nodes[ 3 ] . node . get_our_node_id ( ) , & mut events) ;
2711+ {
2712+ let mut update_message = match update_message_t0_dave {
2713+ MessageSendEvent :: UpdateHTLCs { ref mut updates, .. } => {
2714+ assert_eq ! ( updates. update_add_htlcs. len( ) , 1 ) ;
2715+ updates. update_add_htlcs . get_mut ( 0 )
2716+ }
2717+ _ => panic ! ( )
2718+ } ;
2719+ update_message. map ( |msg| {
2720+ // corrupt the onion packet
2721+ msg. onion_routing_packet . hmac = [ 1 ; 32 ] ;
2722+ } ) ;
2723+ }
2724+
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 ) ;
2727+ do_pass_along_path ( args) ;
2728+
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+ }
2738+ {
2739+ let downstream_id = 4 ;
2740+ let upstream_id = 2 ;
2741+ 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 ]
2744+ ) ;
2745+ do_commitment_signed_dance ( & nodes[ upstream_id] , & nodes[ downstream_id] , & unblinded_node_updates. commitment_signed , true , false ) ;
2746+ }
2747+ {
2748+ let downstream_id = 2 ;
2749+ let upstream_id = 1 ;
2750+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ downstream_id] , nodes[ upstream_id] . node. get_our_node_id( ) ) ;
2751+ nodes[ upstream_id] . node . handle_update_fail_htlc (
2752+ nodes[ downstream_id] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2753+ ) ;
2754+ do_commitment_signed_dance ( & nodes[ upstream_id] , & nodes[ downstream_id] , & unblinded_node_updates. commitment_signed , true , false ) ;
2755+ }
2756+ {
2757+ let downstream_id = 1 ;
2758+ let upstream_id = 0 ;
2759+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ downstream_id] , nodes[ upstream_id] . node. get_our_node_id( ) ) ;
2760+ nodes[ upstream_id] . node . handle_update_fail_htlc (
2761+ nodes[ downstream_id] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2762+ ) ;
2763+ do_commitment_signed_dance ( & nodes[ upstream_id] , & nodes[ downstream_id] , & unblinded_node_updates. commitment_signed , false , false ) ;
2764+ }
2765+ {
2766+ let payment_failed_conditions = PaymentFailedConditions :: new ( )
2767+ . expected_htlc_error_data ( 0x2000 | 25 , & [ 0 ; 0 ] ) ;
2768+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false , payment_failed_conditions) ;
2769+ }
2770+ }
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 ( ) ,
2774+ None , first_message_event. clone ( ) , false , Some ( payment_preimage) ) ;
2775+
2776+ check_added_monitors ! ( & nodes[ 2 ] , 1 ) ;
2777+ let mut events = nodes[ 2 ] . node . get_and_clear_pending_msg_events ( ) ;
2778+ assert_eq ! ( events. len( ) , 1 ) ;
2779+
2780+ let mut update_message_carol_t0 = remove_first_msg_event_to_node ( & nodes[ 4 ] . node . get_our_node_id ( ) , & mut events) ;
2781+ {
2782+ let mut update_message = match update_message_carol_t0 {
2783+ MessageSendEvent :: UpdateHTLCs { ref mut updates, .. } => {
2784+ assert_eq ! ( updates. update_add_htlcs. len( ) , 1 ) ;
2785+ updates. update_add_htlcs . get_mut ( 0 )
2786+ }
2787+ _ => panic ! ( )
2788+ } ;
2789+ update_message. map ( |msg| {
2790+ // corrupt the onion packet
2791+ msg. onion_routing_packet . hmac = [ 1 ; 32 ] ;
2792+ } ) ;
2793+ }
2794+
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 ) ;
2797+ do_pass_along_path ( args) ;
2798+
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_malformed_htlc (
2804+ nodes[ downstream_id] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_malformed_htlcs [ 0 ]
2805+ ) ;
2806+ do_commitment_signed_dance ( & nodes[ upstream_id] , & nodes[ downstream_id] , & unblinded_node_updates. commitment_signed , true , false ) ;
2807+ }
2808+ {
2809+ let downstream_id = 2 ;
2810+ let upstream_id = 1 ;
2811+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ downstream_id] , nodes[ upstream_id] . node. get_our_node_id( ) ) ;
2812+ nodes[ upstream_id] . node . handle_update_fail_htlc (
2813+ nodes[ downstream_id] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2814+ ) ;
2815+ do_commitment_signed_dance ( & nodes[ upstream_id] , & nodes[ downstream_id] , & unblinded_node_updates. commitment_signed , true , false ) ;
2816+ }
2817+ {
2818+ let downstream_id = 1 ;
2819+ let upstream_id = 0 ;
2820+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ downstream_id] , nodes[ upstream_id] . node. get_our_node_id( ) ) ;
2821+ nodes[ upstream_id] . node . handle_update_fail_htlc (
2822+ nodes[ downstream_id] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2823+ ) ;
2824+ do_commitment_signed_dance ( & nodes[ upstream_id] , & nodes[ downstream_id] , & unblinded_node_updates. commitment_signed , false , false ) ;
2825+ }
2826+ {
2827+ let payment_failed_conditions = PaymentFailedConditions :: new ( )
2828+ . expected_htlc_error_data ( 0x2000 | 25 , & [ 0 ; 0 ] ) ;
2829+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false , payment_failed_conditions) ;
2830+ }
26892831 }
26902832 }
26912833}
26922834
26932835#[ test]
26942836fn test_unblinded_trampoline_forward ( ) {
2695- do_test_unblinded_trampoline_forward ( true ) ;
2696- do_test_unblinded_trampoline_forward ( false ) ;
2837+ do_test_unblinded_trampoline_forward ( None ) ;
2838+ do_test_unblinded_trampoline_forward ( Some ( TrampolineForwardFailureScenario :: NoRoute ) ) ;
2839+ do_test_unblinded_trampoline_forward ( Some ( TrampolineForwardFailureScenario :: InvalidInterTrampolineOnion ) ) ;
2840+ do_test_unblinded_trampoline_forward ( Some ( TrampolineForwardFailureScenario :: InvalidRecipientOnion ) ) ;
26972841}
26982842
26992843#[ test]
0 commit comments