@@ -1962,11 +1962,8 @@ fn test_trampoline_inbound_payment_decoding() {
19621962 } ;
19631963}
19641964
1965- #[ test]
19661965#[ cfg( trampoline) ]
1967- fn test_successful_trampoline_single_hop_receive ( ) {
1968- // Simulate a payment of A (0) -> B (1) -> C(Trampoline (blinded intro)) (2)
1969-
1966+ fn do_test_trampoline_single_hop_receive ( success : bool ) {
19701967 const TOTAL_NODE_COUNT : usize = 3 ;
19711968 let secp_ctx = Secp256k1 :: new ( ) ;
19721969
@@ -1982,6 +1979,7 @@ fn test_successful_trampoline_single_hop_receive() {
19821979 connect_blocks ( & nodes[ i] , ( TOTAL_NODE_COUNT as u32 ) * CHAN_CONFIRM_DEPTH + 1 - nodes[ i] . best_block_info ( ) . 1 ) ;
19831980 }
19841981
1982+ let alice_node_id = nodes[ 0 ] . node ( ) . get_our_node_id ( ) ;
19851983 let bob_node_id = nodes[ 1 ] . node ( ) . get_our_node_id ( ) ;
19861984 let carol_node_id = nodes[ 2 ] . node ( ) . get_our_node_id ( ) ;
19871985
@@ -1990,129 +1988,51 @@ fn test_successful_trampoline_single_hop_receive() {
19901988
19911989 let amt_msat = 1000 ;
19921990 let ( payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash ( & nodes[ 2 ] , Some ( amt_msat) , None ) ;
1993- let payee_tlvs = UnauthenticatedReceiveTlvs {
1994- payment_secret,
1995- payment_constraints : PaymentConstraints {
1996- max_cltv_expiry : u32:: max_value ( ) ,
1997- htlc_minimum_msat : amt_msat,
1998- } ,
1999- payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
2000- } ;
2001-
2002- let nonce = Nonce ( [ 42u8 ; 16 ] ) ;
2003- let expanded_key = nodes[ 2 ] . keys_manager . get_inbound_payment_key ( ) ;
2004- let payee_tlvs = payee_tlvs. authenticate ( nonce, & expanded_key) ;
2005- let carol_unblinded_tlvs = payee_tlvs. encode ( ) ;
20061991
2007- let path = [ ( carol_node_id, WithoutLength ( & carol_unblinded_tlvs) ) ] ;
20081992 let carol_alice_trampoline_session_priv = secret_from_hex ( "a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03" ) ;
20091993 let carol_blinding_point = PublicKey :: from_secret_key ( & secp_ctx, & carol_alice_trampoline_session_priv) ;
2010- let carol_blinded_hops = blinded_path:: utils:: construct_blinded_hops (
2011- & secp_ctx, path. into_iter ( ) , & carol_alice_trampoline_session_priv
2012- ) . unwrap ( ) ;
2013-
2014- let route = Route {
2015- paths : vec ! [ Path {
2016- hops: vec![
2017- // Bob
2018- RouteHop {
2019- pubkey: bob_node_id,
2020- node_features: NodeFeatures :: empty( ) ,
2021- short_channel_id: alice_bob_scid,
2022- channel_features: ChannelFeatures :: empty( ) ,
2023- fee_msat: 1000 ,
2024- cltv_expiry_delta: 48 ,
2025- maybe_announced_channel: false ,
2026- } ,
2027-
2028- // Carol
2029- RouteHop {
2030- pubkey: carol_node_id,
2031- node_features: NodeFeatures :: empty( ) ,
2032- short_channel_id: bob_carol_scid,
2033- channel_features: ChannelFeatures :: empty( ) ,
2034- fee_msat: 0 ,
2035- cltv_expiry_delta: 48 ,
2036- maybe_announced_channel: false ,
2037- }
2038- ] ,
2039- blinded_tail: Some ( BlindedTail {
2040- trampoline_hops: vec![
2041- // Carol
2042- TrampolineHop {
2043- pubkey: carol_node_id,
2044- node_features: Features :: empty( ) ,
2045- fee_msat: amt_msat,
2046- cltv_expiry_delta: 24 ,
2047- } ,
2048- ] ,
2049- hops: carol_blinded_hops,
2050- blinding_point: carol_blinding_point,
2051- excess_final_cltv_expiry_delta: 39 ,
2052- final_value_msat: amt_msat,
2053- } )
2054- } ] ,
2055- route_params : None ,
2056- } ;
2057-
2058- nodes[ 0 ] . node . send_payment_with_route ( route, payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) ) . unwrap ( ) ;
2059-
2060- check_added_monitors ! ( & nodes[ 0 ] , 1 ) ;
2061- pass_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] , & nodes[ 2 ] ] ] , amt_msat, payment_hash, payment_secret) ;
2062- claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , payment_preimage) ;
2063- }
2064-
2065- #[ test]
2066- #[ cfg( trampoline) ]
2067- fn test_trampoline_blinded_decoding_failure ( ) {
2068- // Simulate a payment failure of A (0) -> B (1) -> C(Trampoline (blinded forward)) (2)
2069-
2070- const TOTAL_NODE_COUNT : usize = 3 ;
2071- let secp_ctx = Secp256k1 :: new ( ) ;
2072-
2073- let chanmon_cfgs = create_chanmon_cfgs ( TOTAL_NODE_COUNT ) ;
2074- let node_cfgs = create_node_cfgs ( TOTAL_NODE_COUNT , & chanmon_cfgs) ;
2075- let node_chanmgrs = create_node_chanmgrs ( TOTAL_NODE_COUNT , & node_cfgs, & vec ! [ None ; TOTAL_NODE_COUNT ] ) ;
2076- let mut nodes = create_network ( TOTAL_NODE_COUNT , & node_cfgs, & node_chanmgrs) ;
2077-
2078- let ( _, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
2079- let ( _, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) ;
2080-
2081- for i in 0 ..TOTAL_NODE_COUNT { // connect all nodes' blocks
2082- connect_blocks ( & nodes[ i] , ( TOTAL_NODE_COUNT as u32 ) * CHAN_CONFIRM_DEPTH + 1 - nodes[ i] . best_block_info ( ) . 1 ) ;
2083- }
1994+ let carol_blinded_hops = if success {
1995+ let payee_tlvs = UnauthenticatedReceiveTlvs {
1996+ payment_secret,
1997+ payment_constraints : PaymentConstraints {
1998+ max_cltv_expiry : u32:: max_value ( ) ,
1999+ htlc_minimum_msat : amt_msat,
2000+ } ,
2001+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
2002+ } ;
20842003
2085- let alice_node_id = nodes[ 0 ] . node ( ) . get_our_node_id ( ) ;
2086- let bob_node_id = nodes[ 1 ] . node ( ) . get_our_node_id ( ) ;
2087- let carol_node_id = nodes[ 2 ] . node ( ) . get_our_node_id ( ) ;
2004+ let nonce = Nonce ( [ 42u8 ; 16 ] ) ;
2005+ let expanded_key = nodes[ 2 ] . keys_manager . get_inbound_payment_key ( ) ;
2006+ let payee_tlvs = payee_tlvs. authenticate ( nonce, & expanded_key) ;
2007+ let carol_unblinded_tlvs = payee_tlvs. encode ( ) ;
20882008
2089- let alice_bob_scid = nodes[ 0 ] . node ( ) . list_channels ( ) . iter ( ) . find ( |c| c. channel_id == chan_id_alice_bob) . unwrap ( ) . short_channel_id . unwrap ( ) ;
2090- let bob_carol_scid = nodes[ 1 ] . node ( ) . list_channels ( ) . iter ( ) . find ( |c| c. channel_id == chan_id_bob_carol) . unwrap ( ) . short_channel_id . unwrap ( ) ;
2009+ let path = [ ( carol_node_id, WithoutLength ( & carol_unblinded_tlvs) ) ] ;
2010+ blinded_path:: utils:: construct_blinded_hops (
2011+ & secp_ctx, path. into_iter ( ) , & carol_alice_trampoline_session_priv
2012+ ) . unwrap ( )
2013+ } else {
2014+ let payee_tlvs = blinded_path:: payment:: TrampolineForwardTlvs {
2015+ next_trampoline : alice_node_id,
2016+ payment_constraints : PaymentConstraints {
2017+ max_cltv_expiry : u32:: max_value ( ) ,
2018+ htlc_minimum_msat : amt_msat,
2019+ } ,
2020+ features : BlindedHopFeatures :: empty ( ) ,
2021+ payment_relay : PaymentRelay {
2022+ cltv_expiry_delta : 0 ,
2023+ fee_proportional_millionths : 0 ,
2024+ fee_base_msat : 0 ,
2025+ } ,
2026+ next_blinding_override : None ,
2027+ } ;
20912028
2092- let amt_msat = 1000 ;
2093- let ( payment_preimage, payment_hash, _) = get_payment_preimage_hash ( & nodes[ 2 ] , Some ( amt_msat) , None ) ;
2094- let payee_tlvs = blinded_path:: payment:: TrampolineForwardTlvs {
2095- next_trampoline : alice_node_id,
2096- payment_constraints : PaymentConstraints {
2097- max_cltv_expiry : u32:: max_value ( ) ,
2098- htlc_minimum_msat : amt_msat,
2099- } ,
2100- features : BlindedHopFeatures :: empty ( ) ,
2101- payment_relay : PaymentRelay {
2102- cltv_expiry_delta : 0 ,
2103- fee_proportional_millionths : 0 ,
2104- fee_base_msat : 0 ,
2105- } ,
2106- next_blinding_override : None ,
2029+ let carol_unblinded_tlvs = payee_tlvs. encode ( ) ;
2030+ let path = [ ( carol_node_id, WithoutLength ( & carol_unblinded_tlvs) ) ] ;
2031+ blinded_path:: utils:: construct_blinded_hops (
2032+ & secp_ctx, path. into_iter ( ) , & carol_alice_trampoline_session_priv
2033+ ) . unwrap ( )
21072034 } ;
21082035
2109- let carol_unblinded_tlvs = payee_tlvs. encode ( ) ;
2110- let path = [ ( carol_node_id, WithoutLength ( & carol_unblinded_tlvs) ) ] ;
2111- let carol_alice_trampoline_session_priv = secret_from_hex ( "a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03" ) ;
2112- let carol_blinding_point = PublicKey :: from_secret_key ( & secp_ctx, & carol_alice_trampoline_session_priv) ;
2113- let carol_blinded_hops = blinded_path:: utils:: construct_blinded_hops (
2114- & secp_ctx, path. into_iter ( ) , & carol_alice_trampoline_session_priv
2115- ) . unwrap ( ) ;
21162036
21172037 let route = Route {
21182038 paths : vec ! [ Path {
@@ -2160,71 +2080,86 @@ fn test_trampoline_blinded_decoding_failure() {
21602080
21612081 nodes[ 0 ] . node . send_payment_with_route ( route. clone ( ) , payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) ) . unwrap ( ) ;
21622082
2163- let replacement_onion = {
2164- // create a substitute onion where the last Trampoline hop is a forward
2165- let trampoline_secret_key = secret_from_hex ( "0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799" ) ;
2166- let prng_seed = secret_from_hex ( "fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9" ) ;
2167- let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
2083+ check_added_monitors ! ( & nodes[ 0 ] , 1 ) ;
21682084
2169- let mut blinded_tail = route. paths [ 0 ] . blinded_tail . clone ( ) . unwrap ( ) ;
2085+ if success {
2086+ pass_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] , & nodes[ 2 ] ] ] , amt_msat, payment_hash, payment_secret) ;
2087+ claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , payment_preimage) ;
2088+ } else {
2089+ let replacement_onion = {
2090+ // create a substitute onion where the last Trampoline hop is a forward
2091+ let trampoline_secret_key = secret_from_hex ( "0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799" ) ;
2092+ let prng_seed = secret_from_hex ( "fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9" ) ;
2093+ let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
21702094
2171- // append some dummy blinded hop so the intro hop looks like a forward
2172- blinded_tail. hops . push ( BlindedHop {
2173- blinded_node_id : alice_node_id,
2174- encrypted_payload : vec ! [ ] ,
2175- } ) ;
2095+ let mut blinded_tail = route. paths [ 0 ] . blinded_tail . clone ( ) . unwrap ( ) ;
21762096
2177- let ( mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils:: build_trampoline_onion_payloads ( & blinded_tail, amt_msat, & recipient_onion_fields, 32 , & None ) . unwrap ( ) ;
2097+ // append some dummy blinded hop so the intro hop looks like a forward
2098+ blinded_tail. hops . push ( BlindedHop {
2099+ blinded_node_id : alice_node_id,
2100+ encrypted_payload : vec ! [ ] ,
2101+ } ) ;
21782102
2179- // pop the last dummy hop
2180- trampoline_payloads. pop ( ) ;
2103+ let ( mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils:: build_trampoline_onion_payloads ( & blinded_tail, amt_msat, & recipient_onion_fields, 32 , & None ) . unwrap ( ) ;
21812104
2182- let trampoline_onion_keys = onion_utils:: construct_trampoline_onion_keys ( & secp_ctx, & route. paths [ 0 ] . blinded_tail . as_ref ( ) . unwrap ( ) , & trampoline_secret_key) . unwrap ( ) ;
2183- let trampoline_packet = onion_utils:: construct_trampoline_onion_packet (
2184- trampoline_payloads,
2185- trampoline_onion_keys,
2186- prng_seed. secret_bytes ( ) ,
2187- & payment_hash,
2188- None ,
2189- ) . unwrap ( ) ;
2105+ // pop the last dummy hop
2106+ trampoline_payloads. pop ( ) ;
21902107
2191- let outer_session_priv = secret_from_hex ( "e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677" ) ;
2108+ let trampoline_onion_keys = onion_utils:: construct_trampoline_onion_keys ( & secp_ctx, & route. paths [ 0 ] . blinded_tail . as_ref ( ) . unwrap ( ) , & trampoline_secret_key) . unwrap ( ) ;
2109+ let trampoline_packet = onion_utils:: construct_trampoline_onion_packet (
2110+ trampoline_payloads,
2111+ trampoline_onion_keys,
2112+ prng_seed. secret_bytes ( ) ,
2113+ & payment_hash,
2114+ None ,
2115+ ) . unwrap ( ) ;
21922116
2193- let ( outer_payloads, _, _) = onion_utils:: build_onion_payloads ( & route. paths [ 0 ] , outer_total_msat, & recipient_onion_fields, outer_starting_htlc_offset, & None , None , Some ( trampoline_packet) ) . unwrap ( ) ;
2194- let outer_onion_keys = onion_utils:: construct_onion_keys ( & secp_ctx, & route. clone ( ) . paths [ 0 ] , & outer_session_priv) . unwrap ( ) ;
2195- let outer_packet = onion_utils:: construct_onion_packet (
2196- outer_payloads,
2197- outer_onion_keys,
2198- prng_seed. secret_bytes ( ) ,
2199- & payment_hash,
2200- ) . unwrap ( ) ;
2117+ let outer_session_priv = secret_from_hex ( "e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677" ) ;
22012118
2202- outer_packet
2203- } ;
2119+ let ( outer_payloads, _, _) = onion_utils:: build_onion_payloads ( & route. paths [ 0 ] , outer_total_msat, & recipient_onion_fields, outer_starting_htlc_offset, & None , None , Some ( trampoline_packet) ) . unwrap ( ) ;
2120+ let outer_onion_keys = onion_utils:: construct_onion_keys ( & secp_ctx, & route. clone ( ) . paths [ 0 ] , & outer_session_priv) . unwrap ( ) ;
2121+ let outer_packet = onion_utils:: construct_onion_packet (
2122+ outer_payloads,
2123+ outer_onion_keys,
2124+ prng_seed. secret_bytes ( ) ,
2125+ & payment_hash,
2126+ ) . unwrap ( ) ;
22042127
2205- check_added_monitors ! ( & nodes[ 0 ] , 1 ) ;
2128+ outer_packet
2129+ } ;
22062130
2207- // Check that we've queued the HTLCs of the async keysend payment.
2208- let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
2209- assert_eq ! ( events. len( ) , 1 ) ;
2210- let mut first_message_event = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
2211- let mut update_message = match first_message_event {
2212- MessageSendEvent :: UpdateHTLCs { ref mut updates, .. } => {
2213- assert_eq ! ( updates. update_add_htlcs. len( ) , 1 ) ;
2214- updates. update_add_htlcs . get_mut ( 0 )
2215- } ,
2216- _ => panic ! ( )
2217- } ;
2218- update_message. map ( |msg| {
2219- msg. onion_routing_packet = replacement_onion. clone ( ) ;
2220- } ) ;
2221-
2222- let route: & [ & Node ] = & [ & nodes[ 1 ] , & nodes[ 2 ] ] ;
2223- let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , route, amt_msat, payment_hash, first_message_event)
2224- . with_payment_preimage ( payment_preimage)
2225- . without_claimable_event ( )
2226- . expect_failure ( HTLCDestination :: InvalidOnion ) ;
2227- do_pass_along_path ( args) ;
2131+ // Check that we've queued the HTLCs of the async keysend payment.
2132+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
2133+ assert_eq ! ( events. len( ) , 1 ) ;
2134+ let mut first_message_event = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
2135+ let mut update_message = match first_message_event {
2136+ MessageSendEvent :: UpdateHTLCs { ref mut updates, .. } => {
2137+ assert_eq ! ( updates. update_add_htlcs. len( ) , 1 ) ;
2138+ updates. update_add_htlcs . get_mut ( 0 )
2139+ } ,
2140+ _ => panic ! ( )
2141+ } ;
2142+ update_message. map ( |msg| {
2143+ msg. onion_routing_packet = replacement_onion. clone ( ) ;
2144+ } ) ;
2145+
2146+ let route: & [ & Node ] = & [ & nodes[ 1 ] , & nodes[ 2 ] ] ;
2147+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , route, amt_msat, payment_hash, first_message_event)
2148+ . with_payment_preimage ( payment_preimage)
2149+ . without_claimable_event ( )
2150+ . expect_failure ( HTLCDestination :: InvalidOnion ) ;
2151+ do_pass_along_path ( args) ;
22282152
2229- fail_blinded_htlc_backwards ( payment_hash, 1 , & [ & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] ] , false ) ;
2153+ fail_blinded_htlc_backwards ( payment_hash, 1 , & [ & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] ] , false ) ;
2154+ }
2155+ }
2156+
2157+ #[ test]
2158+ #[ cfg( trampoline) ]
2159+ fn test_trampoline_single_hop_receive ( ) {
2160+ // Simulate a payment of A (0) -> B (1) -> C(Trampoline (blinded intro)) (2)
2161+ do_test_trampoline_single_hop_receive ( true ) ;
2162+
2163+ // Simulate a payment failure of A (0) -> B (1) -> C(Trampoline (blinded forward)) (2)
2164+ do_test_trampoline_single_hop_receive ( false ) ;
22302165}
0 commit comments