@@ -87,6 +87,9 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
8787 & self , recipient : PublicKey , first_hops : Vec < ChannelDetails > , tlvs : ReceiveTlvs ,
8888 amount_msats : u64 , secp_ctx : & Secp256k1 < T >
8989 ) -> Result < Vec < ( BlindedPayInfo , BlindedPath ) > , ( ) > {
90+ let entropy_source = & * self . entropy_source ;
91+ let recipient_node_id = NodeId :: from_pubkey ( & recipient) ;
92+
9093 // Limit the number of blinded paths that are computed.
9194 const MAX_PAYMENT_PATHS : usize = 3 ;
9295
@@ -95,17 +98,20 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
9598 const MIN_PEER_CHANNELS : usize = 3 ;
9699
97100 let network_graph = self . network_graph . deref ( ) . read_only ( ) ;
98- let paths = first_hops. into_iter ( )
101+ let counterparty_channels = first_hops. into_iter ( )
99102 . filter ( |details| details. counterparty . features . supports_route_blinding ( ) )
100103 . filter ( |details| amount_msats <= details. inbound_capacity_msat )
101104 . filter ( |details| amount_msats >= details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) )
102105 . filter ( |details| amount_msats <= details. inbound_htlc_maximum_msat . unwrap_or ( u64:: MAX ) )
103- . filter ( |details| network_graph
106+ // Limit to counterparties with announced channels
107+ . filter_map ( |details|
108+ network_graph
104109 . node ( & NodeId :: from_pubkey ( & details. counterparty . node_id ) )
105- . map ( |node_info| node_info. channels . len ( ) >= MIN_PEER_CHANNELS )
106- . unwrap_or ( false )
110+ . map ( |info| & info. channels [ ..] )
111+ . and_then ( |channels| ( channels. len ( ) >= MIN_PEER_CHANNELS ) . then ( || channels) )
112+ . map ( |channels| ( details, channels) )
107113 )
108- . filter_map ( |details| {
114+ . filter_map ( |( details, counterparty_channels ) | {
109115 let short_channel_id = match details. get_inbound_payment_scid ( ) {
110116 Some ( short_channel_id) => short_channel_id,
111117 None => return None ,
@@ -123,7 +129,7 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
123129 max_cltv_expiry : tlvs. payment_constraints . max_cltv_expiry + cltv_expiry_delta,
124130 htlc_minimum_msat : details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) ,
125131 } ;
126- Some ( payment:: ForwardNode {
132+ let forward_node = payment:: ForwardNode {
127133 tlvs : ForwardTlvs {
128134 short_channel_id,
129135 payment_relay,
@@ -132,29 +138,88 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
132138 } ,
133139 node_id : details. counterparty . node_id ,
134140 htlc_maximum_msat : details. inbound_htlc_maximum_msat . unwrap_or ( u64:: MAX ) ,
135- } )
141+ } ;
142+ Some ( ( forward_node, counterparty_channels) )
143+ } ) ;
144+
145+ let three_hop_paths = counterparty_channels. clone ( )
146+ // Pair counterparties with their other channels
147+ . flat_map ( |( forward_node, counterparty_channels) |
148+ counterparty_channels
149+ . iter ( )
150+ . filter_map ( |scid| network_graph. channels ( ) . get_key_value ( scid) )
151+ . filter_map ( move |( scid, info) | info
152+ . as_directed_to ( & NodeId :: from_pubkey ( & forward_node. node_id ) )
153+ . map ( |( info, source) | ( source, * scid, info) )
154+ )
155+ . filter ( |( source, _, _) | * * source != recipient_node_id)
156+ . filter ( |( source, _, _) | network_graph
157+ . node ( source)
158+ . and_then ( |info| info. announcement_info . as_ref ( ) )
159+ . map ( |info| info. features . supports_route_blinding ( ) )
160+ . unwrap_or ( false )
161+ )
162+ . filter ( |( _, _, info) | amount_msats >= info. direction ( ) . htlc_minimum_msat )
163+ . filter ( |( _, _, info) | amount_msats <= info. direction ( ) . htlc_maximum_msat )
164+ . map ( move |( source, scid, info) | ( source, scid, info, forward_node. clone ( ) ) )
165+ )
166+ // Construct blinded paths where the counterparty's counterparty is the introduction
167+ // node:
168+ //
169+ // source --- info ---> counterparty --- counterparty_forward_node ---> recipient
170+ . filter_map ( |( introduction_node_id, scid, info, counterparty_forward_node) | {
171+ let htlc_minimum_msat = info. direction ( ) . htlc_minimum_msat ;
172+ let htlc_maximum_msat = info. direction ( ) . htlc_maximum_msat ;
173+ let payment_relay: PaymentRelay = match info. try_into ( ) {
174+ Ok ( payment_relay) => payment_relay,
175+ Err ( ( ) ) => return None ,
176+ } ;
177+ let payment_constraints = PaymentConstraints {
178+ max_cltv_expiry : payment_relay. cltv_expiry_delta as u32
179+ + counterparty_forward_node. tlvs . payment_constraints . max_cltv_expiry ,
180+ htlc_minimum_msat,
181+ } ;
182+ let introduction_forward_node = payment:: ForwardNode {
183+ tlvs : ForwardTlvs {
184+ short_channel_id : scid,
185+ payment_relay,
186+ payment_constraints,
187+ features : BlindedHopFeatures :: empty ( ) ,
188+ } ,
189+ node_id : introduction_node_id. as_pubkey ( ) . unwrap ( ) ,
190+ htlc_maximum_msat,
191+ } ;
192+ Some ( BlindedPath :: new_for_payment (
193+ & [ introduction_forward_node, counterparty_forward_node] , recipient,
194+ tlvs. clone ( ) , u64:: MAX , MIN_FINAL_CLTV_EXPIRY_DELTA , entropy_source, secp_ctx
195+ ) )
136196 } )
137- . map ( |forward_node| {
197+ . take ( MAX_PAYMENT_PATHS ) ;
198+
199+ let two_hop_paths = counterparty_channels
200+ . map ( |( forward_node, _) | {
138201 BlindedPath :: new_for_payment (
139202 & [ forward_node] , recipient, tlvs. clone ( ) , u64:: MAX , MIN_FINAL_CLTV_EXPIRY_DELTA ,
140- & * self . entropy_source , secp_ctx
203+ entropy_source, secp_ctx
141204 )
142205 } )
143- . take ( MAX_PAYMENT_PATHS )
144- . collect :: < Result < Vec < _ > , _ > > ( ) ;
145-
146- match paths {
147- Ok ( paths) if !paths. is_empty ( ) => Ok ( paths) ,
148- _ => {
149- if network_graph. nodes ( ) . contains_key ( & NodeId :: from_pubkey ( & recipient) ) {
150- BlindedPath :: one_hop_for_payment (
151- recipient, tlvs, MIN_FINAL_CLTV_EXPIRY_DELTA , & * self . entropy_source , secp_ctx
152- ) . map ( |path| vec ! [ path] )
153- } else {
154- Err ( ( ) )
155- }
156- } ,
157- }
206+ . take ( MAX_PAYMENT_PATHS ) ;
207+
208+ three_hop_paths
209+ . collect :: < Result < Vec < _ > , _ > > ( ) . ok ( )
210+ . and_then ( |paths| ( !paths. is_empty ( ) ) . then ( || paths) )
211+ . or_else ( || two_hop_paths. collect :: < Result < Vec < _ > , _ > > ( ) . ok ( ) )
212+ . and_then ( |paths| ( !paths. is_empty ( ) ) . then ( || paths) )
213+ . or_else ( || network_graph
214+ . node ( & NodeId :: from_pubkey ( & recipient) ) . ok_or ( ( ) )
215+ . and_then ( |_| BlindedPath :: one_hop_for_payment (
216+ recipient, tlvs, MIN_FINAL_CLTV_EXPIRY_DELTA , entropy_source, secp_ctx
217+ )
218+ )
219+ . map ( |path| vec ! [ path] )
220+ . ok ( )
221+ )
222+ . ok_or ( ( ) )
158223 }
159224}
160225
0 commit comments