@@ -2417,3 +2417,162 @@ fn no_extra_retries_on_back_to_back_fail() {
2417
2417
_ => panic ! ( "Unexpected event" ) ,
2418
2418
}
2419
2419
}
2420
+
2421
+ #[ test]
2422
+ fn test_simple_partial_retry ( ) {
2423
+ // In the first version of the in-`ChannelManager` payment retries, retries were sent for the
2424
+ // full amount of the payment, rather than only the missing amount. Here we simply test for
2425
+ // this by sending a payment with two parts, failing one, and retrying the second. Note that
2426
+ // `TestRouter` will check that the `RouteParameters` (which contain the amount) matches the
2427
+ // request.
2428
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
2429
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
2430
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
2431
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
2432
+
2433
+ let chan_1_scid = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 0 ) . 0 . contents . short_channel_id ;
2434
+ let chan_2_scid = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 0 ) . 0 . contents . short_channel_id ;
2435
+
2436
+ let amt_msat = 200_000_000 ;
2437
+ let ( _, payment_hash, _, payment_secret) = get_route_and_payment_hash ! ( & nodes[ 0 ] , nodes[ 2 ] , amt_msat) ;
2438
+ #[ cfg( feature = "std" ) ]
2439
+ let payment_expiry_secs = SystemTime :: UNIX_EPOCH . elapsed ( ) . unwrap ( ) . as_secs ( ) + 60 * 60 ;
2440
+ #[ cfg( not( feature = "std" ) ) ]
2441
+ let payment_expiry_secs = 60 * 60 ;
2442
+ let mut invoice_features = InvoiceFeatures :: empty ( ) ;
2443
+ invoice_features. set_variable_length_onion_required ( ) ;
2444
+ invoice_features. set_payment_secret_required ( ) ;
2445
+ invoice_features. set_basic_mpp_optional ( ) ;
2446
+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 1 ] . node . get_our_node_id ( ) , TEST_FINAL_CLTV )
2447
+ . with_expiry_time ( payment_expiry_secs as u64 )
2448
+ . with_features ( invoice_features) ;
2449
+ let route_params = RouteParameters {
2450
+ payment_params,
2451
+ final_value_msat : amt_msat,
2452
+ final_cltv_expiry_delta : TEST_FINAL_CLTV ,
2453
+ } ;
2454
+
2455
+ let mut route = Route {
2456
+ paths : vec ! [
2457
+ vec![ RouteHop {
2458
+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2459
+ node_features: nodes[ 1 ] . node. node_features( ) ,
2460
+ short_channel_id: chan_1_scid,
2461
+ channel_features: nodes[ 1 ] . node. channel_features( ) ,
2462
+ fee_msat: 0 , // nodes[1] will fail the payment as we don't pay its fee
2463
+ cltv_expiry_delta: 100 ,
2464
+ } , RouteHop {
2465
+ pubkey: nodes[ 2 ] . node. get_our_node_id( ) ,
2466
+ node_features: nodes[ 2 ] . node. node_features( ) ,
2467
+ short_channel_id: chan_2_scid,
2468
+ channel_features: nodes[ 2 ] . node. channel_features( ) ,
2469
+ fee_msat: 100_000_000 ,
2470
+ cltv_expiry_delta: 100 ,
2471
+ } ] ,
2472
+ vec![ RouteHop {
2473
+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2474
+ node_features: nodes[ 1 ] . node. node_features( ) ,
2475
+ short_channel_id: chan_1_scid,
2476
+ channel_features: nodes[ 1 ] . node. channel_features( ) ,
2477
+ fee_msat: 100_000 ,
2478
+ cltv_expiry_delta: 100 ,
2479
+ } , RouteHop {
2480
+ pubkey: nodes[ 2 ] . node. get_our_node_id( ) ,
2481
+ node_features: nodes[ 2 ] . node. node_features( ) ,
2482
+ short_channel_id: chan_2_scid,
2483
+ channel_features: nodes[ 2 ] . node. channel_features( ) ,
2484
+ fee_msat: 100_000_000 ,
2485
+ cltv_expiry_delta: 100 ,
2486
+ } ]
2487
+ ] ,
2488
+ payment_params : Some ( PaymentParameters :: from_node_id ( nodes[ 2 ] . node . get_our_node_id ( ) , TEST_FINAL_CLTV ) ) ,
2489
+ } ;
2490
+ nodes[ 0 ] . router . expect_find_route ( route_params. clone ( ) , Ok ( route. clone ( ) ) ) ;
2491
+ let mut second_payment_params = route_params. payment_params . clone ( ) ;
2492
+ second_payment_params. previously_failed_channels = vec ! [ chan_2_scid] ;
2493
+ // We'll only have one retry left at the end, so we'll hlepfully get a max_path_count of 1
2494
+ second_payment_params. max_path_count = 1 ;
2495
+ route. paths . remove ( 0 ) ;
2496
+ nodes[ 0 ] . router . expect_find_route ( RouteParameters {
2497
+ payment_params : second_payment_params,
2498
+ final_value_msat : amt_msat / 2 , final_cltv_expiry_delta : TEST_FINAL_CLTV ,
2499
+ } , Ok ( route. clone ( ) ) ) ;
2500
+
2501
+ nodes[ 0 ] . node . send_payment_with_retry ( payment_hash, & Some ( payment_secret) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 1 ) ) . unwrap ( ) ;
2502
+ let htlc_updates = SendEvent :: from_node ( & nodes[ 0 ] ) ;
2503
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2504
+ assert_eq ! ( htlc_updates. msgs. len( ) , 1 ) ;
2505
+
2506
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & htlc_updates. msgs [ 0 ] ) ;
2507
+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & htlc_updates. commitment_msg ) ;
2508
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2509
+ let ( bs_first_raa, bs_first_cs) = get_revoke_commit_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2510
+
2511
+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_first_raa) ;
2512
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2513
+ let second_htlc_updates = SendEvent :: from_node ( & nodes[ 0 ] ) ;
2514
+
2515
+ nodes[ 0 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_first_cs) ;
2516
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2517
+ let as_first_raa = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2518
+
2519
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & second_htlc_updates. msgs [ 0 ] ) ;
2520
+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & second_htlc_updates. commitment_msg ) ;
2521
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2522
+ let bs_second_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2523
+
2524
+ nodes[ 1 ] . node . handle_revoke_and_ack ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_first_raa) ;
2525
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2526
+ let bs_fail_update = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2527
+
2528
+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_second_raa) ;
2529
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2530
+
2531
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_fail_update. update_fail_htlcs [ 0 ] ) ;
2532
+ nodes[ 0 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_fail_update. commitment_signed ) ;
2533
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2534
+ let ( as_second_raa, as_third_cs) = get_revoke_commit_msgs ! ( nodes[ 0 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2535
+
2536
+ nodes[ 1 ] . node . handle_revoke_and_ack ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_second_raa) ;
2537
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2538
+
2539
+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_third_cs) ;
2540
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2541
+
2542
+ let bs_third_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2543
+
2544
+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_third_raa) ;
2545
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2546
+
2547
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
2548
+ assert_eq ! ( events. len( ) , 2 ) ;
2549
+ match events[ 0 ] {
2550
+ Event :: PaymentPathFailed { payment_hash : ev_payment_hash, payment_failed_permanently, .. } => {
2551
+ assert_eq ! ( payment_hash, ev_payment_hash) ;
2552
+ assert_eq ! ( payment_failed_permanently, false ) ;
2553
+ } ,
2554
+ _ => panic ! ( "Unexpected event" ) ,
2555
+ }
2556
+ match events[ 1 ] {
2557
+ Event :: PendingHTLCsForwardable { .. } => { } ,
2558
+ _ => panic ! ( "Unexpected event" ) ,
2559
+ }
2560
+
2561
+ nodes[ 0 ] . node . process_pending_htlc_forwards ( ) ;
2562
+ let retry_htlc_updates = SendEvent :: from_node ( & nodes[ 0 ] ) ;
2563
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2564
+
2565
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & retry_htlc_updates. msgs [ 0 ] ) ;
2566
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , & retry_htlc_updates. commitment_msg, false , true ) ;
2567
+
2568
+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
2569
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2570
+
2571
+ let bs_forward_update = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 2 ] . node. get_our_node_id( ) ) ;
2572
+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_forward_update. update_add_htlcs [ 0 ] ) ;
2573
+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_forward_update. update_add_htlcs [ 1 ] ) ;
2574
+ commitment_signed_dance ! ( nodes[ 2 ] , nodes[ 1 ] , & bs_forward_update. commitment_signed, false ) ;
2575
+
2576
+ expect_pending_htlcs_forwardable ! ( nodes[ 2 ] ) ;
2577
+ expect_payment_claimable ! ( nodes[ 2 ] , payment_hash, payment_secret, amt_msat) ;
2578
+ }
0 commit comments