@@ -2223,17 +2223,26 @@ macro_rules! expect_payment_path_successful {
2223
2223
}
2224
2224
}
2225
2225
2226
+ /// Returns the total fee earned by this HTLC forward, in msat.
2226
2227
pub fn expect_payment_forwarded < CM : AChannelManager , H : NodeHolder < CM =CM > > (
2227
2228
event : Event , node : & H , prev_node : & H , next_node : & H , expected_fee : Option < u64 > ,
2228
2229
expected_extra_fees_msat : Option < u64 > , upstream_force_closed : bool ,
2229
- downstream_force_closed : bool
2230
- ) {
2230
+ downstream_force_closed : bool , allow_1_msat_fee_overpay : bool ,
2231
+ ) -> Option < u64 > {
2231
2232
match event {
2232
2233
Event :: PaymentForwarded {
2233
2234
total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
2234
2235
outbound_amount_forwarded_msat : _, skimmed_fee_msat
2235
2236
} => {
2236
- assert_eq ! ( total_fee_earned_msat, expected_fee) ;
2237
+ if allow_1_msat_fee_overpay {
2238
+ // Aggregating fees for blinded paths may result in a rounding error, causing slight
2239
+ // overpayment in fees.
2240
+ let actual_fee = total_fee_earned_msat. unwrap ( ) ;
2241
+ let expected_fee = expected_fee. unwrap ( ) ;
2242
+ assert ! ( actual_fee == expected_fee || actual_fee == expected_fee + 1 ) ;
2243
+ } else {
2244
+ assert_eq ! ( total_fee_earned_msat, expected_fee) ;
2245
+ }
2237
2246
2238
2247
// Check that the (knowingly) withheld amount is always less or equal to the expected
2239
2248
// overpaid amount.
@@ -2248,6 +2257,7 @@ pub fn expect_payment_forwarded<CM: AChannelManager, H: NodeHolder<CM=CM>>(
2248
2257
assert ! ( node. node( ) . list_channels( ) . iter( ) . any( |x| x. counterparty. node_id == next_node. node( ) . get_our_node_id( ) && x. channel_id == next_channel_id. unwrap( ) ) ) ;
2249
2258
}
2250
2259
assert_eq ! ( claim_from_onchain_tx, downstream_force_closed) ;
2260
+ total_fee_earned_msat
2251
2261
} ,
2252
2262
_ => panic ! ( "Unexpected event" ) ,
2253
2263
}
@@ -2260,7 +2270,7 @@ macro_rules! expect_payment_forwarded {
2260
2270
assert_eq!( events. len( ) , 1 ) ;
2261
2271
$crate:: ln:: functional_test_utils:: expect_payment_forwarded(
2262
2272
events. pop( ) . unwrap( ) , & $node, & $prev_node, & $next_node, $expected_fee, None ,
2263
- $upstream_force_closed, $downstream_force_closed
2273
+ $upstream_force_closed, $downstream_force_closed, false
2264
2274
) ;
2265
2275
}
2266
2276
}
@@ -2472,7 +2482,60 @@ fn fail_payment_along_path<'a, 'b, 'c>(expected_path: &[&Node<'a, 'b, 'c>]) {
2472
2482
}
2473
2483
}
2474
2484
2475
- pub fn do_pass_along_path < ' a , ' b , ' c > ( origin_node : & Node < ' a , ' b , ' c > , expected_path : & [ & Node < ' a , ' b , ' c > ] , recv_value : u64 , our_payment_hash : PaymentHash , our_payment_secret : Option < PaymentSecret > , ev : MessageSendEvent , payment_claimable_expected : bool , clear_recipient_events : bool , expected_preimage : Option < PaymentPreimage > , is_probe : bool ) -> Option < Event > {
2485
+ pub struct PassAlongPathArgs < ' a , ' b , ' c , ' d > {
2486
+ pub origin_node : & ' a Node < ' b , ' c , ' d > ,
2487
+ pub expected_path : & ' a [ & ' a Node < ' b , ' c , ' d > ] ,
2488
+ pub recv_value : u64 ,
2489
+ pub payment_hash : PaymentHash ,
2490
+ pub payment_secret : Option < PaymentSecret > ,
2491
+ pub event : MessageSendEvent ,
2492
+ pub payment_claimable_expected : bool ,
2493
+ pub clear_recipient_events : bool ,
2494
+ pub expected_preimage : Option < PaymentPreimage > ,
2495
+ pub is_probe : bool ,
2496
+ }
2497
+
2498
+ impl < ' a , ' b , ' c , ' d > PassAlongPathArgs < ' a , ' b , ' c , ' d > {
2499
+ pub fn new (
2500
+ origin_node : & ' a Node < ' b , ' c , ' d > , expected_path : & ' a [ & ' a Node < ' b , ' c , ' d > ] , recv_value : u64 ,
2501
+ payment_hash : PaymentHash , event : MessageSendEvent ,
2502
+ ) -> Self {
2503
+ Self {
2504
+ origin_node, expected_path, recv_value, payment_hash, payment_secret : None , event,
2505
+ payment_claimable_expected : true , clear_recipient_events : true , expected_preimage : None ,
2506
+ is_probe : false ,
2507
+ }
2508
+ }
2509
+ pub fn without_clearing_recipient_events ( mut self ) -> Self {
2510
+ self . clear_recipient_events = false ;
2511
+ self
2512
+ }
2513
+ pub fn is_probe ( mut self ) -> Self {
2514
+ self . payment_claimable_expected = false ;
2515
+ self . is_probe = true ;
2516
+ self
2517
+ }
2518
+ pub fn without_claimable_event ( mut self ) -> Self {
2519
+ self . payment_claimable_expected = false ;
2520
+ self
2521
+ }
2522
+ pub fn with_payment_secret ( mut self , payment_secret : PaymentSecret ) -> Self {
2523
+ self . payment_secret = Some ( payment_secret) ;
2524
+ self
2525
+ }
2526
+ pub fn with_payment_preimage ( mut self , payment_preimage : PaymentPreimage ) -> Self {
2527
+ self . expected_preimage = Some ( payment_preimage) ;
2528
+ self
2529
+ }
2530
+ }
2531
+
2532
+ pub fn do_pass_along_path < ' a , ' b , ' c > ( args : PassAlongPathArgs ) -> Option < Event > {
2533
+ let PassAlongPathArgs {
2534
+ origin_node, expected_path, recv_value, payment_hash : our_payment_hash,
2535
+ payment_secret : our_payment_secret, event : ev, payment_claimable_expected,
2536
+ clear_recipient_events, expected_preimage, is_probe
2537
+ } = args;
2538
+
2476
2539
let mut payment_event = SendEvent :: from_event ( ev) ;
2477
2540
let mut prev_node = origin_node;
2478
2541
let mut event = None ;
@@ -2539,7 +2602,17 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p
2539
2602
}
2540
2603
2541
2604
pub fn pass_along_path < ' a , ' b , ' c > ( origin_node : & Node < ' a , ' b , ' c > , expected_path : & [ & Node < ' a , ' b , ' c > ] , recv_value : u64 , our_payment_hash : PaymentHash , our_payment_secret : Option < PaymentSecret > , ev : MessageSendEvent , payment_claimable_expected : bool , expected_preimage : Option < PaymentPreimage > ) -> Option < Event > {
2542
- do_pass_along_path ( origin_node, expected_path, recv_value, our_payment_hash, our_payment_secret, ev, payment_claimable_expected, true , expected_preimage, false )
2605
+ let mut args = PassAlongPathArgs :: new ( origin_node, expected_path, recv_value, our_payment_hash, ev) ;
2606
+ if !payment_claimable_expected {
2607
+ args = args. without_claimable_event ( ) ;
2608
+ }
2609
+ if let Some ( payment_secret) = our_payment_secret {
2610
+ args = args. with_payment_secret ( payment_secret) ;
2611
+ }
2612
+ if let Some ( payment_preimage) = expected_preimage {
2613
+ args = args. with_payment_preimage ( payment_preimage) ;
2614
+ }
2615
+ do_pass_along_path ( args)
2543
2616
}
2544
2617
2545
2618
pub fn send_probe_along_route < ' a , ' b , ' c > ( origin_node : & Node < ' a , ' b , ' c > , expected_route : & [ & [ & Node < ' a , ' b , ' c > ] ] ) {
@@ -2551,7 +2624,10 @@ pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expect
2551
2624
for path in expected_route. iter ( ) {
2552
2625
let ev = remove_first_msg_event_to_node ( & path[ 0 ] . node . get_our_node_id ( ) , & mut events) ;
2553
2626
2554
- do_pass_along_path ( origin_node, path, 0 , PaymentHash ( [ 0_u8 ; 32 ] ) , None , ev, false , false , None , true ) ;
2627
+ do_pass_along_path ( PassAlongPathArgs :: new ( origin_node, path, 0 , PaymentHash ( [ 0_u8 ; 32 ] ) , ev)
2628
+ . is_probe ( )
2629
+ . without_clearing_recipient_events ( ) ) ;
2630
+
2555
2631
let nodes_to_fail_payment: Vec < _ > = vec ! [ origin_node] . into_iter ( ) . chain ( path. iter ( ) . cloned ( ) ) . collect ( ) ;
2556
2632
2557
2633
fail_payment_along_path ( nodes_to_fail_payment. as_slice ( ) ) ;
@@ -2598,6 +2674,14 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
2598
2674
pub expected_min_htlc_overpay : Vec < u32 > ,
2599
2675
pub skip_last : bool ,
2600
2676
pub payment_preimage : PaymentPreimage ,
2677
+ // Allow forwarding nodes to have taken 1 msat more fee than expected based on the downstream
2678
+ // fulfill amount.
2679
+ //
2680
+ // Necessary because our test utils calculate the expected fee for an intermediate node based on
2681
+ // the amount was claimed in their downstream peer's fulfill, but blinded intermediate nodes
2682
+ // calculate their fee based on the inbound amount from their upstream peer, causing a difference
2683
+ // in rounding.
2684
+ pub allow_1_msat_fee_overpay : bool ,
2601
2685
}
2602
2686
2603
2687
impl < ' a , ' b , ' c , ' d > ClaimAlongRouteArgs < ' a , ' b , ' c , ' d > {
@@ -2608,6 +2692,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
2608
2692
Self {
2609
2693
origin_node, expected_paths, expected_extra_fees : vec ! [ 0 ; expected_paths. len( ) ] ,
2610
2694
expected_min_htlc_overpay : vec ! [ 0 ; expected_paths. len( ) ] , skip_last : false , payment_preimage,
2695
+ allow_1_msat_fee_overpay : false ,
2611
2696
}
2612
2697
}
2613
2698
pub fn skip_last ( mut self , skip_last : bool ) -> Self {
@@ -2622,15 +2707,21 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
2622
2707
self . expected_min_htlc_overpay = extra_fees;
2623
2708
self
2624
2709
}
2710
+ pub fn allow_1_msat_fee_overpay ( mut self ) -> Self {
2711
+ self . allow_1_msat_fee_overpay = true ;
2712
+ self
2713
+ }
2625
2714
}
2626
2715
2627
2716
pub fn pass_claimed_payment_along_route < ' a , ' b , ' c , ' d > ( args : ClaimAlongRouteArgs ) -> u64 {
2628
2717
let ClaimAlongRouteArgs {
2629
2718
origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last,
2630
- payment_preimage : our_payment_preimage
2719
+ payment_preimage : our_payment_preimage, allow_1_msat_fee_overpay ,
2631
2720
} = args;
2632
2721
let claim_event = expected_paths[ 0 ] . last ( ) . unwrap ( ) . node . get_and_clear_pending_events ( ) ;
2633
2722
assert_eq ! ( claim_event. len( ) , 1 ) ;
2723
+ #[ allow( unused) ]
2724
+ let mut fwd_amt_msat = 0 ;
2634
2725
match claim_event[ 0 ] {
2635
2726
Event :: PaymentClaimed {
2636
2727
purpose : PaymentPurpose :: SpontaneousPayment ( preimage) ,
@@ -2647,6 +2738,7 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
2647
2738
assert_eq ! ( htlcs. len( ) , expected_paths. len( ) ) ; // One per path.
2648
2739
assert_eq ! ( htlcs. iter( ) . map( |h| h. value_msat) . sum:: <u64 >( ) , amount_msat) ;
2649
2740
expected_paths. iter ( ) . zip ( htlcs) . for_each ( |( path, htlc) | check_claimed_htlc_channel ( origin_node, path, htlc) ) ;
2741
+ fwd_amt_msat = amount_msat;
2650
2742
} ,
2651
2743
Event :: PaymentClaimed {
2652
2744
purpose : PaymentPurpose :: InvoicePayment { .. } ,
@@ -2659,6 +2751,7 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
2659
2751
assert_eq ! ( htlcs. len( ) , expected_paths. len( ) ) ; // One per path.
2660
2752
assert_eq ! ( htlcs. iter( ) . map( |h| h. value_msat) . sum:: <u64 >( ) , amount_msat) ;
2661
2753
expected_paths. iter ( ) . zip ( htlcs) . for_each ( |( path, htlc) | check_claimed_htlc_channel ( origin_node, path, htlc) ) ;
2754
+ fwd_amt_msat = amount_msat;
2662
2755
}
2663
2756
_ => panic ! ( ) ,
2664
2757
}
@@ -2690,8 +2783,12 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
2690
2783
per_path_msgs. push ( msgs_from_ev ! ( & events[ 0 ] ) ) ;
2691
2784
} else {
2692
2785
for expected_path in expected_paths. iter ( ) {
2693
- // For MPP payments, we always want the message to the first node in the path.
2694
- let ev = remove_first_msg_event_to_node ( & expected_path[ 0 ] . node . get_our_node_id ( ) , & mut events) ;
2786
+ // For MPP payments, we want the fulfill message from the payee to the penultimate hop in the
2787
+ // path.
2788
+ let penultimate_hop_node_id = expected_path. iter ( ) . rev ( ) . skip ( 1 ) . next ( )
2789
+ . map ( |n| n. node . get_our_node_id ( ) )
2790
+ . unwrap_or ( origin_node. node . get_our_node_id ( ) ) ;
2791
+ let ev = remove_first_msg_event_to_node ( & penultimate_hop_node_id, & mut events) ;
2695
2792
per_path_msgs. push ( msgs_from_ev ! ( & ev) ) ;
2696
2793
}
2697
2794
}
@@ -2715,15 +2812,20 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
2715
2812
{
2716
2813
$node. node. handle_update_fulfill_htlc( & $prev_node. node. get_our_node_id( ) , & next_msgs. as_ref( ) . unwrap( ) . 0 ) ;
2717
2814
let mut fee = {
2718
- let per_peer_state = $node. node. per_peer_state. read( ) . unwrap( ) ;
2719
- let peer_state = per_peer_state. get( & $prev_node. node. get_our_node_id( ) )
2720
- . unwrap( ) . lock( ) . unwrap( ) ;
2721
- let channel = peer_state. channel_by_id. get( & next_msgs. as_ref( ) . unwrap( ) . 0 . channel_id) . unwrap( ) ;
2722
- if let Some ( prev_config) = channel. context( ) . prev_config( ) {
2723
- prev_config. forwarding_fee_base_msat
2724
- } else {
2725
- channel. context( ) . config( ) . forwarding_fee_base_msat
2726
- }
2815
+ let ( base_fee, prop_fee) = {
2816
+ let per_peer_state = $node. node. per_peer_state. read( ) . unwrap( ) ;
2817
+ let peer_state = per_peer_state. get( & $prev_node. node. get_our_node_id( ) )
2818
+ . unwrap( ) . lock( ) . unwrap( ) ;
2819
+ let channel = peer_state. channel_by_id. get( & next_msgs. as_ref( ) . unwrap( ) . 0 . channel_id) . unwrap( ) ;
2820
+ if let Some ( prev_config) = channel. context( ) . prev_config( ) {
2821
+ ( prev_config. forwarding_fee_base_msat as u64 ,
2822
+ prev_config. forwarding_fee_proportional_millionths as u64 )
2823
+ } else {
2824
+ ( channel. context( ) . config( ) . forwarding_fee_base_msat as u64 ,
2825
+ channel. context( ) . config( ) . forwarding_fee_proportional_millionths as u64 )
2826
+ }
2827
+ } ;
2828
+ ( ( fwd_amt_msat * prop_fee / 1_000_000 ) + base_fee) as u32
2727
2829
} ;
2728
2830
2729
2831
let mut expected_extra_fee = None ;
@@ -2734,9 +2836,10 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
2734
2836
}
2735
2837
let mut events = $node. node. get_and_clear_pending_events( ) ;
2736
2838
assert_eq!( events. len( ) , 1 ) ;
2737
- expect_payment_forwarded( events. pop( ) . unwrap( ) , * $node, $next_node, $prev_node,
2738
- Some ( fee as u64 ) , expected_extra_fee, false , false ) ;
2739
- expected_total_fee_msat += fee as u64 ;
2839
+ let actual_fee = expect_payment_forwarded( events. pop( ) . unwrap( ) , * $node, $next_node, $prev_node,
2840
+ Some ( fee as u64 ) , expected_extra_fee, false , false , allow_1_msat_fee_overpay) ;
2841
+ expected_total_fee_msat += actual_fee. unwrap( ) ;
2842
+ fwd_amt_msat += actual_fee. unwrap( ) ;
2740
2843
check_added_monitors!( $node, 1 ) ;
2741
2844
let new_next_msgs = if $new_msgs {
2742
2845
let events = $node. node. get_and_clear_pending_msg_events( ) ;
0 commit comments