Skip to content

Commit 3899c15

Browse files
committed
test(p2p): tests for connections with the same id
1 parent 2eb70e5 commit 3899c15

File tree

10 files changed

+281
-30
lines changed

10 files changed

+281
-30
lines changed

node/testing/src/cluster/mod.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use openmina_node_native::{http_server, rpc::RpcService, NodeService, RpcSender}
3434
use rand::{rngs::StdRng, SeedableRng};
3535
use serde::Serialize;
3636

37+
use crate::node::TestPeerId;
3738
use crate::{
3839
network_debugger::Debugger,
3940
node::{Node, NodeTestingConfig, RustNodeTestingConfig},
@@ -112,16 +113,18 @@ impl Cluster {
112113
pub fn add_rust_node(&mut self, testing_config: RustNodeTestingConfig) -> ClusterNodeId {
113114
let node_i = self.nodes.len();
114115
let (shutdown_tx, shutdown_rx) = mpsc::channel(1);
115-
let secret_key = if testing_config.randomize_peer_id {
116-
P2pSecretKey::from_bytes(rand::random())
117-
} else {
118-
let mut bytes = [0; 32];
119-
let bytes_len = bytes.len();
120-
let i_bytes = node_i.to_be_bytes();
121-
let i = bytes_len - i_bytes.len();
122-
bytes[i..bytes_len].copy_from_slice(&i_bytes);
123-
P2pSecretKey::from_bytes(bytes)
124-
};
116+
let secret_key = P2pSecretKey::from_bytes(match testing_config.peer_id {
117+
TestPeerId::Derived => {
118+
let mut bytes = [0; 32];
119+
let bytes_len = bytes.len();
120+
let i_bytes = node_i.to_be_bytes();
121+
let i = bytes_len - i_bytes.len();
122+
bytes[i..bytes_len].copy_from_slice(&i_bytes);
123+
bytes
124+
}
125+
TestPeerId::Random => rand::random(),
126+
TestPeerId::Bytes(bytes) => bytes,
127+
});
125128
let pub_key = secret_key.public_key();
126129

127130
let http_port = self

node/testing/src/node/config.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::time::Duration;
22

3-
use node::p2p::connection::outgoing::P2pConnectionOutgoingInitOpts;
3+
use node::p2p::{connection::outgoing::P2pConnectionOutgoingInitOpts};
44
use serde::{Deserialize, Serialize};
55

66
#[derive(Serialize, Deserialize, Debug, Clone)]
@@ -9,6 +9,14 @@ pub enum NodeTestingConfig {
99
Rust(RustNodeTestingConfig),
1010
}
1111

12+
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
13+
pub enum TestPeerId {
14+
#[default]
15+
Derived,
16+
Random,
17+
Bytes([u8; 32]),
18+
}
19+
1220
#[derive(Serialize, Deserialize, Debug, Clone)]
1321
pub struct RustNodeTestingConfig {
1422
pub chain_id: String,
@@ -17,7 +25,7 @@ pub struct RustNodeTestingConfig {
1725
pub ask_initial_peers_interval: Duration,
1826
pub initial_peers: Vec<P2pConnectionOutgoingInitOpts>,
1927
pub libp2p_port: Option<u16>,
20-
pub randomize_peer_id: bool,
28+
pub peer_id: TestPeerId,
2129
}
2230

2331
impl RustNodeTestingConfig {
@@ -29,7 +37,7 @@ impl RustNodeTestingConfig {
2937
ask_initial_peers_interval: Duration::from_secs(10),
3038
initial_peers: vec![],
3139
libp2p_port: None,
32-
randomize_peer_id: false,
40+
peer_id: TestPeerId::default(),
3341
}
3442
}
3543

@@ -58,8 +66,13 @@ impl RustNodeTestingConfig {
5866
self
5967
}
6068

61-
pub fn randomize_peer_id(mut self) -> Self {
62-
self.randomize_peer_id = true;
69+
pub fn with_random_peer_id(mut self) -> Self {
70+
self.peer_id = TestPeerId::Random;
71+
self
72+
}
73+
74+
pub fn with_peer_id(mut self, bytes: [u8; 32]) -> Self {
75+
self.peer_id = TestPeerId::Bytes(bytes);
6376
self
6477
}
6578
}

node/testing/src/node/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod config;
2-
pub use config::{NodeTestingConfig, RustNodeTestingConfig};
2+
pub use config::{NodeTestingConfig, RustNodeTestingConfig, TestPeerId};
33

44
use node::event_source::{Event, EventSourceNewEventAction};
55
use node::p2p::PeerId;

node/testing/src/scenarios/driver.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ pub fn connection_finalized_event(
6464
}
6565
}
6666

67+
pub fn connection_finalized_with_res_event(
68+
pred: impl Fn(ClusterNodeId, &PeerId, &Result<(), String>) -> bool,
69+
) -> impl Fn(ClusterNodeId, &Event, &State) -> bool {
70+
move |node_id, event, _| {
71+
matches!(
72+
event,
73+
Event::P2p(P2pEvent::Connection(P2pConnectionEvent::Finalized(peer, res))) if pred(node_id, peer, res)
74+
)
75+
}
76+
}
77+
6778
pub fn as_listen_new_addr_event(event: &Event) -> Option<(&Multiaddr, &P2pListenerId)> {
6879
if let Event::P2p(P2pEvent::Listen(P2pListenEvent::NewListenAddr { listener_id, addr })) = event
6980
{
@@ -282,6 +293,7 @@ pub async fn wait_for_nodes_listening_on_localhost<'cluster>(
282293
driver.run_until(duration, pred).await
283294
}
284295

296+
285297
/// Creates `num` Rust nodes in the cluster
286298
pub fn add_rust_nodes<'cluster, N, NodeIds, PeerIds>(
287299
driver: &mut Driver,

node/testing/src/scenarios/p2p/basic_incoming_connections.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use std::{time::Duration, collections::BTreeSet};
1+
use std::{collections::BTreeSet, time::Duration};
22

33
use crate::{
44
node::RustNodeTestingConfig,
55
scenarios::{
6-
add_rust_nodes, connection_finalized_event, wait_for_nodes_listening_on_localhost,
7-
ClusterRunner, Driver, as_connection_finalized_event,
6+
add_rust_nodes, as_connection_finalized_event, connection_finalized_event,
7+
connection_finalized_with_res_event, wait_for_nodes_listening_on_localhost, ClusterRunner,
8+
Driver,
89
},
910
};
1011

@@ -64,8 +65,7 @@ impl AcceptMultipleIncomingConnections {
6465

6566
let mut driver = Driver::new(runner);
6667

67-
let (node_ut, _) =
68-
driver.add_rust_node(RustNodeTestingConfig::berkeley_default());
68+
let (node_ut, _) = driver.add_rust_node(RustNodeTestingConfig::berkeley_default());
6969
assert!(
7070
wait_for_nodes_listening_on_localhost(&mut driver, Duration::from_secs(30), [node_ut])
7171
.await
@@ -104,6 +104,59 @@ impl AcceptMultipleIncomingConnections {
104104
.run_until(Duration::from_secs(3 * 60), pred)
105105
.await
106106
.unwrap();
107-
assert!(satisfied, "did not accept connection from peers: {:?}", peer_ids);
107+
assert!(
108+
satisfied,
109+
"did not accept connection from peers: {:?}",
110+
peer_ids
111+
);
112+
}
113+
}
114+
115+
/// Node should not accept connection from itself.
116+
#[derive(documented::Documented, Default, Clone, Copy)]
117+
pub struct DoesNotAcceptConnectionFromSelf;
118+
119+
impl DoesNotAcceptConnectionFromSelf {
120+
pub async fn run<'cluster>(self, runner: ClusterRunner<'cluster>) {
121+
let mut driver = Driver::new(runner);
122+
let (node_ut, node_ut_peer_id) =
123+
driver.add_rust_node(RustNodeTestingConfig::berkeley_default());
124+
125+
assert!(
126+
wait_for_nodes_listening_on_localhost(&mut driver, Duration::from_secs(60), [node_ut])
127+
.await
128+
.unwrap(),
129+
"node should be listening"
130+
);
131+
132+
driver
133+
.exec_step(crate::scenario::ScenarioStep::ConnectNodes {
134+
dialer: node_ut,
135+
listener: crate::scenario::ListenerNode::Rust(node_ut),
136+
})
137+
.await
138+
.expect("connect event should be dispatched"); // should it?
139+
140+
// wait for node under test receives connection event
141+
let connected = driver
142+
.wait_for(
143+
Duration::from_secs(10),
144+
connection_finalized_with_res_event(|node_id, peer, res| {
145+
node_id == node_ut && peer == &node_ut_peer_id && res.is_err()
146+
}),
147+
)
148+
.await
149+
.unwrap()
150+
.expect("connected event");
151+
152+
let state = driver
153+
.exec_even_step(connected)
154+
.await
155+
.unwrap()
156+
.expect("connected event sholuld be executed");
157+
assert!(
158+
state.p2p.get_ready_peer(&node_ut_peer_id).is_none(),
159+
"self-peer should not be ready"
160+
);
108161
}
109162
}

node/testing/src/scenarios/p2p/basic_outgoing_connections.rs

Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::{collections::BTreeSet, time::Duration};
22

3-
use node::p2p::{P2pPeerState, P2pPeerStatus, PeerId};
3+
use node::p2p::{identity::SecretKey, P2pPeerState, P2pPeerStatus, PeerId};
44

55
use crate::{
66
cluster::ClusterNodeId,
77
node::RustNodeTestingConfig,
88
scenarios::{
99
add_rust_nodes, as_connection_finalized_event, connection_finalized_event,
10-
wait_for_nodes_listening_on_localhost, ClusterRunner, Driver,
10+
wait_for_nodes_listening_on_localhost, ClusterRunner, Driver, connection_finalized_with_res_event,
1111
},
1212
};
1313

@@ -125,3 +125,147 @@ impl MakeMultipleOutgoingConnections {
125125
assert!(satisfied, "did not connect to peers: {:?}", peer_ids);
126126
}
127127
}
128+
129+
/// Node shouldn't establish connection with a node with the same peer_id.
130+
#[derive(documented::Documented, Default, Clone, Copy)]
131+
pub struct DontConnectToNodeWithSameId;
132+
133+
impl DontConnectToNodeWithSameId {
134+
pub async fn run<'cluster>(self, runner: ClusterRunner<'cluster>) {
135+
let mut driver = Driver::new(runner);
136+
137+
let port = 11108;
138+
let node_ut_port = 11109;
139+
let bytes: [u8; 32] = rand::random();
140+
141+
// start a node with the same peer_id on different port
142+
let (node, _) = driver.add_rust_node(
143+
RustNodeTestingConfig::berkeley_default()
144+
.libp2p_port(port)
145+
.with_peer_id(bytes)
146+
);
147+
// wait for it to be ready
148+
assert!(
149+
wait_for_nodes_listening_on_localhost(&mut driver, Duration::from_secs(30), [node])
150+
.await
151+
.unwrap(),
152+
"node should be listening"
153+
);
154+
155+
// start node under test with the other node as its initial peer
156+
let (node_ut, _) = driver.add_rust_node(
157+
RustNodeTestingConfig::berkeley_default()
158+
.libp2p_port(node_ut_port)
159+
.with_peer_id(bytes)
160+
);
161+
162+
driver
163+
.exec_step(crate::scenario::ScenarioStep::ConnectNodes {
164+
dialer: node_ut,
165+
listener: crate::scenario::ListenerNode::Rust(node),
166+
})
167+
.await
168+
.expect("connect event should be dispatched");
169+
170+
let connected = driver
171+
.wait_for(
172+
Duration::from_secs(60),
173+
connection_finalized_event(|node_id, _peer| node_id == node_ut),
174+
)
175+
.await
176+
.unwrap();
177+
178+
assert!(connected.is_none(), "the node sholdn't try to connect to itself");
179+
}
180+
}
181+
182+
/// Node shouldn't connect to itself even if its address specified in initial peers.
183+
#[derive(documented::Documented, Default, Clone, Copy)]
184+
pub struct DontConnectToSelfInitialPeer;
185+
186+
impl DontConnectToSelfInitialPeer {
187+
pub async fn run<'cluster>(self, runner: ClusterRunner<'cluster>) {
188+
let mut driver = Driver::new(runner);
189+
190+
let port = 11109;
191+
let bytes: [u8; 32] = rand::random();
192+
let peer_id = SecretKey::from_bytes(bytes.clone()).public_key().peer_id().to_libp2p_string();
193+
let self_maddr = format!("/ip4/127.0.0.1/tcp/{port}/p2p/{peer_id}")
194+
.parse()
195+
.unwrap();
196+
let (node_ut, _) = driver.add_rust_node(
197+
RustNodeTestingConfig::berkeley_default()
198+
.libp2p_port(port)
199+
.with_peer_id(bytes)
200+
.initial_peers(vec![self_maddr]),
201+
);
202+
assert!(
203+
wait_for_nodes_listening_on_localhost(&mut driver, Duration::from_secs(30), [node_ut])
204+
.await
205+
.unwrap(),
206+
"node should be listening"
207+
);
208+
209+
let connected = driver
210+
.wait_for(
211+
Duration::from_secs(60),
212+
connection_finalized_with_res_event(|node_id, _peer, _res| node_id == node_ut),
213+
)
214+
.await
215+
.unwrap();
216+
217+
assert!(connected.is_none(), "the node sholdn't try to connect to itself");
218+
}
219+
}
220+
221+
/// Node shouldn't connect to a node with the same peer id even if its address specified in initial peers.
222+
#[derive(documented::Documented, Default, Clone, Copy)]
223+
pub struct DontConnectToInitialPeerWithSameId;
224+
225+
impl DontConnectToInitialPeerWithSameId {
226+
pub async fn run<'cluster>(self, runner: ClusterRunner<'cluster>) {
227+
let mut driver = Driver::new(runner);
228+
229+
let port = 11108;
230+
let node_ut_port = 11109;
231+
let bytes: [u8; 32] = rand::random();
232+
let peer_id = SecretKey::from_bytes(bytes.clone()).public_key().peer_id().to_libp2p_string();
233+
234+
235+
let self_maddr = format!("/ip4/127.0.0.1/tcp/{port}/p2p/{peer_id}")
236+
.parse()
237+
.unwrap();
238+
239+
// start a node with the same peer_id on different port
240+
let (node, _) = driver.add_rust_node(
241+
RustNodeTestingConfig::berkeley_default()
242+
.libp2p_port(port)
243+
.with_peer_id(bytes)
244+
);
245+
// wait for it to be ready
246+
assert!(
247+
wait_for_nodes_listening_on_localhost(&mut driver, Duration::from_secs(30), [node])
248+
.await
249+
.unwrap(),
250+
"node should be listening"
251+
);
252+
253+
// start node under test with the other node as its initial peer
254+
let (node_ut, _) = driver.add_rust_node(
255+
RustNodeTestingConfig::berkeley_default()
256+
.libp2p_port(node_ut_port)
257+
.with_peer_id(bytes)
258+
.initial_peers(vec![self_maddr]),
259+
);
260+
261+
let connected = driver
262+
.wait_for(
263+
Duration::from_secs(60),
264+
connection_finalized_with_res_event(|node_id, _peer, _res| node_id == node_ut),
265+
)
266+
.await
267+
.unwrap();
268+
269+
assert!(connected.is_none(), "the node sholdn't try to connect to itself");
270+
}
271+
}

node/testing/src/scenarios/solo_node/basic_connectivity_accept_incoming.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl SoloNodeBasicConnectivityAcceptIncoming {
4646
.ask_initial_peers_interval(Duration::from_secs(3600))
4747
.max_peers(MAX_PEERS_PER_NODE)
4848
.initial_peers(initial_peers)
49-
.randomize_peer_id();
49+
.with_random_peer_id();
5050

5151
let node_id = runner.add_rust_node(config);
5252

0 commit comments

Comments
 (0)