@@ -2342,3 +2342,122 @@ fn test_trampoline_unblinded_receive() {
2342
2342
claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , payment_preimage) ;
2343
2343
}
2344
2344
2345
+ #[ test]
2346
+ fn test_trampoline_forward_rejection ( ) {
2347
+ const TOTAL_NODE_COUNT : usize = 3 ;
2348
+
2349
+ let chanmon_cfgs = create_chanmon_cfgs ( TOTAL_NODE_COUNT ) ;
2350
+ let node_cfgs = create_node_cfgs ( TOTAL_NODE_COUNT , & chanmon_cfgs) ;
2351
+ let node_chanmgrs = create_node_chanmgrs ( TOTAL_NODE_COUNT , & node_cfgs, & vec ! [ None ; TOTAL_NODE_COUNT ] ) ;
2352
+ let mut nodes = create_network ( TOTAL_NODE_COUNT , & node_cfgs, & node_chanmgrs) ;
2353
+
2354
+ let ( _, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
2355
+ let ( _, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) ;
2356
+
2357
+ for i in 0 ..TOTAL_NODE_COUNT { // connect all nodes' blocks
2358
+ connect_blocks ( & nodes[ i] , ( TOTAL_NODE_COUNT as u32 ) * CHAN_CONFIRM_DEPTH + 1 - nodes[ i] . best_block_info ( ) . 1 ) ;
2359
+ }
2360
+
2361
+ let alice_node_id = nodes[ 0 ] . node ( ) . get_our_node_id ( ) ;
2362
+ let bob_node_id = nodes[ 1 ] . node ( ) . get_our_node_id ( ) ;
2363
+ let carol_node_id = nodes[ 2 ] . node ( ) . get_our_node_id ( ) ;
2364
+
2365
+ let alice_bob_scid = nodes[ 0 ] . node ( ) . list_channels ( ) . iter ( ) . find ( |c| c. channel_id == chan_id_alice_bob) . unwrap ( ) . short_channel_id . unwrap ( ) ;
2366
+ let bob_carol_scid = nodes[ 1 ] . node ( ) . list_channels ( ) . iter ( ) . find ( |c| c. channel_id == chan_id_bob_carol) . unwrap ( ) . short_channel_id . unwrap ( ) ;
2367
+
2368
+ let amt_msat = 1000 ;
2369
+ let ( payment_preimage, payment_hash, _) = get_payment_preimage_hash ( & nodes[ 2 ] , Some ( amt_msat) , None ) ;
2370
+
2371
+ let route = Route {
2372
+ paths : vec ! [ Path {
2373
+ hops: vec![
2374
+ // Bob
2375
+ RouteHop {
2376
+ pubkey: bob_node_id,
2377
+ node_features: NodeFeatures :: empty( ) ,
2378
+ short_channel_id: alice_bob_scid,
2379
+ channel_features: ChannelFeatures :: empty( ) ,
2380
+ fee_msat: 1000 ,
2381
+ cltv_expiry_delta: 48 ,
2382
+ maybe_announced_channel: false ,
2383
+ } ,
2384
+
2385
+ // Carol
2386
+ RouteHop {
2387
+ pubkey: carol_node_id,
2388
+ node_features: NodeFeatures :: empty( ) ,
2389
+ short_channel_id: bob_carol_scid,
2390
+ channel_features: ChannelFeatures :: empty( ) ,
2391
+ fee_msat: 0 ,
2392
+ cltv_expiry_delta: 48 ,
2393
+ maybe_announced_channel: false ,
2394
+ }
2395
+ ] ,
2396
+ blinded_tail: Some ( BlindedTail {
2397
+ trampoline_hops: vec![
2398
+ // Carol
2399
+ TrampolineHop {
2400
+ pubkey: carol_node_id,
2401
+ node_features: Features :: empty( ) ,
2402
+ fee_msat: amt_msat,
2403
+ cltv_expiry_delta: 24 ,
2404
+ } ,
2405
+
2406
+ // Alice (unreachable)
2407
+ TrampolineHop {
2408
+ pubkey: alice_node_id,
2409
+ node_features: Features :: empty( ) ,
2410
+ fee_msat: amt_msat,
2411
+ cltv_expiry_delta: 24 ,
2412
+ } ,
2413
+ ] ,
2414
+ hops: vec![ BlindedHop {
2415
+ // Fake public key
2416
+ blinded_node_id: alice_node_id,
2417
+ encrypted_payload: vec![ ] ,
2418
+ } ] ,
2419
+ blinding_point: alice_node_id,
2420
+ excess_final_cltv_expiry_delta: 39 ,
2421
+ final_value_msat: amt_msat,
2422
+ } )
2423
+ } ] ,
2424
+ route_params : None ,
2425
+ } ;
2426
+
2427
+ nodes[ 0 ] . node . send_payment_with_route ( route. clone ( ) , payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) ) . unwrap ( ) ;
2428
+
2429
+ check_added_monitors ! ( & nodes[ 0 ] , 1 ) ;
2430
+
2431
+ // pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret);
2432
+
2433
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
2434
+ assert_eq ! ( events. len( ) , 1 ) ;
2435
+ let first_message_event = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
2436
+
2437
+ let route: & [ & Node ] = & [ & nodes[ 1 ] , & nodes[ 2 ] ] ;
2438
+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , route, amt_msat, payment_hash, first_message_event)
2439
+ . with_payment_preimage ( payment_preimage)
2440
+ . without_claimable_event ( )
2441
+ . expect_failure ( HTLCDestination :: FailedPayment { payment_hash } ) ;
2442
+ do_pass_along_path ( args) ;
2443
+
2444
+ {
2445
+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ 2 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2446
+ nodes[ 1 ] . node . handle_update_fail_htlc (
2447
+ nodes[ 2 ] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2448
+ ) ;
2449
+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 2 ] , & unblinded_node_updates. commitment_signed , true , false ) ;
2450
+ }
2451
+ {
2452
+ let unblinded_node_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2453
+ nodes[ 0 ] . node . handle_update_fail_htlc (
2454
+ nodes[ 1 ] . node . get_our_node_id ( ) , & unblinded_node_updates. update_fail_htlcs [ 0 ]
2455
+ ) ;
2456
+ do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 1 ] , & unblinded_node_updates. commitment_signed , false , false ) ;
2457
+ }
2458
+ {
2459
+ let payment_failed_conditions = PaymentFailedConditions :: new ( )
2460
+ . expected_htlc_error_data ( 0x4000 | 10 , & [ 0 ; 0 ] ) ;
2461
+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false , payment_failed_conditions) ;
2462
+ }
2463
+ }
0 commit comments