77// You may not use this file except in accordance with one or both of these
88// licenses.
99
10- use bitcoin:: secp256k1:: Secp256k1 ;
10+ use bitcoin:: secp256k1:: { Secp256k1 , SecretKey } ;
1111use crate :: blinded_path:: BlindedPath ;
1212use crate :: blinded_path:: payment:: { ForwardNode , ForwardTlvs , PaymentConstraints , PaymentRelay , ReceiveTlvs } ;
1313use crate :: events:: MessageSendEventsProvider ;
@@ -16,6 +16,7 @@ use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
1616use crate :: ln:: features:: BlindedHopFeatures ;
1717use crate :: ln:: functional_test_utils:: * ;
1818use crate :: ln:: msgs:: ChannelMessageHandler ;
19+ use crate :: ln:: onion_utils;
1920use crate :: ln:: onion_utils:: INVALID_ONION_BLINDING ;
2021use crate :: ln:: outbound_payment:: Retry ;
2122use crate :: prelude:: * ;
@@ -113,14 +114,29 @@ fn mpp_to_one_hop_blinded_path() {
113114 claim_payment_along_route ( & nodes[ 0 ] , expected_route, false , payment_preimage) ;
114115}
115116
117+ enum ForwardCheckFail {
118+ // Fail a check on the inbound onion payload. In this case, we underflow when calculating the
119+ // outgoing cltv_expiry.
120+ InboundOnionCheck ,
121+ // The forwarding node's payload is encoded as a receive, i.e. the next hop HMAC is [0; 32].
122+ ForwardPayloadEncodedAsReceive ,
123+ }
124+
116125#[ test]
117126fn forward_checks_failure ( ) {
127+ do_forward_checks_failure ( ForwardCheckFail :: InboundOnionCheck ) ;
128+ do_forward_checks_failure ( ForwardCheckFail :: ForwardPayloadEncodedAsReceive ) ;
129+ }
130+
131+ fn do_forward_checks_failure ( check : ForwardCheckFail ) {
118132 // Ensure we'll fail backwards properly if a forwarding check fails on initial update_add
119133 // receipt.
120134 let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
121135 let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
122136 let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
123- let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
137+ let mut nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
138+ // We need the session priv to construct a bogus onion packet later.
139+ * nodes[ 0 ] . keys_manager . override_random_bytes . lock ( ) . unwrap ( ) = Some ( [ 3 ; 32 ] ) ;
124140 create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
125141 let chan_upd_1_2 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) . 0 . contents ;
126142
@@ -158,6 +174,8 @@ fn forward_checks_failure() {
158174
159175 let route_params = RouteParameters :: from_payment_params_and_value (
160176 PaymentParameters :: blinded ( vec ! [ blinded_path] ) , amt_msat) ;
177+ let route = get_route ( & nodes[ 0 ] , & route_params) . unwrap ( ) ;
178+ node_cfgs[ 0 ] . router . expect_find_route ( route_params. clone ( ) , Ok ( route. clone ( ) ) ) ;
161179 nodes[ 0 ] . node . send_payment ( payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 0 ) ) . unwrap ( ) ;
162180 check_added_monitors ( & nodes[ 0 ] , 1 ) ;
163181
@@ -167,7 +185,22 @@ fn forward_checks_failure() {
167185 let mut payment_event = SendEvent :: from_event ( ev) ;
168186
169187 let mut update_add = & mut payment_event. msgs [ 0 ] ;
170- update_add. cltv_expiry = 10 ; // causes outbound CLTV expiry to underflow
188+ match check {
189+ ForwardCheckFail :: InboundOnionCheck => {
190+ update_add. cltv_expiry = 10 ; // causes outbound CLTV expiry to underflow
191+ } ,
192+ ForwardCheckFail :: ForwardPayloadEncodedAsReceive => {
193+ let session_priv = SecretKey :: from_slice ( & [ 3 ; 32 ] ) . unwrap ( ) ;
194+ let onion_keys = onion_utils:: construct_onion_keys ( & Secp256k1 :: new ( ) , & route. paths [ 0 ] , & session_priv) . unwrap ( ) ;
195+ let cur_height = nodes[ 0 ] . best_block_info ( ) . 1 ;
196+ let ( mut onion_payloads, ..) = onion_utils:: build_onion_payloads (
197+ & route. paths [ 0 ] , amt_msat, RecipientOnionFields :: spontaneous_empty ( ) , cur_height, & None ) . unwrap ( ) ;
198+ // Remove the receive payload so the blinded forward payload is encoded as a final payload
199+ // (i.e. next_hop_hmac == [0; 32])
200+ onion_payloads. pop ( ) ;
201+ update_add. onion_routing_packet = onion_utils:: construct_onion_packet ( onion_payloads, onion_keys, [ 0 ; 32 ] , & payment_hash) . unwrap ( ) ;
202+ } ,
203+ }
171204 nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
172205 check_added_monitors ! ( nodes[ 1 ] , 0 ) ;
173206 do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 0 ] , & payment_event. commitment_msg , true , true ) ;
0 commit comments