Skip to content

Commit f8545fd

Browse files
committed
WIP: three-hop blinded paths
1 parent 8b38ce0 commit f8545fd

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
@@ -405,6 +405,9 @@ where
405405
>(
406406
&self, recipient: PublicKey, peers: I, secp_ctx: &Secp256k1<T>, compact_paths: bool
407407
) -> Result<Vec<BlindedPath>, ()> {
408+
let entropy_source = &*self.entropy_source;
409+
let recipient_node_id = NodeId::from_pubkey(&recipient);
410+
408411
// Limit the number of blinded paths that are computed.
409412
const MAX_PATHS: usize = 3;
410413

@@ -417,40 +420,67 @@ where
417420
network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient));
418421

419422
let mut peer_info = peers
423+
.map(|peer| (NodeId::from_pubkey(&peer.node_id), peer))
420424
// Limit to peers with announced channels
421-
.filter_map(|peer|
425+
.filter_map(|(node_id, peer)|
422426
network_graph
423-
.node(&NodeId::from_pubkey(&peer.node_id))
427+
.node(&node_id)
424428
.filter(|info| info.channels.len() >= MIN_PEER_CHANNELS)
425-
.map(|info| (peer, info.is_tor_only(), info.channels.len()))
429+
.map(|info| (node_id, peer, info.is_tor_only(), &info.channels))
426430
)
427431
// Exclude Tor-only nodes when the recipient is announced.
428-
.filter(|(_, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
432+
.filter(|(_, _, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
429433
.collect::<Vec<_>>();
430434

431435
// Prefer using non-Tor nodes with the most channels as the introduction node.
432-
peer_info.sort_unstable_by(|(_, a_tor_only, a_channels), (_, b_tor_only, b_channels)| {
433-
a_tor_only.cmp(b_tor_only).then(a_channels.cmp(b_channels).reverse())
436+
peer_info.sort_unstable_by(|(_, _, a_tor_only, a_channels), (_, _, b_tor_only, b_channels)| {
437+
a_tor_only.cmp(b_tor_only).then(a_channels.len().cmp(&b_channels.len()).reverse())
434438
});
435439

436-
let paths = peer_info.into_iter()
437-
.map(|(peer, _, _)| {
438-
BlindedPath::new_for_message(&[peer], recipient, &*self.entropy_source, secp_ctx)
439-
})
440-
.take(MAX_PATHS)
441-
.collect::<Result<Vec<_>, _>>();
442-
443-
let mut paths = match paths {
444-
Ok(paths) if !paths.is_empty() => Ok(paths),
445-
_ => {
446-
if is_recipient_announced {
447-
BlindedPath::one_hop_for_message(recipient, &*self.entropy_source, secp_ctx)
448-
.map(|path| vec![path])
449-
} else {
450-
Err(())
451-
}
452-
},
453-
}?;
440+
let three_hop_paths = peer_info.iter()
441+
// Pair peers with their other peers
442+
.flat_map(|(node_id, peer, _, channels)|
443+
channels
444+
.iter()
445+
.filter_map(|scid| network_graph.channels().get(scid))
446+
.filter_map(move |info| info
447+
.as_directed_to(&node_id)
448+
.map(|(_, source)| source)
449+
)
450+
.filter(|source| **source != recipient_node_id)
451+
.filter(|source| network_graph
452+
.node(source)
453+
.and_then(|info| info.announcement_info.as_ref())
454+
.map(|info| info.features.supports_onion_messages())
455+
.unwrap_or(false)
456+
)
457+
.filter_map(|source| source.as_pubkey().ok())
458+
.map(move |source_pubkey| (source_pubkey, peer.clone()))
459+
)
460+
.map(|(source_pubkey, peer)| BlindedPath::new_for_message(&[ForwardNode { node_id: source_pubkey, short_channel_id: None }, peer], recipient, entropy_source, secp_ctx))
461+
.take(MAX_PATHS);
462+
463+
let two_hop_paths = peer_info
464+
.iter()
465+
.map(|(_, peer, _, _)| BlindedPath::new_for_message(&[peer.clone()], recipient, entropy_source, secp_ctx))
466+
.take(MAX_PATHS);
467+
468+
let mut paths = three_hop_paths
469+
.collect::<Result<Vec<_>, _>>().ok()
470+
.and_then(|paths| (!paths.is_empty()).then(|| paths))
471+
.or_else(|| two_hop_paths.collect::<Result<Vec<_>, _>>().ok())
472+
.and_then(|paths| (!paths.is_empty()).then(|| paths))
473+
.or_else(|| is_recipient_announced
474+
.then(|| BlindedPath::one_hop_for_message(recipient, entropy_source, secp_ctx)
475+
.map(|path| vec![path])
476+
.unwrap_or(vec![])
477+
)
478+
)
479+
.ok_or(())?;
480+
481+
if paths.is_empty() {
482+
return Err(());
483+
}
454484

455485
if compact_paths {
456486
for path in &mut paths {

0 commit comments

Comments
 (0)