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