Skip to content

Commit 9f1ffab

Browse files
committed
Look up node id from scid in OnionMessenger
When forwarding onion messages, the next node may be represented by a short channel id instead of a node id. Parameterize OnionMessenger with a NodeIdLookUp trait to find which node is the next hop. Implement the trait for ChannelManager for forwarding to channel counterparties. Also use this trait when advancing a blinded path one hop when the sender is the introduction node.
1 parent 32a5139 commit 9f1ffab

File tree

7 files changed

+125
-39
lines changed

7 files changed

+125
-39
lines changed

fuzz/src/onion_message.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bitcoin::secp256k1::ecdh::SharedSecret;
66
use bitcoin::secp256k1::ecdsa::RecoverableSignature;
77
use bitcoin::secp256k1::schnorr;
88

9-
use lightning::blinded_path::BlindedPath;
9+
use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
1010
use lightning::ln::features::InitFeatures;
1111
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
1212
use lightning::ln::script::ShutdownScript;
@@ -36,12 +36,13 @@ pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
3636
node_secret: secret,
3737
counter: AtomicU64::new(0),
3838
};
39+
let node_id_lookup = EmptyNodeIdLookUp {};
3940
let message_router = TestMessageRouter {};
4041
let offers_msg_handler = TestOffersMessageHandler {};
4142
let custom_msg_handler = TestCustomMessageHandler {};
4243
let onion_messenger = OnionMessenger::new(
43-
&keys_manager, &keys_manager, logger, &message_router, &offers_msg_handler,
44-
&custom_msg_handler
44+
&keys_manager, &keys_manager, logger, &node_id_lookup, &message_router,
45+
&offers_msg_handler, &custom_msg_handler
4546
);
4647

4748
let peer_node_id = {

lightning/src/blinded_path/message.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
33
#[allow(unused_imports)]
44
use crate::prelude::*;
55

6-
use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode};
6+
use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NodeIdLookUp};
77
use crate::blinded_path::utils;
88
use crate::io;
99
use crate::io::Cursor;
@@ -84,9 +84,14 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
8484

8585
// Advance the blinded onion message path by one hop, so make the second hop into the new
8686
// introduction node.
87-
pub(crate) fn advance_path_by_one<NS: Deref, T: secp256k1::Signing + secp256k1::Verification>(
88-
path: &mut BlindedPath, node_signer: &NS, secp_ctx: &Secp256k1<T>
89-
) -> Result<(), ()> where NS::Target: NodeSigner {
87+
pub(crate) fn advance_path_by_one<NS: Deref, NL: Deref, T>(
88+
path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
89+
) -> Result<(), ()>
90+
where
91+
NS::Target: NodeSigner,
92+
NL::Target: NodeIdLookUp,
93+
T: secp256k1::Signing + secp256k1::Verification,
94+
{
9095
let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?;
9196
let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
9297
let encrypted_control_tlvs = path.blinded_hops.remove(0).encrypted_payload;
@@ -98,7 +103,10 @@ pub(crate) fn advance_path_by_one<NS: Deref, T: secp256k1::Signing + secp256k1::
98103
}) => {
99104
let next_node_id = match next_hop {
100105
NextHop::NodeId(pubkey) => pubkey,
101-
NextHop::ShortChannelId(_) => todo!(),
106+
NextHop::ShortChannelId(scid) => match node_id_lookup.next_node_id(scid) {
107+
Some(pubkey) => pubkey,
108+
None => return Err(()),
109+
},
102110
};
103111
let mut new_blinding_point = match next_blinding_override {
104112
Some(blinding_point) => blinding_point,

lightning/src/blinded_path/mod.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,37 @@ pub enum IntroductionNode {
5858
///
5959
/// [BOLT 7]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#the-channel_announcement-message
6060
/// [`ChannelAnnouncement`]: crate::ln::msgs::ChannelAnnouncement
61-
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
61+
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
6262
pub enum Direction {
6363
/// The lesser node id when compared lexicographically in ascending order.
6464
NodeOne,
6565
/// The greater node id when compared lexicographically in ascending order.
6666
NodeTwo,
6767
}
6868

69+
/// An interface for looking up the node id of a channel counterparty for the purpose of forwarding
70+
/// an [`OnionMessage`].
71+
///
72+
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
73+
pub trait NodeIdLookUp {
74+
/// Returns the node id of the forwarding node's channel counterparty with `short_channel_id`.
75+
///
76+
/// Here, the forwarding node is referring to the node of the [`OnionMessenger`] parameterized
77+
/// by the [`NodeIdLookUp`] and the counterparty to one of that node's peers.
78+
///
79+
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
80+
fn next_node_id(&self, short_channel_id: u64) -> Option<PublicKey>;
81+
}
82+
83+
/// A [`NodeIdLookUp`] that always returns `None`.
84+
pub struct EmptyNodeIdLookUp {}
85+
86+
impl NodeIdLookUp for EmptyNodeIdLookUp {
87+
fn next_node_id(&self, _short_channel_id: u64) -> Option<PublicKey> {
88+
None
89+
}
90+
}
91+
6992
/// An encrypted payload and node id corresponding to a hop in a payment or onion message path, to
7093
/// be encoded in the sender's onion packet. These hops cannot be identified by outside observers
7194
/// and thus can be used to hide the identity of the recipient.
@@ -238,4 +261,17 @@ impl Direction {
238261
Direction::NodeTwo => core::cmp::max(node_a, node_b),
239262
}
240263
}
264+
265+
/// Returns the [`PublicKey`] from the inputs corresponding to the direction.
266+
pub fn select_pubkey<'a>(&self, node_a: &'a PublicKey, node_b: &'a PublicKey) -> &'a PublicKey {
267+
let (node_one, node_two) = if NodeId::from_pubkey(node_a) < NodeId::from_pubkey(node_b) {
268+
(node_a, node_b)
269+
} else {
270+
(node_b, node_a)
271+
};
272+
match self {
273+
Direction::NodeOne => node_one,
274+
Direction::NodeTwo => node_two,
275+
}
276+
}
241277
}

lightning/src/ln/channelmanager.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey};
3131
use bitcoin::secp256k1::Secp256k1;
3232
use bitcoin::{secp256k1, Sequence};
3333

34-
use crate::blinded_path::BlindedPath;
34+
use crate::blinded_path::{BlindedPath, NodeIdLookUp};
3535
use crate::blinded_path::payment::{PaymentConstraints, ReceiveTlvs};
3636
use crate::chain;
3737
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
@@ -10433,6 +10433,23 @@ where
1043310433
}
1043410434
}
1043510435

10436+
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
10437+
NodeIdLookUp for ChannelManager<M, T, ES, NS, SP, F, R, L>
10438+
where
10439+
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
10440+
T::Target: BroadcasterInterface,
10441+
ES::Target: EntropySource,
10442+
NS::Target: NodeSigner,
10443+
SP::Target: SignerProvider,
10444+
F::Target: FeeEstimator,
10445+
R::Target: Router,
10446+
L::Target: Logger,
10447+
{
10448+
fn next_node_id(&self, short_channel_id: u64) -> Option<PublicKey> {
10449+
self.short_to_chan_info.read().unwrap().get(&short_channel_id).map(|(pubkey, _)| *pubkey)
10450+
}
10451+
}
10452+
1043610453
/// Fetches the set of [`NodeFeatures`] flags that are provided by or required by
1043710454
/// [`ChannelManager`].
1043810455
pub(crate) fn provided_node_features(config: &UserConfig) -> NodeFeatures {

lightning/src/ln/functional_test_utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ type TestOnionMessenger<'chan_man, 'node_cfg, 'chan_mon_cfg> = OnionMessenger<
415415
DedicatedEntropy,
416416
&'node_cfg test_utils::TestKeysInterface,
417417
&'chan_mon_cfg test_utils::TestLogger,
418+
&'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
418419
&'node_cfg test_utils::TestMessageRouter<'chan_mon_cfg>,
419420
&'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
420421
IgnoringMessageHandler,
@@ -3199,8 +3200,8 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
31993200
for i in 0..node_count {
32003201
let dedicated_entropy = DedicatedEntropy(RandomBytes::new([i as u8; 32]));
32013202
let onion_messenger = OnionMessenger::new(
3202-
dedicated_entropy, cfgs[i].keys_manager, cfgs[i].logger, &cfgs[i].message_router,
3203-
&chan_mgrs[i], IgnoringMessageHandler {},
3203+
dedicated_entropy, cfgs[i].keys_manager, cfgs[i].logger, &chan_mgrs[i],
3204+
&cfgs[i].message_router, &chan_mgrs[i], IgnoringMessageHandler {},
32043205
);
32053206
let gossip_sync = P2PGossipSync::new(cfgs[i].network_graph.as_ref(), None, cfgs[i].logger);
32063207
let wallet_source = Arc::new(test_utils::TestWalletSource::new(SecretKey::from_slice(&[i as u8 + 1; 32]).unwrap()));

lightning/src/onion_message/functional_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
//! Onion message testing and test utilities live here.
1111
12-
use crate::blinded_path::BlindedPath;
12+
use crate::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
1313
use crate::events::{Event, EventsProvider};
1414
use crate::ln::features::{ChannelFeatures, InitFeatures};
1515
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -42,6 +42,7 @@ struct MessengerNode {
4242
Arc<test_utils::TestKeysInterface>,
4343
Arc<test_utils::TestNodeSigner>,
4444
Arc<test_utils::TestLogger>,
45+
Arc<EmptyNodeIdLookUp>,
4546
Arc<DefaultMessageRouter<
4647
Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
4748
Arc<test_utils::TestLogger>,
@@ -175,6 +176,7 @@ fn create_nodes_using_secrets(secrets: Vec<SecretKey>) -> Vec<MessengerNode> {
175176
let entropy_source = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
176177
let node_signer = Arc::new(test_utils::TestNodeSigner::new(secret_key));
177178

179+
let node_id_lookup = Arc::new(EmptyNodeIdLookUp {});
178180
let message_router = Arc::new(
179181
DefaultMessageRouter::new(network_graph.clone(), entropy_source.clone())
180182
);
@@ -185,7 +187,7 @@ fn create_nodes_using_secrets(secrets: Vec<SecretKey>) -> Vec<MessengerNode> {
185187
node_id: node_signer.get_node_id(Recipient::Node).unwrap(),
186188
entropy_source: entropy_source.clone(),
187189
messenger: OnionMessenger::new(
188-
entropy_source, node_signer, logger.clone(), message_router,
190+
entropy_source, node_signer, logger.clone(), node_id_lookup, message_router,
189191
offers_message_handler, custom_message_handler.clone()
190192
),
191193
custom_message_handler,

0 commit comments

Comments
 (0)