@@ -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