@@ -3285,6 +3285,90 @@ fn async_payment_mpp() {
3285
3285
claim_payment_along_route ( ClaimAlongRouteArgs :: new ( sender, expected_route, keysend_preimage) ) ;
3286
3286
}
3287
3287
3288
+ #[ test]
3289
+ fn fallback_to_one_hop_release_htlc_path ( ) {
3290
+ // Check that if the sender's LSP's message router fails to find a blinded path when creating a
3291
+ // path for the release_held_htlc message, they will fall back to manually creating a 1-hop
3292
+ // blinded path.
3293
+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
3294
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
3295
+
3296
+ let ( sender_cfg, recipient_cfg) = ( often_offline_node_cfg ( ) , often_offline_node_cfg ( ) ) ;
3297
+ let mut sender_lsp_cfg = test_default_channel_config ( ) ;
3298
+ sender_lsp_cfg. enable_htlc_hold = true ;
3299
+ let mut invoice_server_cfg = test_default_channel_config ( ) ;
3300
+ invoice_server_cfg. accept_forwards_to_priv_channels = true ;
3301
+
3302
+ let node_chanmgrs = create_node_chanmgrs (
3303
+ 4 ,
3304
+ & node_cfgs,
3305
+ & [ Some ( sender_cfg) , Some ( sender_lsp_cfg) , Some ( invoice_server_cfg) , Some ( recipient_cfg) ] ,
3306
+ ) ;
3307
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
3308
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
3309
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) ;
3310
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 1_000_000 , 0 ) ;
3311
+ // Make sure all nodes are at the same block height
3312
+ let node_max_height =
3313
+ nodes. iter ( ) . map ( |node| node. blocks . lock ( ) . unwrap ( ) . len ( ) ) . max ( ) . unwrap ( ) as u32 ;
3314
+ connect_blocks ( & nodes[ 0 ] , node_max_height - nodes[ 0 ] . best_block_info ( ) . 1 ) ;
3315
+ connect_blocks ( & nodes[ 1 ] , node_max_height - nodes[ 1 ] . best_block_info ( ) . 1 ) ;
3316
+ connect_blocks ( & nodes[ 2 ] , node_max_height - nodes[ 2 ] . best_block_info ( ) . 1 ) ;
3317
+ connect_blocks ( & nodes[ 3 ] , node_max_height - nodes[ 3 ] . best_block_info ( ) . 1 ) ;
3318
+ let sender = & nodes[ 0 ] ;
3319
+ let sender_lsp = & nodes[ 1 ] ;
3320
+ let invoice_server = & nodes[ 2 ] ;
3321
+ let recipient = & nodes[ 3 ] ;
3322
+
3323
+ let amt_msat = 5000 ;
3324
+ let ( static_invoice, peer_node_id, static_invoice_om) =
3325
+ build_async_offer_and_init_payment ( amt_msat, & nodes) ;
3326
+
3327
+ // Force the sender_lsp's call to MessageRouter::create_blinded_paths to fail so it has to fall
3328
+ // back to a 1-hop blinded path when creating the paths for its revoke_and_ack message.
3329
+ sender_lsp. message_router . create_blinded_paths_res_override . lock ( ) . unwrap ( ) . 1 = Some ( Err ( ( ) ) ) ;
3330
+
3331
+ let payment_hash =
3332
+ lock_in_htlc_for_static_invoice ( & static_invoice_om, peer_node_id, sender, sender_lsp) ;
3333
+
3334
+ // Check that we actually had to fall back to a 1-hop path.
3335
+ assert ! ( sender_lsp. message_router. create_blinded_paths_res_override. lock( ) . unwrap( ) . 0 > 0 ) ;
3336
+ sender_lsp. message_router . create_blinded_paths_res_override . lock ( ) . unwrap ( ) . 1 = None ;
3337
+
3338
+ sender_lsp. node . process_pending_htlc_forwards ( ) ;
3339
+ let ( peer_id, held_htlc_om) =
3340
+ extract_held_htlc_available_oms ( sender, & [ sender_lsp, invoice_server, recipient] )
3341
+ . pop ( )
3342
+ . unwrap ( ) ;
3343
+ recipient. onion_messenger . handle_onion_message ( peer_id, & held_htlc_om) ;
3344
+
3345
+ // The release_htlc OM should go straight to the sender's LSP since they created a 1-hop blinded
3346
+ // path to themselves for receiving it.
3347
+ let release_htlc_om = recipient
3348
+ . onion_messenger
3349
+ . next_onion_message_for_peer ( sender_lsp. node . get_our_node_id ( ) )
3350
+ . unwrap ( ) ;
3351
+ sender_lsp
3352
+ . onion_messenger
3353
+ . handle_onion_message ( recipient. node . get_our_node_id ( ) , & release_htlc_om) ;
3354
+
3355
+ sender_lsp. node . process_pending_htlc_forwards ( ) ;
3356
+ let mut events = sender_lsp. node . get_and_clear_pending_msg_events ( ) ;
3357
+ assert_eq ! ( events. len( ) , 1 ) ;
3358
+ let ev = remove_first_msg_event_to_node ( & invoice_server. node . get_our_node_id ( ) , & mut events) ;
3359
+ check_added_monitors ! ( sender_lsp, 1 ) ;
3360
+
3361
+ let path: & [ & Node ] = & [ invoice_server, recipient] ;
3362
+ let args = PassAlongPathArgs :: new ( sender_lsp, path, amt_msat, payment_hash, ev) ;
3363
+ let claimable_ev = do_pass_along_path ( args) . unwrap ( ) ;
3364
+
3365
+ let route: & [ & [ & Node ] ] = & [ & [ sender_lsp, invoice_server, recipient] ] ;
3366
+ let keysend_preimage = extract_payment_preimage ( & claimable_ev) ;
3367
+ let ( res, _) =
3368
+ claim_payment_along_route ( ClaimAlongRouteArgs :: new ( sender, route, keysend_preimage) ) ;
3369
+ assert_eq ! ( res, Some ( PaidBolt12Invoice :: StaticInvoice ( static_invoice) ) ) ;
3370
+ }
3371
+
3288
3372
#[ test]
3289
3373
fn fail_held_htlcs_when_cfg_unset ( ) {
3290
3374
// Test that if we receive a held HTLC but `UserConfig::enable_htlc_hold` is unset, we will fail
0 commit comments