@@ -7691,6 +7691,203 @@ mod tests {
76917691		assert_eq ! ( route. paths. len( ) ,  1 ) ; 
76927692		assert_eq ! ( route. get_total_amount( ) ,  amt_msat) ; 
76937693	} 
7694+ 
7695+ 	#[ test]  
7696+ 	fn  first_hop_preferred_over_hint ( )  { 
7697+ 		// Check that if we have a first hop to a peer we'd always prefer that over a route hint 
7698+ 		// they gave us, but we'd still consider all subsequent hints if they are more attractive. 
7699+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
7700+ 		let  logger = Arc :: new ( ln_test_utils:: TestLogger :: new ( ) ) ; 
7701+ 		let  network_graph = Arc :: new ( NetworkGraph :: new ( Network :: Testnet ,  Arc :: clone ( & logger) ) ) ; 
7702+ 		let  gossip_sync = P2PGossipSync :: new ( Arc :: clone ( & network_graph) ,  None ,  Arc :: clone ( & logger) ) ; 
7703+ 		let  scorer = ln_test_utils:: TestScorer :: new ( ) ; 
7704+ 		let  keys_manager = ln_test_utils:: TestKeysInterface :: new ( & [ 0u8 ;  32 ] ,  Network :: Testnet ) ; 
7705+ 		let  random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ; 
7706+ 		let  config = UserConfig :: default ( ) ; 
7707+ 
7708+ 		let  amt_msat = 1_000_000 ; 
7709+ 		let  ( our_privkey,  our_node_id,  privkeys,  nodes)  = get_nodes ( & secp_ctx) ; 
7710+ 
7711+ 		add_channel ( & gossip_sync,  & secp_ctx,  & our_privkey,  & privkeys[ 0 ] , 
7712+ 			ChannelFeatures :: from_le_bytes ( id_to_feature_flags ( 1 ) ) ,  1 ) ; 
7713+ 		update_channel ( & gossip_sync,  & secp_ctx,  & our_privkey,  UnsignedChannelUpdate  { 
7714+ 			chain_hash :  genesis_block ( Network :: Testnet ) . header . block_hash ( ) , 
7715+ 			short_channel_id :  1 , 
7716+ 			timestamp :  1 , 
7717+ 			flags :  0 , 
7718+ 			cltv_expiry_delta :  42 , 
7719+ 			htlc_minimum_msat :  1_000 , 
7720+ 			htlc_maximum_msat :  10_000_000 , 
7721+ 			fee_base_msat :  800 , 
7722+ 			fee_proportional_millionths :  0 , 
7723+ 			excess_data :  Vec :: new ( ) 
7724+ 		} ) ; 
7725+ 		update_channel ( & gossip_sync,  & secp_ctx,  & privkeys[ 0 ] ,  UnsignedChannelUpdate  { 
7726+ 			chain_hash :  genesis_block ( Network :: Testnet ) . header . block_hash ( ) , 
7727+ 			short_channel_id :  1 , 
7728+ 			timestamp :  1 , 
7729+ 			flags :  1 , 
7730+ 			cltv_expiry_delta :  42 , 
7731+ 			htlc_minimum_msat :  1_000 , 
7732+ 			htlc_maximum_msat :  10_000_000 , 
7733+ 			fee_base_msat :  800 , 
7734+ 			fee_proportional_millionths :  0 , 
7735+ 			excess_data :  Vec :: new ( ) 
7736+ 		} ) ; 
7737+ 
7738+ 		add_channel ( & gossip_sync,  & secp_ctx,  & privkeys[ 0 ] ,  & privkeys[ 1 ] , 
7739+ 			ChannelFeatures :: from_le_bytes ( id_to_feature_flags ( 1 ) ) ,  2 ) ; 
7740+ 		update_channel ( & gossip_sync,  & secp_ctx,  & privkeys[ 0 ] ,  UnsignedChannelUpdate  { 
7741+ 			chain_hash :  genesis_block ( Network :: Testnet ) . header . block_hash ( ) , 
7742+ 			short_channel_id :  2 , 
7743+ 			timestamp :  2 , 
7744+ 			flags :  0 , 
7745+ 			cltv_expiry_delta :  42 , 
7746+ 			htlc_minimum_msat :  1_000 , 
7747+ 			htlc_maximum_msat :  10_000_000 , 
7748+ 			fee_base_msat :  800 , 
7749+ 			fee_proportional_millionths :  0 , 
7750+ 			excess_data :  Vec :: new ( ) 
7751+ 		} ) ; 
7752+ 		update_channel ( & gossip_sync,  & secp_ctx,  & privkeys[ 1 ] ,  UnsignedChannelUpdate  { 
7753+ 			chain_hash :  genesis_block ( Network :: Testnet ) . header . block_hash ( ) , 
7754+ 			short_channel_id :  2 , 
7755+ 			timestamp :  2 , 
7756+ 			flags :  1 , 
7757+ 			cltv_expiry_delta :  42 , 
7758+ 			htlc_minimum_msat :  1_000 , 
7759+ 			htlc_maximum_msat :  10_000_000 , 
7760+ 			fee_base_msat :  800 , 
7761+ 			fee_proportional_millionths :  0 , 
7762+ 			excess_data :  Vec :: new ( ) 
7763+ 		} ) ; 
7764+ 
7765+ 		let  dest_node_id = nodes[ 2 ] ; 
7766+ 
7767+ 		let  route_hint = RouteHint ( vec ! [ RouteHintHop  { 
7768+ 			src_node_id:  our_node_id, 
7769+ 			short_channel_id:  44 , 
7770+ 			fees:  RoutingFees  { 
7771+ 				base_msat:  234 , 
7772+ 				proportional_millionths:  0 , 
7773+ 			} , 
7774+ 			cltv_expiry_delta:  10 , 
7775+ 			htlc_minimum_msat:  None , 
7776+ 			htlc_maximum_msat:  Some ( 5_000_000 ) , 
7777+ 		} , 
7778+ 		RouteHintHop  { 
7779+ 			src_node_id:  nodes[ 0 ] , 
7780+ 			short_channel_id:  45 , 
7781+ 			fees:  RoutingFees  { 
7782+ 				base_msat:  123 , 
7783+ 				proportional_millionths:  0 , 
7784+ 			} , 
7785+ 			cltv_expiry_delta:  10 , 
7786+ 			htlc_minimum_msat:  None , 
7787+ 			htlc_maximum_msat:  None , 
7788+ 		} ] ) ; 
7789+ 
7790+ 		let  payment_params = PaymentParameters :: from_node_id ( dest_node_id,  42 ) 
7791+ 			. with_route_hints ( vec ! [ route_hint] ) . unwrap ( ) 
7792+ 			. with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ; 
7793+ 		let  route_params = RouteParameters :: from_payment_params_and_value ( 
7794+ 			payment_params,  amt_msat) ; 
7795+ 
7796+ 		// First create an insufficient first hop for channel with SCID 1 and check we'd use the 
7797+ 		// route hint. 
7798+ 		let  first_hop = get_channel_details ( Some ( 1 ) ,  nodes[ 0 ] , 
7799+ 			channelmanager:: provided_init_features ( & config) ,  999_999 ) ; 
7800+ 		let  first_hops = vec ! [ first_hop] ; 
7801+ 
7802+ 		let  route = get_route ( & our_node_id,  & route_params. clone ( ) ,  & network_graph. read_only ( ) , 
7803+ 			Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,  Arc :: clone ( & logger) ,  & scorer, 
7804+ 			& Default :: default ( ) ,  & random_seed_bytes) . unwrap ( ) ; 
7805+ 		assert_eq ! ( route. paths. len( ) ,  1 ) ; 
7806+ 		assert_eq ! ( route. get_total_amount( ) ,  amt_msat) ; 
7807+ 		assert_eq ! ( route. paths[ 0 ] . hops. len( ) ,  2 ) ; 
7808+ 		assert_eq ! ( route. paths[ 0 ] . hops[ 0 ] . short_channel_id,  44 ) ; 
7809+ 		assert_eq ! ( route. paths[ 0 ] . hops[ 1 ] . short_channel_id,  45 ) ; 
7810+ 		assert_eq ! ( route. get_total_fees( ) ,  123 ) ; 
7811+ 
7812+ 		// Now check we would trust our first hop info, i.e., fail if we detect the route hint is 
7813+ 		// for a first hop channel. 
7814+ 		let  mut  first_hop = get_channel_details ( Some ( 1 ) ,  nodes[ 0 ] ,  channelmanager:: provided_init_features ( & config) ,  999_999 ) ; 
7815+ 		first_hop. outbound_scid_alias  = Some ( 44 ) ; 
7816+ 		let  first_hops = vec ! [ first_hop] ; 
7817+ 
7818+ 		let  route_res = get_route ( & our_node_id,  & route_params. clone ( ) ,  & network_graph. read_only ( ) , 
7819+ 			Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,  Arc :: clone ( & logger) ,  & scorer, 
7820+ 			& Default :: default ( ) ,  & random_seed_bytes) ; 
7821+ 		assert ! ( route_res. is_err( ) ) ; 
7822+ 
7823+ 		// Finally check we'd use the first hop if has sufficient outbound capacity. But we'd stil 
7824+ 		// use the cheaper second hop of the route hint. 
7825+ 		let  mut  first_hop = get_channel_details ( Some ( 1 ) ,  nodes[ 0 ] , 
7826+ 			channelmanager:: provided_init_features ( & config) ,  10_000_000 ) ; 
7827+ 		first_hop. outbound_scid_alias  = Some ( 44 ) ; 
7828+ 		let  first_hops = vec ! [ first_hop] ; 
7829+ 
7830+ 		let  route = get_route ( & our_node_id,  & route_params. clone ( ) ,  & network_graph. read_only ( ) , 
7831+ 			Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,  Arc :: clone ( & logger) ,  & scorer, 
7832+ 			& Default :: default ( ) ,  & random_seed_bytes) . unwrap ( ) ; 
7833+ 		assert_eq ! ( route. paths. len( ) ,  1 ) ; 
7834+ 		assert_eq ! ( route. get_total_amount( ) ,  amt_msat) ; 
7835+ 		assert_eq ! ( route. paths[ 0 ] . hops. len( ) ,  2 ) ; 
7836+ 		assert_eq ! ( route. paths[ 0 ] . hops[ 0 ] . short_channel_id,  1 ) ; 
7837+ 		assert_eq ! ( route. paths[ 0 ] . hops[ 1 ] . short_channel_id,  45 ) ; 
7838+ 		assert_eq ! ( route. get_total_fees( ) ,  123 ) ; 
7839+ 	} 
7840+ 
7841+ 	#[ test]  
7842+ 	fn  allow_us_being_first_hint ( )  { 
7843+ 		// Check that we consider a route hint even if we are the src of the first hop. 
7844+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
7845+ 		let  logger = Arc :: new ( ln_test_utils:: TestLogger :: new ( ) ) ; 
7846+ 		let  network_graph = Arc :: new ( NetworkGraph :: new ( Network :: Testnet ,  Arc :: clone ( & logger) ) ) ; 
7847+ 		let  scorer = ln_test_utils:: TestScorer :: new ( ) ; 
7848+ 		let  keys_manager = ln_test_utils:: TestKeysInterface :: new ( & [ 0u8 ;  32 ] ,  Network :: Testnet ) ; 
7849+ 		let  random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ; 
7850+ 		let  config = UserConfig :: default ( ) ; 
7851+ 
7852+ 		let  ( _,  our_node_id,  _,  nodes)  = get_nodes ( & secp_ctx) ; 
7853+ 
7854+ 		let  amt_msat = 1_000_000 ; 
7855+ 		let  dest_node_id = nodes[ 1 ] ; 
7856+ 
7857+ 		let  first_hop = get_channel_details ( Some ( 1 ) ,  nodes[ 0 ] ,  channelmanager:: provided_init_features ( & config) ,  10_000_000 ) ; 
7858+ 		let  first_hops = vec ! [ first_hop] ; 
7859+ 
7860+ 		let  route_hint = RouteHint ( vec ! [ RouteHintHop  { 
7861+ 			src_node_id:  our_node_id, 
7862+ 			short_channel_id:  44 , 
7863+ 			fees:  RoutingFees  { 
7864+ 				base_msat:  123 , 
7865+ 				proportional_millionths:  0 , 
7866+ 			} , 
7867+ 			cltv_expiry_delta:  10 , 
7868+ 			htlc_minimum_msat:  None , 
7869+ 			htlc_maximum_msat:  None , 
7870+ 		} ] ) ; 
7871+ 
7872+ 		let  payment_params = PaymentParameters :: from_node_id ( dest_node_id,  42 ) 
7873+ 			. with_route_hints ( vec ! [ route_hint] ) . unwrap ( ) 
7874+ 			. with_bolt11_features ( channelmanager:: provided_invoice_features ( & config) ) . unwrap ( ) ; 
7875+ 
7876+ 		let  route_params = RouteParameters :: from_payment_params_and_value ( 
7877+ 			payment_params,  amt_msat) ; 
7878+ 
7879+ 
7880+ 		let  route = get_route ( & our_node_id,  & route_params,  & network_graph. read_only ( ) , 
7881+ 			Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,  Arc :: clone ( & logger) ,  & scorer, 
7882+ 			& Default :: default ( ) ,  & random_seed_bytes) . unwrap ( ) ; 
7883+ 
7884+ 		assert_eq ! ( route. paths. len( ) ,  1 ) ; 
7885+ 		assert_eq ! ( route. get_total_amount( ) ,  amt_msat) ; 
7886+ 		assert_eq ! ( route. get_total_fees( ) ,  0 ) ; 
7887+ 		assert_eq ! ( route. paths[ 0 ] . hops. len( ) ,  1 ) ; 
7888+ 
7889+ 		assert_eq ! ( route. paths[ 0 ] . hops[ 0 ] . short_channel_id,  44 ) ; 
7890+ 	} 
76947891} 
76957892
76967893#[ cfg( all( any( test,  ldk_bench) ,  not( feature = "no-std" ) ) ) ]  
0 commit comments