@@ -540,6 +540,14 @@ where
540540 entropy_source : ES ,
541541}
542542
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+
543551impl < G : Deref < Target = NetworkGraph < L > > , L : Deref , ES : Deref > DefaultMessageRouter < G , L , ES >
544552where
545553 L :: Target : Logger ,
@@ -595,40 +603,46 @@ where
595603 a_tor_only. cmp ( b_tor_only) . then ( a_channels. cmp ( b_channels) . reverse ( ) )
596604 } ) ;
597605
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
600627 . 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] ) )
611629 . 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 ( ) )
626637 . 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+ }
632646
633647 if compact_paths {
634648 for path in & mut paths {
0 commit comments