Skip to content

Commit 32a5139

Browse files
committed
Resolve IntroductionNode::DirectedShortChannelId
When OnionMessenger creates an OnionMessage to a Destination, the latter may contain an IntroductionNode::DirectedShortChannelId inside a BlindedPath. Resolve these in DefaultMessageRouter and handle unresolved ones in OnionMessenger.
1 parent 7002180 commit 32a5139

File tree

1 file changed

+49
-17
lines changed

1 file changed

+49
-17
lines changed

lightning/src/onion_message/messenger.rs

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::sign::{EntropySource, NodeSigner, Recipient};
2323
use crate::ln::features::{InitFeatures, NodeFeatures};
2424
use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler, SocketAddress};
2525
use crate::ln::onion_utils;
26-
use crate::routing::gossip::{NetworkGraph, NodeId};
26+
use crate::routing::gossip::{NetworkGraph, NodeId, ReadOnlyNetworkGraph};
2727
use super::packet::OnionMessageContents;
2828
use super::packet::ParsedOnionMessageContents;
2929
use super::offers::OffersMessageHandler;
@@ -318,15 +318,21 @@ where
318318
ES::Target: EntropySource,
319319
{
320320
fn find_path(
321-
&self, sender: PublicKey, peers: Vec<PublicKey>, destination: Destination
321+
&self, sender: PublicKey, peers: Vec<PublicKey>, mut destination: Destination
322322
) -> Result<OnionMessagePath, ()> {
323-
let first_node = destination.first_node();
323+
let network_graph = self.network_graph.deref().read_only();
324+
destination.resolve(&network_graph);
325+
326+
let first_node = match destination.first_node() {
327+
Some(first_node) => first_node,
328+
None => return Err(()),
329+
};
330+
324331
if peers.contains(&first_node) || sender == first_node {
325332
Ok(OnionMessagePath {
326333
intermediate_nodes: vec![], destination, first_node_addresses: None
327334
})
328335
} else {
329-
let network_graph = self.network_graph.deref().read_only();
330336
let node_announcement = network_graph
331337
.node(&NodeId::from_pubkey(&first_node))
332338
.and_then(|node_info| node_info.announcement_info.as_ref())
@@ -416,11 +422,11 @@ pub struct OnionMessagePath {
416422

417423
impl OnionMessagePath {
418424
/// Returns the first node in the path.
419-
pub fn first_node(&self) -> PublicKey {
425+
pub fn first_node(&self) -> Option<PublicKey> {
420426
self.intermediate_nodes
421427
.first()
422428
.copied()
423-
.unwrap_or_else(|| self.destination.first_node())
429+
.or_else(|| self.destination.first_node())
424430
}
425431
}
426432

@@ -434,20 +440,36 @@ pub enum Destination {
434440
}
435441

436442
impl Destination {
443+
/// Attempts to resolve the [`IntroductionNode::DirectedShortChannelId`] of a
444+
/// [`Destination::BlindedPath`] to a [`IntroductionNode::NodeId`], if applicable, using the
445+
/// provided [`ReadOnlyNetworkGraph`].
446+
pub fn resolve(&mut self, network_graph: &ReadOnlyNetworkGraph) {
447+
if let Destination::BlindedPath(path) = self {
448+
if let IntroductionNode::DirectedShortChannelId(..) = path.introduction_node {
449+
if let Some(pubkey) = path
450+
.public_introduction_node_id(network_graph)
451+
.and_then(|node_id| node_id.as_pubkey().ok())
452+
{
453+
path.introduction_node = IntroductionNode::NodeId(pubkey);
454+
}
455+
}
456+
}
457+
}
458+
437459
pub(super) fn num_hops(&self) -> usize {
438460
match self {
439461
Destination::Node(_) => 1,
440462
Destination::BlindedPath(BlindedPath { blinded_hops, .. }) => blinded_hops.len(),
441463
}
442464
}
443465

444-
fn first_node(&self) -> PublicKey {
466+
fn first_node(&self) -> Option<PublicKey> {
445467
match self {
446-
Destination::Node(node_id) => *node_id,
468+
Destination::Node(node_id) => Some(*node_id),
447469
Destination::BlindedPath(BlindedPath { introduction_node, .. }) => {
448470
match introduction_node {
449-
IntroductionNode::NodeId(pubkey) => *pubkey,
450-
IntroductionNode::DirectedShortChannelId(..) => todo!(),
471+
IntroductionNode::NodeId(pubkey) => Some(*pubkey),
472+
IntroductionNode::DirectedShortChannelId(..) => None,
451473
}
452474
},
453475
}
@@ -492,6 +514,10 @@ pub enum SendError {
492514
///
493515
/// [`NodeSigner`]: crate::sign::NodeSigner
494516
GetNodeIdFailed,
517+
/// The provided [`Destination`] has a blinded path with an unresolved introduction node. An
518+
/// attempt to resolve it in the [`MessageRouter`] when finding an [`OnionMessagePath`] likely
519+
/// failed.
520+
UnresolvedIntroductionNode,
495521
/// We attempted to send to a blinded path where we are the introduction node, and failed to
496522
/// advance the blinded path to make the second hop the new introduction node. Either
497523
/// [`NodeSigner::ecdh`] failed, we failed to tweak the current blinding point to get the
@@ -576,7 +602,9 @@ where
576602
if let Destination::BlindedPath(ref mut blinded_path) = destination {
577603
let introduction_node_id = match blinded_path.introduction_node {
578604
IntroductionNode::NodeId(pubkey) => pubkey,
579-
IntroductionNode::DirectedShortChannelId(..) => todo!(),
605+
IntroductionNode::DirectedShortChannelId(..) => {
606+
return Err(SendError::UnresolvedIntroductionNode);
607+
},
580608
};
581609
let our_node_id = node_signer.get_node_id(Recipient::Node)
582610
.map_err(|()| SendError::GetNodeIdFailed)?;
@@ -597,14 +625,16 @@ where
597625
Destination::BlindedPath(BlindedPath { introduction_node, blinding_point, .. }) => {
598626
match introduction_node {
599627
IntroductionNode::NodeId(pubkey) => (*pubkey, *blinding_point),
600-
IntroductionNode::DirectedShortChannelId(..) => todo!(),
628+
IntroductionNode::DirectedShortChannelId(..) => {
629+
return Err(SendError::UnresolvedIntroductionNode);
630+
},
601631
}
602632
}
603633
}
604634
};
605635
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
606-
&secp_ctx, &intermediate_nodes, destination, contents, reply_path, &blinding_secret)
607-
.map_err(|e| SendError::Secp256k1(e))?;
636+
&secp_ctx, &intermediate_nodes, destination, contents, reply_path, &blinding_secret
637+
)?;
608638

609639
let prng_seed = entropy_source.get_secure_random_bytes();
610640
let onion_routing_packet = construct_onion_message_packet(
@@ -1144,7 +1174,7 @@ pub type SimpleRefOnionMessenger<
11441174
fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + secp256k1::Verification>(
11451175
secp_ctx: &Secp256k1<S>, unblinded_path: &[PublicKey], destination: Destination, message: T,
11461176
mut reply_path: Option<BlindedPath>, session_priv: &SecretKey
1147-
) -> Result<(Vec<(Payload<T>, [u8; 32])>, Vec<onion_utils::OnionKeys>), secp256k1::Error> {
1177+
) -> Result<(Vec<(Payload<T>, [u8; 32])>, Vec<onion_utils::OnionKeys>), SendError> {
11481178
let num_hops = unblinded_path.len() + destination.num_hops();
11491179
let mut payloads = Vec::with_capacity(num_hops);
11501180
let mut onion_packet_keys = Vec::with_capacity(num_hops);
@@ -1154,7 +1184,9 @@ fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + sec
11541184
Destination::BlindedPath(BlindedPath { introduction_node, blinding_point, blinded_hops }) => {
11551185
let introduction_node_id = match introduction_node {
11561186
IntroductionNode::NodeId(pubkey) => pubkey,
1157-
IntroductionNode::DirectedShortChannelId(..) => todo!(),
1187+
IntroductionNode::DirectedShortChannelId(..) => {
1188+
return Err(SendError::UnresolvedIntroductionNode);
1189+
},
11581190
};
11591191
(Some((*introduction_node_id, *blinding_point)), blinded_hops.len())
11601192
},
@@ -1206,7 +1238,7 @@ fn packet_payloads_and_keys<T: OnionMessageContents, S: secp256k1::Signing + sec
12061238
mu,
12071239
});
12081240
}
1209-
)?;
1241+
).map_err(|e| SendError::Secp256k1(e))?;
12101242

12111243
if let Some(control_tlvs) = final_control_tlvs {
12121244
payloads.push((Payload::Receive {

0 commit comments

Comments
 (0)