@@ -267,6 +267,98 @@ fn one_hop_blinded_path_with_dummy_hops() {
267267 claim_payment_along_route ( claim_args) ;
268268}
269269
270+ #[ test]
271+ fn one_hop_blinded_path_with_dummy_hops_underpaid ( ) {
272+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
273+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
274+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
275+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
276+ let chan_upd =
277+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) . 0 . contents ;
278+
279+ let amt_msat = 5000 ;
280+ let ( _, payment_hash, payment_secret) =
281+ get_payment_preimage_hash ( & nodes[ 1 ] , Some ( amt_msat) , None ) ;
282+ let payee_tlvs = ReceiveTlvs {
283+ payment_secret,
284+ payment_constraints : PaymentConstraints {
285+ max_cltv_expiry : u32:: max_value ( ) ,
286+ htlc_minimum_msat : chan_upd. htlc_minimum_msat ,
287+ } ,
288+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
289+ } ;
290+ let receive_auth_key = chanmon_cfgs[ 1 ] . keys_manager . get_receive_auth_key ( ) ;
291+ let dummy_tlvs = [ DummyTlvs :: default ( ) ; 2 ] ;
292+
293+ let mut secp_ctx = Secp256k1 :: new ( ) ;
294+ // Advertise a receive path that includes dummy-hop relay requirements.
295+ let blinded_path = BlindedPaymentPath :: new_with_dummy_hops (
296+ & [ ] ,
297+ nodes[ 1 ] . node . get_our_node_id ( ) ,
298+ & dummy_tlvs,
299+ receive_auth_key,
300+ payee_tlvs,
301+ u64:: MAX ,
302+ TEST_FINAL_CLTV as u16 ,
303+ & chanmon_cfgs[ 1 ] . keys_manager ,
304+ & secp_ctx,
305+ )
306+ . unwrap ( ) ;
307+ assert ! ( blinded_path. payinfo. fee_base_msat > 0 ) ;
308+ assert ! ( blinded_path. payinfo. cltv_expiry_delta > TEST_FINAL_CLTV as u16 ) ;
309+
310+ let mut route_params = RouteParameters :: from_payment_params_and_value (
311+ PaymentParameters :: blinded ( vec ! [ blinded_path] ) ,
312+ amt_msat,
313+ ) ;
314+ if let Payee :: Blinded { ref mut route_hints, .. } = route_params. payment_params . payee {
315+ // Simulate a payer that funds only the recipient amount, not the dummy-hop fees.
316+ route_hints[ 0 ] . payinfo . fee_base_msat = 0 ;
317+ route_hints[ 0 ] . payinfo . fee_proportional_millionths = 0 ;
318+ } else {
319+ panic ! ( ) ;
320+ }
321+
322+ nodes[ 0 ]
323+ . node
324+ . send_payment (
325+ payment_hash,
326+ RecipientOnionFields :: spontaneous_empty ( amt_msat) ,
327+ PaymentId ( payment_hash. 0 ) ,
328+ route_params,
329+ Retry :: Attempts ( 0 ) ,
330+ )
331+ . unwrap ( ) ;
332+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
333+
334+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
335+ assert_eq ! ( events. len( ) , 1 ) ;
336+ let ev = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
337+
338+ let path = & [ & nodes[ 1 ] ] ;
339+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , path, amt_msat, payment_hash, ev)
340+ // The receiver rejects the HTLC while processing the hidden dummy hops.
341+ . expect_failure ( HTLCHandlingFailureType :: Receive { payment_hash } )
342+ . with_payment_secret ( payment_secret)
343+ . with_dummy_tlvs ( & dummy_tlvs) ;
344+ do_pass_along_path ( args) ;
345+
346+ let mut updates = get_htlc_update_msgs ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) ) ;
347+ // Blinded receive failures are surfaced to the sender as malformed onion blinding errors.
348+ nodes[ 0 ] . node . handle_update_fail_malformed_htlc (
349+ nodes[ 1 ] . node . get_our_node_id ( ) ,
350+ & updates. update_fail_malformed_htlcs [ 0 ] ,
351+ ) ;
352+ do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 1 ] , & updates. commitment_signed , false , false ) ;
353+ expect_payment_failed_conditions (
354+ & nodes[ 0 ] ,
355+ payment_hash,
356+ false ,
357+ PaymentFailedConditions :: new ( )
358+ . expected_htlc_error_data ( LocalHTLCFailureReason :: InvalidOnionBlinding , & [ 0 ; 32 ] ) ,
359+ ) ;
360+ }
361+
270362#[ test]
271363#[ rustfmt:: skip]
272364fn mpp_to_one_hop_blinded_path ( ) {
0 commit comments