@@ -171,7 +171,19 @@ impl InFlightHtlcs {
171
171
172
172
/// Takes in a path with payer's node id and adds the path's details to `InFlightHtlcs`.
173
173
pub fn process_path ( & mut self , path : & Path , payer_node_id : PublicKey ) {
174
- if path. hops . is_empty ( ) { return } ;
174
+ if path. len ( ) == 0 { return } ;
175
+
176
+ let mut cumulative_msat = 0 ;
177
+ if let Some ( tail) = & path. blinded_tail {
178
+ cumulative_msat += tail. final_value_msat + tail. fee_msat ;
179
+ self . 0
180
+ . entry ( ( tail. intro_node_scid ,
181
+ NodeId :: from_pubkey ( & path. hops . last ( ) . map_or ( payer_node_id, |hop| hop. pubkey ) ) <
182
+ NodeId :: from_pubkey ( & tail. path . introduction_node_id ) ) )
183
+ . and_modify ( |used_liquidity_msat| * used_liquidity_msat += cumulative_msat)
184
+ . or_insert ( cumulative_msat) ;
185
+ }
186
+
175
187
// total_inflight_map needs to be direction-sensitive when keeping track of the HTLC value
176
188
// that is held up. However, the `hops` array, which is a path returned by `find_route` in
177
189
// the router excludes the payer node. In the following lines, the payer's information is
@@ -180,7 +192,6 @@ impl InFlightHtlcs {
180
192
let reversed_hops_with_payer = path. hops . iter ( ) . rev ( ) . skip ( 1 )
181
193
. map ( |hop| hop. pubkey )
182
194
. chain ( core:: iter:: once ( payer_node_id) ) ;
183
- let mut cumulative_msat = 0 ;
184
195
185
196
// Taking the reversed vector from above, we zip it with just the reversed hops list to
186
197
// work "backwards" of the given path, since the last hop's `fee_msat` actually represents
@@ -292,6 +303,13 @@ pub struct Path {
292
303
pub blinded_tail : Option < BlindedTail > ,
293
304
}
294
305
306
+ impl Path {
307
+ /// The length of this path, including the hops of its [`Path::blinded_tail`], if any.
308
+ pub fn len ( & self ) -> usize {
309
+ self . hops . len ( ) + self . blinded_tail . as_ref ( ) . map_or ( 0 , |tail| tail. path . blinded_hops . len ( ) )
310
+ }
311
+ }
312
+
295
313
/// A route directs a payment from the sender (us) to the recipient. If the recipient supports MPP,
296
314
/// it can take multiple paths. Each path is composed of one or more hops through the network.
297
315
#[ derive( Clone , Hash , PartialEq , Eq ) ]
@@ -2249,10 +2267,11 @@ fn build_route_from_hops_internal<L: Deref>(
2249
2267
2250
2268
#[ cfg( test) ]
2251
2269
mod tests {
2270
+ use crate :: blinded_path:: BlindedPath ;
2252
2271
use crate :: routing:: gossip:: { NetworkGraph , P2PGossipSync , NodeId , EffectiveCapacity } ;
2253
2272
use crate :: routing:: utxo:: UtxoResult ;
2254
2273
use crate :: routing:: router:: { get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
2255
- Path , PaymentParameters , Route , RouteHint , RouteHintHop , RouteHop , RoutingFees ,
2274
+ BlindedTail , InFlightHtlcs , Path , PaymentParameters , Route , RouteHint , RouteHintHop , RouteHop , RoutingFees ,
2256
2275
DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA , MAX_PATH_LENGTH_ESTIMATE } ;
2257
2276
use crate :: routing:: scoring:: { ChannelUsage , FixedPenaltyScorer , Score , ProbabilisticScorer , ProbabilisticScoringParameters } ;
2258
2277
use crate :: routing:: test_utils:: { add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel} ;
@@ -5749,6 +5768,36 @@ mod tests {
5749
5768
let route = get_route ( & our_id, & payment_params, & network_graph. read_only ( ) , None , 100 , 42 , Arc :: clone ( & logger) , & scorer, & random_seed_bytes) ;
5750
5769
assert ! ( route. is_ok( ) ) ;
5751
5770
}
5771
+
5772
+ #[ test]
5773
+ fn blinded_path_inflight_processing ( ) {
5774
+ // Ensure we'll score the channel that's inbound to a blinded path's introduction node.
5775
+ let mut inflight_htlcs = InFlightHtlcs :: new ( ) ;
5776
+ let path = Path {
5777
+ hops : vec ! [ RouteHop {
5778
+ pubkey: ln_test_utils:: pubkey( 42 ) ,
5779
+ node_features: NodeFeatures :: empty( ) ,
5780
+ short_channel_id: 42 ,
5781
+ channel_features: ChannelFeatures :: empty( ) ,
5782
+ fee_msat: 100 ,
5783
+ cltv_expiry_delta: 0 ,
5784
+ } ] ,
5785
+ blinded_tail : Some ( BlindedTail {
5786
+ path : BlindedPath {
5787
+ introduction_node_id : ln_test_utils:: pubkey ( 43 ) ,
5788
+ blinding_point : ln_test_utils:: pubkey ( 44 ) ,
5789
+ blinded_hops : Vec :: new ( ) ,
5790
+ } ,
5791
+ intro_node_scid : 43 ,
5792
+ fee_msat : 1 ,
5793
+ cltv_expiry_delta : 0 ,
5794
+ final_value_msat : 200 ,
5795
+ } ) ,
5796
+ } ;
5797
+ inflight_htlcs. process_path ( & path, ln_test_utils:: pubkey ( 44 ) ) ;
5798
+ assert_eq ! ( * inflight_htlcs. 0 . get( & ( 42 , true ) ) . unwrap( ) , 301 ) ;
5799
+ assert_eq ! ( * inflight_htlcs. 0 . get( & ( 43 , false ) ) . unwrap( ) , 201 ) ;
5800
+ }
5752
5801
}
5753
5802
5754
5803
#[ cfg( all( test, not( feature = "no-std" ) ) ) ]
0 commit comments