@@ -1622,9 +1622,13 @@ where L::Target: Logger {
16221622 |info| info. features . supports_basic_mpp ( ) ) )
16231623 } else { false } ;
16241624
1625- log_trace ! ( logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph" , our_node_pubkey,
1626- LoggedPayeePubkey ( payment_params. payee. node_id( ) ) , if allow_mpp { "with" } else { "without" } ,
1627- first_hops. map( |hops| hops. len( ) ) . unwrap_or( 0 ) , if first_hops. is_some( ) { "" } else { "not " } ) ;
1625+ let max_total_routing_fee_msat = route_params. max_total_routing_fee_msat . unwrap_or ( u64:: max_value ( ) ) ;
1626+
1627+ log_trace ! ( logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph with a fee limit of {} msat" ,
1628+ our_node_pubkey, LoggedPayeePubkey ( payment_params. payee. node_id( ) ) ,
1629+ if allow_mpp { "with" } else { "without" } ,
1630+ first_hops. map( |hops| hops. len( ) ) . unwrap_or( 0 ) , if first_hops. is_some( ) { "" } else { "not " } ,
1631+ max_total_routing_fee_msat) ;
16281632
16291633 // Step (1).
16301634 // Prepare the data we'll use for payee-to-payer search by
@@ -1788,9 +1792,9 @@ where L::Target: Logger {
17881792 #[ allow( unused_comparisons) ] // $next_hops_path_htlc_minimum_msat is 0 in some calls so rustc complains
17891793 let may_overpay_to_meet_path_minimum_msat =
17901794 ( ( amount_to_transfer_over_msat < $candidate. htlc_minimum_msat( ) &&
1791- recommended_value_msat > $candidate. htlc_minimum_msat( ) ) ||
1795+ recommended_value_msat >= $candidate. htlc_minimum_msat( ) ) ||
17921796 ( amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat &&
1793- recommended_value_msat > $next_hops_path_htlc_minimum_msat) ) ;
1797+ recommended_value_msat >= $next_hops_path_htlc_minimum_msat) ) ;
17941798
17951799 let payment_failed_on_this_channel = scid_opt. map_or( false ,
17961800 |scid| payment_params. previously_failed_channels. contains( & scid) ) ;
@@ -1890,7 +1894,6 @@ where L::Target: Logger {
18901894 }
18911895
18921896 // Ignore hops if augmenting the current path to them would put us over `max_total_routing_fee_msat`
1893- let max_total_routing_fee_msat = route_params. max_total_routing_fee_msat. unwrap_or( u64 :: max_value( ) ) ;
18941897 if total_fee_msat > max_total_routing_fee_msat {
18951898 if should_log_candidate {
18961899 log_trace!( logger, "Ignoring {} due to exceeding max total routing fee limit." , LoggedCandidateHop ( & $candidate) ) ;
@@ -2454,6 +2457,9 @@ where L::Target: Logger {
24542457 // because we deterministically terminated the search due to low liquidity.
24552458 if !found_new_path && channel_saturation_pow_half != 0 {
24562459 channel_saturation_pow_half = 0 ;
2460+ } else if !found_new_path && hit_minimum_limit && already_collected_value_msat < final_value_msat && path_value_msat != recommended_value_msat {
2461+ log_trace ! ( logger, "Failed to collect enough value, but running again to collect extra paths with a potentially higher limit." ) ;
2462+ path_value_msat = recommended_value_msat;
24572463 } else if already_collected_value_msat >= recommended_value_msat || !found_new_path {
24582464 log_trace ! ( logger, "Have now collected {} msat (seeking {} msat) in paths. Last path loop {} a new path." ,
24592465 already_collected_value_msat, recommended_value_msat, if found_new_path { "found" } else { "did not find" } ) ;
@@ -2625,21 +2631,22 @@ where L::Target: Logger {
26252631 // Make sure we would never create a route with more paths than we allow.
26262632 debug_assert ! ( paths. len( ) <= payment_params. max_path_count. into( ) ) ;
26272633
2628- // Make sure we would never create a route whose total fees exceed max_total_routing_fee_msat.
2629- if let Some ( max_total_routing_fee_msat) = route_params. max_total_routing_fee_msat {
2630- if paths. iter ( ) . map ( |p| p. fee_msat ( ) ) . sum :: < u64 > ( ) > max_total_routing_fee_msat {
2631- return Err ( LightningError { err : format ! ( "Failed to find route that adheres to the maximum total fee limit of {}msat" ,
2632- max_total_routing_fee_msat) , action : ErrorAction :: IgnoreError } ) ;
2633- }
2634- }
2635-
26362634 if let Some ( node_features) = payment_params. payee . node_features ( ) {
26372635 for path in paths. iter_mut ( ) {
26382636 path. hops . last_mut ( ) . unwrap ( ) . node_features = node_features. clone ( ) ;
26392637 }
26402638 }
26412639
26422640 let route = Route { paths, route_params : Some ( route_params. clone ( ) ) } ;
2641+
2642+ // Make sure we would never create a route whose total fees exceed max_total_routing_fee_msat.
2643+ if let Some ( max_total_routing_fee_msat) = route_params. max_total_routing_fee_msat {
2644+ if route. get_total_fees ( ) > max_total_routing_fee_msat {
2645+ return Err ( LightningError { err : format ! ( "Failed to find route that adheres to the maximum total fee limit of {}msat" ,
2646+ max_total_routing_fee_msat) , action : ErrorAction :: IgnoreError } ) ;
2647+ }
2648+ }
2649+
26432650 log_info ! ( logger, "Got route: {}" , log_route!( route) ) ;
26442651 Ok ( route)
26452652}
@@ -3223,6 +3230,67 @@ mod tests {
32233230 assert_eq ! ( fees, 5_000 ) ;
32243231 }
32253232
3233+ #[ test]
3234+ fn htlc_minimum_recipient_overpay_test ( ) {
3235+ let ( secp_ctx, network_graph, gossip_sync, _, logger) = build_graph ( ) ;
3236+ let ( _, our_id, privkeys, nodes) = get_nodes ( & secp_ctx) ;
3237+ let config = UserConfig :: default ( ) ;
3238+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 2 ] , 42 ) . with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ;
3239+ let scorer = ln_test_utils:: TestScorer :: new ( ) ;
3240+ let keys_manager = ln_test_utils:: TestKeysInterface :: new ( & [ 0u8 ; 32 ] , Network :: Testnet ) ;
3241+ let random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ;
3242+
3243+ // Route to node2 over a single path which requires overpaying the recipient themselves.
3244+
3245+ // First disable all paths except the us -> node1 -> node2 path
3246+ update_channel ( & gossip_sync, & secp_ctx, & privkeys[ 2 ] , UnsignedChannelUpdate {
3247+ chain_hash : genesis_block ( Network :: Testnet ) . header . block_hash ( ) ,
3248+ short_channel_id : 13 ,
3249+ timestamp : 2 ,
3250+ flags : 3 ,
3251+ cltv_expiry_delta : 0 ,
3252+ htlc_minimum_msat : 0 ,
3253+ htlc_maximum_msat : 0 ,
3254+ fee_base_msat : 0 ,
3255+ fee_proportional_millionths : 0 ,
3256+ excess_data : Vec :: new ( )
3257+ } ) ;
3258+
3259+ // Set channel 4 to free but with a high htlc_minimum_msat
3260+ update_channel ( & gossip_sync, & secp_ctx, & privkeys[ 1 ] , UnsignedChannelUpdate {
3261+ chain_hash : genesis_block ( Network :: Testnet ) . header . block_hash ( ) ,
3262+ short_channel_id : 4 ,
3263+ timestamp : 2 ,
3264+ flags : 0 ,
3265+ cltv_expiry_delta : 0 ,
3266+ htlc_minimum_msat : 15_000 ,
3267+ htlc_maximum_msat : MAX_VALUE_MSAT ,
3268+ fee_base_msat : 0 ,
3269+ fee_proportional_millionths : 0 ,
3270+ excess_data : Vec :: new ( )
3271+ } ) ;
3272+
3273+ // Now check that we'll fail to find a path if we fail to find a path if the htlc_minimum
3274+ // is overrun. Note that the fees are actually calculated on 3*payment amount as that's
3275+ // what we try to find a route for, so this test only just happens to work out to exactly
3276+ // the fee limit.
3277+ let mut route_params = RouteParameters :: from_payment_params_and_value (
3278+ payment_params. clone ( ) , 5_000 ) ;
3279+ route_params. max_total_routing_fee_msat = Some ( 9_999 ) ;
3280+ if let Err ( LightningError { err, action : ErrorAction :: IgnoreError } ) = get_route ( & our_id,
3281+ & route_params, & network_graph. read_only ( ) , None , Arc :: clone ( & logger) , & scorer,
3282+ & Default :: default ( ) , & random_seed_bytes) {
3283+ assert_eq ! ( err, "Failed to find route that adheres to the maximum total fee limit of 9999msat" ) ;
3284+ } else { panic ! ( ) ; }
3285+
3286+ let mut route_params = RouteParameters :: from_payment_params_and_value (
3287+ payment_params. clone ( ) , 5_000 ) ;
3288+ route_params. max_total_routing_fee_msat = Some ( 10_000 ) ;
3289+ let route = get_route ( & our_id, & route_params, & network_graph. read_only ( ) , None ,
3290+ Arc :: clone ( & logger) , & scorer, & Default :: default ( ) , & random_seed_bytes) . unwrap ( ) ;
3291+ assert_eq ! ( route. get_total_fees( ) , 10_000 ) ;
3292+ }
3293+
32263294 #[ test]
32273295 fn disable_channels_test ( ) {
32283296 let ( secp_ctx, network_graph, gossip_sync, _, logger) = build_graph ( ) ;
0 commit comments