@@ -90,6 +90,8 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
90
90
& self , recipient : PublicKey , first_hops : Vec < ChannelDetails > , tlvs : ReceiveTlvs ,
91
91
amount_msats : u64 , entropy_source : & ES , secp_ctx : & Secp256k1 < T >
92
92
) -> Result < Vec < ( BlindedPayInfo , BlindedPath ) > , ( ) > {
93
+ let recipient_node_id = NodeId :: from_pubkey ( & recipient) ;
94
+
93
95
// Limit the number of blinded paths that are computed.
94
96
const MAX_PAYMENT_PATHS : usize = 3 ;
95
97
@@ -103,12 +105,15 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
103
105
. filter ( |details| amount_msats <= details. inbound_capacity_msat )
104
106
. filter ( |details| amount_msats >= details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) )
105
107
. 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
107
111
. 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) )
110
115
)
111
- . filter_map ( |details| {
116
+ . filter_map ( |( details, counterparty_channels ) | {
112
117
let short_channel_id = match details. get_inbound_payment_scid ( ) {
113
118
Some ( short_channel_id) => short_channel_id,
114
119
None => return None ,
@@ -131,7 +136,7 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
131
136
max_cltv_expiry : tlvs. payment_constraints . max_cltv_expiry + cltv_expiry_delta,
132
137
htlc_minimum_msat : details. inbound_htlc_minimum_msat . unwrap_or ( 0 ) ,
133
138
} ;
134
- Some ( ForwardNode {
139
+ let forward_node = ForwardNode {
135
140
tlvs : ForwardTlvs {
136
141
short_channel_id,
137
142
payment_relay,
@@ -140,11 +145,57 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
140
145
} ,
141
146
node_id : details. counterparty . node_id ,
142
147
htlc_maximum_msat : details. inbound_htlc_maximum_msat . unwrap_or ( u64:: MAX ) ,
143
- } )
148
+ } ;
149
+ Some ( ( forward_node, counterparty_channels) )
144
150
} )
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
+ } ;
146
196
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
148
199
)
149
200
} )
150
201
. take ( MAX_PAYMENT_PATHS )
0 commit comments