@@ -2223,17 +2223,26 @@ macro_rules! expect_payment_path_successful {
22232223 }
22242224}
22252225
2226+ /// Returns the total fee earned by this HTLC forward, in msat.
22262227pub fn expect_payment_forwarded < CM : AChannelManager , H : NodeHolder < CM =CM > > (
22272228 event : Event , node : & H , prev_node : & H , next_node : & H , expected_fee : Option < u64 > ,
22282229 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 > {
22312232 match event {
22322233 Event :: PaymentForwarded {
22332234 total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
22342235 outbound_amount_forwarded_msat : _, skimmed_fee_msat
22352236 } => {
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+ }
22372246
22382247 // Check that the (knowingly) withheld amount is always less or equal to the expected
22392248 // overpaid amount.
@@ -2248,6 +2257,7 @@ pub fn expect_payment_forwarded<CM: AChannelManager, H: NodeHolder<CM=CM>>(
22482257 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( ) ) ) ;
22492258 }
22502259 assert_eq ! ( claim_from_onchain_tx, downstream_force_closed) ;
2260+ total_fee_earned_msat
22512261 } ,
22522262 _ => panic ! ( "Unexpected event" ) ,
22532263 }
@@ -2260,7 +2270,7 @@ macro_rules! expect_payment_forwarded {
22602270 assert_eq!( events. len( ) , 1 ) ;
22612271 $crate:: ln:: functional_test_utils:: expect_payment_forwarded(
22622272 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
22642274 ) ;
22652275 }
22662276}
@@ -2472,7 +2482,60 @@ fn fail_payment_along_path<'a, 'b, 'c>(expected_path: &[&Node<'a, 'b, 'c>]) {
24722482 }
24732483}
24742484
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+
24762539 let mut payment_event = SendEvent :: from_event ( ev) ;
24772540 let mut prev_node = origin_node;
24782541 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
25392602}
25402603
25412604pub 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)
25432616}
25442617
25452618pub 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
25512624 for path in expected_route. iter ( ) {
25522625 let ev = remove_first_msg_event_to_node ( & path[ 0 ] . node . get_our_node_id ( ) , & mut events) ;
25532626
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+
25552631 let nodes_to_fail_payment: Vec < _ > = vec ! [ origin_node] . into_iter ( ) . chain ( path. iter ( ) . cloned ( ) ) . collect ( ) ;
25562632
25572633 fail_payment_along_path ( nodes_to_fail_payment. as_slice ( ) ) ;
@@ -2598,6 +2674,14 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
25982674 pub expected_min_htlc_overpay : Vec < u32 > ,
25992675 pub skip_last : bool ,
26002676 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 ,
26012685}
26022686
26032687impl < ' a , ' b , ' c , ' d > ClaimAlongRouteArgs < ' a , ' b , ' c , ' d > {
@@ -2608,6 +2692,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
26082692 Self {
26092693 origin_node, expected_paths, expected_extra_fees : vec ! [ 0 ; expected_paths. len( ) ] ,
26102694 expected_min_htlc_overpay : vec ! [ 0 ; expected_paths. len( ) ] , skip_last : false , payment_preimage,
2695+ allow_1_msat_fee_overpay : false ,
26112696 }
26122697 }
26132698 pub fn skip_last ( mut self , skip_last : bool ) -> Self {
@@ -2622,15 +2707,21 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
26222707 self . expected_min_htlc_overpay = extra_fees;
26232708 self
26242709 }
2710+ pub fn allow_1_msat_fee_overpay ( mut self ) -> Self {
2711+ self . allow_1_msat_fee_overpay = true ;
2712+ self
2713+ }
26252714}
26262715
26272716pub fn pass_claimed_payment_along_route < ' a , ' b , ' c , ' d > ( args : ClaimAlongRouteArgs ) -> u64 {
26282717 let ClaimAlongRouteArgs {
26292718 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 ,
26312720 } = args;
26322721 let claim_event = expected_paths[ 0 ] . last ( ) . unwrap ( ) . node . get_and_clear_pending_events ( ) ;
26332722 assert_eq ! ( claim_event. len( ) , 1 ) ;
2723+ #[ allow( unused) ]
2724+ let mut fwd_amt_msat = 0 ;
26342725 match claim_event[ 0 ] {
26352726 Event :: PaymentClaimed {
26362727 purpose : PaymentPurpose :: SpontaneousPayment ( preimage) ,
@@ -2647,6 +2738,7 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
26472738 assert_eq ! ( htlcs. len( ) , expected_paths. len( ) ) ; // One per path.
26482739 assert_eq ! ( htlcs. iter( ) . map( |h| h. value_msat) . sum:: <u64 >( ) , amount_msat) ;
26492740 expected_paths. iter ( ) . zip ( htlcs) . for_each ( |( path, htlc) | check_claimed_htlc_channel ( origin_node, path, htlc) ) ;
2741+ fwd_amt_msat = amount_msat;
26502742 } ,
26512743 Event :: PaymentClaimed {
26522744 purpose : PaymentPurpose :: InvoicePayment { .. } ,
@@ -2659,6 +2751,7 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
26592751 assert_eq ! ( htlcs. len( ) , expected_paths. len( ) ) ; // One per path.
26602752 assert_eq ! ( htlcs. iter( ) . map( |h| h. value_msat) . sum:: <u64 >( ) , amount_msat) ;
26612753 expected_paths. iter ( ) . zip ( htlcs) . for_each ( |( path, htlc) | check_claimed_htlc_channel ( origin_node, path, htlc) ) ;
2754+ fwd_amt_msat = amount_msat;
26622755 }
26632756 _ => panic ! ( ) ,
26642757 }
@@ -2690,8 +2783,12 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
26902783 per_path_msgs. push ( msgs_from_ev ! ( & events[ 0 ] ) ) ;
26912784 } else {
26922785 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) ;
26952792 per_path_msgs. push ( msgs_from_ev ! ( & ev) ) ;
26962793 }
26972794 }
@@ -2715,15 +2812,20 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
27152812 {
27162813 $node. node. handle_update_fulfill_htlc( & $prev_node. node. get_our_node_id( ) , & next_msgs. as_ref( ) . unwrap( ) . 0 ) ;
27172814 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
27272829 } ;
27282830
27292831 let mut expected_extra_fee = None ;
@@ -2734,9 +2836,10 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArg
27342836 }
27352837 let mut events = $node. node. get_and_clear_pending_events( ) ;
27362838 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( ) ;
27402843 check_added_monitors!( $node, 1 ) ;
27412844 let new_next_msgs = if $new_msgs {
27422845 let events = $node. node. get_and_clear_pending_msg_events( ) ;
0 commit comments