Skip to content

Commit 04b53fe

Browse files
committed
WIP: three-hop blinded paths
1 parent 5766bd6 commit 04b53fe

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
@@ -398,6 +398,9 @@ where
398398
>(
399399
&self, recipient: PublicKey, peers: I, secp_ctx: &Secp256k1<T>, compact_paths: bool
400400
) -> Result<Vec<BlindedPath>, ()> {
401+
let entropy_source = &*self.entropy_source;
402+
let recipient_node_id = NodeId::from_pubkey(&recipient);
403+
401404
// Limit the number of blinded paths that are computed.
402405
const MAX_PATHS: usize = 3;
403406

@@ -410,40 +413,67 @@ where
410413
network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient));
411414

412415
let mut peer_info = peers
416+
.map(|peer| (NodeId::from_pubkey(&peer.node_id), peer))
413417
// Limit to peers with announced channels
414-
.filter_map(|peer|
418+
.filter_map(|(node_id, peer)|
415419
network_graph
416-
.node(&NodeId::from_pubkey(&peer.node_id))
420+
.node(&node_id)
417421
.filter(|info| info.channels.len() >= MIN_PEER_CHANNELS)
418-
.map(|info| (peer, info.is_tor_only(), info.channels.len()))
422+
.map(|info| (node_id, peer, info.is_tor_only(), &info.channels))
419423
)
420424
// Exclude Tor-only nodes when the recipient is announced.
421-
.filter(|(_, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
425+
.filter(|(_, _, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
422426
.collect::<Vec<_>>();
423427

424428
// Prefer using non-Tor nodes with the most channels as the introduction node.
425-
peer_info.sort_unstable_by(|(_, a_tor_only, a_channels), (_, b_tor_only, b_channels)| {
426-
a_tor_only.cmp(b_tor_only).then(a_channels.cmp(b_channels).reverse())
429+
peer_info.sort_unstable_by(|(_, _, a_tor_only, a_channels), (_, _, b_tor_only, b_channels)| {
430+
a_tor_only.cmp(b_tor_only).then(a_channels.len().cmp(&b_channels.len()).reverse())
427431
});
428432

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

448478
if compact_paths {
449479
for path in &mut paths {

0 commit comments

Comments
 (0)