Skip to content

Commit 7c6f9f1

Browse files
Add test utilities and integration tests for onion messages
1 parent 547c221 commit 7c6f9f1

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// This file is Copyright its original authors, visible in version control
2+
// history.
3+
//
4+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7+
// You may not use this file except in accordance with one or both of these
8+
// licenses.
9+
10+
//! Onion message testing and test utilities live here.
11+
12+
use chain::keysinterface::{KeysInterface, Recipient};
13+
use super::{BlindedRoute, Destination, OnionMessenger};
14+
use util::enforcing_trait_impls::EnforcingSigner;
15+
use util::test_utils;
16+
17+
use bitcoin::network::constants::Network;
18+
use bitcoin::secp256k1::{PublicKey, Secp256k1};
19+
20+
use sync::Arc;
21+
22+
struct MessengerNode {
23+
keys_manager: Arc<test_utils::TestKeysInterface>,
24+
messenger: OnionMessenger<EnforcingSigner, Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestLogger>>,
25+
logger: Arc<test_utils::TestLogger>,
26+
}
27+
28+
impl MessengerNode {
29+
fn get_node_pk(&self) -> PublicKey {
30+
let secp_ctx = Secp256k1::new();
31+
PublicKey::from_secret_key(&secp_ctx, &self.keys_manager.get_node_secret(Recipient::Node).unwrap())
32+
}
33+
}
34+
35+
fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
36+
let mut res = Vec::new();
37+
for i in 0..num_messengers {
38+
let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i)));
39+
let seed = [i as u8; 32];
40+
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
41+
res.push(MessengerNode {
42+
keys_manager: keys_manager.clone(),
43+
messenger: OnionMessenger::new(keys_manager, logger.clone()),
44+
logger,
45+
});
46+
}
47+
res
48+
}
49+
50+
fn pass_along_path(mut path: Vec<MessengerNode>, expected_path_id: Option<[u8; 32]>) {
51+
let mut prev_node = path.remove(0);
52+
let num_nodes = path.len();
53+
for (idx, node) in path.into_iter().enumerate() {
54+
let events = prev_node.messenger.release_pending_msgs();
55+
assert_eq!(events.len(), 1);
56+
let onion_msg = {
57+
let msgs = events.get(&node.get_node_pk()).unwrap();
58+
assert_eq!(msgs.len(), 1);
59+
msgs[0].clone()
60+
};
61+
node.messenger.handle_onion_message(&prev_node.get_node_pk(), &onion_msg);
62+
if idx == num_nodes - 1 {
63+
node.logger.assert_log_contains(
64+
"lightning::onion_message::messenger".to_string(),
65+
format!("Received an onion message with path_id: {:02x?}", expected_path_id).to_string(), 1);
66+
}
67+
prev_node = node;
68+
}
69+
}
70+
71+
#[test]
72+
fn one_hop() {
73+
let nodes = create_nodes(2);
74+
75+
nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk())).unwrap();
76+
pass_along_path(nodes, None);
77+
}
78+
79+
#[test]
80+
fn two_unblinded_hops() {
81+
let nodes = create_nodes(3);
82+
83+
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk()], Destination::Node(nodes[2].get_node_pk())).unwrap();
84+
pass_along_path(nodes, None);
85+
}
86+
87+
#[test]
88+
fn two_unblinded_two_blinded() {
89+
let nodes = create_nodes(5);
90+
91+
let secp_ctx = Secp256k1::new();
92+
let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
93+
94+
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedRoute(blinded_route)).unwrap();
95+
pass_along_path(nodes, None);
96+
}
97+
98+
#[test]
99+
fn three_blinded_hops() {
100+
let nodes = create_nodes(4);
101+
102+
let secp_ctx = Secp256k1::new();
103+
let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
104+
105+
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route)).unwrap();
106+
pass_along_path(nodes, None);
107+
}

lightning/src/onion_message/messenger.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
246246
},
247247
};
248248
}
249+
250+
#[cfg(test)]
251+
pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, Vec<msgs::OnionMessage>> {
252+
let mut pending_msgs = self.pending_messages.lock().unwrap();
253+
let mut msgs = HashMap::new();
254+
core::mem::swap(&mut *pending_msgs, &mut msgs);
255+
msgs
256+
}
249257
}
250258

251259
// TODO: parameterize the below Simple* types with OnionMessenger and handle the messages it

lightning/src/onion_message/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ mod blinded_route;
2424
mod messenger;
2525
mod packet;
2626
mod utils;
27+
#[cfg(test)]
28+
mod functional_tests;
2729

2830
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
2931
pub use self::blinded_route::{BlindedRoute, BlindedHop};

0 commit comments

Comments
 (0)