@@ -2061,9 +2061,19 @@ where L::Target: Logger {
20612061						Some ( fee)  => fee, 
20622062						None  => continue 
20632063					} ; 
2064+ 					let  path_min = { 
2065+ 						let  blinded_path_min = candidate. htlc_minimum_msat ( ) ; 
2066+ 						let  path_min_fees = match  compute_fees ( blinded_path_min,  candidate. fees ( ) )  { 
2067+ 							Some ( fee)  => fee, 
2068+ 							None  => continue 
2069+ 						} ; 
2070+ 						match  blinded_path_min. checked_add ( path_min_fees)  { 
2071+ 							Some ( min)  => min, 
2072+ 							None  => continue 
2073+ 						} 
2074+ 					} ; 
20642075					add_entry ! ( first_hop_candidate,  our_node_id,  intro_node_id,  blinded_path_fee, 
2065- 						path_contribution_msat,  candidate. htlc_minimum_msat( ) ,  0_u64 , 
2066- 						candidate. cltv_expiry_delta( ) , 
2076+ 						path_contribution_msat,  path_min,  0_u64 ,  candidate. cltv_expiry_delta( ) , 
20672077						candidate. blinded_path( ) . map_or( 1 ,  |bp| bp. blinded_hops. len( )  as  u8 ) ) ; 
20682078				} 
20692079			} 
@@ -7190,6 +7200,10 @@ mod tests {
71907200
71917201	#[ test]  
71927202	fn  min_htlc_overpay_violates_max_htlc ( )  { 
7203+ 		do_min_htlc_overpay_violates_max_htlc ( true ) ; 
7204+ 		do_min_htlc_overpay_violates_max_htlc ( false ) ; 
7205+ 	} 
7206+ 	fn  do_min_htlc_overpay_violates_max_htlc ( blinded_payee :  bool )  { 
71937207		// Test that if overpaying to meet a later hop's min_htlc and causes us to violate an earlier 
71947208		// hop's max_htlc, we discard that invalid path. Previously we would consider the path to be 
71957209		// valid and hit a debug panic asserting that the used liquidity for a hop was less than its 
@@ -7211,21 +7225,45 @@ mod tests {
72117225			first_hop_outbound_capacity
72127226		) ] ; 
72137227
7214- 		let  route_hint = RouteHint ( vec ! [ RouteHintHop  { 
7215- 			src_node_id:  nodes[ 0 ] , 
7216- 			short_channel_id:  44 , 
7217- 			fees:  RoutingFees  { 
7218- 				base_msat:  1_6778_3453 , 
7219- 				proportional_millionths:  0 , 
7220- 			} , 
7221- 			cltv_expiry_delta:  10 , 
7222- 			htlc_minimum_msat:  Some ( 2_5165_8240 ) , 
7223- 			htlc_maximum_msat:  None , 
7224- 		} ] ) ; 
7228+ 		let  base_fee = 1_6778_3453 ; 
7229+ 		let  htlc_min = 2_5165_8240 ; 
7230+ 		let  payment_params = if  blinded_payee { 
7231+ 			let  blinded_path = BlindedPath  { 
7232+ 				introduction_node_id :  nodes[ 0 ] , 
7233+ 				blinding_point :  ln_test_utils:: pubkey ( 42 ) , 
7234+ 				blinded_hops :  vec ! [ 
7235+ 					BlindedHop  {  blinded_node_id:  ln_test_utils:: pubkey( 42  as  u8 ) ,  encrypted_payload:  Vec :: new( )  } , 
7236+ 					BlindedHop  {  blinded_node_id:  ln_test_utils:: pubkey( 42  as  u8 ) ,  encrypted_payload:  Vec :: new( )  } 
7237+ 				] , 
7238+ 			} ; 
7239+ 			let  blinded_payinfo = BlindedPayInfo  { 
7240+ 				fee_base_msat :  base_fee, 
7241+ 				fee_proportional_millionths :  0 , 
7242+ 				htlc_minimum_msat :  htlc_min, 
7243+ 				htlc_maximum_msat :  htlc_min *  1000 , 
7244+ 				cltv_expiry_delta :  0 , 
7245+ 				features :  BlindedHopFeatures :: empty ( ) , 
7246+ 			} ; 
7247+ 			let  bolt12_features:  Bolt12InvoiceFeatures  = channelmanager:: provided_invoice_features ( & config) . to_context ( ) ; 
7248+ 			PaymentParameters :: blinded ( vec ! [ ( blinded_payinfo,  blinded_path) ] ) 
7249+ 				. with_bolt12_features ( bolt12_features. clone ( ) ) . unwrap ( ) 
7250+ 		}  else  { 
7251+ 			let  route_hint = RouteHint ( vec ! [ RouteHintHop  { 
7252+ 				src_node_id:  nodes[ 0 ] , 
7253+ 				short_channel_id:  44 , 
7254+ 				fees:  RoutingFees  { 
7255+ 					base_msat:  base_fee, 
7256+ 					proportional_millionths:  0 , 
7257+ 				} , 
7258+ 				cltv_expiry_delta:  10 , 
7259+ 				htlc_minimum_msat:  Some ( htlc_min) , 
7260+ 				htlc_maximum_msat:  None , 
7261+ 			} ] ) ; 
72257262
7226- 		let  payment_params = PaymentParameters :: from_node_id ( nodes[ 1 ] ,  42 ) 
7227- 			. with_route_hints ( vec ! [ route_hint] ) . unwrap ( ) 
7228- 			. with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ; 
7263+ 			PaymentParameters :: from_node_id ( nodes[ 1 ] ,  42 ) 
7264+ 				. with_route_hints ( vec ! [ route_hint] ) . unwrap ( ) 
7265+ 				. with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) 
7266+ 		} ; 
72297267
72307268		let  netgraph = network_graph. read_only ( ) ; 
72317269		let  route_params = RouteParameters :: from_payment_params_and_value ( 
@@ -7240,6 +7278,11 @@ mod tests {
72407278
72417279	#[ test]  
72427280	fn  previously_used_liquidity_violates_max_htlc ( )  { 
7281+ 		do_previously_used_liquidity_violates_max_htlc ( true ) ; 
7282+ 		do_previously_used_liquidity_violates_max_htlc ( false ) ; 
7283+ 
7284+ 	} 
7285+ 	fn  do_previously_used_liquidity_violates_max_htlc ( blinded_payee :  bool )  { 
72437286		// Test that if a candidate hop would cause us to violate an upstream hop's available 
72447287		// contribution amount due to a previously found path, we will not consider that candidate in 
72457288		// path construction. Previously we would construct an invalid path and hit a debug panic 
@@ -7261,51 +7304,50 @@ mod tests {
72617304			Some ( 122 ) ,  nodes[ 0 ] ,  channelmanager:: provided_init_features( & config) ,  179_5000 
72627305		) ] ; 
72637306
7264- 		let  route_hints = vec ! [ RouteHint ( vec![ RouteHintHop  { 
7265- 			src_node_id:  nodes[ 0 ] , 
7266- 			short_channel_id:  42 , 
7267- 			fees:  RoutingFees  { 
7268- 				base_msat:  0 , 
7269- 				proportional_millionths:  0 , 
7270- 			} , 
7271- 			cltv_expiry_delta:  10 , 
7272- 			htlc_minimum_msat:  Some ( 1_4392 ) , 
7273- 			htlc_maximum_msat:  Some ( 143_9200 ) , 
7274- 		} ] ) ,  RouteHint ( vec![ RouteHintHop  { 
7275- 			src_node_id:  nodes[ 0 ] , 
7276- 			short_channel_id:  43 , 
7277- 			fees:  RoutingFees  { 
7278- 				base_msat:  425_9840 , 
7279- 				proportional_millionths:  0 , 
7280- 			} , 
7281- 			cltv_expiry_delta:  10 , 
7282- 			htlc_minimum_msat:  Some ( 19_7401 ) , 
7283- 			htlc_maximum_msat:  Some ( 1974_0100 ) , 
7284- 		} ] ) ,  RouteHint ( vec![ RouteHintHop  { 
7285- 			src_node_id:  nodes[ 0 ] , 
7286- 			short_channel_id:  44 , 
7287- 			fees:  RoutingFees  { 
7288- 				base_msat:  0 , 
7289- 				proportional_millionths:  0 , 
7290- 			} , 
7291- 			cltv_expiry_delta:  10 , 
7292- 			htlc_minimum_msat:  Some ( 1027 ) , 
7293- 			htlc_maximum_msat:  Some ( 10_2700 ) , 
7294- 		} ] ) ,  RouteHint ( vec![ RouteHintHop  { 
7295- 			src_node_id:  nodes[ 0 ] , 
7296- 			short_channel_id:  45 , 
7297- 			fees:  RoutingFees  { 
7298- 				base_msat:  0 , 
7299- 				proportional_millionths:  0 , 
7300- 			} , 
7301- 			cltv_expiry_delta:  10 , 
7302- 			htlc_minimum_msat:  Some ( 6_5535 ) , 
7303- 			htlc_maximum_msat:  Some ( 655_3500 ) , 
7304- 		} ] ) ] ; 
7305- 
7306- 		let  payment_params = PaymentParameters :: from_node_id ( nodes[ 1 ] ,  42 ) 
7307- 			. with_route_hints ( route_hints) . unwrap ( ) 
7308- 			. with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ; 
7307+ 		let  base_fees = [ 0 ,  425_9840 ,  0 ,  0 ] ; 
7308+ 		let  htlc_mins = [ 1_4392 ,  19_7401 ,  1027 ,  6_5535 ] ; 
7309+ 		let  payment_params = if  blinded_payee { 
7310+ 			let  blinded_path = BlindedPath  { 
7311+ 				introduction_node_id :  nodes[ 0 ] , 
7312+ 				blinding_point :  ln_test_utils:: pubkey ( 42 ) , 
7313+ 				blinded_hops :  vec ! [ 
7314+ 					BlindedHop  {  blinded_node_id:  ln_test_utils:: pubkey( 42  as  u8 ) ,  encrypted_payload:  Vec :: new( )  } , 
7315+ 					BlindedHop  {  blinded_node_id:  ln_test_utils:: pubkey( 42  as  u8 ) ,  encrypted_payload:  Vec :: new( )  } 
7316+ 				] , 
7317+ 			} ; 
7318+ 			let  mut  blinded_hints = Vec :: new ( ) ; 
7319+ 			for  ( base_fee,  htlc_min)  in  base_fees. iter ( ) . zip ( htlc_mins. iter ( ) )  { 
7320+ 				blinded_hints. push ( ( BlindedPayInfo  { 
7321+ 					fee_base_msat :  * base_fee, 
7322+ 					fee_proportional_millionths :  0 , 
7323+ 					htlc_minimum_msat :  * htlc_min, 
7324+ 					htlc_maximum_msat :  htlc_min *  100 , 
7325+ 					cltv_expiry_delta :  10 , 
7326+ 					features :  BlindedHopFeatures :: empty ( ) , 
7327+ 				} ,  blinded_path. clone ( ) ) ) ; 
7328+ 			} 
7329+ 			let  bolt12_features:  Bolt12InvoiceFeatures  = channelmanager:: provided_invoice_features ( & config) . to_context ( ) ; 
7330+ 			PaymentParameters :: blinded ( blinded_hints. clone ( ) ) 
7331+ 				. with_bolt12_features ( bolt12_features. clone ( ) ) . unwrap ( ) 
7332+ 		}  else  { 
7333+ 			let  mut  route_hints = Vec :: new ( ) ; 
7334+ 			for  ( idx,  ( base_fee,  htlc_min) )  in  base_fees. iter ( ) . zip ( htlc_mins. iter ( ) ) . enumerate ( )  { 
7335+ 				route_hints. push ( RouteHint ( vec ! [ RouteHintHop  { 
7336+ 					src_node_id:  nodes[ 0 ] , 
7337+ 					short_channel_id:  42  + idx as  u64 , 
7338+ 					fees:  RoutingFees  { 
7339+ 						base_msat:  * base_fee, 
7340+ 						proportional_millionths:  0 , 
7341+ 					} , 
7342+ 					cltv_expiry_delta:  10 , 
7343+ 					htlc_minimum_msat:  Some ( * htlc_min) , 
7344+ 					htlc_maximum_msat:  Some ( htlc_min *  100 ) , 
7345+ 				} ] ) ) ; 
7346+ 			} 
7347+ 			PaymentParameters :: from_node_id ( nodes[ 1 ] ,  42 ) 
7348+ 				. with_route_hints ( route_hints) . unwrap ( ) 
7349+ 				. with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) 
7350+ 		} ; 
73097351
73107352		let  netgraph = network_graph. read_only ( ) ; 
73117353		let  route_params = RouteParameters :: from_payment_params_and_value ( 
0 commit comments