@@ -540,6 +540,14 @@ where
540
540
entropy_source : ES ,
541
541
}
542
542
543
+ // Target total length (in hops) for non-compact blinded paths.
544
+ // We pad with dummy hops until the path reaches this length,
545
+ // obscuring the recipient's true position.
546
+ //
547
+ // Compact paths are optimized for minimal size, so we avoid
548
+ // adding dummy hops to them.
549
+ pub ( crate ) const PADDED_PATH_LENGTH : usize = 4 ;
550
+
543
551
impl < G : Deref < Target = NetworkGraph < L > > , L : Deref , ES : Deref > DefaultMessageRouter < G , L , ES >
544
552
where
545
553
L :: Target : Logger ,
@@ -595,40 +603,46 @@ where
595
603
a_tor_only. cmp ( b_tor_only) . then ( a_channels. cmp ( b_channels) . reverse ( ) )
596
604
} ) ;
597
605
598
- let entropy = & * * entropy_source;
599
- let paths = peer_info
606
+ let build_path = |intermediate_hops : & [ MessageForwardNode ] | {
607
+ let dummy_hops_count = if compact_paths {
608
+ 0
609
+ } else {
610
+ // Add one for the final recipient TLV
611
+ PADDED_PATH_LENGTH . saturating_sub ( intermediate_hops. len ( ) + 1 )
612
+ } ;
613
+
614
+ BlindedMessagePath :: new_with_dummy_hops (
615
+ intermediate_hops,
616
+ recipient,
617
+ dummy_hops_count,
618
+ local_node_receive_key,
619
+ context. clone ( ) ,
620
+ & * * entropy_source,
621
+ secp_ctx,
622
+ )
623
+ } ;
624
+
625
+ // Try to create paths from peer info, fall back to direct path if needed
626
+ let mut paths = peer_info
600
627
. into_iter ( )
601
- . map ( |( peer, _, _) | {
602
- BlindedMessagePath :: new (
603
- & [ peer] ,
604
- recipient,
605
- local_node_receive_key,
606
- context. clone ( ) ,
607
- entropy,
608
- secp_ctx,
609
- )
610
- } )
628
+ . map ( |( peer, _, _) | build_path ( & [ peer] ) )
611
629
. take ( MAX_PATHS )
612
- . collect :: < Result < Vec < _ > , _ > > ( ) ;
613
-
614
- let mut paths = match paths {
615
- Ok ( paths) if !paths. is_empty ( ) => Ok ( paths) ,
616
- _ => {
617
- if is_recipient_announced {
618
- BlindedMessagePath :: new (
619
- & [ ] ,
620
- recipient,
621
- local_node_receive_key,
622
- context,
623
- & * * entropy_source,
624
- secp_ctx,
625
- )
630
+ . collect :: < Result < Vec < _ > , _ > > ( )
631
+ . ok ( )
632
+ . filter ( |paths| !paths. is_empty ( ) )
633
+ . or_else ( || {
634
+ is_recipient_announced
635
+ . then ( || build_path ( & [ ] ) )
636
+ . and_then ( |result| result. ok ( ) )
626
637
. map ( |path| vec ! [ path] )
627
- } else {
628
- Err ( ( ) )
629
- }
630
- } ,
631
- } ?;
638
+ } )
639
+ . ok_or ( ( ) ) ?;
640
+
641
+ // Sanity check: Ones the paths are created for the non-compact case, ensure
642
+ // each of them are of the length `PADDED_PATH_LENGTH`.
643
+ if !compact_paths {
644
+ debug_assert ! ( paths. iter( ) . all( |path| path. blinded_hops( ) . len( ) == PADDED_PATH_LENGTH ) ) ;
645
+ }
632
646
633
647
if compact_paths {
634
648
for path in & mut paths {
0 commit comments