@@ -90,6 +90,8 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
9090		& self ,  recipient :  PublicKey ,  first_hops :  Vec < ChannelDetails > ,  tlvs :  ReceiveTlvs , 
9191		amount_msats :  u64 ,  entropy_source :  & ES ,  secp_ctx :  & Secp256k1 < T > 
9292	)  -> Result < Vec < ( BlindedPayInfo ,  BlindedPath ) > ,  ( ) >  { 
93+ 		let  recipient_node_id = NodeId :: from_pubkey ( & recipient) ; 
94+ 
9395		// Limit the number of blinded paths that are computed. 
9496		const  MAX_PAYMENT_PATHS :  usize  = 3 ; 
9597
@@ -103,12 +105,15 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
103105			. filter ( |details| amount_msats <= details. inbound_capacity_msat ) 
104106			. filter ( |details| amount_msats >= details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) ) 
105107			. filter ( |details| amount_msats <= details. inbound_htlc_maximum_msat . unwrap_or ( u64:: MAX ) ) 
106- 			. filter ( |details| network_graph
108+ 			// Limit to counterparties with announced channels 
109+ 			. filter_map ( |details|
110+ 				network_graph
107111					. node ( & NodeId :: from_pubkey ( & details. counterparty . node_id ) ) 
108- 					. map ( |node_info| node_info. channels . len ( )  >= MIN_PEER_CHANNELS ) 
109- 					. unwrap_or ( false ) 
112+ 					. map ( |info| & info. channels [ ..] ) 
113+ 					. and_then ( |channels| ( channels. len ( )  >= MIN_PEER_CHANNELS ) . then ( || channels) ) 
114+ 					. map ( |channels| ( details,  channels) ) 
110115			) 
111- 			. filter_map ( |details| { 
116+ 			. filter_map ( |( details,  counterparty_channels ) | { 
112117				let  short_channel_id = match  details. get_inbound_payment_scid ( )  { 
113118					Some ( short_channel_id)  => short_channel_id, 
114119					None  => return  None , 
@@ -131,7 +136,7 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
131136					max_cltv_expiry :  tlvs. payment_constraints . max_cltv_expiry  + cltv_expiry_delta, 
132137					htlc_minimum_msat :  details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) , 
133138				} ; 
134- 				Some ( ForwardNode  { 
139+ 				let  forward_node =  ForwardNode  { 
135140					tlvs :  ForwardTlvs  { 
136141						short_channel_id, 
137142						payment_relay, 
@@ -140,11 +145,57 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
140145					} , 
141146					node_id :  details. counterparty . node_id , 
142147					htlc_maximum_msat :  details. inbound_htlc_maximum_msat . unwrap_or ( u64:: MAX ) , 
143- 				} ) 
148+ 				} ; 
149+ 				Some ( ( forward_node,  counterparty_channels) ) 
144150			} ) 
145- 			. map ( |forward_node| { 
151+ 			// Pair counterparties with their other channels 
152+ 			. flat_map ( |( forward_node,  counterparty_channels) |
153+ 				counterparty_channels
154+ 					. iter ( ) 
155+ 					. filter_map ( |scid| network_graph. channels ( ) . get_key_value ( scid) ) 
156+ 					. filter_map ( move  |( scid,  info) | info
157+ 						. as_directed_to ( & NodeId :: from_pubkey ( & forward_node. node_id ) ) 
158+ 						. map ( |( info,  source) | ( source,  * scid,  info) ) 
159+ 					) 
160+ 					. filter ( |( source,  _,  _) | * * source != recipient_node_id) 
161+ 					. filter ( |( source,  _,  _) | network_graph
162+ 						. node ( source) 
163+ 						. and_then ( |info| info. announcement_info . as_ref ( ) ) 
164+ 						. map ( |info| info. features . supports_route_blinding ( ) ) 
165+ 						. unwrap_or ( false ) 
166+ 					) 
167+ 					. filter ( |( _,  _,  info) | amount_msats >= info. direction ( ) . htlc_minimum_msat ) 
168+ 					. filter ( |( _,  _,  info) | amount_msats <= info. direction ( ) . htlc_maximum_msat ) 
169+ 					. map ( move  |( source,  scid,  info) | ( source,  scid,  info,  forward_node. clone ( ) ) ) 
170+ 			) 
171+ 			// Construct blinded paths where the counterparty's counterparty is the introduction 
172+ 			// node: 
173+ 			// 
174+ 			// source --- info ---> counterparty --- counterparty_forward_node ---> recipient 
175+ 			. map ( |( introduction_node_id,  scid,  info,  counterparty_forward_node) | { 
176+ 				let  introduction_forward_node = { 
177+ 					let  htlc_minimum_msat = info. direction ( ) . htlc_minimum_msat ; 
178+ 					let  htlc_maximum_msat = info. direction ( ) . htlc_maximum_msat ; 
179+ 					let  payment_relay:  PaymentRelay  = info. into ( ) ; 
180+ 					let  payment_constraints = PaymentConstraints  { 
181+ 						max_cltv_expiry :  payment_relay. cltv_expiry_delta  as  u32 
182+ 							+ counterparty_forward_node. tlvs . payment_constraints . max_cltv_expiry , 
183+ 						htlc_minimum_msat, 
184+ 					} ; 
185+ 					ForwardNode  { 
186+ 						tlvs :  ForwardTlvs  { 
187+ 							short_channel_id :  scid, 
188+ 							payment_relay, 
189+ 							payment_constraints, 
190+ 							features :  BlindedHopFeatures :: empty ( ) , 
191+ 						} , 
192+ 						node_id :  introduction_node_id. as_pubkey ( ) . unwrap ( ) , 
193+ 						htlc_maximum_msat, 
194+ 					} 
195+ 				} ; 
146196				BlindedPath :: new_for_payment ( 
147- 					& [ forward_node] ,  recipient,  tlvs. clone ( ) ,  u64:: MAX ,  entropy_source,  secp_ctx
197+ 					& [ introduction_forward_node,  counterparty_forward_node] ,  recipient, 
198+ 					tlvs. clone ( ) ,  u64:: MAX ,  entropy_source,  secp_ctx
148199				) 
149200			} ) 
150201			. take ( MAX_PAYMENT_PATHS ) 
0 commit comments