tests.rs 34.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.

use super::*;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
18
use futures::{channel::oneshot, executor, stream::BoxStream};
19

Shawn Tabrizi's avatar
Shawn Tabrizi committed
20
use assert_matches::assert_matches;
21
22
use async_trait::async_trait;
use parking_lot::Mutex;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
23
24
25
26
27
use std::{
	borrow::Cow,
	collections::HashSet,
	sync::atomic::{AtomicBool, Ordering},
};
28
29
30

use sc_network::{Event as NetworkEvent, IfDisconnected};

31
use polkadot_node_network_protocol::{request_response::outgoing::Requests, view, ObservedRole};
32
use polkadot_node_subsystem_test_helpers::{
Andronik Ordian's avatar
Andronik Ordian committed
33
	SingleItemSink, SingleItemStream, TestSubsystemContextHandle,
34
35
36
};
use polkadot_node_subsystem_util::metered;
use polkadot_primitives::v1::AuthorityDiscoveryId;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
37
38
39
use polkadot_subsystem::{
	jaeger,
	messages::{
40
41
		ApprovalDistributionMessage, BitfieldDistributionMessage, GossipSupportMessage,
		StatementDistributionMessage,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
42
43
44
	},
	ActiveLeavesUpdate, FromOverseer, LeafStatus, OverseerSignal,
};
45
use sc_network::Multiaddr;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
46
use sp_keyring::Sr25519Keyring;
47

Shawn Tabrizi's avatar
Shawn Tabrizi committed
48
use crate::{network::Network, validator_discovery::AuthorityDiscovery, Rep};
49
50
51
52
53
54
55
56
57
58

#[derive(Debug, PartialEq)]
pub enum NetworkAction {
	/// Note a change in reputation for a peer.
	ReputationChange(PeerId, Rep),
	/// Disconnect a peer from the given peer-set.
	DisconnectPeer(PeerId, PeerSet),
	/// Write a notification to a given peer on the given peer-set.
	WriteNotification(PeerId, PeerSet, Vec<u8>),
}
59
60
61
62

// The subsystem's view of the network - only supports a single call to `event_stream`.
#[derive(Clone)]
struct TestNetwork {
Andronik Ordian's avatar
Andronik Ordian committed
63
	net_events: Arc<Mutex<Option<SingleItemStream<NetworkEvent>>>>,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
64
	action_tx: Arc<Mutex<metered::UnboundedMeteredSender<NetworkAction>>>,
65
66
}

67
#[derive(Clone, Debug)]
68
69
70
71
72
struct TestAuthorityDiscovery;

// The test's view of the network. This receives updates from the subsystem in the form
// of `NetworkAction`s.
struct TestNetworkHandle {
Andronik Ordian's avatar
Andronik Ordian committed
73
74
	action_rx: metered::UnboundedMeteredReceiver<NetworkAction>,
	net_tx: SingleItemSink<NetworkEvent>,
75
76
}

77
fn new_test_network() -> (TestNetwork, TestNetworkHandle, TestAuthorityDiscovery) {
Andronik Ordian's avatar
Andronik Ordian committed
78
79
80
81
82
83
	let (net_tx, net_rx) = polkadot_node_subsystem_test_helpers::single_item_sink();
	let (action_tx, action_rx) = metered::unbounded();

	(
		TestNetwork {
			net_events: Arc::new(Mutex::new(Some(net_rx))),
84
			action_tx: Arc::new(Mutex::new(action_tx)),
Andronik Ordian's avatar
Andronik Ordian committed
85
		},
Shawn Tabrizi's avatar
Shawn Tabrizi committed
86
		TestNetworkHandle { action_rx, net_tx },
Andronik Ordian's avatar
Andronik Ordian committed
87
88
		TestAuthorityDiscovery,
	)
89
90
91
92
}

#[async_trait]
impl Network for TestNetwork {
Andronik Ordian's avatar
Andronik Ordian committed
93
	fn event_stream(&mut self) -> BoxStream<'static, NetworkEvent> {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
94
95
		self.net_events
			.lock()
Andronik Ordian's avatar
Andronik Ordian committed
96
97
98
99
100
			.take()
			.expect("Subsystem made more than one call to `event_stream`")
			.boxed()
	}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
101
102
103
104
105
	async fn add_to_peers_set(
		&mut self,
		_protocol: Cow<'static, str>,
		_: HashSet<Multiaddr>,
	) -> Result<(), String> {
Andronik Ordian's avatar
Andronik Ordian committed
106
107
108
		Ok(())
	}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
109
110
111
112
113
	async fn remove_from_peers_set(
		&mut self,
		_protocol: Cow<'static, str>,
		_: HashSet<Multiaddr>,
	) -> Result<(), String> {
Andronik Ordian's avatar
Andronik Ordian committed
114
115
116
		Ok(())
	}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
117
118
119
120
121
122
	async fn start_request<AD: AuthorityDiscovery>(
		&self,
		_: &mut AD,
		_: Requests,
		_: IfDisconnected,
	) {
Andronik Ordian's avatar
Andronik Ordian committed
123
124
	}

125
	fn report_peer(&self, who: PeerId, cost_benefit: Rep) {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
126
127
128
129
		self.action_tx
			.lock()
			.unbounded_send(NetworkAction::ReputationChange(who, cost_benefit))
			.unwrap();
130
131
132
	}

	fn disconnect_peer(&self, who: PeerId, peer_set: PeerSet) {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
133
134
135
136
		self.action_tx
			.lock()
			.unbounded_send(NetworkAction::DisconnectPeer(who, peer_set))
			.unwrap();
137
138
	}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
139
140
141
142
143
	fn write_notification(&self, who: PeerId, peer_set: PeerSet, message: Vec<u8>) {
		self.action_tx
			.lock()
			.unbounded_send(NetworkAction::WriteNotification(who, peer_set, message))
			.unwrap();
Andronik Ordian's avatar
Andronik Ordian committed
144
	}
145
146
147
148
}

#[async_trait]
impl validator_discovery::AuthorityDiscovery for TestAuthorityDiscovery {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
149
150
151
152
	async fn get_addresses_by_authority_id(
		&mut self,
		_authority: AuthorityDiscoveryId,
	) -> Option<Vec<Multiaddr>> {
Andronik Ordian's avatar
Andronik Ordian committed
153
154
		None
	}
155

Shawn Tabrizi's avatar
Shawn Tabrizi committed
156
157
158
159
	async fn get_authority_id_by_peer_id(
		&mut self,
		_peer_id: PeerId,
	) -> Option<AuthorityDiscoveryId> {
Andronik Ordian's avatar
Andronik Ordian committed
160
161
		None
	}
162
163
164
}

impl TestNetworkHandle {
Andronik Ordian's avatar
Andronik Ordian committed
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	// Get the next network action.
	async fn next_network_action(&mut self) -> NetworkAction {
		self.action_rx.next().await.expect("subsystem concluded early")
	}

	// Wait for the next N network actions.
	async fn next_network_actions(&mut self, n: usize) -> Vec<NetworkAction> {
		let mut v = Vec::with_capacity(n);
		for _ in 0..n {
			v.push(self.next_network_action().await);
		}

		v
	}

	async fn connect_peer(&mut self, peer: PeerId, peer_set: PeerSet, role: ObservedRole) {
		self.send_network_event(NetworkEvent::NotificationStreamOpened {
			remote: peer,
			protocol: peer_set.into_protocol_name(),
			negotiated_fallback: None,
			role: role.into(),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
186
187
		})
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
188
189
190
191
192
193
	}

	async fn disconnect_peer(&mut self, peer: PeerId, peer_set: PeerSet) {
		self.send_network_event(NetworkEvent::NotificationStreamClosed {
			remote: peer,
			protocol: peer_set.into_protocol_name(),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
194
195
		})
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
196
197
198
199
200
201
	}

	async fn peer_message(&mut self, peer: PeerId, peer_set: PeerSet, message: Vec<u8>) {
		self.send_network_event(NetworkEvent::NotificationsReceived {
			remote: peer,
			messages: vec![(peer_set.into_protocol_name(), message.into())],
Shawn Tabrizi's avatar
Shawn Tabrizi committed
202
203
		})
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
204
205
206
207
208
	}

	async fn send_network_event(&mut self, event: NetworkEvent) {
		self.net_tx.send(event).await.expect("subsystem concluded early");
	}
209
210
211
212
}

/// Assert that the given actions contain the given `action`.
fn assert_network_actions_contains(actions: &[NetworkAction], action: &NetworkAction) {
Andronik Ordian's avatar
Andronik Ordian committed
213
214
215
	if !actions.iter().any(|x| x == action) {
		panic!("Could not find `{:?}` in `{:?}`", action, actions);
	}
216
217
218
219
}

#[derive(Clone)]
struct TestSyncOracle {
Andronik Ordian's avatar
Andronik Ordian committed
220
221
	flag: Arc<AtomicBool>,
	done_syncing_sender: Arc<Mutex<Option<oneshot::Sender<()>>>>,
222
223
224
}

struct TestSyncOracleHandle {
Andronik Ordian's avatar
Andronik Ordian committed
225
226
	done_syncing_receiver: oneshot::Receiver<()>,
	flag: Arc<AtomicBool>,
227
228
229
}

impl TestSyncOracleHandle {
Andronik Ordian's avatar
Andronik Ordian committed
230
231
232
	fn set_done(&self) {
		self.flag.store(false, Ordering::SeqCst);
	}
233

Andronik Ordian's avatar
Andronik Ordian committed
234
235
236
	async fn await_mode_switch(self) {
		let _ = self.done_syncing_receiver.await;
	}
237
238
239
}

impl SyncOracle for TestSyncOracle {
Andronik Ordian's avatar
Andronik Ordian committed
240
241
	fn is_major_syncing(&mut self) -> bool {
		let is_major_syncing = self.flag.load(Ordering::SeqCst);
242

Andronik Ordian's avatar
Andronik Ordian committed
243
244
245
246
247
		if !is_major_syncing {
			if let Some(sender) = self.done_syncing_sender.lock().take() {
				let _ = sender.send(());
			}
		}
248

Andronik Ordian's avatar
Andronik Ordian committed
249
250
		is_major_syncing
	}
251

Andronik Ordian's avatar
Andronik Ordian committed
252
253
254
	fn is_offline(&mut self) -> bool {
		unimplemented!("not used in network bridge")
	}
255
256
257
258
}

// val - result of `is_major_syncing`.
fn make_sync_oracle(val: bool) -> (TestSyncOracle, TestSyncOracleHandle) {
Andronik Ordian's avatar
Andronik Ordian committed
259
260
261
262
	let (tx, rx) = oneshot::channel();
	let flag = Arc::new(AtomicBool::new(val));

	(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
263
264
		TestSyncOracle { flag: flag.clone(), done_syncing_sender: Arc::new(Mutex::new(Some(tx))) },
		TestSyncOracleHandle { flag, done_syncing_receiver: rx },
Andronik Ordian's avatar
Andronik Ordian committed
265
	)
266
267
268
}

fn done_syncing_oracle() -> Box<dyn SyncOracle + Send> {
Andronik Ordian's avatar
Andronik Ordian committed
269
270
	let (oracle, _) = make_sync_oracle(false);
	Box::new(oracle)
271
272
273
274
275
}

type VirtualOverseer = TestSubsystemContextHandle<NetworkBridgeMessage>;

struct TestHarness {
Andronik Ordian's avatar
Andronik Ordian committed
276
277
	network_handle: TestNetworkHandle,
	virtual_overseer: VirtualOverseer,
278
279
}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
280
fn test_harness<T: Future<Output = VirtualOverseer>>(
Andronik Ordian's avatar
Andronik Ordian committed
281
282
	sync_oracle: Box<dyn SyncOracle + Send>,
	test: impl FnOnce(TestHarness) -> T,
283
) {
Andronik Ordian's avatar
Andronik Ordian committed
284
	let pool = sp_core::testing::TaskExecutor::new();
285
	let (mut network, network_handle, discovery) = new_test_network();
Shawn Tabrizi's avatar
Shawn Tabrizi committed
286
287
	let (context, virtual_overseer) =
		polkadot_node_subsystem_test_helpers::make_subsystem_context(pool);
Andronik Ordian's avatar
Andronik Ordian committed
288
289
290
291
292
293
294
295
296
	let network_stream = network.event_stream();

	let bridge = NetworkBridge {
		network_service: network,
		authority_discovery_service: discovery,
		metrics: Metrics(None),
		sync_oracle,
	};

Shawn Tabrizi's avatar
Shawn Tabrizi committed
297
	let network_bridge = run_network(bridge, context, network_stream)
Andronik Ordian's avatar
Andronik Ordian committed
298
299
300
		.map_err(|_| panic!("subsystem execution failed"))
		.map(|_| ());

Shawn Tabrizi's avatar
Shawn Tabrizi committed
301
	let test_fut = test(TestHarness { network_handle, virtual_overseer });
Andronik Ordian's avatar
Andronik Ordian committed
302
303
304
305

	futures::pin_mut!(test_fut);
	futures::pin_mut!(network_bridge);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
306
307
308
309
310
311
312
	let _ = executor::block_on(future::join(
		async move {
			let mut virtual_overseer = test_fut.await;
			virtual_overseer.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
		},
		network_bridge,
	));
313
314
315
}

async fn assert_sends_validation_event_to_all(
Andronik Ordian's avatar
Andronik Ordian committed
316
317
	event: NetworkBridgeEvent<protocol_v1::ValidationProtocol>,
	virtual_overseer: &mut TestSubsystemContextHandle<NetworkBridgeMessage>,
318
) {
Andronik Ordian's avatar
Andronik Ordian committed
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
	// Ordering must match the enum variant order
	// in `AllMessages`.
	assert_matches!(
		virtual_overseer.recv().await,
		AllMessages::StatementDistribution(
			StatementDistributionMessage::NetworkBridgeUpdateV1(e)
		) if e == event.focus().expect("could not focus message")
	);

	assert_matches!(
		virtual_overseer.recv().await,
		AllMessages::BitfieldDistribution(
			BitfieldDistributionMessage::NetworkBridgeUpdateV1(e)
		) if e == event.focus().expect("could not focus message")
	);

	assert_matches!(
		virtual_overseer.recv().await,
		AllMessages::ApprovalDistribution(
			ApprovalDistributionMessage::NetworkBridgeUpdateV1(e)
		) if e == event.focus().expect("could not focus message")
	);
341
342
343
344
345
346
347

	assert_matches!(
		virtual_overseer.recv().await,
		AllMessages::GossipSupport(
			GossipSupportMessage::NetworkBridgeUpdateV1(e)
		) if e == event.focus().expect("could not focus message")
	);
348
349
350
}

async fn assert_sends_collation_event_to_all(
Andronik Ordian's avatar
Andronik Ordian committed
351
352
	event: NetworkBridgeEvent<protocol_v1::CollationProtocol>,
	virtual_overseer: &mut TestSubsystemContextHandle<NetworkBridgeMessage>,
353
) {
Andronik Ordian's avatar
Andronik Ordian committed
354
355
356
357
358
359
	assert_matches!(
		virtual_overseer.recv().await,
		AllMessages::CollatorProtocol(
			CollatorProtocolMessage::NetworkBridgeUpdateV1(e)
		) if e == event.focus().expect("could not focus message")
	)
360
361
362
363
}

#[test]
fn send_our_view_upon_connection() {
Andronik Ordian's avatar
Andronik Ordian committed
364
365
	let (oracle, handle) = make_sync_oracle(false);
	test_harness(Box::new(oracle), |test_harness| async move {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
366
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
Andronik Ordian's avatar
Andronik Ordian committed
367
368
369
370

		let peer = PeerId::random();

		let head = Hash::repeat_byte(1);
Shawn Tabrizi's avatar
Shawn Tabrizi committed
371
372
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(
Andronik Ordian's avatar
Andronik Ordian committed
373
374
375
376
377
				ActiveLeavesUpdate::start_work(ActivatedLeaf {
					hash: head,
					number: 1,
					status: LeafStatus::Fresh,
					span: Arc::new(jaeger::Span::Disabled),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
378
379
380
				}),
			)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
381
382
383

		handle.await_mode_switch().await;

Shawn Tabrizi's avatar
Shawn Tabrizi committed
384
385
386
387
388
389
		network_handle
			.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
390
391
392
393
394
395
396
397

		let view = view![head];
		let actions = network_handle.next_network_actions(2).await;
		assert_network_actions_contains(
			&actions,
			&NetworkAction::WriteNotification(
				peer.clone(),
				PeerSet::Validation,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
398
				WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(view.clone()).encode(),
Andronik Ordian's avatar
Andronik Ordian committed
399
400
401
402
403
404
405
			),
		);
		assert_network_actions_contains(
			&actions,
			&NetworkAction::WriteNotification(
				peer.clone(),
				PeerSet::Collation,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
406
				WireMessage::<protocol_v1::CollationProtocol>::ViewUpdate(view.clone()).encode(),
Andronik Ordian's avatar
Andronik Ordian committed
407
408
409
410
			),
		);
		virtual_overseer
	});
411
412
413
414
}

#[test]
fn sends_view_updates_to_peers() {
Andronik Ordian's avatar
Andronik Ordian committed
415
416
417
418
419
420
421
	let (oracle, handle) = make_sync_oracle(false);
	test_harness(Box::new(oracle), |test_harness| async move {
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;

		let peer_a = PeerId::random();
		let peer_b = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
422
423
424
425
426
427
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate {
				activated: Default::default(),
				deactivated: Default::default(),
			})))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
428
429
430

		handle.await_mode_switch().await;

Shawn Tabrizi's avatar
Shawn Tabrizi committed
431
432
433
434
435
436
		network_handle
			.connect_peer(peer_a.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer_b.clone(), PeerSet::Collation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
437
438

		let actions = network_handle.next_network_actions(2).await;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
439
440
		let wire_message =
			WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(View::default()).encode();
Andronik Ordian's avatar
Andronik Ordian committed
441
442
443

		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
444
			&NetworkAction::WriteNotification(peer_a, PeerSet::Validation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
445
446
447
448
		);

		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
449
			&NetworkAction::WriteNotification(peer_b, PeerSet::Collation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
450
451
452
453
		);

		let hash_a = Hash::repeat_byte(1);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
454
455
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(
Andronik Ordian's avatar
Andronik Ordian committed
456
457
458
459
460
				ActiveLeavesUpdate::start_work(ActivatedLeaf {
					hash: hash_a,
					number: 1,
					status: LeafStatus::Fresh,
					span: Arc::new(jaeger::Span::Disabled),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
461
462
463
				}),
			)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
464
465

		let actions = network_handle.next_network_actions(2).await;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
466
467
		let wire_message =
			WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(view![hash_a]).encode();
Andronik Ordian's avatar
Andronik Ordian committed
468
469
470

		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
471
			&NetworkAction::WriteNotification(peer_a, PeerSet::Validation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
472
473
474
475
		);

		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
476
			&NetworkAction::WriteNotification(peer_b, PeerSet::Collation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
477
478
479
		);
		virtual_overseer
	});
480
481
482
483
}

#[test]
fn do_not_send_view_update_until_synced() {
Andronik Ordian's avatar
Andronik Ordian committed
484
485
486
487
488
489
490
	let (oracle, handle) = make_sync_oracle(true);
	test_harness(Box::new(oracle), |test_harness| async move {
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;

		let peer_a = PeerId::random();
		let peer_b = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
491
492
493
494
495
496
		network_handle
			.connect_peer(peer_a.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer_b.clone(), PeerSet::Collation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
497
498
499

		{
			let actions = network_handle.next_network_actions(2).await;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
500
501
502
			let wire_message =
				WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(View::default())
					.encode();
Andronik Ordian's avatar
Andronik Ordian committed
503
504
505
506
507
508
509
510
511
512
513
514

			assert_network_actions_contains(
				&actions,
				&NetworkAction::WriteNotification(
					peer_a,
					PeerSet::Validation,
					wire_message.clone(),
				),
			);

			assert_network_actions_contains(
				&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
515
				&NetworkAction::WriteNotification(peer_b, PeerSet::Collation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
516
517
518
519
520
521
			);
		}

		let hash_a = Hash::repeat_byte(1);
		let hash_b = Hash::repeat_byte(1);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
522
523
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(
Andronik Ordian's avatar
Andronik Ordian committed
524
525
526
527
528
				ActiveLeavesUpdate::start_work(ActivatedLeaf {
					hash: hash_a,
					number: 1,
					status: LeafStatus::Fresh,
					span: Arc::new(jaeger::Span::Disabled),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
529
530
531
				}),
			)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
532
533
534
535
536
537

		// delay until the previous update has certainly been processed.
		futures_timer::Delay::new(std::time::Duration::from_millis(100)).await;

		handle.set_done();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
538
539
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(
Andronik Ordian's avatar
Andronik Ordian committed
540
541
542
543
544
				ActiveLeavesUpdate::start_work(ActivatedLeaf {
					hash: hash_b,
					number: 1,
					status: LeafStatus::Fresh,
					span: Arc::new(jaeger::Span::Disabled),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
545
546
547
				}),
			)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
548
549
550
551
552
553

		handle.await_mode_switch().await;

		// There should be a mode switch only for the second view update.
		{
			let actions = network_handle.next_network_actions(2).await;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
554
555
556
			let wire_message =
				WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(view![hash_a, hash_b])
					.encode();
Andronik Ordian's avatar
Andronik Ordian committed
557
558
559
560
561
562
563
564
565
566
567
568

			assert_network_actions_contains(
				&actions,
				&NetworkAction::WriteNotification(
					peer_a,
					PeerSet::Validation,
					wire_message.clone(),
				),
			);

			assert_network_actions_contains(
				&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
569
				&NetworkAction::WriteNotification(peer_b, PeerSet::Collation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
570
571
572
573
			);
		}
		virtual_overseer
	});
574
575
576
577
}

#[test]
fn do_not_send_view_update_when_only_finalized_block_changed() {
Andronik Ordian's avatar
Andronik Ordian committed
578
579
580
581
582
583
	test_harness(done_syncing_oracle(), |test_harness| async move {
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;

		let peer_a = PeerId::random();
		let peer_b = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
584
585
586
587
588
589
		network_handle
			.connect_peer(peer_a.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer_b.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
590
591
592

		let hash_a = Hash::repeat_byte(1);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
593
594
595
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::BlockFinalized(Hash::random(), 5)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
596
597
598
599

		// Send some empty active leaves update
		//
		// This should not trigger a view update to our peers.
Shawn Tabrizi's avatar
Shawn Tabrizi committed
600
601
602
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::default())))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
603
604

		// This should trigger the view update to our peers.
Shawn Tabrizi's avatar
Shawn Tabrizi committed
605
606
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(
Andronik Ordian's avatar
Andronik Ordian committed
607
608
609
610
611
				ActiveLeavesUpdate::start_work(ActivatedLeaf {
					hash: hash_a,
					number: 1,
					status: LeafStatus::Fresh,
					span: Arc::new(jaeger::Span::Disabled),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
612
613
614
				}),
			)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
615
616

		let actions = network_handle.next_network_actions(4).await;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
617
618
619
		let wire_message =
			WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(View::new(vec![hash_a], 5))
				.encode();
Andronik Ordian's avatar
Andronik Ordian committed
620
621
622

		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
623
			&NetworkAction::WriteNotification(peer_a, PeerSet::Validation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
624
625
626
627
		);

		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
628
			&NetworkAction::WriteNotification(peer_b, PeerSet::Validation, wire_message.clone()),
Andronik Ordian's avatar
Andronik Ordian committed
629
630
631
		);
		virtual_overseer
	});
632
633
634
635
}

#[test]
fn peer_view_updates_sent_via_overseer() {
Andronik Ordian's avatar
Andronik Ordian committed
636
	test_harness(done_syncing_oracle(), |test_harness| async move {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
637
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
Andronik Ordian's avatar
Andronik Ordian committed
638
639
640

		let peer = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
641
642
643
		network_handle
			.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
644
645
646
647
648
649
650
651

		let view = view![Hash::repeat_byte(1)];

		// bridge will inform about all connected peers.
		{
			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
652
653
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
654
655
656
657

			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
658
659
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
660
661
		}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
662
663
664
665
666
667
668
		network_handle
			.peer_message(
				peer.clone(),
				PeerSet::Validation,
				WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(view.clone()).encode(),
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
669
670
671
672

		assert_sends_validation_event_to_all(
			NetworkBridgeEvent::PeerViewChange(peer.clone(), view),
			&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
673
674
		)
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
675
676
		virtual_overseer
	});
677
678
679
680
}

#[test]
fn peer_messages_sent_via_overseer() {
Andronik Ordian's avatar
Andronik Ordian committed
681
	test_harness(done_syncing_oracle(), |test_harness| async move {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
682
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
Andronik Ordian's avatar
Andronik Ordian committed
683
684
685

		let peer = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
686
687
688
		network_handle
			.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
689
690
691
692
693
694

		// bridge will inform about all connected peers.
		{
			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
695
696
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
697
698
699
700

			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
701
702
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
703
704
		}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
705
706
		let approval_distribution_message =
			protocol_v1::ApprovalDistributionMessage::Approvals(Vec::new());
Andronik Ordian's avatar
Andronik Ordian committed
707
708
709
710
711

		let message = protocol_v1::ValidationProtocol::ApprovalDistribution(
			approval_distribution_message.clone(),
		);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
712
713
714
715
716
717
718
		network_handle
			.peer_message(
				peer.clone(),
				PeerSet::Validation,
				WireMessage::ProtocolMessage(message.clone()).encode(),
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

		network_handle.disconnect_peer(peer.clone(), PeerSet::Validation).await;

		// Approval distribution message comes first, and the message is only sent to that subsystem.
		// then a disconnection event arises that is sent to all validation networking subsystems.

		assert_matches!(
			virtual_overseer.recv().await,
			AllMessages::ApprovalDistribution(
				ApprovalDistributionMessage::NetworkBridgeUpdateV1(
					NetworkBridgeEvent::PeerMessage(p, m)
				)
			) => {
				assert_eq!(p, peer);
				assert_eq!(m, approval_distribution_message);
			}
		);

		assert_sends_validation_event_to_all(
			NetworkBridgeEvent::PeerDisconnected(peer),
			&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
740
741
		)
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
742
743
		virtual_overseer
	});
744
745
746
747
}

#[test]
fn peer_disconnect_from_just_one_peerset() {
Andronik Ordian's avatar
Andronik Ordian committed
748
	test_harness(done_syncing_oracle(), |test_harness| async move {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
749
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
Andronik Ordian's avatar
Andronik Ordian committed
750
751
752

		let peer = PeerId::random();

Robert Klotzner's avatar
Robert Klotzner committed
753
754
755
756
757
758
759
		network_handle
			.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full)
			.await;

Andronik Ordian's avatar
Andronik Ordian committed
760
761
762
763
764
		// bridge will inform about all connected peers.
		{
			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
765
766
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
767
768
769
770

			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
771
772
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
773
774
775
776
777
778
		}

		{
			assert_sends_collation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
779
780
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
781
782
783
784

			assert_sends_collation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
785
786
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
787
788
789
790
791
792
793
		}

		network_handle.disconnect_peer(peer.clone(), PeerSet::Validation).await;

		assert_sends_validation_event_to_all(
			NetworkBridgeEvent::PeerDisconnected(peer.clone()),
			&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
794
795
		)
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
796
797
798
799
800

		// to show that we're still connected on the collation protocol, send a view update.

		let hash_a = Hash::repeat_byte(1);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
801
802
		virtual_overseer
			.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(
Andronik Ordian's avatar
Andronik Ordian committed
803
804
805
806
807
				ActiveLeavesUpdate::start_work(ActivatedLeaf {
					hash: hash_a,
					number: 1,
					status: LeafStatus::Fresh,
					span: Arc::new(jaeger::Span::Disabled),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
808
809
810
				}),
			)))
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
811
812

		let actions = network_handle.next_network_actions(3).await;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
813
814
		let wire_message =
			WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(view![hash_a]).encode();
Andronik Ordian's avatar
Andronik Ordian committed
815
816
817
818
819
820
821
822
823
824
825

		assert_network_actions_contains(
			&actions,
			&NetworkAction::WriteNotification(
				peer.clone(),
				PeerSet::Collation,
				wire_message.clone(),
			),
		);
		virtual_overseer
	});
826
827
828
829
}

#[test]
fn relays_collation_protocol_messages() {
Andronik Ordian's avatar
Andronik Ordian committed
830
	test_harness(done_syncing_oracle(), |test_harness| async move {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
831
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
Andronik Ordian's avatar
Andronik Ordian committed
832
833
834
835

		let peer_a = PeerId::random();
		let peer_b = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
836
837
838
839
840
841
		network_handle
			.connect_peer(peer_a.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer_b.clone(), PeerSet::Collation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
842
843
844
845
846
847

		// bridge will inform about all connected peers.
		{
			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer_a.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
848
849
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
850
851
852
853

			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer_a.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
854
855
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
856
857
858
859
860
861
		}

		{
			assert_sends_collation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer_b.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
862
863
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
864
865
866
867

			assert_sends_collation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer_b.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
868
869
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
870
871
872
873
874
875
876
877
878
879
		}

		// peer A gets reported for sending a collation message.

		let collator_protocol_message = protocol_v1::CollatorProtocolMessage::Declare(
			Sr25519Keyring::Alice.public().into(),
			Default::default(),
			Default::default(),
		);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
880
881
		let message =
			protocol_v1::CollationProtocol::CollatorProtocol(collator_protocol_message.clone());
Andronik Ordian's avatar
Andronik Ordian committed
882

Shawn Tabrizi's avatar
Shawn Tabrizi committed
883
884
885
886
887
888
889
		network_handle
			.peer_message(
				peer_a.clone(),
				PeerSet::Collation,
				WireMessage::ProtocolMessage(message.clone()).encode(),
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
890
891
892
893

		let actions = network_handle.next_network_actions(3).await;
		assert_network_actions_contains(
			&actions,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
894
			&NetworkAction::ReputationChange(peer_a.clone(), UNCONNECTED_PEERSET_COST),
Andronik Ordian's avatar
Andronik Ordian committed
895
896
897
898
		);

		// peer B has the message relayed.

Shawn Tabrizi's avatar
Shawn Tabrizi committed
899
900
901
902
903
904
905
		network_handle
			.peer_message(
				peer_b.clone(),
				PeerSet::Collation,
				WireMessage::ProtocolMessage(message.clone()).encode(),
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
906
907
908
909
910
911
912
913
914
915
916
917
918
919

		assert_matches!(
			virtual_overseer.recv().await,
			AllMessages::CollatorProtocol(
				CollatorProtocolMessage::NetworkBridgeUpdateV1(
					NetworkBridgeEvent::PeerMessage(p, m)
				)
			) => {
				assert_eq!(p, peer_b);
				assert_eq!(m, collator_protocol_message);
			}
		);
		virtual_overseer
	});
920
921
922
923
}

#[test]
fn different_views_on_different_peer_sets() {
Andronik Ordian's avatar
Andronik Ordian committed
924
	test_harness(done_syncing_oracle(), |test_harness| async move {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
925
		let TestHarness { mut network_handle, mut virtual_overseer } = test_harness;
Andronik Ordian's avatar
Andronik Ordian committed
926
927
928

		let peer = PeerId::random();

Shawn Tabrizi's avatar
Shawn Tabrizi committed
929
930
931
932
933
934
		network_handle
			.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full)
			.await;
		network_handle
			.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
935
936
937
938
939
940

		// bridge will inform about all connected peers.
		{
			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
941
942
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
943
944
945
946

			assert_sends_validation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
947
948
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
949
950
951
952
953
954
		}

		{
			assert_sends_collation_event_to_all(
				NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
955
956
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
957
958
959
960

			assert_sends_collation_event_to_all(
				NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()),
				&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
961
962
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
963
964
965
966
967
		}

		let view_a = view![Hash::repeat_byte(1)];
		let view_b = view![Hash::repeat_byte(2)];

Shawn Tabrizi's avatar
Shawn Tabrizi committed
968
969
970
971
972
973
974
		network_handle
			.peer_message(
				peer.clone(),
				PeerSet::Validation,
				WireMessage::<protocol_v1::ValidationProtocol>::ViewUpdate(view_a.clone()).encode(),
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
975

Shawn Tabrizi's avatar
Shawn Tabrizi committed
976
977
978
979
980
981
982
		network_handle
			.peer_message(
				peer.clone(),
				PeerSet::Collation,
				WireMessage::<protocol_v1::CollationProtocol>::ViewUpdate(view_b.clone()).encode(),
			)
			.await;
Andronik Ordian's avatar
Andronik Ordian committed
983
984
985
986

		assert_sends_validation_event_to_all(
			NetworkBridgeEvent::PeerViewChange(peer.clone(), view_a.clone()),
			&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
987
988
		)
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
989
990
991
992

		assert_sends_collation_event_to_all(
			NetworkBridgeEvent::PeerViewChange(peer.clone(), view_b.clone()),
			&mut virtual_overseer,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
993
994
		)
		.await;
Andronik Ordian's avatar
Andronik Ordian committed
995
996
		virtual_overseer
	});
997
998
999
1000
}

#[test]
fn sent_views_include_finalized_number_update() {
For faster browsing, not all history is shown. View entire blame