@@ -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
@@ -98,37 +100,88 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
98100 const MIN_PEER_CHANNELS : usize = 3 ;
99101
100102 let network_graph = self . network_graph . deref ( ) . read_only ( ) ;
101- first_hops. into_iter ( )
102- . filter ( |details| details. is_public )
103+ first_hops. iter ( )
103104 . filter ( |details| details. counterparty . features . supports_route_blinding ( ) )
104105 . filter ( |details| amount_msats <= details. inbound_capacity_msat )
105106 . filter ( |details| amount_msats >= details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) )
106107 . filter ( |details| amount_msats <= details. inbound_htlc_maximum_msat . unwrap_or ( 0 ) )
107- . filter ( |details| network_graph
108- . node ( & NodeId :: from_pubkey ( & details. counterparty . node_id ) )
109- . map ( |node_info| node_info. channels . len ( ) >= MIN_PEER_CHANNELS )
110- . unwrap_or ( false )
108+ . map ( |details| ( details, NodeId :: from_pubkey ( & details. counterparty . node_id ) ) )
109+ // Limit to counterparties with announced channels
110+ . filter_map ( |( details, counterparty_node_id) |
111+ network_graph
112+ . node ( & counterparty_node_id)
113+ . map ( |info| & info. channels [ ..] )
114+ . and_then ( |channels| ( channels. len ( ) >= MIN_PEER_CHANNELS ) . then ( || channels) )
115+ . map ( |channels| ( details, counterparty_node_id, channels) )
116+ )
117+ // Pair counterparties with their other channels
118+ . flat_map ( |( details, counterparty_node_id, counterparty_channels) |
119+ counterparty_channels
120+ . iter ( )
121+ . filter_map ( |scid| network_graph. channels ( ) . get_key_value ( scid) )
122+ . filter_map ( move |( scid, info) | info
123+ . as_directed_to ( & counterparty_node_id)
124+ . map ( |( info, source) | ( source, * scid, info) )
125+ )
126+ . filter ( |( source, _, _) | * * source != recipient_node_id)
127+ . filter ( |( source, _, _) | network_graph
128+ . node ( source)
129+ . and_then ( |info| info. announcement_info . as_ref ( ) )
130+ . map ( |info| info. features . supports_route_blinding ( ) )
131+ . unwrap_or ( false )
132+ )
133+ . filter ( |( _, _, info) | amount_msats >= info. direction ( ) . htlc_minimum_msat )
134+ . filter ( |( _, _, info) | amount_msats <= info. direction ( ) . htlc_maximum_msat )
135+ . map ( move |( source, scid, info) | ( source, scid, info, details) )
111136 )
112- . map ( |details| {
113- let short_channel_id = details. get_inbound_payment_scid ( ) . unwrap ( ) ;
114- let payment_relay: PaymentRelay = details. counterparty . forwarding_info . unwrap ( ) . into ( ) ;
115- let payment_constraints = PaymentConstraints {
116- max_cltv_expiry : tlvs. payment_constraints . max_cltv_expiry
117- + payment_relay. cltv_expiry_delta as u32 ,
118- htlc_minimum_msat : details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) ,
137+ // Construct blinded paths where the counterparty's counterparty is the introduction
138+ // node:
139+ //
140+ // source --- info ---> counterparty --- details ---> recipient
141+ . map ( |( introduction_node_id, scid, info, details) | {
142+ let counterparty_forward_node = {
143+ let short_channel_id = details. get_inbound_payment_scid ( ) . unwrap ( ) ;
144+ let payment_relay: PaymentRelay =
145+ details. counterparty . forwarding_info . clone ( ) . unwrap ( ) . into ( ) ;
146+ let payment_constraints = PaymentConstraints {
147+ max_cltv_expiry : payment_relay. cltv_expiry_delta as u32
148+ + tlvs. payment_constraints . max_cltv_expiry ,
149+ htlc_minimum_msat : details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) ,
150+ } ;
151+ ForwardNode {
152+ tlvs : ForwardTlvs {
153+ short_channel_id,
154+ payment_relay,
155+ payment_constraints,
156+ features : BlindedHopFeatures :: empty ( ) ,
157+ } ,
158+ node_id : details. counterparty . node_id ,
159+ htlc_maximum_msat : details. inbound_htlc_maximum_msat . unwrap_or ( 0 ) ,
160+ }
119161 } ;
120- let forward_node = ForwardNode {
121- tlvs : ForwardTlvs {
122- short_channel_id,
123- payment_relay,
124- payment_constraints,
125- features : BlindedHopFeatures :: empty ( ) ,
126- } ,
127- node_id : details. counterparty . node_id ,
128- htlc_maximum_msat : details. inbound_htlc_maximum_msat . unwrap_or ( 0 ) ,
162+ let introduction_forward_node = {
163+ let htlc_minimum_msat = info. direction ( ) . htlc_minimum_msat ;
164+ let htlc_maximum_msat = info. direction ( ) . htlc_maximum_msat ;
165+ let payment_relay: PaymentRelay = info. into ( ) ;
166+ let payment_constraints = PaymentConstraints {
167+ max_cltv_expiry : payment_relay. cltv_expiry_delta as u32
168+ + counterparty_forward_node. tlvs . payment_constraints . max_cltv_expiry ,
169+ htlc_minimum_msat,
170+ } ;
171+ ForwardNode {
172+ tlvs : ForwardTlvs {
173+ short_channel_id : scid,
174+ payment_relay,
175+ payment_constraints,
176+ features : BlindedHopFeatures :: empty ( ) ,
177+ } ,
178+ node_id : introduction_node_id. as_pubkey ( ) . unwrap ( ) ,
179+ htlc_maximum_msat,
180+ }
129181 } ;
130182 BlindedPath :: new_for_payment (
131- & [ forward_node] , recipient, tlvs. clone ( ) , u64:: MAX , entropy_source, secp_ctx
183+ & [ introduction_forward_node, counterparty_forward_node] , recipient,
184+ tlvs. clone ( ) , u64:: MAX , entropy_source, secp_ctx
132185 )
133186 } )
134187 . take ( MAX_PAYMENT_PATHS )
0 commit comments