Skip to content

Commit 744af6f

Browse files
committed
WIP: three-hop blinded paths
1 parent 8e3a220 commit 744af6f

File tree

1 file changed

+54
-24
lines changed

1 file changed

+54
-24
lines changed

lightning/src/onion_message/messenger.rs

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,9 @@ where
490490
>(
491491
&self, recipient: PublicKey, peers: I, secp_ctx: &Secp256k1<T>, compact_paths: bool
492492
) -> Result<Vec<BlindedPath>, ()> {
493+
let entropy_source = &*self.entropy_source;
494+
let recipient_node_id = NodeId::from_pubkey(&recipient);
495+
493496
// Limit the number of blinded paths that are computed.
494497
const MAX_PATHS: usize = 3;
495498

@@ -502,40 +505,67 @@ where
502505
network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient));
503506

504507
let mut peer_info = peers
508+
.map(|peer| (NodeId::from_pubkey(&peer.node_id), peer))
505509
// Limit to peers with announced channels
506-
.filter_map(|peer|
510+
.filter_map(|(node_id, peer)|
507511
network_graph
508-
.node(&NodeId::from_pubkey(&peer.node_id))
512+
.node(&node_id)
509513
.filter(|info| info.channels.len() >= MIN_PEER_CHANNELS)
510-
.map(|info| (peer, info.is_tor_only(), info.channels.len()))
514+
.map(|info| (node_id, peer, info.is_tor_only(), &info.channels))
511515
)
512516
// Exclude Tor-only nodes when the recipient is announced.
513-
.filter(|(_, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
517+
.filter(|(_, _, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
514518
.collect::<Vec<_>>();
515519

516520
// Prefer using non-Tor nodes with the most channels as the introduction node.
517-
peer_info.sort_unstable_by(|(_, a_tor_only, a_channels), (_, b_tor_only, b_channels)| {
518-
a_tor_only.cmp(b_tor_only).then(a_channels.cmp(b_channels).reverse())
521+
peer_info.sort_unstable_by(|(_, _, a_tor_only, a_channels), (_, _, b_tor_only, b_channels)| {
522+
a_tor_only.cmp(b_tor_only).then(a_channels.len().cmp(&b_channels.len()).reverse())
519523
});
520524

521-
let paths = peer_info.into_iter()
522-
.map(|(peer, _, _)| {
523-
BlindedPath::new_for_message(&[peer], recipient, &*self.entropy_source, secp_ctx)
524-
})
525-
.take(MAX_PATHS)
526-
.collect::<Result<Vec<_>, _>>();
527-
528-
let mut paths = match paths {
529-
Ok(paths) if !paths.is_empty() => Ok(paths),
530-
_ => {
531-
if is_recipient_announced {
532-
BlindedPath::one_hop_for_message(recipient, &*self.entropy_source, secp_ctx)
533-
.map(|path| vec![path])
534-
} else {
535-
Err(())
536-
}
537-
},
538-
}?;
525+
let three_hop_paths = peer_info.iter()
526+
// Pair peers with their other peers
527+
.flat_map(|(node_id, peer, _, channels)|
528+
channels
529+
.iter()
530+
.filter_map(|scid| network_graph.channels().get(scid))
531+
.filter_map(move |info| info
532+
.as_directed_to(&node_id)
533+
.map(|(_, source)| source)
534+
)
535+
.filter(|source| **source != recipient_node_id)
536+
.filter(|source| network_graph
537+
.node(source)
538+
.and_then(|info| info.announcement_info.as_ref())
539+
.map(|info| info.features().supports_onion_messages())
540+
.unwrap_or(false)
541+
)
542+
.filter_map(|source| source.as_pubkey().ok())
543+
.map(move |source_pubkey| (source_pubkey, peer.clone()))
544+
)
545+
.map(|(source_pubkey, peer)| BlindedPath::new_for_message(&[ForwardNode { node_id: source_pubkey, short_channel_id: None }, peer], recipient, entropy_source, secp_ctx))
546+
.take(MAX_PATHS);
547+
548+
let two_hop_paths = peer_info
549+
.iter()
550+
.map(|(_, peer, _, _)| BlindedPath::new_for_message(&[peer.clone()], recipient, entropy_source, secp_ctx))
551+
.take(MAX_PATHS);
552+
553+
let mut paths = three_hop_paths
554+
.collect::<Result<Vec<_>, _>>().ok()
555+
.and_then(|paths| (!paths.is_empty()).then(|| paths))
556+
.or_else(|| two_hop_paths.collect::<Result<Vec<_>, _>>().ok())
557+
.and_then(|paths| (!paths.is_empty()).then(|| paths))
558+
.or_else(|| is_recipient_announced
559+
.then(|| BlindedPath::one_hop_for_message(recipient, entropy_source, secp_ctx)
560+
.map(|path| vec![path])
561+
.unwrap_or(vec![])
562+
)
563+
)
564+
.ok_or(())?;
565+
566+
if paths.is_empty() {
567+
return Err(());
568+
}
539569

540570
if compact_paths {
541571
for path in &mut paths {

0 commit comments

Comments
 (0)