diff --git a/polkadot/node/collation-generation/src/lib.rs b/polkadot/node/collation-generation/src/lib.rs index e1893b6fb1..c52dcc846c 100644 --- a/polkadot/node/collation-generation/src/lib.rs +++ b/polkadot/node/collation-generation/src/lib.rs @@ -49,6 +49,9 @@ use std::sync::Arc; mod error; +#[cfg(test)] +mod tests; + const LOG_TARGET: &'static str = "parachain::collation-generation"; /// Collation Generation Subsystem @@ -506,6 +509,3 @@ impl metrics::Metrics for Metrics { Ok(Metrics(Some(metrics))) } } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/collation-generation/src/tests.rs b/polkadot/node/collation-generation/src/tests.rs index 7f13205c52..8c663e7f7b 100644 --- a/polkadot/node/collation-generation/src/tests.rs +++ b/polkadot/node/collation-generation/src/tests.rs @@ -15,358 +15,358 @@ // along with Polkadot. If not, see . mod handle_new_activations { - use super::super::*; - use futures::{ - lock::Mutex, - task::{Context as FuturesContext, Poll}, - Future, - }; - use polkadot_node_primitives::{Collation, CollationResult, BlockData, PoV, POV_BOMB_LIMIT}; - use polkadot_node_subsystem::messages::{ - AllMessages, RuntimeApiMessage, RuntimeApiRequest, - }; - use polkadot_node_subsystem_test_helpers::{ - subsystem_test_harness, TestSubsystemContextHandle, - }; - use polkadot_primitives::v1::{ - CollatorPair, Id as ParaId, PersistedValidationData, ScheduledCore, ValidationCode, - }; - use std::pin::Pin; + use super::super::*; + use futures::{ + lock::Mutex, + task::{Context as FuturesContext, Poll}, + Future, + }; + use polkadot_node_primitives::{Collation, CollationResult, BlockData, PoV, POV_BOMB_LIMIT}; + use polkadot_node_subsystem::messages::{ + AllMessages, RuntimeApiMessage, RuntimeApiRequest, + }; + use polkadot_node_subsystem_test_helpers::{ + subsystem_test_harness, TestSubsystemContextHandle, + }; + use polkadot_primitives::v1::{ + CollatorPair, Id as ParaId, PersistedValidationData, ScheduledCore, ValidationCode, + }; + use std::pin::Pin; - fn test_collation() -> Collation { - Collation { - upward_messages: Default::default(), - horizontal_messages: Default::default(), - new_validation_code: Default::default(), - head_data: Default::default(), - proof_of_validity: PoV { - block_data: BlockData(Vec::new()), - }, - processed_downward_messages: Default::default(), - hrmp_watermark: Default::default(), - } - } + fn test_collation() -> Collation { + Collation { + upward_messages: Default::default(), + horizontal_messages: Default::default(), + new_validation_code: Default::default(), + head_data: Default::default(), + proof_of_validity: PoV { + block_data: BlockData(Vec::new()), + }, + processed_downward_messages: Default::default(), + hrmp_watermark: Default::default(), + } + } - fn test_collation_compressed() -> Collation { - let mut collation = test_collation(); - let compressed = PoV { - block_data: BlockData(sp_maybe_compressed_blob::compress( - &collation.proof_of_validity.block_data.0, - POV_BOMB_LIMIT, - ).unwrap()) - }; - collation.proof_of_validity = compressed; - collation - } + fn test_collation_compressed() -> Collation { + let mut collation = test_collation(); + let compressed = PoV { + block_data: BlockData(sp_maybe_compressed_blob::compress( + &collation.proof_of_validity.block_data.0, + POV_BOMB_LIMIT, + ).unwrap()) + }; + collation.proof_of_validity = compressed; + collation + } - fn test_validation_data() -> PersistedValidationData { - let mut persisted_validation_data: PersistedValidationData = Default::default(); - persisted_validation_data.max_pov_size = 1024; - persisted_validation_data - } + fn test_validation_data() -> PersistedValidationData { + let mut persisted_validation_data: PersistedValidationData = Default::default(); + persisted_validation_data.max_pov_size = 1024; + persisted_validation_data + } - // Box + Unpin + Send - struct TestCollator; + // Box + Unpin + Send + struct TestCollator; - impl Future for TestCollator { - type Output = Option; + impl Future for TestCollator { + type Output = Option; - fn poll(self: Pin<&mut Self>, _cx: &mut FuturesContext) -> Poll { - Poll::Ready(Some(CollationResult { collation: test_collation(), result_sender: None })) - } - } + fn poll(self: Pin<&mut Self>, _cx: &mut FuturesContext) -> Poll { + Poll::Ready(Some(CollationResult { collation: test_collation(), result_sender: None })) + } + } - impl Unpin for TestCollator {} + impl Unpin for TestCollator {} - fn test_config>(para_id: Id) -> Arc { - Arc::new(CollationGenerationConfig { - key: CollatorPair::generate().0, - collator: Box::new(|_: Hash, _vd: &PersistedValidationData| { - TestCollator.boxed() - }), - para_id: para_id.into(), - }) - } + fn test_config>(para_id: Id) -> Arc { + Arc::new(CollationGenerationConfig { + key: CollatorPair::generate().0, + collator: Box::new(|_: Hash, _vd: &PersistedValidationData| { + TestCollator.boxed() + }), + para_id: para_id.into(), + }) + } - fn scheduled_core_for>(para_id: Id) -> ScheduledCore { - ScheduledCore { - para_id: para_id.into(), - collator: None, - } - } + fn scheduled_core_for>(para_id: Id) -> ScheduledCore { + ScheduledCore { + para_id: para_id.into(), + collator: None, + } + } - #[test] - fn requests_availability_per_relay_parent() { - let activated_hashes: Vec = vec![ - [1; 32].into(), - [4; 32].into(), - [9; 32].into(), - [16; 32].into(), - ]; + #[test] + fn requests_availability_per_relay_parent() { + let activated_hashes: Vec = vec![ + [1; 32].into(), + [4; 32].into(), + [9; 32].into(), + [16; 32].into(), + ]; - let requested_availability_cores = Arc::new(Mutex::new(Vec::new())); + let requested_availability_cores = Arc::new(Mutex::new(Vec::new())); - let overseer_requested_availability_cores = requested_availability_cores.clone(); - let overseer = |mut handle: TestSubsystemContextHandle| async move { - loop { - match handle.try_recv().await { - None => break, - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request(hash, RuntimeApiRequest::AvailabilityCores(tx)))) => { - overseer_requested_availability_cores.lock().await.push(hash); - tx.send(Ok(vec![])).unwrap(); - } - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request(_hash, RuntimeApiRequest::Validators(tx)))) => { - tx.send(Ok(vec![Default::default(); 3])).unwrap(); - } - Some(msg) => panic!("didn't expect any other overseer requests given no availability cores; got {:?}", msg), - } - } - }; + let overseer_requested_availability_cores = requested_availability_cores.clone(); + let overseer = |mut handle: TestSubsystemContextHandle| async move { + loop { + match handle.try_recv().await { + None => break, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request(hash, RuntimeApiRequest::AvailabilityCores(tx)))) => { + overseer_requested_availability_cores.lock().await.push(hash); + tx.send(Ok(vec![])).unwrap(); + } + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request(_hash, RuntimeApiRequest::Validators(tx)))) => { + tx.send(Ok(vec![Default::default(); 3])).unwrap(); + } + Some(msg) => panic!("didn't expect any other overseer requests given no availability cores; got {:?}", msg), + } + } + }; - let (tx, _rx) = mpsc::channel(0); + let (tx, _rx) = mpsc::channel(0); - let subsystem_activated_hashes = activated_hashes.clone(); - subsystem_test_harness(overseer, |mut ctx| async move { - handle_new_activations( - test_config(123u32), - subsystem_activated_hashes, - &mut ctx, - Metrics(None), - &tx, - ) - .await - .unwrap(); - }); + let subsystem_activated_hashes = activated_hashes.clone(); + subsystem_test_harness(overseer, |mut ctx| async move { + handle_new_activations( + test_config(123u32), + subsystem_activated_hashes, + &mut ctx, + Metrics(None), + &tx, + ) + .await + .unwrap(); + }); - let mut requested_availability_cores = Arc::try_unwrap(requested_availability_cores) - .expect("overseer should have shut down by now") - .into_inner(); - requested_availability_cores.sort(); + let mut requested_availability_cores = Arc::try_unwrap(requested_availability_cores) + .expect("overseer should have shut down by now") + .into_inner(); + requested_availability_cores.sort(); - assert_eq!(requested_availability_cores, activated_hashes); - } + assert_eq!(requested_availability_cores, activated_hashes); + } - #[test] - fn requests_validation_data_for_scheduled_matches() { - let activated_hashes: Vec = vec![ - Hash::repeat_byte(1), - Hash::repeat_byte(4), - Hash::repeat_byte(9), - Hash::repeat_byte(16), - ]; + #[test] + fn requests_validation_data_for_scheduled_matches() { + let activated_hashes: Vec = vec![ + Hash::repeat_byte(1), + Hash::repeat_byte(4), + Hash::repeat_byte(9), + Hash::repeat_byte(16), + ]; - let requested_validation_data = Arc::new(Mutex::new(Vec::new())); + let requested_validation_data = Arc::new(Mutex::new(Vec::new())); - let overseer_requested_validation_data = requested_validation_data.clone(); - let overseer = |mut handle: TestSubsystemContextHandle| async move { - loop { - match handle.try_recv().await { - None => break, - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - hash, - RuntimeApiRequest::AvailabilityCores(tx), - ))) => { - tx.send(Ok(vec![ - CoreState::Free, - // this is weird, see explanation below - CoreState::Scheduled(scheduled_core_for( - (hash.as_fixed_bytes()[0] * 4) as u32, - )), - CoreState::Scheduled(scheduled_core_for( - (hash.as_fixed_bytes()[0] * 5) as u32, - )), - ])) - .unwrap(); - } - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - hash, - RuntimeApiRequest::PersistedValidationData( - _para_id, - _occupied_core_assumption, - tx, - ), - ))) => { - overseer_requested_validation_data - .lock() - .await - .push(hash); - tx.send(Ok(Default::default())).unwrap(); - } - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _hash, - RuntimeApiRequest::Validators(tx), - ))) => { - tx.send(Ok(vec![Default::default(); 3])).unwrap(); - } - Some(msg) => { - panic!("didn't expect any other overseer requests; got {:?}", msg) - } - } - } - }; + let overseer_requested_validation_data = requested_validation_data.clone(); + let overseer = |mut handle: TestSubsystemContextHandle| async move { + loop { + match handle.try_recv().await { + None => break, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::AvailabilityCores(tx), + ))) => { + tx.send(Ok(vec![ + CoreState::Free, + // this is weird, see explanation below + CoreState::Scheduled(scheduled_core_for( + (hash.as_fixed_bytes()[0] * 4) as u32, + )), + CoreState::Scheduled(scheduled_core_for( + (hash.as_fixed_bytes()[0] * 5) as u32, + )), + ])) + .unwrap(); + } + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::PersistedValidationData( + _para_id, + _occupied_core_assumption, + tx, + ), + ))) => { + overseer_requested_validation_data + .lock() + .await + .push(hash); + tx.send(Ok(Default::default())).unwrap(); + } + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::Validators(tx), + ))) => { + tx.send(Ok(vec![Default::default(); 3])).unwrap(); + } + Some(msg) => { + panic!("didn't expect any other overseer requests; got {:?}", msg) + } + } + } + }; - let (tx, _rx) = mpsc::channel(0); + let (tx, _rx) = mpsc::channel(0); - subsystem_test_harness(overseer, |mut ctx| async move { - handle_new_activations(test_config(16), activated_hashes, &mut ctx, Metrics(None), &tx) - .await - .unwrap(); - }); + subsystem_test_harness(overseer, |mut ctx| async move { + handle_new_activations(test_config(16), activated_hashes, &mut ctx, Metrics(None), &tx) + .await + .unwrap(); + }); - let requested_validation_data = Arc::try_unwrap(requested_validation_data) - .expect("overseer should have shut down by now") - .into_inner(); + let requested_validation_data = Arc::try_unwrap(requested_validation_data) + .expect("overseer should have shut down by now") + .into_inner(); - // the only activated hash should be from the 4 hash: - // each activated hash generates two scheduled cores: one with its value * 4, one with its value * 5 - // given that the test configuration has a para_id of 16, there's only one way to get that value: with the 4 - // hash. - assert_eq!(requested_validation_data, vec![[4; 32].into()]); - } + // the only activated hash should be from the 4 hash: + // each activated hash generates two scheduled cores: one with its value * 4, one with its value * 5 + // given that the test configuration has a para_id of 16, there's only one way to get that value: with the 4 + // hash. + assert_eq!(requested_validation_data, vec![[4; 32].into()]); + } - #[test] - fn sends_distribute_collation_message() { - let activated_hashes: Vec = vec![ - Hash::repeat_byte(1), - Hash::repeat_byte(4), - Hash::repeat_byte(9), - Hash::repeat_byte(16), - ]; + #[test] + fn sends_distribute_collation_message() { + let activated_hashes: Vec = vec![ + Hash::repeat_byte(1), + Hash::repeat_byte(4), + Hash::repeat_byte(9), + Hash::repeat_byte(16), + ]; - let overseer = |mut handle: TestSubsystemContextHandle| async move { - loop { - match handle.try_recv().await { - None => break, - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - hash, - RuntimeApiRequest::AvailabilityCores(tx), - ))) => { - tx.send(Ok(vec![ - CoreState::Free, - // this is weird, see explanation below - CoreState::Scheduled(scheduled_core_for( - (hash.as_fixed_bytes()[0] * 4) as u32, - )), - CoreState::Scheduled(scheduled_core_for( - (hash.as_fixed_bytes()[0] * 5) as u32, - )), - ])) - .unwrap(); - } - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _hash, - RuntimeApiRequest::PersistedValidationData( - _para_id, - _occupied_core_assumption, - tx, - ), - ))) => { - tx.send(Ok(Some(test_validation_data()))).unwrap(); - } - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _hash, - RuntimeApiRequest::Validators(tx), - ))) => { - tx.send(Ok(vec![Default::default(); 3])).unwrap(); - } - Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _hash, - RuntimeApiRequest::ValidationCode( - _para_id, - OccupiedCoreAssumption::Free, - tx, - ), - ))) => { - tx.send(Ok(Some(ValidationCode(vec![1, 2, 3])))).unwrap(); - } - Some(msg) => { - panic!("didn't expect any other overseer requests; got {:?}", msg) - } - } - } - }; + let overseer = |mut handle: TestSubsystemContextHandle| async move { + loop { + match handle.try_recv().await { + None => break, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::AvailabilityCores(tx), + ))) => { + tx.send(Ok(vec![ + CoreState::Free, + // this is weird, see explanation below + CoreState::Scheduled(scheduled_core_for( + (hash.as_fixed_bytes()[0] * 4) as u32, + )), + CoreState::Scheduled(scheduled_core_for( + (hash.as_fixed_bytes()[0] * 5) as u32, + )), + ])) + .unwrap(); + } + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::PersistedValidationData( + _para_id, + _occupied_core_assumption, + tx, + ), + ))) => { + tx.send(Ok(Some(test_validation_data()))).unwrap(); + } + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::Validators(tx), + ))) => { + tx.send(Ok(vec![Default::default(); 3])).unwrap(); + } + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::ValidationCode( + _para_id, + OccupiedCoreAssumption::Free, + tx, + ), + ))) => { + tx.send(Ok(Some(ValidationCode(vec![1, 2, 3])))).unwrap(); + } + Some(msg) => { + panic!("didn't expect any other overseer requests; got {:?}", msg) + } + } + } + }; - let config = test_config(16); - let subsystem_config = config.clone(); + let config = test_config(16); + let subsystem_config = config.clone(); - let (tx, rx) = mpsc::channel(0); + let (tx, rx) = mpsc::channel(0); - // empty vec doesn't allocate on the heap, so it's ok we throw it away - let sent_messages = Arc::new(Mutex::new(Vec::new())); - let subsystem_sent_messages = sent_messages.clone(); - subsystem_test_harness(overseer, |mut ctx| async move { - handle_new_activations(subsystem_config, activated_hashes, &mut ctx, Metrics(None), &tx) - .await - .unwrap(); + // empty vec doesn't allocate on the heap, so it's ok we throw it away + let sent_messages = Arc::new(Mutex::new(Vec::new())); + let subsystem_sent_messages = sent_messages.clone(); + subsystem_test_harness(overseer, |mut ctx| async move { + handle_new_activations(subsystem_config, activated_hashes, &mut ctx, Metrics(None), &tx) + .await + .unwrap(); - std::mem::drop(tx); + std::mem::drop(tx); - // collect all sent messages - *subsystem_sent_messages.lock().await = rx.collect().await; - }); + // collect all sent messages + *subsystem_sent_messages.lock().await = rx.collect().await; + }); - let sent_messages = Arc::try_unwrap(sent_messages) - .expect("subsystem should have shut down by now") - .into_inner(); + let sent_messages = Arc::try_unwrap(sent_messages) + .expect("subsystem should have shut down by now") + .into_inner(); - // we expect a single message to be sent, containing a candidate receipt. - // we don't care too much about the commitments_hash right now, but let's ensure that we've calculated the - // correct descriptor - let expect_pov_hash = test_collation_compressed().proof_of_validity.hash(); - let expect_validation_data_hash = test_validation_data().hash(); - let expect_relay_parent = Hash::repeat_byte(4); - let expect_validation_code_hash = ValidationCode(vec![1, 2, 3]).hash(); - let expect_payload = collator_signature_payload( - &expect_relay_parent, - &config.para_id, - &expect_validation_data_hash, - &expect_pov_hash, - &expect_validation_code_hash, - ); - let expect_descriptor = CandidateDescriptor { - signature: config.key.sign(&expect_payload), - para_id: config.para_id, - relay_parent: expect_relay_parent, - collator: config.key.public(), - persisted_validation_data_hash: expect_validation_data_hash, - pov_hash: expect_pov_hash, - erasure_root: Default::default(), // this isn't something we're checking right now - para_head: test_collation().head_data.hash(), - validation_code_hash: expect_validation_code_hash, - }; + // we expect a single message to be sent, containing a candidate receipt. + // we don't care too much about the commitments_hash right now, but let's ensure that we've calculated the + // correct descriptor + let expect_pov_hash = test_collation_compressed().proof_of_validity.hash(); + let expect_validation_data_hash = test_validation_data().hash(); + let expect_relay_parent = Hash::repeat_byte(4); + let expect_validation_code_hash = ValidationCode(vec![1, 2, 3]).hash(); + let expect_payload = collator_signature_payload( + &expect_relay_parent, + &config.para_id, + &expect_validation_data_hash, + &expect_pov_hash, + &expect_validation_code_hash, + ); + let expect_descriptor = CandidateDescriptor { + signature: config.key.sign(&expect_payload), + para_id: config.para_id, + relay_parent: expect_relay_parent, + collator: config.key.public(), + persisted_validation_data_hash: expect_validation_data_hash, + pov_hash: expect_pov_hash, + erasure_root: Default::default(), // this isn't something we're checking right now + para_head: test_collation().head_data.hash(), + validation_code_hash: expect_validation_code_hash, + }; - assert_eq!(sent_messages.len(), 1); - match &sent_messages[0] { - AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation( - CandidateReceipt { descriptor, .. }, - _pov, - .. - )) => { - // signature generation is non-deterministic, so we can't just assert that the - // expected descriptor is correct. What we can do is validate that the produced - // descriptor has a valid signature, then just copy in the generated signature - // and check the rest of the fields for equality. - assert!(CollatorPair::verify( - &descriptor.signature, - &collator_signature_payload( - &descriptor.relay_parent, - &descriptor.para_id, - &descriptor.persisted_validation_data_hash, - &descriptor.pov_hash, - &descriptor.validation_code_hash, - ) - .as_ref(), - &descriptor.collator, - )); - let expect_descriptor = { - let mut expect_descriptor = expect_descriptor; - expect_descriptor.signature = descriptor.signature.clone(); - expect_descriptor.erasure_root = descriptor.erasure_root.clone(); - expect_descriptor - }; - assert_eq!(descriptor, &expect_descriptor); - } - _ => panic!("received wrong message type"), - } - } + assert_eq!(sent_messages.len(), 1); + match &sent_messages[0] { + AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation( + CandidateReceipt { descriptor, .. }, + _pov, + .. + )) => { + // signature generation is non-deterministic, so we can't just assert that the + // expected descriptor is correct. What we can do is validate that the produced + // descriptor has a valid signature, then just copy in the generated signature + // and check the rest of the fields for equality. + assert!(CollatorPair::verify( + &descriptor.signature, + &collator_signature_payload( + &descriptor.relay_parent, + &descriptor.para_id, + &descriptor.persisted_validation_data_hash, + &descriptor.pov_hash, + &descriptor.validation_code_hash, + ) + .as_ref(), + &descriptor.collator, + )); + let expect_descriptor = { + let mut expect_descriptor = expect_descriptor; + expect_descriptor.signature = descriptor.signature.clone(); + expect_descriptor.erasure_root = descriptor.erasure_root.clone(); + expect_descriptor + }; + assert_eq!(descriptor, &expect_descriptor); + } + _ => panic!("received wrong message type"), + } + } } diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index dd13621597..7a730aa8cf 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -43,6 +43,9 @@ use std::{pin::Pin, collections::BTreeMap, sync::Arc}; use thiserror::Error; use futures_timer::Delay; +#[cfg(test)] +mod tests; + /// How long to wait before proposing. const PRE_PROPOSE_TIMEOUT: std::time::Duration = core::time::Duration::from_millis(2000); @@ -599,6 +602,3 @@ impl metrics::Metrics for Metrics { /// The provisioning subsystem. pub type ProvisioningSubsystem = JobSubsystem; - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/core/runtime-api/src/lib.rs b/polkadot/node/core/runtime-api/src/lib.rs index 31d0471fe3..839cbfa393 100644 --- a/polkadot/node/core/runtime-api/src/lib.rs +++ b/polkadot/node/core/runtime-api/src/lib.rs @@ -44,6 +44,9 @@ use cache::{RequestResult, RequestResultCache}; mod cache; +#[cfg(test)] +mod tests; + const LOG_TARGET: &str = "parachain::runtime-api"; /// The number of maximum runtime api requests can be executed in parallel. Further requests will be buffered. @@ -411,6 +414,3 @@ impl metrics::Metrics for Metrics { Ok(Metrics(Some(metrics))) } } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/network/approval-distribution/src/lib.rs b/polkadot/node/network/approval-distribution/src/lib.rs index 6492caa2b1..04cc835e21 100644 --- a/polkadot/node/network/approval-distribution/src/lib.rs +++ b/polkadot/node/network/approval-distribution/src/lib.rs @@ -20,10 +20,6 @@ #![warn(missing_docs)] -#[cfg(test)] -mod tests; - - use std::collections::{BTreeMap, HashMap, HashSet, hash_map}; use futures::{channel::oneshot, FutureExt as _}; use polkadot_primitives::v1::{ @@ -47,6 +43,9 @@ use polkadot_node_network_protocol::{ PeerId, View, v1 as protocol_v1, UnifiedReputationChange as Rep, }; +#[cfg(test)] +mod tests; + const LOG_TARGET: &str = "parachain::approval-distribution"; const COST_UNEXPECTED_MESSAGE: Rep = Rep::CostMinor("Peer sent an out-of-view assignment or approval"); diff --git a/polkadot/node/network/availability-recovery/src/lib.rs b/polkadot/node/network/availability-recovery/src/lib.rs index 4a4efc66bf..711c191c81 100644 --- a/polkadot/node/network/availability-recovery/src/lib.rs +++ b/polkadot/node/network/availability-recovery/src/lib.rs @@ -51,6 +51,7 @@ use polkadot_node_network_protocol::{ }; use polkadot_node_subsystem_util::request_session_info; use polkadot_erasure_coding::{branches, branch_hash, recovery_threshold, obtain_chunks_v1}; + mod error; #[cfg(test)] diff --git a/polkadot/node/network/bridge/src/lib.rs b/polkadot/node/network/bridge/src/lib.rs index 8618d06d14..8635dbe501 100644 --- a/polkadot/node/network/bridge/src/lib.rs +++ b/polkadot/node/network/bridge/src/lib.rs @@ -64,6 +64,8 @@ use network::{Network, send_message}; mod multiplexer; pub use multiplexer::RequestMultiplexer; +#[cfg(test)] +mod tests; /// The maximum amount of heads a peer is allowed to have in their view at any time. /// @@ -1131,9 +1133,3 @@ async fn dispatch_collation_events_to_all( ctx.send_messages(events.into_iter().flat_map(messages_for)).await } - - - - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/network/bridge/src/tests.rs b/polkadot/node/network/bridge/src/tests.rs index 4fceeb212c..74ca4501e1 100644 --- a/polkadot/node/network/bridge/src/tests.rs +++ b/polkadot/node/network/bridge/src/tests.rs @@ -31,12 +31,12 @@ use sc_network::{Event as NetworkEvent, IfDisconnected}; use polkadot_subsystem::{jaeger, ActiveLeavesUpdate, FromOverseer, OverseerSignal, LeafStatus}; use polkadot_subsystem::messages::{ - ApprovalDistributionMessage, - BitfieldDistributionMessage, - StatementDistributionMessage + ApprovalDistributionMessage, + BitfieldDistributionMessage, + StatementDistributionMessage }; use polkadot_node_subsystem_test_helpers::{ - SingleItemSink, SingleItemStream, TestSubsystemContextHandle, + SingleItemSink, SingleItemStream, TestSubsystemContextHandle, }; use polkadot_node_subsystem_util::metered; use polkadot_node_network_protocol::view; @@ -52,9 +52,9 @@ use crate::validator_discovery::AuthorityDiscovery; // The subsystem's view of the network - only supports a single call to `event_stream`. #[derive(Clone)] struct TestNetwork { - net_events: Arc>>>, - action_tx: metered::UnboundedMeteredSender, - _req_configs: Vec, + net_events: Arc>>>, + action_tx: metered::UnboundedMeteredSender, + _req_configs: Vec, } #[derive(Clone)] @@ -63,1253 +63,1253 @@ struct TestAuthorityDiscovery; // The test's view of the network. This receives updates from the subsystem in the form // of `NetworkAction`s. struct TestNetworkHandle { - action_rx: metered::UnboundedMeteredReceiver, - net_tx: SingleItemSink, + action_rx: metered::UnboundedMeteredReceiver, + net_tx: SingleItemSink, } fn new_test_network(req_configs: Vec) -> ( - TestNetwork, - TestNetworkHandle, - TestAuthorityDiscovery, + TestNetwork, + TestNetworkHandle, + TestAuthorityDiscovery, ) { - let (net_tx, net_rx) = polkadot_node_subsystem_test_helpers::single_item_sink(); - let (action_tx, action_rx) = metered::unbounded(); + 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))), - action_tx, - _req_configs: req_configs, - }, - TestNetworkHandle { - action_rx, - net_tx, - }, - TestAuthorityDiscovery, - ) + ( + TestNetwork { + net_events: Arc::new(Mutex::new(Some(net_rx))), + action_tx, + _req_configs: req_configs, + }, + TestNetworkHandle { + action_rx, + net_tx, + }, + TestAuthorityDiscovery, + ) } #[async_trait] impl Network for TestNetwork { - fn event_stream(&mut self) -> BoxStream<'static, NetworkEvent> { - self.net_events.lock() - .take() - .expect("Subsystem made more than one call to `event_stream`") - .boxed() - } + fn event_stream(&mut self) -> BoxStream<'static, NetworkEvent> { + self.net_events.lock() + .take() + .expect("Subsystem made more than one call to `event_stream`") + .boxed() + } - async fn add_to_peers_set(&mut self, _protocol: Cow<'static, str>, _: HashSet) -> Result<(), String> { - Ok(()) - } + async fn add_to_peers_set(&mut self, _protocol: Cow<'static, str>, _: HashSet) -> Result<(), String> { + Ok(()) + } - async fn remove_from_peers_set(&mut self, _protocol: Cow<'static, str>, _: HashSet) -> Result<(), String> { - Ok(()) - } + async fn remove_from_peers_set(&mut self, _protocol: Cow<'static, str>, _: HashSet) -> Result<(), String> { + Ok(()) + } - fn action_sink<'a>(&'a mut self) - -> Pin + Send + 'a>> - { - Box::pin((&mut self.action_tx).sink_map_err(Into::into)) - } + fn action_sink<'a>(&'a mut self) + -> Pin + Send + 'a>> + { + Box::pin((&mut self.action_tx).sink_map_err(Into::into)) + } - async fn start_request(&self, _: &mut AD, _: Requests, _: IfDisconnected) { - } + async fn start_request(&self, _: &mut AD, _: Requests, _: IfDisconnected) { + } } #[async_trait] impl validator_discovery::AuthorityDiscovery for TestAuthorityDiscovery { - async fn get_addresses_by_authority_id(&mut self, _authority: AuthorityDiscoveryId) -> Option> { - None - } + async fn get_addresses_by_authority_id(&mut self, _authority: AuthorityDiscoveryId) -> Option> { + None + } - async fn get_authority_id_by_peer_id(&mut self, _peer_id: PeerId) -> Option { - None - } + async fn get_authority_id_by_peer_id(&mut self, _peer_id: PeerId) -> Option { + None + } } impl TestNetworkHandle { - // Get the next network action. - async fn next_network_action(&mut self) -> NetworkAction { - self.action_rx.next().await.expect("subsystem concluded early") - } + // 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 { - let mut v = Vec::with_capacity(n); - for _ in 0..n { - v.push(self.next_network_action().await); - } + // Wait for the next N network actions. + async fn next_network_actions(&mut self, n: usize) -> Vec { + let mut v = Vec::with_capacity(n); + for _ in 0..n { + v.push(self.next_network_action().await); + } - v - } + 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(), - }).await; - } + 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(), + }).await; + } - 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(), - }).await; - } + 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(), + }).await; + } - async fn peer_message(&mut self, peer: PeerId, peer_set: PeerSet, message: Vec) { - self.send_network_event(NetworkEvent::NotificationsReceived { - remote: peer, - messages: vec![(peer_set.into_protocol_name(), message.into())], - }).await; - } + async fn peer_message(&mut self, peer: PeerId, peer_set: PeerSet, message: Vec) { + self.send_network_event(NetworkEvent::NotificationsReceived { + remote: peer, + messages: vec![(peer_set.into_protocol_name(), message.into())], + }).await; + } - async fn send_network_event(&mut self, event: NetworkEvent) { - self.net_tx.send(event).await.expect("subsystem concluded early"); - } + async fn send_network_event(&mut self, event: NetworkEvent) { + self.net_tx.send(event).await.expect("subsystem concluded early"); + } } /// Assert that the given actions contain the given `action`. fn assert_network_actions_contains(actions: &[NetworkAction], action: &NetworkAction) { - if !actions.iter().any(|x| x == action) { - panic!("Could not find `{:?}` in `{:?}`", action, actions); - } + if !actions.iter().any(|x| x == action) { + panic!("Could not find `{:?}` in `{:?}`", action, actions); + } } #[derive(Clone)] struct TestSyncOracle { - flag: Arc, - done_syncing_sender: Arc>>>, + flag: Arc, + done_syncing_sender: Arc>>>, } struct TestSyncOracleHandle { - done_syncing_receiver: oneshot::Receiver<()>, - flag: Arc, + done_syncing_receiver: oneshot::Receiver<()>, + flag: Arc, } impl TestSyncOracleHandle { - fn set_done(&self) { - self.flag.store(false, Ordering::SeqCst); - } + fn set_done(&self) { + self.flag.store(false, Ordering::SeqCst); + } - async fn await_mode_switch(self) { - let _ = self.done_syncing_receiver.await; - } + async fn await_mode_switch(self) { + let _ = self.done_syncing_receiver.await; + } } impl SyncOracle for TestSyncOracle { - fn is_major_syncing(&mut self) -> bool { - let is_major_syncing = self.flag.load(Ordering::SeqCst); + fn is_major_syncing(&mut self) -> bool { + let is_major_syncing = self.flag.load(Ordering::SeqCst); - if !is_major_syncing { - if let Some(sender) = self.done_syncing_sender.lock().take() { - let _ = sender.send(()); - } - } + if !is_major_syncing { + if let Some(sender) = self.done_syncing_sender.lock().take() { + let _ = sender.send(()); + } + } - is_major_syncing - } + is_major_syncing + } - fn is_offline(&mut self) -> bool { - unimplemented!("not used in network bridge") - } + fn is_offline(&mut self) -> bool { + unimplemented!("not used in network bridge") + } } // val - result of `is_major_syncing`. fn make_sync_oracle(val: bool) -> (TestSyncOracle, TestSyncOracleHandle) { - let (tx, rx) = oneshot::channel(); - let flag = Arc::new(AtomicBool::new(val)); + let (tx, rx) = oneshot::channel(); + let flag = Arc::new(AtomicBool::new(val)); - ( - TestSyncOracle { - flag: flag.clone(), - done_syncing_sender: Arc::new(Mutex::new(Some(tx))), - }, - TestSyncOracleHandle { - flag, - done_syncing_receiver: rx, - } - ) + ( + TestSyncOracle { + flag: flag.clone(), + done_syncing_sender: Arc::new(Mutex::new(Some(tx))), + }, + TestSyncOracleHandle { + flag, + done_syncing_receiver: rx, + } + ) } fn done_syncing_oracle() -> Box { - let (oracle, _) = make_sync_oracle(false); - Box::new(oracle) + let (oracle, _) = make_sync_oracle(false); + Box::new(oracle) } type VirtualOverseer = TestSubsystemContextHandle; struct TestHarness { - network_handle: TestNetworkHandle, - virtual_overseer: VirtualOverseer, + network_handle: TestNetworkHandle, + virtual_overseer: VirtualOverseer, } fn test_harness>( - sync_oracle: Box, - test: impl FnOnce(TestHarness) -> T, + sync_oracle: Box, + test: impl FnOnce(TestHarness) -> T, ) { - let pool = sp_core::testing::TaskExecutor::new(); - let (request_multiplexer, req_configs) = RequestMultiplexer::new(); - let (mut network, network_handle, discovery) = new_test_network(req_configs); - let (context, virtual_overseer) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - let network_stream = network.event_stream(); + let pool = sp_core::testing::TaskExecutor::new(); + let (request_multiplexer, req_configs) = RequestMultiplexer::new(); + let (mut network, network_handle, discovery) = new_test_network(req_configs); + let (context, virtual_overseer) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); + let network_stream = network.event_stream(); - let bridge = NetworkBridge { - network_service: network, - authority_discovery_service: discovery, - request_multiplexer, - metrics: Metrics(None), - sync_oracle, - }; + let bridge = NetworkBridge { + network_service: network, + authority_discovery_service: discovery, + request_multiplexer, + metrics: Metrics(None), + sync_oracle, + }; - let network_bridge = run_network( - bridge, - context, - network_stream, - ) - .map_err(|_| panic!("subsystem execution failed")) - .map(|_| ()); + let network_bridge = run_network( + bridge, + context, + network_stream, + ) + .map_err(|_| panic!("subsystem execution failed")) + .map(|_| ()); - let test_fut = test(TestHarness { - network_handle, - virtual_overseer, - }); + let test_fut = test(TestHarness { + network_handle, + virtual_overseer, + }); - futures::pin_mut!(test_fut); - futures::pin_mut!(network_bridge); + futures::pin_mut!(test_fut); + futures::pin_mut!(network_bridge); - 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)); + 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)); } async fn assert_sends_validation_event_to_all( - event: NetworkBridgeEvent, - virtual_overseer: &mut TestSubsystemContextHandle, + event: NetworkBridgeEvent, + virtual_overseer: &mut TestSubsystemContextHandle, ) { - // 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") - ); + // 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::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") - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::ApprovalDistribution( + ApprovalDistributionMessage::NetworkBridgeUpdateV1(e) + ) if e == event.focus().expect("could not focus message") + ); } async fn assert_sends_collation_event_to_all( - event: NetworkBridgeEvent, - virtual_overseer: &mut TestSubsystemContextHandle, + event: NetworkBridgeEvent, + virtual_overseer: &mut TestSubsystemContextHandle, ) { - assert_matches!( - virtual_overseer.recv().await, - AllMessages::CollatorProtocol( - CollatorProtocolMessage::NetworkBridgeUpdateV1(e) - ) if e == event.focus().expect("could not focus message") - ) + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CollatorProtocol( + CollatorProtocolMessage::NetworkBridgeUpdateV1(e) + ) if e == event.focus().expect("could not focus message") + ) } #[test] fn send_our_view_upon_connection() { - 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 (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 = PeerId::random(); + let peer = PeerId::random(); - let head = Hash::repeat_byte(1); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: head, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + let head = Hash::repeat_byte(1); + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: head, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - handle.await_mode_switch().await; + handle.await_mode_switch().await; - network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; - network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; - let view = view![head]; - let actions = network_handle.next_network_actions(2).await; - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer.clone(), - PeerSet::Validation, - WireMessage::::ViewUpdate( - view.clone(), - ).encode(), - ), - ); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer.clone(), - PeerSet::Collation, - WireMessage::::ViewUpdate( - view.clone(), - ).encode(), - ), - ); - virtual_overseer - }); + let view = view![head]; + let actions = network_handle.next_network_actions(2).await; + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer.clone(), + PeerSet::Validation, + WireMessage::::ViewUpdate( + view.clone(), + ).encode(), + ), + ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer.clone(), + PeerSet::Collation, + WireMessage::::ViewUpdate( + view.clone(), + ).encode(), + ), + ); + virtual_overseer + }); } #[test] fn sends_view_updates_to_peers() { - 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 (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(); + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate { - activated: Default::default(), - deactivated: Default::default(), - } - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate { + activated: Default::default(), + deactivated: Default::default(), + } + )) + ).await; - handle.await_mode_switch().await; + handle.await_mode_switch().await; - network_handle.connect_peer( - peer_a.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; - network_handle.connect_peer( - peer_b.clone(), - PeerSet::Collation, - ObservedRole::Full, - ).await; + network_handle.connect_peer( + peer_a.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; + network_handle.connect_peer( + peer_b.clone(), + PeerSet::Collation, + ObservedRole::Full, + ).await; - let actions = network_handle.next_network_actions(2).await; - let wire_message = WireMessage::::ViewUpdate( - View::default(), - ).encode(); + let actions = network_handle.next_network_actions(2).await; + let wire_message = WireMessage::::ViewUpdate( + View::default(), + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_a, - PeerSet::Validation, - wire_message.clone(), - ), - ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_a, + PeerSet::Validation, + wire_message.clone(), + ), + ); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_b, - PeerSet::Collation, - wire_message.clone(), - ), - ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_b, + PeerSet::Collation, + wire_message.clone(), + ), + ); - let hash_a = Hash::repeat_byte(1); + let hash_a = Hash::repeat_byte(1); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - let actions = network_handle.next_network_actions(2).await; - let wire_message = WireMessage::::ViewUpdate( - view![hash_a] - ).encode(); + let actions = network_handle.next_network_actions(2).await; + let wire_message = WireMessage::::ViewUpdate( + view![hash_a] + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_a, - PeerSet::Validation, - wire_message.clone(), - ), - ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_a, + PeerSet::Validation, + wire_message.clone(), + ), + ); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_b, - PeerSet::Collation, - wire_message.clone(), - ), - ); - virtual_overseer - }); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_b, + PeerSet::Collation, + wire_message.clone(), + ), + ); + virtual_overseer + }); } #[test] fn do_not_send_view_update_until_synced() { - 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 (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(); + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); - network_handle.connect_peer( - peer_a.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; - network_handle.connect_peer( - peer_b.clone(), - PeerSet::Collation, - ObservedRole::Full, - ).await; + network_handle.connect_peer( + peer_a.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; + network_handle.connect_peer( + peer_b.clone(), + PeerSet::Collation, + ObservedRole::Full, + ).await; - { - let actions = network_handle.next_network_actions(2).await; - let wire_message = WireMessage::::ViewUpdate( - View::default(), - ).encode(); + { + let actions = network_handle.next_network_actions(2).await; + let wire_message = WireMessage::::ViewUpdate( + View::default(), + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_a, - PeerSet::Validation, - wire_message.clone(), - ), - ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_a, + PeerSet::Validation, + wire_message.clone(), + ), + ); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_b, - PeerSet::Collation, - wire_message.clone(), - ), - ); - } + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_b, + PeerSet::Collation, + wire_message.clone(), + ), + ); + } - let hash_a = Hash::repeat_byte(1); - let hash_b = Hash::repeat_byte(1); + let hash_a = Hash::repeat_byte(1); + let hash_b = Hash::repeat_byte(1); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - // delay until the previous update has certainly been processed. - futures_timer::Delay::new(std::time::Duration::from_millis(100)).await; + // delay until the previous update has certainly been processed. + futures_timer::Delay::new(std::time::Duration::from_millis(100)).await; - handle.set_done(); + handle.set_done(); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_b, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: hash_b, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - handle.await_mode_switch().await; + 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; - let wire_message = WireMessage::::ViewUpdate( - view![hash_a, hash_b] - ).encode(); + // There should be a mode switch only for the second view update. + { + let actions = network_handle.next_network_actions(2).await; + let wire_message = WireMessage::::ViewUpdate( + view![hash_a, hash_b] + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_a, - PeerSet::Validation, - wire_message.clone(), - ), - ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_a, + PeerSet::Validation, + wire_message.clone(), + ), + ); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_b, - PeerSet::Collation, - wire_message.clone(), - ), - ); - } - virtual_overseer - }); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_b, + PeerSet::Collation, + wire_message.clone(), + ), + ); + } + virtual_overseer + }); } #[test] fn do_not_send_view_update_when_only_finalized_block_changed() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { mut network_handle, mut virtual_overseer } = test_harness; + 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(); + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); - network_handle.connect_peer( - peer_a.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; - network_handle.connect_peer( - peer_b.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; + network_handle.connect_peer( + peer_a.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; + network_handle.connect_peer( + peer_b.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; - let hash_a = Hash::repeat_byte(1); + let hash_a = Hash::repeat_byte(1); - virtual_overseer.send(FromOverseer::Signal(OverseerSignal::BlockFinalized(Hash::random(), 5))).await; + virtual_overseer.send(FromOverseer::Signal(OverseerSignal::BlockFinalized(Hash::random(), 5))).await; - // Send some empty active leaves update - // - // This should not trigger a view update to our peers. - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::default())) - ).await; + // Send some empty active leaves update + // + // This should not trigger a view update to our peers. + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::default())) + ).await; - // This should trigger the view update to our peers. - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + // This should trigger the view update to our peers. + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - let actions = network_handle.next_network_actions(4).await; - let wire_message = WireMessage::::ViewUpdate( - View::new(vec![hash_a], 5) - ).encode(); + let actions = network_handle.next_network_actions(4).await; + let wire_message = WireMessage::::ViewUpdate( + View::new(vec![hash_a], 5) + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_a, - PeerSet::Validation, - wire_message.clone(), - ), - ); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_a, + PeerSet::Validation, + wire_message.clone(), + ), + ); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_b, - PeerSet::Validation, - wire_message.clone(), - ), - ); - virtual_overseer - }); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_b, + PeerSet::Validation, + wire_message.clone(), + ), + ); + virtual_overseer + }); } #[test] fn peer_view_updates_sent_via_overseer() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut network_handle, - mut virtual_overseer, - } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { + mut network_handle, + mut virtual_overseer, + } = test_harness; - let peer = PeerId::random(); + let peer = PeerId::random(); - network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; - let view = view![Hash::repeat_byte(1)]; + let view = view![Hash::repeat_byte(1)]; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - // bridge will inform about all connected peers. - { - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + // bridge will inform about all connected peers. + { + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - network_handle.peer_message( - peer.clone(), - PeerSet::Validation, - WireMessage::::ViewUpdate( - view.clone(), - ).encode(), - ).await; + network_handle.peer_message( + peer.clone(), + PeerSet::Validation, + WireMessage::::ViewUpdate( + view.clone(), + ).encode(), + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), view), - &mut virtual_overseer, - ).await; - virtual_overseer - }); + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), view), + &mut virtual_overseer, + ).await; + virtual_overseer + }); } #[test] fn peer_messages_sent_via_overseer() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut network_handle, - mut virtual_overseer, - } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { + mut network_handle, + mut virtual_overseer, + } = test_harness; - let peer = PeerId::random(); + let peer = PeerId::random(); - network_handle.connect_peer( - peer.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; + network_handle.connect_peer( + peer.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - // bridge will inform about all connected peers. - { - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + // bridge will inform about all connected peers. + { + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - let approval_distribution_message = protocol_v1::ApprovalDistributionMessage::Approvals( - Vec::new() - ); + let approval_distribution_message = protocol_v1::ApprovalDistributionMessage::Approvals( + Vec::new() + ); - let message = protocol_v1::ValidationProtocol::ApprovalDistribution( - approval_distribution_message.clone(), - ); + let message = protocol_v1::ValidationProtocol::ApprovalDistribution( + approval_distribution_message.clone(), + ); - network_handle.peer_message( - peer.clone(), - PeerSet::Validation, - WireMessage::ProtocolMessage(message.clone()).encode(), - ).await; + network_handle.peer_message( + peer.clone(), + PeerSet::Validation, + WireMessage::ProtocolMessage(message.clone()).encode(), + ).await; - network_handle.disconnect_peer(peer.clone(), PeerSet::Validation).await; + 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. + // 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_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, - ).await; - virtual_overseer - }); + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerDisconnected(peer), + &mut virtual_overseer, + ).await; + virtual_overseer + }); } #[test] fn peer_disconnect_from_just_one_peerset() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut network_handle, - mut virtual_overseer, - } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { + mut network_handle, + mut virtual_overseer, + } = test_harness; - let peer = PeerId::random(); + let peer = PeerId::random(); - network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; - network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - // bridge will inform about all connected peers. - { - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + // bridge will inform about all connected peers. + { + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - { - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + { + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - network_handle.disconnect_peer(peer.clone(), PeerSet::Validation).await; + network_handle.disconnect_peer(peer.clone(), PeerSet::Validation).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerDisconnected(peer.clone()), - &mut virtual_overseer, - ).await; + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerDisconnected(peer.clone()), + &mut virtual_overseer, + ).await; - // to show that we're still connected on the collation protocol, send a view update. + // to show that we're still connected on the collation protocol, send a view update. - let hash_a = Hash::repeat_byte(1); + let hash_a = Hash::repeat_byte(1); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - let actions = network_handle.next_network_actions(3).await; - let wire_message = WireMessage::::ViewUpdate( - view![hash_a] - ).encode(); + let actions = network_handle.next_network_actions(3).await; + let wire_message = WireMessage::::ViewUpdate( + view![hash_a] + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer.clone(), - PeerSet::Collation, - wire_message.clone(), - ), - ); - virtual_overseer - }); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer.clone(), + PeerSet::Collation, + wire_message.clone(), + ), + ); + virtual_overseer + }); } #[test] fn relays_collation_protocol_messages() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut network_handle, - mut virtual_overseer, - } = test_harness; + 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(); + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - network_handle.connect_peer(peer_a.clone(), PeerSet::Validation, ObservedRole::Full).await; - network_handle.connect_peer(peer_b.clone(), PeerSet::Collation, ObservedRole::Full).await; + network_handle.connect_peer(peer_a.clone(), PeerSet::Validation, ObservedRole::Full).await; + network_handle.connect_peer(peer_b.clone(), PeerSet::Collation, ObservedRole::Full).await; - // bridge will inform about all connected peers. - { - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer_a.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + // bridge will inform about all connected peers. + { + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer_a.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer_a.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer_a.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - { - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer_b.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + { + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer_b.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer_b.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer_b.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - // peer A gets reported for sending a collation message. + // 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(), - ); + let collator_protocol_message = protocol_v1::CollatorProtocolMessage::Declare( + Sr25519Keyring::Alice.public().into(), + Default::default(), + Default::default(), + ); - let message = protocol_v1::CollationProtocol::CollatorProtocol( - collator_protocol_message.clone() - ); + let message = protocol_v1::CollationProtocol::CollatorProtocol( + collator_protocol_message.clone() + ); - network_handle.peer_message( - peer_a.clone(), - PeerSet::Collation, - WireMessage::ProtocolMessage(message.clone()).encode(), - ).await; + network_handle.peer_message( + peer_a.clone(), + PeerSet::Collation, + WireMessage::ProtocolMessage(message.clone()).encode(), + ).await; - let actions = network_handle.next_network_actions(3).await; - assert_network_actions_contains( - &actions, - &NetworkAction::ReputationChange( - peer_a.clone(), - UNCONNECTED_PEERSET_COST, - ), - ); + let actions = network_handle.next_network_actions(3).await; + assert_network_actions_contains( + &actions, + &NetworkAction::ReputationChange( + peer_a.clone(), + UNCONNECTED_PEERSET_COST, + ), + ); - // peer B has the message relayed. + // peer B has the message relayed. - network_handle.peer_message( - peer_b.clone(), - PeerSet::Collation, - WireMessage::ProtocolMessage(message.clone()).encode(), - ).await; + network_handle.peer_message( + peer_b.clone(), + PeerSet::Collation, + WireMessage::ProtocolMessage(message.clone()).encode(), + ).await; - 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 - }); + 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 + }); } #[test] fn different_views_on_different_peer_sets() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut network_handle, - mut virtual_overseer, - } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { + mut network_handle, + mut virtual_overseer, + } = test_harness; - let peer = PeerId::random(); + let peer = PeerId::random(); - network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; - network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - // bridge will inform about all connected peers. - { - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + // bridge will inform about all connected peers. + { + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - { - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + { + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - let view_a = view![Hash::repeat_byte(1)]; - let view_b = view![Hash::repeat_byte(2)]; + let view_a = view![Hash::repeat_byte(1)]; + let view_b = view![Hash::repeat_byte(2)]; - network_handle.peer_message( - peer.clone(), - PeerSet::Validation, - WireMessage::::ViewUpdate(view_a.clone()).encode(), - ).await; + network_handle.peer_message( + peer.clone(), + PeerSet::Validation, + WireMessage::::ViewUpdate(view_a.clone()).encode(), + ).await; - network_handle.peer_message( - peer.clone(), - PeerSet::Collation, - WireMessage::::ViewUpdate(view_b.clone()).encode(), - ).await; + network_handle.peer_message( + peer.clone(), + PeerSet::Collation, + WireMessage::::ViewUpdate(view_b.clone()).encode(), + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), view_a.clone()), - &mut virtual_overseer, - ).await; + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), view_a.clone()), + &mut virtual_overseer, + ).await; - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), view_b.clone()), - &mut virtual_overseer, - ).await; - virtual_overseer - }); + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), view_b.clone()), + &mut virtual_overseer, + ).await; + virtual_overseer + }); } #[test] fn sent_views_include_finalized_number_update() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { mut network_handle, mut virtual_overseer } = test_harness; + 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_a = PeerId::random(); - network_handle.connect_peer( - peer_a.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; + network_handle.connect_peer( + peer_a.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; - let hash_a = Hash::repeat_byte(1); - let hash_b = Hash::repeat_byte(2); + let hash_a = Hash::repeat_byte(1); + let hash_b = Hash::repeat_byte(2); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::BlockFinalized(hash_a, 1)) - ).await; - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: hash_b, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }) - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::BlockFinalized(hash_a, 1)) + ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: hash_b, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }) + )) + ).await; - let actions = network_handle.next_network_actions(2).await; - let wire_message = WireMessage::::ViewUpdate( - View::new(vec![hash_b], 1) - ).encode(); + let actions = network_handle.next_network_actions(2).await; + let wire_message = WireMessage::::ViewUpdate( + View::new(vec![hash_b], 1) + ).encode(); - assert_network_actions_contains( - &actions, - &NetworkAction::WriteNotification( - peer_a.clone(), - PeerSet::Validation, - wire_message.clone(), - ), - ); - virtual_overseer - }); + assert_network_actions_contains( + &actions, + &NetworkAction::WriteNotification( + peer_a.clone(), + PeerSet::Validation, + wire_message.clone(), + ), + ); + virtual_overseer + }); } #[test] fn view_finalized_number_can_not_go_down() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { mut network_handle, virtual_overseer } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { mut network_handle, virtual_overseer } = test_harness; - let peer_a = PeerId::random(); + let peer_a = PeerId::random(); - network_handle.connect_peer( - peer_a.clone(), - PeerSet::Validation, - ObservedRole::Full, - ).await; + network_handle.connect_peer( + peer_a.clone(), + PeerSet::Validation, + ObservedRole::Full, + ).await; - network_handle.peer_message( - peer_a.clone(), - PeerSet::Validation, - WireMessage::::ViewUpdate( - View::new(vec![Hash::repeat_byte(0x01)], 1), - ).encode(), - ).await; + network_handle.peer_message( + peer_a.clone(), + PeerSet::Validation, + WireMessage::::ViewUpdate( + View::new(vec![Hash::repeat_byte(0x01)], 1), + ).encode(), + ).await; - network_handle.peer_message( - peer_a.clone(), - PeerSet::Validation, - WireMessage::::ViewUpdate( - View::new(vec![], 0), - ).encode(), - ).await; + network_handle.peer_message( + peer_a.clone(), + PeerSet::Validation, + WireMessage::::ViewUpdate( + View::new(vec![], 0), + ).encode(), + ).await; - let actions = network_handle.next_network_actions(2).await; - assert_network_actions_contains( - &actions, - &NetworkAction::ReputationChange( - peer_a.clone(), - MALFORMED_VIEW_COST, - ), - ); - virtual_overseer - }); + let actions = network_handle.next_network_actions(2).await; + assert_network_actions_contains( + &actions, + &NetworkAction::ReputationChange( + peer_a.clone(), + MALFORMED_VIEW_COST, + ), + ); + virtual_overseer + }); } #[test] fn send_messages_to_peers() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut network_handle, - mut virtual_overseer, - } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { + mut network_handle, + mut virtual_overseer, + } = test_harness; - let peer = PeerId::random(); + let peer = PeerId::random(); - network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; - network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Validation, ObservedRole::Full).await; + network_handle.connect_peer(peer.clone(), PeerSet::Collation, ObservedRole::Full).await; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - // bridge will inform about all connected peers. - { - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + // bridge will inform about all connected peers. + { + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_validation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_validation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - { - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), - &mut virtual_overseer, - ).await; + { + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerConnected(peer.clone(), ObservedRole::Full, None), + &mut virtual_overseer, + ).await; - assert_sends_collation_event_to_all( - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), - &mut virtual_overseer, - ).await; - } + assert_sends_collation_event_to_all( + NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + &mut virtual_overseer, + ).await; + } - // consume peer view changes - { - let _peer_view_changes = network_handle.next_network_actions(2).await; - } + // consume peer view changes + { + let _peer_view_changes = network_handle.next_network_actions(2).await; + } - // send a validation protocol message. + // send a validation protocol message. - { - let approval_distribution_message = protocol_v1::ApprovalDistributionMessage::Approvals( - Vec::new() - ); + { + let approval_distribution_message = protocol_v1::ApprovalDistributionMessage::Approvals( + Vec::new() + ); - let message = protocol_v1::ValidationProtocol::ApprovalDistribution( - approval_distribution_message.clone(), - ); + let message = protocol_v1::ValidationProtocol::ApprovalDistribution( + approval_distribution_message.clone(), + ); - virtual_overseer.send(FromOverseer::Communication { - msg: NetworkBridgeMessage::SendValidationMessage( - vec![peer.clone()], - message.clone(), - ) - }).await; + virtual_overseer.send(FromOverseer::Communication { + msg: NetworkBridgeMessage::SendValidationMessage( + vec![peer.clone()], + message.clone(), + ) + }).await; - assert_eq!( - network_handle.next_network_action().await, - NetworkAction::WriteNotification( - peer.clone(), - PeerSet::Validation, - WireMessage::ProtocolMessage(message).encode(), - ) - ); - } + assert_eq!( + network_handle.next_network_action().await, + NetworkAction::WriteNotification( + peer.clone(), + PeerSet::Validation, + WireMessage::ProtocolMessage(message).encode(), + ) + ); + } - // send a collation protocol message. + // send a collation protocol message. - { - let collator_protocol_message = protocol_v1::CollatorProtocolMessage::Declare( - Sr25519Keyring::Alice.public().into(), - Default::default(), - Default::default(), - ); + { + let collator_protocol_message = protocol_v1::CollatorProtocolMessage::Declare( + Sr25519Keyring::Alice.public().into(), + Default::default(), + Default::default(), + ); - let message = protocol_v1::CollationProtocol::CollatorProtocol( - collator_protocol_message.clone() - ); + let message = protocol_v1::CollationProtocol::CollatorProtocol( + collator_protocol_message.clone() + ); - virtual_overseer.send(FromOverseer::Communication { - msg: NetworkBridgeMessage::SendCollationMessage( - vec![peer.clone()], - message.clone(), - ) - }).await; + virtual_overseer.send(FromOverseer::Communication { + msg: NetworkBridgeMessage::SendCollationMessage( + vec![peer.clone()], + message.clone(), + ) + }).await; - assert_eq!( - network_handle.next_network_action().await, - NetworkAction::WriteNotification( - peer.clone(), - PeerSet::Collation, - WireMessage::ProtocolMessage(message).encode(), - ) - ); - } - virtual_overseer - }); + assert_eq!( + network_handle.next_network_action().await, + NetworkAction::WriteNotification( + peer.clone(), + PeerSet::Collation, + WireMessage::ProtocolMessage(message).encode(), + ) + ); + } + virtual_overseer + }); } #[test] fn spread_event_to_subsystems_is_up_to_date() { - // Number of subsystems expected to be interested in a network event, - // and hence the network event broadcasted to. - const EXPECTED_COUNT: usize = 3; + // Number of subsystems expected to be interested in a network event, + // and hence the network event broadcasted to. + const EXPECTED_COUNT: usize = 3; - let mut cnt = 0_usize; - for msg in AllMessages::dispatch_iter(NetworkBridgeEvent::PeerDisconnected(PeerId::random())) { - match msg { - AllMessages::CandidateValidation(_) => unreachable!("Not interested in network events"), - AllMessages::CandidateBacking(_) => unreachable!("Not interested in network events"), - AllMessages::ChainApi(_) => unreachable!("Not interested in network events"), - AllMessages::CollatorProtocol(_) => unreachable!("Not interested in network events"), - AllMessages::StatementDistribution(_) => { cnt += 1; } - AllMessages::AvailabilityDistribution(_) => unreachable!("Not interested in network events"), - AllMessages::AvailabilityRecovery(_) => unreachable!("Not interested in network events"), - AllMessages::BitfieldDistribution(_) => { cnt += 1; } - AllMessages::BitfieldSigning(_) => unreachable!("Not interested in network events"), - AllMessages::Provisioner(_) => unreachable!("Not interested in network events"), - AllMessages::RuntimeApi(_) => unreachable!("Not interested in network events"), - AllMessages::AvailabilityStore(_) => unreachable!("Not interested in network events"), - AllMessages::NetworkBridge(_) => unreachable!("Not interested in network events"), - AllMessages::CollationGeneration(_) => unreachable!("Not interested in network events"), - AllMessages::ApprovalVoting(_) => unreachable!("Not interested in network events"), - AllMessages::ApprovalDistribution(_) => { cnt += 1; } - AllMessages::GossipSupport(_) => unreachable!("Not interested in network events"), - // Add variants here as needed, `{ cnt += 1; }` for those that need to be - // notified, `unreachable!()` for those that should not. - } - } - assert_eq!(cnt, EXPECTED_COUNT); + let mut cnt = 0_usize; + for msg in AllMessages::dispatch_iter(NetworkBridgeEvent::PeerDisconnected(PeerId::random())) { + match msg { + AllMessages::CandidateValidation(_) => unreachable!("Not interested in network events"), + AllMessages::CandidateBacking(_) => unreachable!("Not interested in network events"), + AllMessages::ChainApi(_) => unreachable!("Not interested in network events"), + AllMessages::CollatorProtocol(_) => unreachable!("Not interested in network events"), + AllMessages::StatementDistribution(_) => { cnt += 1; } + AllMessages::AvailabilityDistribution(_) => unreachable!("Not interested in network events"), + AllMessages::AvailabilityRecovery(_) => unreachable!("Not interested in network events"), + AllMessages::BitfieldDistribution(_) => { cnt += 1; } + AllMessages::BitfieldSigning(_) => unreachable!("Not interested in network events"), + AllMessages::Provisioner(_) => unreachable!("Not interested in network events"), + AllMessages::RuntimeApi(_) => unreachable!("Not interested in network events"), + AllMessages::AvailabilityStore(_) => unreachable!("Not interested in network events"), + AllMessages::NetworkBridge(_) => unreachable!("Not interested in network events"), + AllMessages::CollationGeneration(_) => unreachable!("Not interested in network events"), + AllMessages::ApprovalVoting(_) => unreachable!("Not interested in network events"), + AllMessages::ApprovalDistribution(_) => { cnt += 1; } + AllMessages::GossipSupport(_) => unreachable!("Not interested in network events"), + // Add variants here as needed, `{ cnt += 1; }` for those that need to be + // notified, `unreachable!()` for those that should not. + } + } + assert_eq!(cnt, EXPECTED_COUNT); } #[test] fn our_view_updates_decreasing_order_and_limited_to_max() { - test_harness(done_syncing_oracle(), |test_harness| async move { - let TestHarness { - mut virtual_overseer, - .. - } = test_harness; + test_harness(done_syncing_oracle(), |test_harness| async move { + let TestHarness { + mut virtual_overseer, + .. + } = test_harness; - // to show that we're still connected on the collation protocol, send a view update. + // to show that we're still connected on the collation protocol, send a view update. - let hashes = (0..MAX_VIEW_HEADS * 3).map(|i| Hash::repeat_byte(i as u8)); + let hashes = (0..MAX_VIEW_HEADS * 3).map(|i| Hash::repeat_byte(i as u8)); - virtual_overseer.send( - FromOverseer::Signal(OverseerSignal::ActiveLeaves( - // These are in reverse order, so the subsystem must sort internally to - // get the correct view. - ActiveLeavesUpdate { - activated: hashes.enumerate().map(|(i, h)| ActivatedLeaf { - hash: h, - number: i as _, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }).rev().collect(), - deactivated: Default::default(), - } - )) - ).await; + virtual_overseer.send( + FromOverseer::Signal(OverseerSignal::ActiveLeaves( + // These are in reverse order, so the subsystem must sort internally to + // get the correct view. + ActiveLeavesUpdate { + activated: hashes.enumerate().map(|(i, h)| ActivatedLeaf { + hash: h, + number: i as _, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }).rev().collect(), + deactivated: Default::default(), + } + )) + ).await; - let view_heads = (MAX_VIEW_HEADS * 2 .. MAX_VIEW_HEADS * 3).rev() - .map(|i| (Hash::repeat_byte(i as u8), Arc::new(jaeger::Span::Disabled)) ); + let view_heads = (MAX_VIEW_HEADS * 2 .. MAX_VIEW_HEADS * 3).rev() + .map(|i| (Hash::repeat_byte(i as u8), Arc::new(jaeger::Span::Disabled)) ); - let our_view = OurView::new( - view_heads, - 0, - ); + let our_view = OurView::new( + view_heads, + 0, + ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::StatementFetchingReceiver(_) - ) - ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::StatementFetchingReceiver(_) + ) + ); - assert_sends_validation_event_to_all( - NetworkBridgeEvent::OurViewChange(our_view.clone()), - &mut virtual_overseer, - ).await; + assert_sends_validation_event_to_all( + NetworkBridgeEvent::OurViewChange(our_view.clone()), + &mut virtual_overseer, + ).await; - assert_sends_collation_event_to_all( - NetworkBridgeEvent::OurViewChange(our_view), - &mut virtual_overseer, - ).await; - virtual_overseer - }); + assert_sends_collation_event_to_all( + NetworkBridgeEvent::OurViewChange(our_view), + &mut virtual_overseer, + ).await; + virtual_overseer + }); } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs index 4e1d3bdbd0..5ddbc8f561 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs @@ -44,6 +44,9 @@ use polkadot_node_primitives::{SignedFullStatement, Statement, PoV}; use crate::error::{Fatal, NonFatal, log_error}; use super::{LOG_TARGET, Result}; +#[cfg(test)] +mod tests; + const COST_UNEXPECTED_MESSAGE: Rep = Rep::CostMinor("An unexpected message"); #[derive(Clone, Default)] @@ -866,6 +869,3 @@ pub(crate) async fn run( } } } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs index a9b6ebe5d5..19f6fffebb 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs @@ -50,6 +50,9 @@ use polkadot_subsystem::{ use super::{modify_reputation, Result, LOG_TARGET}; +#[cfg(test)] +mod tests; + const COLLATION_FETCH_TIMEOUT: Duration = Duration::from_secs(2); const COST_UNEXPECTED_MESSAGE: Rep = Rep::CostMinor("An unexpected message"); @@ -1244,6 +1247,3 @@ where false } } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests.rs index 6ab0b1eb28..a6cfde80ba 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests.rs @@ -25,15 +25,15 @@ use sp_keyring::Sr25519Keyring; use assert_matches::assert_matches; use polkadot_primitives::v1::{ - CollatorPair, ValidatorId, ValidatorIndex, CoreState, CandidateDescriptor, - GroupRotationInfo, ScheduledCore, OccupiedCore, GroupIndex, + CollatorPair, ValidatorId, ValidatorIndex, CoreState, CandidateDescriptor, + GroupRotationInfo, ScheduledCore, OccupiedCore, GroupIndex, }; use polkadot_node_primitives::BlockData; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_subsystem_testhelpers as test_helpers; use polkadot_subsystem::messages::{RuntimeApiMessage, RuntimeApiRequest}; use polkadot_node_network_protocol::{our_view, ObservedRole, - request_response::Requests + request_response::Requests }; const ACTIVITY_TIMEOUT: Duration = Duration::from_millis(50); @@ -41,442 +41,442 @@ const DECLARE_TIMEOUT: Duration = Duration::from_millis(25); #[derive(Clone)] struct TestState { - chain_ids: Vec, - relay_parent: Hash, - collators: Vec, - validators: Vec, - validator_public: Vec, - validator_groups: Vec>, - group_rotation_info: GroupRotationInfo, - cores: Vec, + chain_ids: Vec, + relay_parent: Hash, + collators: Vec, + validators: Vec, + validator_public: Vec, + validator_groups: Vec>, + group_rotation_info: GroupRotationInfo, + cores: Vec, } impl Default for TestState { - fn default() -> Self { - let chain_a = ParaId::from(1); - let chain_b = ParaId::from(2); + fn default() -> Self { + let chain_a = ParaId::from(1); + let chain_b = ParaId::from(2); - let chain_ids = vec![chain_a, chain_b]; - let relay_parent = Hash::repeat_byte(0x05); - let collators = iter::repeat(()) - .map(|_| CollatorPair::generate().0) - .take(4) - .collect(); + let chain_ids = vec![chain_a, chain_b]; + let relay_parent = Hash::repeat_byte(0x05); + let collators = iter::repeat(()) + .map(|_| CollatorPair::generate().0) + .take(4) + .collect(); - let validators = vec![ - Sr25519Keyring::Alice, - Sr25519Keyring::Bob, - Sr25519Keyring::Charlie, - Sr25519Keyring::Dave, - Sr25519Keyring::Eve, - ]; + let validators = vec![ + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::Eve, + ]; - let validator_public = validators.iter().map(|k| k.public().into()).collect(); - let validator_groups = vec![ - vec![ValidatorIndex(0), ValidatorIndex(1)], - vec![ValidatorIndex(2), ValidatorIndex(3)], - vec![ValidatorIndex(4)], - ]; + let validator_public = validators.iter().map(|k| k.public().into()).collect(); + let validator_groups = vec![ + vec![ValidatorIndex(0), ValidatorIndex(1)], + vec![ValidatorIndex(2), ValidatorIndex(3)], + vec![ValidatorIndex(4)], + ]; - let group_rotation_info = GroupRotationInfo { - session_start_block: 0, - group_rotation_frequency: 1, - now: 0, - }; + let group_rotation_info = GroupRotationInfo { + session_start_block: 0, + group_rotation_frequency: 1, + now: 0, + }; - let cores = vec![ - CoreState::Scheduled(ScheduledCore { - para_id: chain_ids[0], - collator: None, - }), - CoreState::Free, - CoreState::Occupied(OccupiedCore { - next_up_on_available: None, - occupied_since: 0, - time_out_at: 1, - next_up_on_time_out: None, - availability: Default::default(), - group_responsible: GroupIndex(0), - candidate_hash: Default::default(), - candidate_descriptor: { - let mut d = CandidateDescriptor::default(); - d.para_id = chain_ids[1]; + let cores = vec![ + CoreState::Scheduled(ScheduledCore { + para_id: chain_ids[0], + collator: None, + }), + CoreState::Free, + CoreState::Occupied(OccupiedCore { + next_up_on_available: None, + occupied_since: 0, + time_out_at: 1, + next_up_on_time_out: None, + availability: Default::default(), + group_responsible: GroupIndex(0), + candidate_hash: Default::default(), + candidate_descriptor: { + let mut d = CandidateDescriptor::default(); + d.para_id = chain_ids[1]; - d - }, - }), - ]; + d + }, + }), + ]; - Self { - chain_ids, - relay_parent, - collators, - validators, - validator_public, - validator_groups, - group_rotation_info, - cores, - } - } + Self { + chain_ids, + relay_parent, + collators, + validators, + validator_public, + validator_groups, + group_rotation_info, + cores, + } + } } type VirtualOverseer = test_helpers::TestSubsystemContextHandle; struct TestHarness { - virtual_overseer: VirtualOverseer, + virtual_overseer: VirtualOverseer, } fn test_harness>(test: impl FnOnce(TestHarness) -> T) { - let _ = env_logger::builder() - .is_test(true) - .filter( - Some("polkadot_collator_protocol"), - log::LevelFilter::Trace, - ) - .filter( - Some(LOG_TARGET), - log::LevelFilter::Trace, - ) - .try_init(); + let _ = env_logger::builder() + .is_test(true) + .filter( + Some("polkadot_collator_protocol"), + log::LevelFilter::Trace, + ) + .filter( + Some(LOG_TARGET), + log::LevelFilter::Trace, + ) + .try_init(); - let pool = sp_core::testing::TaskExecutor::new(); + let pool = sp_core::testing::TaskExecutor::new(); - let (context, virtual_overseer) = test_helpers::make_subsystem_context(pool.clone()); + let (context, virtual_overseer) = test_helpers::make_subsystem_context(pool.clone()); - let keystore = TestKeyStore::new(); - keystore.sr25519_generate_new( - polkadot_primitives::v1::PARACHAIN_KEY_TYPE_ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ).unwrap(); + let keystore = TestKeyStore::new(); + keystore.sr25519_generate_new( + polkadot_primitives::v1::PARACHAIN_KEY_TYPE_ID, + Some(&Sr25519Keyring::Alice.to_seed()), + ).unwrap(); - let subsystem = run( - context, - Arc::new(keystore), - crate::CollatorEvictionPolicy { - inactive_collator: ACTIVITY_TIMEOUT, - undeclared: DECLARE_TIMEOUT, - }, - Metrics::default(), - ); + let subsystem = run( + context, + Arc::new(keystore), + crate::CollatorEvictionPolicy { + inactive_collator: ACTIVITY_TIMEOUT, + undeclared: DECLARE_TIMEOUT, + }, + Metrics::default(), + ); - let test_fut = test(TestHarness { virtual_overseer }); + let test_fut = test(TestHarness { virtual_overseer }); - futures::pin_mut!(test_fut); - futures::pin_mut!(subsystem); + futures::pin_mut!(test_fut); + futures::pin_mut!(subsystem); - executor::block_on(future::join(async move { - let mut overseer = test_fut.await; - overseer_signal(&mut overseer, OverseerSignal::Conclude).await; - }, subsystem)).1.unwrap(); + executor::block_on(future::join(async move { + let mut overseer = test_fut.await; + overseer_signal(&mut overseer, OverseerSignal::Conclude).await; + }, subsystem)).1.unwrap(); } const TIMEOUT: Duration = Duration::from_millis(200); async fn overseer_send( - overseer: &mut VirtualOverseer, - msg: CollatorProtocolMessage, + overseer: &mut VirtualOverseer, + msg: CollatorProtocolMessage, ) { - tracing::trace!("Sending message:\n{:?}", &msg); - overseer - .send(FromOverseer::Communication { msg }) - .timeout(TIMEOUT) - .await - .expect(&format!("{:?} is enough for sending messages.", TIMEOUT)); + tracing::trace!("Sending message:\n{:?}", &msg); + overseer + .send(FromOverseer::Communication { msg }) + .timeout(TIMEOUT) + .await + .expect(&format!("{:?} is enough for sending messages.", TIMEOUT)); } async fn overseer_recv( - overseer: &mut VirtualOverseer, + overseer: &mut VirtualOverseer, ) -> AllMessages { - let msg = overseer_recv_with_timeout(overseer, TIMEOUT) - .await - .expect(&format!("{:?} is enough to receive messages.", TIMEOUT)); + let msg = overseer_recv_with_timeout(overseer, TIMEOUT) + .await + .expect(&format!("{:?} is enough to receive messages.", TIMEOUT)); - tracing::trace!("Received message:\n{:?}", &msg); + tracing::trace!("Received message:\n{:?}", &msg); - msg + msg } async fn overseer_recv_with_timeout( - overseer: &mut VirtualOverseer, - timeout: Duration, + overseer: &mut VirtualOverseer, + timeout: Duration, ) -> Option { - tracing::trace!("Waiting for message..."); - overseer - .recv() - .timeout(timeout) - .await + tracing::trace!("Waiting for message..."); + overseer + .recv() + .timeout(timeout) + .await } async fn overseer_signal( - overseer: &mut VirtualOverseer, - signal: OverseerSignal, + overseer: &mut VirtualOverseer, + signal: OverseerSignal, ) { - overseer - .send(FromOverseer::Signal(signal)) - .timeout(TIMEOUT) - .await - .expect(&format!("{:?} is more than enough for sending signals.", TIMEOUT)); + overseer + .send(FromOverseer::Signal(signal)) + .timeout(TIMEOUT) + .await + .expect(&format!("{:?} is more than enough for sending signals.", TIMEOUT)); } async fn respond_to_core_info_queries( - virtual_overseer: &mut VirtualOverseer, - test_state: &TestState, + virtual_overseer: &mut VirtualOverseer, + test_state: &TestState, ) { - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _, - RuntimeApiRequest::Validators(tx), - )) => { - let _ = tx.send(Ok(test_state.validator_public.clone())); - } - ); + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::Validators(tx), + )) => { + let _ = tx.send(Ok(test_state.validator_public.clone())); + } + ); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _, - RuntimeApiRequest::ValidatorGroups(tx), - )) => { - let _ = tx.send(Ok(( - test_state.validator_groups.clone(), - test_state.group_rotation_info.clone(), - ))); - } - ); + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::ValidatorGroups(tx), + )) => { + let _ = tx.send(Ok(( + test_state.validator_groups.clone(), + test_state.group_rotation_info.clone(), + ))); + } + ); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _, - RuntimeApiRequest::AvailabilityCores(tx), - )) => { - let _ = tx.send(Ok(test_state.cores.clone())); - } - ); + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::AvailabilityCores(tx), + )) => { + let _ = tx.send(Ok(test_state.cores.clone())); + } + ); } // As we receive a relevant advertisement act on it and issue a collation request. #[test] fn act_on_advertisement() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - let pair = CollatorPair::generate().0; - tracing::trace!("activating"); + let pair = CollatorPair::generate().0; + tracing::trace!("activating"); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ) + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - pair.public(), - test_state.chain_ids[0], - pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + pair.public(), + test_state.chain_ids[0], + pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - test_state.relay_parent, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + test_state.relay_parent, + ) + ) + ) + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, test_state.relay_parent); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - } - _ => panic!("Unexpected request"), - } - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, test_state.relay_parent); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + } + _ => panic!("Unexpected request"), + } + }); - virtual_overseer - }); + virtual_overseer + }); } // Test that other subsystems may modify collators' reputations. #[test] fn collator_reporting_works() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ) + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); - let peer_c = PeerId::random(); + let peer_b = PeerId::random(); + let peer_c = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_c, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_c, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[0].public(), - test_state.chain_ids[0], - test_state.collators[0].sign(&protocol_v1::declare_signature_payload(&peer_b)), - ), - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[0].public(), + test_state.chain_ids[0], + test_state.collators[0].sign(&protocol_v1::declare_signature_payload(&peer_b)), + ), + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_c.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[1].public(), - test_state.chain_ids[0], - test_state.collators[1].sign(&protocol_v1::declare_signature_payload(&peer_c)), - ), - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_c.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[1].public(), + test_state.chain_ids[0], + test_state.collators[1].sign(&protocol_v1::declare_signature_payload(&peer_c)), + ), + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::ReportCollator(test_state.collators[0].public()), - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::ReportCollator(test_state.collators[0].public()), + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(peer, rep), - ) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_REPORT_BAD); - } - ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(peer, rep), + ) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_REPORT_BAD); + } + ); - virtual_overseer - }); + virtual_overseer + }); } // Test that we verify the signatures on `Declare` and `AdvertiseCollation` messages. #[test] fn collator_authentication_verification_works() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b, + ObservedRole::Full, + None, + ), + ) + ).await; - // the peer sends a declare message but sign the wrong payload - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[0].public(), - test_state.chain_ids[0], - test_state.collators[0].sign(&[42]), - ), - )), - ) - .await; + // the peer sends a declare message but sign the wrong payload + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1(NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[0].public(), + test_state.chain_ids[0], + test_state.collators[0].sign(&[42]), + ), + )), + ) + .await; - // it should be reported for sending a message with an invalid signature - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(peer, rep), - ) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_INVALID_SIGNATURE); - } - ); - virtual_overseer - }); + // it should be reported for sending a message with an invalid signature + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(peer, rep), + ) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_INVALID_SIGNATURE); + } + ); + virtual_overseer + }); } // A test scenario that takes the following steps @@ -490,635 +490,635 @@ fn collator_authentication_verification_works() { // - Collations are fetched correctly. #[test] fn fetch_collations_works() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ), - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ), + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); - let peer_c = PeerId::random(); + let peer_b = PeerId::random(); + let peer_c = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_c, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_c, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[0].public(), - test_state.chain_ids[0], - test_state.collators[0].sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[0].public(), + test_state.chain_ids[0], + test_state.collators[0].sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_c.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[1].public(), - test_state.chain_ids[0], - test_state.collators[1].sign(&protocol_v1::declare_signature_payload(&peer_c)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_c.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[1].public(), + test_state.chain_ids[0], + test_state.collators[1].sign(&protocol_v1::declare_signature_payload(&peer_c)), + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - test_state.relay_parent, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + test_state.relay_parent, + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_c.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - test_state.relay_parent, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_c.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + test_state.relay_parent, + ) + ) + ) + ).await; - let response_channel = assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, test_state.relay_parent); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - req.pending_response - } - _ => panic!("Unexpected request"), - } - }); + let response_channel = assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, test_state.relay_parent); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + req.pending_response + } + _ => panic!("Unexpected request"), + } + }); - let mut candidate_a = CandidateReceipt::default(); - candidate_a.descriptor.para_id = test_state.chain_ids[0]; - candidate_a.descriptor.relay_parent = test_state.relay_parent; - response_channel.send(Ok( - CollationFetchingResponse::Collation( - candidate_a.clone(), - PoV { - block_data: BlockData(vec![]), - }, - ).encode() - )).expect("Sending response should succeed"); + let mut candidate_a = CandidateReceipt::default(); + candidate_a.descriptor.para_id = test_state.chain_ids[0]; + candidate_a.descriptor.relay_parent = test_state.relay_parent; + response_channel.send(Ok( + CollationFetchingResponse::Collation( + candidate_a.clone(), + PoV { + block_data: BlockData(vec![]), + }, + ).encode() + )).expect("Sending response should succeed"); - let _ = assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, test_state.relay_parent); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - req.pending_response - } - _ => panic!("Unexpected request"), - } - }); + let _ = assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, test_state.relay_parent); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + req.pending_response + } + _ => panic!("Unexpected request"), + } + }); - virtual_overseer - }); + virtual_overseer + }); } #[test] fn inactive_disconnected() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - let pair = CollatorPair::generate().0; + let pair = CollatorPair::generate().0; - let hash_a = test_state.relay_parent; + let hash_a = test_state.relay_parent; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![hash_a]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![hash_a]) + ) + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - None, - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + None, + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - pair.public(), - test_state.chain_ids[0], - pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + pair.public(), + test_state.chain_ids[0], + pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - test_state.relay_parent, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + test_state.relay_parent, + ) + ) + ) + ).await; - let _ = assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, test_state.relay_parent); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - req.pending_response - } - _ => panic!("Unexpected request"), - } - }); + let _ = assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, test_state.relay_parent); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + req.pending_response + } + _ => panic!("Unexpected request"), + } + }); - Delay::new(ACTIVITY_TIMEOUT * 3).await; + Delay::new(ACTIVITY_TIMEOUT * 3).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( - peer, - rep, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_REQUEST_TIMED_OUT); - } - ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( + peer, + rep, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_REQUEST_TIMED_OUT); + } + ); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( - peer, - peer_set, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(peer_set, PeerSet::Collation); - } - ); - virtual_overseer - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( + peer, + peer_set, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(peer_set, PeerSet::Collation); + } + ); + virtual_overseer + }); } #[test] fn activity_extends_life() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - let pair = CollatorPair::generate().0; + let pair = CollatorPair::generate().0; - let hash_a = test_state.relay_parent; - let hash_b = Hash::repeat_byte(1); - let hash_c = Hash::repeat_byte(2); + let hash_a = test_state.relay_parent; + let hash_b = Hash::repeat_byte(1); + let hash_c = Hash::repeat_byte(2); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![hash_a, hash_b, hash_c]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![hash_a, hash_b, hash_c]) + ) + ).await; - // 3 heads, 3 times. - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + // 3 heads, 3 times. + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - None, - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + None, + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - pair.public(), - test_state.chain_ids[0], - pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + pair.public(), + test_state.chain_ids[0], + pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await; + Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - hash_a, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + hash_a, + ) + ) + ) + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, hash_a); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - } - _ => panic!("Unexpected request"), - } - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, hash_a); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + } + _ => panic!("Unexpected request"), + } + }); - Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await; + Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - hash_b - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + hash_b + ) + ) + ) + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( - peer, - rep, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_REQUEST_TIMED_OUT); - } - ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( + peer, + rep, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_REQUEST_TIMED_OUT); + } + ); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, hash_b); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - } - _ => panic!("Unexpected request"), - } - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, hash_b); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + } + _ => panic!("Unexpected request"), + } + }); - Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await; + Delay::new(ACTIVITY_TIMEOUT * 2 / 3).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - hash_c, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + hash_c, + ) + ) + ) + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( - peer, - rep, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_REQUEST_TIMED_OUT); - } - ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( + peer, + rep, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_REQUEST_TIMED_OUT); + } + ); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, hash_c); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - } - _ => panic!("Unexpected request"), - } - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, hash_c); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + } + _ => panic!("Unexpected request"), + } + }); - Delay::new(ACTIVITY_TIMEOUT * 3 / 2).await; + Delay::new(ACTIVITY_TIMEOUT * 3 / 2).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( - peer, - rep, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_REQUEST_TIMED_OUT); - } - ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( + peer, + rep, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_REQUEST_TIMED_OUT); + } + ); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( - peer, - peer_set, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(peer_set, PeerSet::Collation); - } - ); - virtual_overseer - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( + peer, + peer_set, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(peer_set, PeerSet::Collation); + } + ); + virtual_overseer + }); } #[test] fn disconnect_if_no_declare() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ) + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - None, - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + None, + ) + ) + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( - peer, - peer_set, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(peer_set, PeerSet::Collation); - } - ); - virtual_overseer - }) + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( + peer, + peer_set, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(peer_set, PeerSet::Collation); + } + ); + virtual_overseer + }) } #[test] fn disconnect_if_wrong_declare() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - let pair = CollatorPair::generate().0; + let pair = CollatorPair::generate().0; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ) + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - None, - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + None, + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - pair.public(), - ParaId::from(69), - pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + pair.public(), + ParaId::from(69), + pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( - peer, - rep, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(rep, COST_UNNEEDED_COLLATOR); - } - ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::ReportPeer( + peer, + rep, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(rep, COST_UNNEEDED_COLLATOR); + } + ); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( - peer, - peer_set, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(peer_set, PeerSet::Collation); - } - ); - virtual_overseer - }) + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( + peer, + peer_set, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(peer_set, PeerSet::Collation); + } + ); + virtual_overseer + }) } #[test] fn view_change_clears_old_collators() { - let mut test_state = TestState::default(); + let mut test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - let pair = CollatorPair::generate().0; + let pair = CollatorPair::generate().0; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ) + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); + let peer_b = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - None, - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + None, + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - pair.public(), - test_state.chain_ids[0], - pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + pair.public(), + test_state.chain_ids[0], + pair.sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - let hash_b = Hash::repeat_byte(69); + let hash_b = Hash::repeat_byte(69); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![hash_b]) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![hash_b]) + ) + ).await; - test_state.group_rotation_info = test_state.group_rotation_info.bump_rotation(); - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + test_state.group_rotation_info = test_state.group_rotation_info.bump_rotation(); + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( - peer, - peer_set, - )) => { - assert_eq!(peer, peer_b); - assert_eq!(peer_set, PeerSet::Collation); - } - ); - virtual_overseer - }) + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer( + peer, + peer_set, + )) => { + assert_eq!(peer, peer_b); + assert_eq!(peer_set, PeerSet::Collation); + } + ); + virtual_overseer + }) } // A test scenario that takes the following steps @@ -1132,177 +1132,177 @@ fn view_change_clears_old_collators() { // - Collations are fetched correctly. #[test] fn seconding_works() { - let test_state = TestState::default(); + let test_state = TestState::default(); - test_harness(|test_harness| async move { - let TestHarness { - mut virtual_overseer, - } = test_harness; + test_harness(|test_harness| async move { + let TestHarness { + mut virtual_overseer, + } = test_harness; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) - ), - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::OurViewChange(our_view![test_state.relay_parent]) + ), + ).await; - respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; + respond_to_core_info_queries(&mut virtual_overseer, &test_state).await; - let peer_b = PeerId::random(); - let peer_c = PeerId::random(); + let peer_b = PeerId::random(); + let peer_c = PeerId::random(); - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_c, - ObservedRole::Full, - None, - ), - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_c, + ObservedRole::Full, + None, + ), + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[0].public(), - test_state.chain_ids[0], - test_state.collators[0].sign(&protocol_v1::declare_signature_payload(&peer_b)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[0].public(), + test_state.chain_ids[0], + test_state.collators[0].sign(&protocol_v1::declare_signature_payload(&peer_b)), + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_c.clone(), - protocol_v1::CollatorProtocolMessage::Declare( - test_state.collators[1].public(), - test_state.chain_ids[0], - test_state.collators[1].sign(&protocol_v1::declare_signature_payload(&peer_c)), - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_c.clone(), + protocol_v1::CollatorProtocolMessage::Declare( + test_state.collators[1].public(), + test_state.chain_ids[0], + test_state.collators[1].sign(&protocol_v1::declare_signature_payload(&peer_c)), + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_b.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - test_state.relay_parent, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_b.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + test_state.relay_parent, + ) + ) + ) + ).await; - overseer_send( - &mut virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_c.clone(), - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - test_state.relay_parent, - ) - ) - ) - ).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_c.clone(), + protocol_v1::CollatorProtocolMessage::AdvertiseCollation( + test_state.relay_parent, + ) + ) + ) + ).await; - let response_channel = assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, test_state.relay_parent); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - req.pending_response - } - _ => panic!("Unexpected request"), - } - }); + let response_channel = assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, test_state.relay_parent); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + req.pending_response + } + _ => panic!("Unexpected request"), + } + }); - let mut candidate_a = CandidateReceipt::default(); - // Memoize PoV data to ensure we receive the right one - let pov = PoV { - block_data: BlockData(vec![1, 2, 3, 4, 5]), - }; - candidate_a.descriptor.para_id = test_state.chain_ids[0]; - candidate_a.descriptor.relay_parent = test_state.relay_parent; - response_channel.send(Ok( - CollationFetchingResponse::Collation( - candidate_a.clone(), - pov.clone(), - ).encode() - )).expect("Sending response should succeed"); + let mut candidate_a = CandidateReceipt::default(); + // Memoize PoV data to ensure we receive the right one + let pov = PoV { + block_data: BlockData(vec![1, 2, 3, 4, 5]), + }; + candidate_a.descriptor.para_id = test_state.chain_ids[0]; + candidate_a.descriptor.relay_parent = test_state.relay_parent; + response_channel.send(Ok( + CollationFetchingResponse::Collation( + candidate_a.clone(), + pov.clone(), + ).encode() + )).expect("Sending response should succeed"); - let response_channel = assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) - ) => { - let req = reqs.into_iter().next() - .expect("There should be exactly one request"); - match req { - Requests::CollationFetching(req) => { - let payload = req.payload; - assert_eq!(payload.relay_parent, test_state.relay_parent); - assert_eq!(payload.para_id, test_state.chain_ids[0]); - req.pending_response - } - _ => panic!("Unexpected request"), - } - }); + let response_channel = assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendRequests(reqs, IfDisconnected::ImmediateError) + ) => { + let req = reqs.into_iter().next() + .expect("There should be exactly one request"); + match req { + Requests::CollationFetching(req) => { + let payload = req.payload; + assert_eq!(payload.relay_parent, test_state.relay_parent); + assert_eq!(payload.para_id, test_state.chain_ids[0]); + req.pending_response + } + _ => panic!("Unexpected request"), + } + }); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::CandidateBacking(CandidateBackingMessage::Second(relay_parent, candidate_receipt, incoming_pov) - ) => { - assert_eq!(relay_parent, test_state.relay_parent); - assert_eq!(candidate_receipt.descriptor.para_id, test_state.chain_ids[0]); - assert_eq!(incoming_pov, pov); - }); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::CandidateBacking(CandidateBackingMessage::Second(relay_parent, candidate_receipt, incoming_pov) + ) => { + assert_eq!(relay_parent, test_state.relay_parent); + assert_eq!(candidate_receipt.descriptor.para_id, test_state.chain_ids[0]); + assert_eq!(incoming_pov, pov); + }); - let mut candidate_b = CandidateReceipt::default(); - candidate_b.descriptor.para_id = test_state.chain_ids[0]; - candidate_b.descriptor.relay_parent = test_state.relay_parent; + let mut candidate_b = CandidateReceipt::default(); + candidate_b.descriptor.para_id = test_state.chain_ids[0]; + candidate_b.descriptor.relay_parent = test_state.relay_parent; - // Send second collation to ensure first collation gets seconded - response_channel.send(Ok( - CollationFetchingResponse::Collation( - candidate_b.clone(), - PoV { - block_data: BlockData(vec![]), - }, - ).encode() - )).expect("Sending response should succeed after seconding"); + // Send second collation to ensure first collation gets seconded + response_channel.send(Ok( + CollationFetchingResponse::Collation( + candidate_b.clone(), + PoV { + block_data: BlockData(vec![]), + }, + ).encode() + )).expect("Sending response should succeed after seconding"); - // Ensure we don't receive any message related to candidate backing - // All Peers should get disconnected after successful Candidate Backing Message - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer(_, _) - ) => {}); + // Ensure we don't receive any message related to candidate backing + // All Peers should get disconnected after successful Candidate Backing Message + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridge(NetworkBridgeMessage::DisconnectPeer(_, _) + ) => {}); - virtual_overseer - }); + virtual_overseer + }); } diff --git a/polkadot/node/network/gossip-support/src/lib.rs b/polkadot/node/network/gossip-support/src/lib.rs index 51438a23cc..8a12896bc7 100644 --- a/polkadot/node/network/gossip-support/src/lib.rs +++ b/polkadot/node/network/gossip-support/src/lib.rs @@ -18,9 +18,6 @@ //! and issuing a connection request to the validators relevant to //! the gossiping subsystems on every new session. -#[cfg(test)] -mod tests; - use std::time::{Duration, Instant}; use futures::{channel::oneshot, FutureExt as _}; use polkadot_node_subsystem::{ @@ -38,6 +35,9 @@ use polkadot_node_network_protocol::peer_set::PeerSet; use sp_keystore::{CryptoStore, SyncCryptoStorePtr}; use sp_application_crypto::{Public, AppKey}; +#[cfg(test)] +mod tests; + const LOG_TARGET: &str = "parachain::gossip-support"; // How much time should we wait since the last // authority discovery resolution failure. diff --git a/polkadot/node/network/statement-distribution/src/lib.rs b/polkadot/node/network/statement-distribution/src/lib.rs index ba7b8483a7..f2e570a6b7 100644 --- a/polkadot/node/network/statement-distribution/src/lib.rs +++ b/polkadot/node/network/statement-distribution/src/lib.rs @@ -71,6 +71,9 @@ use requester::{RequesterMessage, fetch}; mod responder; use responder::{ResponderMessage, respond}; +#[cfg(test)] +mod tests; + const COST_UNEXPECTED_STATEMENT: Rep = Rep::CostMinor("Unexpected Statement"); const COST_FETCH_FAIL: Rep = Rep::CostMinor("Requesting `CommittedCandidateReceipt` from peer failed"); const COST_INVALID_SIGNATURE: Rep = Rep::CostMajor("Invalid Statement Signature"); @@ -2044,6 +2047,3 @@ impl metrics::Metrics for Metrics { Ok(Metrics(Some(metrics))) } } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/network/statement-distribution/src/tests.rs b/polkadot/node/network/statement-distribution/src/tests.rs index 26438ed477..b2baa428a5 100644 --- a/polkadot/node/network/statement-distribution/src/tests.rs +++ b/polkadot/node/network/statement-distribution/src/tests.rs @@ -29,1682 +29,1682 @@ use sp_keystore::{CryptoStore, SyncCryptoStorePtr, SyncCryptoStore}; use sc_keystore::LocalKeystore; use polkadot_node_network_protocol::{view, ObservedRole, request_response::Recipient}; use polkadot_subsystem::{ - jaeger, ActivatedLeaf, messages::{RuntimeApiMessage, RuntimeApiRequest}, LeafStatus, + jaeger, ActivatedLeaf, messages::{RuntimeApiMessage, RuntimeApiRequest}, LeafStatus, }; use polkadot_node_network_protocol::request_response::{ - Requests, - v1::{ - StatementFetchingRequest, - StatementFetchingResponse, - }, + Requests, + v1::{ + StatementFetchingRequest, + StatementFetchingResponse, + }, }; #[test] fn active_head_accepts_only_2_seconded_per_validator() { - let validators = vec![ - Sr25519Keyring::Alice.public().into(), - Sr25519Keyring::Bob.public().into(), - Sr25519Keyring::Charlie.public().into(), - ]; - let parent_hash: Hash = [1; 32].into(); + let validators = vec![ + Sr25519Keyring::Alice.public().into(), + Sr25519Keyring::Bob.public().into(), + Sr25519Keyring::Charlie.public().into(), + ]; + let parent_hash: Hash = [1; 32].into(); - let session_index = 1; - let signing_context = SigningContext { - parent_hash, - session_index, - }; + let session_index = 1; + let signing_context = SigningContext { + parent_hash, + session_index, + }; - let candidate_a = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = parent_hash; - c.descriptor.para_id = 1.into(); - c - }; + let candidate_a = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = parent_hash; + c.descriptor.para_id = 1.into(); + c + }; - let candidate_b = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = parent_hash; - c.descriptor.para_id = 2.into(); - c - }; + let candidate_b = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = parent_hash; + c.descriptor.para_id = 2.into(); + c + }; - let candidate_c = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = parent_hash; - c.descriptor.para_id = 3.into(); - c - }; + let candidate_c = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = parent_hash; + c.descriptor.para_id = 3.into(); + c + }; - let mut head_data = ActiveHeadData::new( - validators, - session_index, - PerLeafSpan::new(Arc::new(jaeger::Span::Disabled), "test"), - ); + let mut head_data = ActiveHeadData::new( + validators, + session_index, + PerLeafSpan::new(Arc::new(jaeger::Span::Disabled), "test"), + ); - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = SyncCryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) - ).unwrap(); - let bob_public = SyncCryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Bob.to_seed()) - ).unwrap(); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let alice_public = SyncCryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) + ).unwrap(); + let bob_public = SyncCryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Bob.to_seed()) + ).unwrap(); - // note A - let a_seconded_val_0 = block_on(SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate_a.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(head_data.check_useful_or_unknown(&a_seconded_val_0.clone().into()).is_ok()); - let noted = head_data.note_statement(a_seconded_val_0.clone()); + // note A + let a_seconded_val_0 = block_on(SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate_a.clone()), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(head_data.check_useful_or_unknown(&a_seconded_val_0.clone().into()).is_ok()); + let noted = head_data.note_statement(a_seconded_val_0.clone()); - assert_matches!(noted, NotedStatement::Fresh(_)); + assert_matches!(noted, NotedStatement::Fresh(_)); - // note A (duplicate) - assert_eq!( - head_data.check_useful_or_unknown(&a_seconded_val_0.clone().into()), - Err(DeniedStatement::UsefulButKnown), - ); - let noted = head_data.note_statement(a_seconded_val_0); + // note A (duplicate) + assert_eq!( + head_data.check_useful_or_unknown(&a_seconded_val_0.clone().into()), + Err(DeniedStatement::UsefulButKnown), + ); + let noted = head_data.note_statement(a_seconded_val_0); - assert_matches!(noted, NotedStatement::UsefulButKnown); + assert_matches!(noted, NotedStatement::UsefulButKnown); - // note B - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate_b.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok()); - let noted = head_data.note_statement(statement); - assert_matches!(noted, NotedStatement::Fresh(_)); + // note B + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate_b.clone()), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok()); + let noted = head_data.note_statement(statement); + assert_matches!(noted, NotedStatement::Fresh(_)); - // note C (beyond 2 - ignored) - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate_c.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - )).ok().flatten().expect("should be signed"); - assert_eq!( - head_data.check_useful_or_unknown(&statement.clone().into()), - Err(DeniedStatement::NotUseful), - ); - let noted = head_data.note_statement(statement); - assert_matches!(noted, NotedStatement::NotUseful); + // note C (beyond 2 - ignored) + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate_c.clone()), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + )).ok().flatten().expect("should be signed"); + assert_eq!( + head_data.check_useful_or_unknown(&statement.clone().into()), + Err(DeniedStatement::NotUseful), + ); + let noted = head_data.note_statement(statement); + assert_matches!(noted, NotedStatement::NotUseful); - // note B (new validator) - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate_b.clone()), - &signing_context, - ValidatorIndex(1), - &bob_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok()); - let noted = head_data.note_statement(statement); - assert_matches!(noted, NotedStatement::Fresh(_)); + // note B (new validator) + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate_b.clone()), + &signing_context, + ValidatorIndex(1), + &bob_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok()); + let noted = head_data.note_statement(statement); + assert_matches!(noted, NotedStatement::Fresh(_)); - // note C (new validator) - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate_c.clone()), - &signing_context, - ValidatorIndex(1), - &bob_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok()); - let noted = head_data.note_statement(statement); - assert_matches!(noted, NotedStatement::Fresh(_)); + // note C (new validator) + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate_c.clone()), + &signing_context, + ValidatorIndex(1), + &bob_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok()); + let noted = head_data.note_statement(statement); + assert_matches!(noted, NotedStatement::Fresh(_)); } #[test] fn note_local_works() { - let hash_a = CandidateHash([1; 32].into()); - let hash_b = CandidateHash([2; 32].into()); + let hash_a = CandidateHash([1; 32].into()); + let hash_b = CandidateHash([2; 32].into()); - let mut per_peer_tracker = VcPerPeerTracker::default(); - per_peer_tracker.note_local(hash_a.clone()); - per_peer_tracker.note_local(hash_b.clone()); + let mut per_peer_tracker = VcPerPeerTracker::default(); + per_peer_tracker.note_local(hash_a.clone()); + per_peer_tracker.note_local(hash_b.clone()); - assert!(per_peer_tracker.local_observed.contains(&hash_a)); - assert!(per_peer_tracker.local_observed.contains(&hash_b)); + assert!(per_peer_tracker.local_observed.contains(&hash_a)); + assert!(per_peer_tracker.local_observed.contains(&hash_b)); - assert!(!per_peer_tracker.remote_observed.contains(&hash_a)); - assert!(!per_peer_tracker.remote_observed.contains(&hash_b)); + assert!(!per_peer_tracker.remote_observed.contains(&hash_a)); + assert!(!per_peer_tracker.remote_observed.contains(&hash_b)); } #[test] fn note_remote_works() { - let hash_a = CandidateHash([1; 32].into()); - let hash_b = CandidateHash([2; 32].into()); - let hash_c = CandidateHash([3; 32].into()); + let hash_a = CandidateHash([1; 32].into()); + let hash_b = CandidateHash([2; 32].into()); + let hash_c = CandidateHash([3; 32].into()); - let mut per_peer_tracker = VcPerPeerTracker::default(); - assert!(per_peer_tracker.note_remote(hash_a.clone())); - assert!(per_peer_tracker.note_remote(hash_b.clone())); - assert!(!per_peer_tracker.note_remote(hash_c.clone())); + let mut per_peer_tracker = VcPerPeerTracker::default(); + assert!(per_peer_tracker.note_remote(hash_a.clone())); + assert!(per_peer_tracker.note_remote(hash_b.clone())); + assert!(!per_peer_tracker.note_remote(hash_c.clone())); - assert!(per_peer_tracker.remote_observed.contains(&hash_a)); - assert!(per_peer_tracker.remote_observed.contains(&hash_b)); - assert!(!per_peer_tracker.remote_observed.contains(&hash_c)); + assert!(per_peer_tracker.remote_observed.contains(&hash_a)); + assert!(per_peer_tracker.remote_observed.contains(&hash_b)); + assert!(!per_peer_tracker.remote_observed.contains(&hash_c)); - assert!(!per_peer_tracker.local_observed.contains(&hash_a)); - assert!(!per_peer_tracker.local_observed.contains(&hash_b)); - assert!(!per_peer_tracker.local_observed.contains(&hash_c)); + assert!(!per_peer_tracker.local_observed.contains(&hash_a)); + assert!(!per_peer_tracker.local_observed.contains(&hash_b)); + assert!(!per_peer_tracker.local_observed.contains(&hash_c)); } #[test] fn per_peer_relay_parent_knowledge_send() { - let mut knowledge = PeerRelayParentKnowledge::default(); + let mut knowledge = PeerRelayParentKnowledge::default(); - let hash_a = CandidateHash([1; 32].into()); + let hash_a = CandidateHash([1; 32].into()); - // Sending an un-pinned statement should not work and should have no effect. - assert!(!knowledge.can_send(&(CompactStatement::Valid(hash_a), ValidatorIndex(0)))); - assert!(!knowledge.is_known_candidate(&hash_a)); - assert!(knowledge.sent_statements.is_empty()); - assert!(knowledge.received_statements.is_empty()); - assert!(knowledge.seconded_counts.is_empty()); - assert!(knowledge.received_message_count.is_empty()); + // Sending an un-pinned statement should not work and should have no effect. + assert!(!knowledge.can_send(&(CompactStatement::Valid(hash_a), ValidatorIndex(0)))); + assert!(!knowledge.is_known_candidate(&hash_a)); + assert!(knowledge.sent_statements.is_empty()); + assert!(knowledge.received_statements.is_empty()); + assert!(knowledge.seconded_counts.is_empty()); + assert!(knowledge.received_message_count.is_empty()); - // Make the peer aware of the candidate. - assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0))), true); - assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(1))), false); - assert!(knowledge.is_known_candidate(&hash_a)); - assert_eq!(knowledge.sent_statements.len(), 2); - assert!(knowledge.received_statements.is_empty()); - assert_eq!(knowledge.seconded_counts.len(), 2); - assert!(knowledge.received_message_count.get(&hash_a).is_none()); + // Make the peer aware of the candidate. + assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0))), true); + assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(1))), false); + assert!(knowledge.is_known_candidate(&hash_a)); + assert_eq!(knowledge.sent_statements.len(), 2); + assert!(knowledge.received_statements.is_empty()); + assert_eq!(knowledge.seconded_counts.len(), 2); + assert!(knowledge.received_message_count.get(&hash_a).is_none()); - // And now it should accept the dependent message. - assert_eq!(knowledge.send(&(CompactStatement::Valid(hash_a), ValidatorIndex(0))), false); - assert!(knowledge.is_known_candidate(&hash_a)); - assert_eq!(knowledge.sent_statements.len(), 3); - assert!(knowledge.received_statements.is_empty()); - assert_eq!(knowledge.seconded_counts.len(), 2); - assert!(knowledge.received_message_count.get(&hash_a).is_none()); + // And now it should accept the dependent message. + assert_eq!(knowledge.send(&(CompactStatement::Valid(hash_a), ValidatorIndex(0))), false); + assert!(knowledge.is_known_candidate(&hash_a)); + assert_eq!(knowledge.sent_statements.len(), 3); + assert!(knowledge.received_statements.is_empty()); + assert_eq!(knowledge.seconded_counts.len(), 2); + assert!(knowledge.received_message_count.get(&hash_a).is_none()); } #[test] fn cant_send_after_receiving() { - let mut knowledge = PeerRelayParentKnowledge::default(); + let mut knowledge = PeerRelayParentKnowledge::default(); - let hash_a = CandidateHash([1; 32].into()); - assert!(knowledge.check_can_receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).is_ok()); - assert!(knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).unwrap()); - assert!(!knowledge.can_send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)))); + let hash_a = CandidateHash([1; 32].into()); + assert!(knowledge.check_can_receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).is_ok()); + assert!(knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).unwrap()); + assert!(!knowledge.can_send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)))); } #[test] fn per_peer_relay_parent_knowledge_receive() { - let mut knowledge = PeerRelayParentKnowledge::default(); + let mut knowledge = PeerRelayParentKnowledge::default(); - let hash_a = CandidateHash([1; 32].into()); + let hash_a = CandidateHash([1; 32].into()); - assert_eq!( - knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(0)), 3), - Err(COST_UNEXPECTED_STATEMENT), - ); - assert_eq!( - knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(0)), 3), - Err(COST_UNEXPECTED_STATEMENT), - ); + assert_eq!( + knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(0)), 3), + Err(COST_UNEXPECTED_STATEMENT), + ); + assert_eq!( + knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(0)), 3), + Err(COST_UNEXPECTED_STATEMENT), + ); - assert!(knowledge.check_can_receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).is_ok()); - assert_eq!( - knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3), - Ok(true), - ); + assert!(knowledge.check_can_receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).is_ok()); + assert_eq!( + knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3), + Ok(true), + ); - // Push statements up to the flood limit. - assert!(knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(1)), 3).is_ok()); - assert_eq!( - knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(1)), 3), - Ok(false), - ); + // Push statements up to the flood limit. + assert!(knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(1)), 3).is_ok()); + assert_eq!( + knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(1)), 3), + Ok(false), + ); - assert!(knowledge.is_known_candidate(&hash_a)); - assert_eq!(*knowledge.received_message_count.get(&hash_a).unwrap(), 2); + assert!(knowledge.is_known_candidate(&hash_a)); + assert_eq!(*knowledge.received_message_count.get(&hash_a).unwrap(), 2); - assert!(knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3).is_ok()); - assert_eq!( - knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3), - Ok(false), - ); + assert!(knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3).is_ok()); + assert_eq!( + knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3), + Ok(false), + ); - assert_eq!(*knowledge.received_message_count.get(&hash_a).unwrap(), 3); + assert_eq!(*knowledge.received_message_count.get(&hash_a).unwrap(), 3); - assert_eq!( - knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(7)), 3), - Err(COST_APPARENT_FLOOD), - ); - assert_eq!( - knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(7)), 3), - Err(COST_APPARENT_FLOOD), - ); + assert_eq!( + knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(7)), 3), + Err(COST_APPARENT_FLOOD), + ); + assert_eq!( + knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(7)), 3), + Err(COST_APPARENT_FLOOD), + ); - assert_eq!(*knowledge.received_message_count.get(&hash_a).unwrap(), 3); - assert_eq!(knowledge.received_statements.len(), 3); // number of prior `Ok`s. + assert_eq!(*knowledge.received_message_count.get(&hash_a).unwrap(), 3); + assert_eq!(knowledge.received_statements.len(), 3); // number of prior `Ok`s. - // Now make sure that the seconding limit is respected. - let hash_b = CandidateHash([2; 32].into()); - let hash_c = CandidateHash([3; 32].into()); + // Now make sure that the seconding limit is respected. + let hash_b = CandidateHash([2; 32].into()); + let hash_c = CandidateHash([3; 32].into()); - assert!(knowledge.check_can_receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3).is_ok()); - assert_eq!( - knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), - Ok(true), - ); + assert!(knowledge.check_can_receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3).is_ok()); + assert_eq!( + knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), + Ok(true), + ); - assert_eq!( - knowledge.check_can_receive(&(CompactStatement::Seconded(hash_c), ValidatorIndex(0)), 3), - Err(COST_UNEXPECTED_STATEMENT), - ); - assert_eq!( - knowledge.receive(&(CompactStatement::Seconded(hash_c), ValidatorIndex(0)), 3), - Err(COST_UNEXPECTED_STATEMENT), - ); + assert_eq!( + knowledge.check_can_receive(&(CompactStatement::Seconded(hash_c), ValidatorIndex(0)), 3), + Err(COST_UNEXPECTED_STATEMENT), + ); + assert_eq!( + knowledge.receive(&(CompactStatement::Seconded(hash_c), ValidatorIndex(0)), 3), + Err(COST_UNEXPECTED_STATEMENT), + ); - // Last, make sure that already-known statements are disregarded. - assert_eq!( - knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3), - Err(COST_DUPLICATE_STATEMENT), - ); - assert_eq!( - knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3), - Err(COST_DUPLICATE_STATEMENT), - ); + // Last, make sure that already-known statements are disregarded. + assert_eq!( + knowledge.check_can_receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3), + Err(COST_DUPLICATE_STATEMENT), + ); + assert_eq!( + knowledge.receive(&(CompactStatement::Valid(hash_a), ValidatorIndex(2)), 3), + Err(COST_DUPLICATE_STATEMENT), + ); - assert_eq!( - knowledge.check_can_receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), - Err(COST_DUPLICATE_STATEMENT), - ); - assert_eq!( - knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), - Err(COST_DUPLICATE_STATEMENT), - ); + assert_eq!( + knowledge.check_can_receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), + Err(COST_DUPLICATE_STATEMENT), + ); + assert_eq!( + knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), + Err(COST_DUPLICATE_STATEMENT), + ); } #[test] fn peer_view_update_sends_messages() { - let hash_a = Hash::repeat_byte(1); - let hash_b = Hash::repeat_byte(2); - let hash_c = Hash::repeat_byte(3); + let hash_a = Hash::repeat_byte(1); + let hash_b = Hash::repeat_byte(2); + let hash_c = Hash::repeat_byte(3); - let candidate = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = hash_c; - c.descriptor.para_id = 1.into(); - c - }; - let candidate_hash = candidate.hash(); + let candidate = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = hash_c; + c.descriptor.para_id = 1.into(); + c + }; + let candidate_hash = candidate.hash(); - let old_view = view![hash_a, hash_b]; - let new_view = view![hash_b, hash_c]; + let old_view = view![hash_a, hash_b]; + let new_view = view![hash_b, hash_c]; - let mut active_heads = HashMap::new(); - let validators = vec![ - Sr25519Keyring::Alice.public().into(), - Sr25519Keyring::Bob.public().into(), - Sr25519Keyring::Charlie.public().into(), - ]; + let mut active_heads = HashMap::new(); + let validators = vec![ + Sr25519Keyring::Alice.public().into(), + Sr25519Keyring::Bob.public().into(), + Sr25519Keyring::Charlie.public().into(), + ]; - let session_index = 1; - let signing_context = SigningContext { - parent_hash: hash_c, - session_index, - }; + let session_index = 1; + let signing_context = SigningContext { + parent_hash: hash_c, + session_index, + }; - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = SyncCryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) - ).unwrap(); - let bob_public = SyncCryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Bob.to_seed()) - ).unwrap(); - let charlie_public = SyncCryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Charlie.to_seed()) - ).unwrap(); + let alice_public = SyncCryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) + ).unwrap(); + let bob_public = SyncCryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Bob.to_seed()) + ).unwrap(); + let charlie_public = SyncCryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Charlie.to_seed()) + ).unwrap(); - let new_head_data = { - let mut data = ActiveHeadData::new( - validators, - session_index, - PerLeafSpan::new(Arc::new(jaeger::Span::Disabled), "test"), - ); + let new_head_data = { + let mut data = ActiveHeadData::new( + validators, + session_index, + PerLeafSpan::new(Arc::new(jaeger::Span::Disabled), "test"), + ); - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok()); - let noted = data.note_statement(statement); + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate.clone()), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok()); + let noted = data.note_statement(statement); - assert_matches!(noted, NotedStatement::Fresh(_)); + assert_matches!(noted, NotedStatement::Fresh(_)); - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Valid(candidate_hash), - &signing_context, - ValidatorIndex(1), - &bob_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok()); - let noted = data.note_statement(statement); + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Valid(candidate_hash), + &signing_context, + ValidatorIndex(1), + &bob_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok()); + let noted = data.note_statement(statement); - assert_matches!(noted, NotedStatement::Fresh(_)); + assert_matches!(noted, NotedStatement::Fresh(_)); - let statement = block_on(SignedFullStatement::sign( - &keystore, - Statement::Valid(candidate_hash), - &signing_context, - ValidatorIndex(2), - &charlie_public.into(), - )).ok().flatten().expect("should be signed"); - assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok()); - let noted = data.note_statement(statement); - assert_matches!(noted, NotedStatement::Fresh(_)); + let statement = block_on(SignedFullStatement::sign( + &keystore, + Statement::Valid(candidate_hash), + &signing_context, + ValidatorIndex(2), + &charlie_public.into(), + )).ok().flatten().expect("should be signed"); + assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok()); + let noted = data.note_statement(statement); + assert_matches!(noted, NotedStatement::Fresh(_)); - data - }; + data + }; - active_heads.insert(hash_c, new_head_data); + active_heads.insert(hash_c, new_head_data); - let mut peer_data = PeerData { - view: old_view, - view_knowledge: { - let mut k = HashMap::new(); + let mut peer_data = PeerData { + view: old_view, + view_knowledge: { + let mut k = HashMap::new(); - k.insert(hash_a, Default::default()); - k.insert(hash_b, Default::default()); + k.insert(hash_a, Default::default()); + k.insert(hash_b, Default::default()); - k - }, - maybe_authority: None, - }; + k + }, + maybe_authority: None, + }; - let pool = sp_core::testing::TaskExecutor::new(); - let (mut ctx, mut handle) = - polkadot_node_subsystem_test_helpers - ::make_subsystem_context - ::(pool); - let peer = PeerId::random(); + let pool = sp_core::testing::TaskExecutor::new(); + let (mut ctx, mut handle) = + polkadot_node_subsystem_test_helpers + ::make_subsystem_context + ::(pool); + let peer = PeerId::random(); - executor::block_on(async move { - update_peer_view_and_send_unlocked( - peer.clone(), - &mut peer_data, - &mut ctx, - &active_heads, - new_view.clone(), - &Default::default(), - ).await; + executor::block_on(async move { + update_peer_view_and_send_unlocked( + peer.clone(), + &mut peer_data, + &mut ctx, + &active_heads, + new_view.clone(), + &Default::default(), + ).await; - assert_eq!(peer_data.view, new_view); - assert!(!peer_data.view_knowledge.contains_key(&hash_a)); - assert!(peer_data.view_knowledge.contains_key(&hash_b)); + assert_eq!(peer_data.view, new_view); + assert!(!peer_data.view_knowledge.contains_key(&hash_a)); + assert!(peer_data.view_knowledge.contains_key(&hash_b)); - let c_knowledge = peer_data.view_knowledge.get(&hash_c).unwrap(); + let c_knowledge = peer_data.view_knowledge.get(&hash_c).unwrap(); - assert!(c_knowledge.is_known_candidate(&candidate_hash)); - assert!(c_knowledge.sent_statements.contains( - &(CompactStatement::Seconded(candidate_hash), ValidatorIndex(0)) - )); - assert!(c_knowledge.sent_statements.contains( - &(CompactStatement::Valid(candidate_hash), ValidatorIndex(1)) - )); - assert!(c_knowledge.sent_statements.contains( - &(CompactStatement::Valid(candidate_hash), ValidatorIndex(2)) - )); + assert!(c_knowledge.is_known_candidate(&candidate_hash)); + assert!(c_knowledge.sent_statements.contains( + &(CompactStatement::Seconded(candidate_hash), ValidatorIndex(0)) + )); + assert!(c_knowledge.sent_statements.contains( + &(CompactStatement::Valid(candidate_hash), ValidatorIndex(1)) + )); + assert!(c_knowledge.sent_statements.contains( + &(CompactStatement::Valid(candidate_hash), ValidatorIndex(2)) + )); - // now see if we got the 3 messages from the active head data. - let active_head = active_heads.get(&hash_c).unwrap(); + // now see if we got the 3 messages from the active head data. + let active_head = active_heads.get(&hash_c).unwrap(); - // semi-fragile because hashmap iterator ordering is undefined, but in practice - // it will not change between runs of the program. - for statement in active_head.statements_about(candidate_hash) { - let message = handle.recv().await; - let expected_to = vec![peer.clone()]; - let expected_payload - = statement_message(hash_c, statement.statement.clone()); + // semi-fragile because hashmap iterator ordering is undefined, but in practice + // it will not change between runs of the program. + for statement in active_head.statements_about(candidate_hash) { + let message = handle.recv().await; + let expected_to = vec![peer.clone()]; + let expected_payload + = statement_message(hash_c, statement.statement.clone()); - assert_matches!( - message, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage( - to, - payload, - )) => { - assert_eq!(to, expected_to); - assert_eq!(payload, expected_payload) - } - ) - } - }); + assert_matches!( + message, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage( + to, + payload, + )) => { + assert_eq!(to, expected_to); + assert_eq!(payload, expected_payload) + } + ) + } + }); } #[test] fn circulated_statement_goes_to_all_peers_with_view() { - let hash_a = Hash::repeat_byte(1); - let hash_b = Hash::repeat_byte(2); - let hash_c = Hash::repeat_byte(3); + let hash_a = Hash::repeat_byte(1); + let hash_b = Hash::repeat_byte(2); + let hash_c = Hash::repeat_byte(3); - let candidate = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = hash_b; - c.descriptor.para_id = 1.into(); - c - }; + let candidate = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = hash_b; + c.descriptor.para_id = 1.into(); + c + }; - let peer_a = PeerId::random(); - let peer_b = PeerId::random(); - let peer_c = PeerId::random(); + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); + let peer_c = PeerId::random(); - let peer_a_view = view![hash_a]; - let peer_b_view = view![hash_a, hash_b]; - let peer_c_view = view![hash_b, hash_c]; + let peer_a_view = view![hash_a]; + let peer_b_view = view![hash_a, hash_b]; + let peer_c_view = view![hash_b, hash_c]; - let session_index = 1; + let session_index = 1; - let peer_data_from_view = |view: View| PeerData { - view: view.clone(), - view_knowledge: view.iter().map(|v| (v.clone(), Default::default())).collect(), - maybe_authority: None, - }; + let peer_data_from_view = |view: View| PeerData { + view: view.clone(), + view_knowledge: view.iter().map(|v| (v.clone(), Default::default())).collect(), + maybe_authority: None, + }; - let mut peer_data: HashMap<_, _> = vec![ - (peer_a.clone(), peer_data_from_view(peer_a_view)), - (peer_b.clone(), peer_data_from_view(peer_b_view)), - (peer_c.clone(), peer_data_from_view(peer_c_view)), - ].into_iter().collect(); + let mut peer_data: HashMap<_, _> = vec![ + (peer_a.clone(), peer_data_from_view(peer_a_view)), + (peer_b.clone(), peer_data_from_view(peer_b_view)), + (peer_c.clone(), peer_data_from_view(peer_c_view)), + ].into_iter().collect(); - let pool = sp_core::testing::TaskExecutor::new(); - let (mut ctx, mut handle) = - polkadot_node_subsystem_test_helpers - ::make_subsystem_context - ::(pool); + let pool = sp_core::testing::TaskExecutor::new(); + let (mut ctx, mut handle) = + polkadot_node_subsystem_test_helpers + ::make_subsystem_context + ::(pool); - executor::block_on(async move { - let signing_context = SigningContext { - parent_hash: hash_b, - session_index, - }; + executor::block_on(async move { + let signing_context = SigningContext { + parent_hash: hash_b, + session_index, + }; - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = CryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) - ).await.unwrap(); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let alice_public = CryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) + ).await.unwrap(); - let statement = SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ).await.ok().flatten().expect("should be signed"); + let statement = SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + ).await.ok().flatten().expect("should be signed"); - let comparator = StoredStatementComparator { - compact: statement.payload().to_compact(), - validator_index: ValidatorIndex(0), - signature: statement.signature().clone() - }; - let statement = StoredStatement { - comparator: &comparator, - statement: &statement, - }; + let comparator = StoredStatementComparator { + compact: statement.payload().to_compact(), + validator_index: ValidatorIndex(0), + signature: statement.signature().clone() + }; + let statement = StoredStatement { + comparator: &comparator, + statement: &statement, + }; - let needs_dependents = circulate_statement( - &mut peer_data, - &mut ctx, - hash_b, - statement, - Vec::new(), - ).await; + let needs_dependents = circulate_statement( + &mut peer_data, + &mut ctx, + hash_b, + statement, + Vec::new(), + ).await; - { - assert_eq!(needs_dependents.len(), 2); - assert!(needs_dependents.contains(&peer_b)); - assert!(needs_dependents.contains(&peer_c)); - } + { + assert_eq!(needs_dependents.len(), 2); + assert!(needs_dependents.contains(&peer_b)); + assert!(needs_dependents.contains(&peer_c)); + } - let fingerprint = (statement.compact().clone(), ValidatorIndex(0)); + let fingerprint = (statement.compact().clone(), ValidatorIndex(0)); - assert!( - peer_data.get(&peer_b).unwrap() - .view_knowledge.get(&hash_b).unwrap() - .sent_statements.contains(&fingerprint), - ); + assert!( + peer_data.get(&peer_b).unwrap() + .view_knowledge.get(&hash_b).unwrap() + .sent_statements.contains(&fingerprint), + ); - assert!( - peer_data.get(&peer_c).unwrap() - .view_knowledge.get(&hash_b).unwrap() - .sent_statements.contains(&fingerprint), - ); + assert!( + peer_data.get(&peer_c).unwrap() + .view_knowledge.get(&hash_b).unwrap() + .sent_statements.contains(&fingerprint), + ); - let message = handle.recv().await; - assert_matches!( - message, - AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage( - to, - payload, - )) => { - assert_eq!(to.len(), 2); - assert!(to.contains(&peer_b)); - assert!(to.contains(&peer_c)); + let message = handle.recv().await; + assert_matches!( + message, + AllMessages::NetworkBridge(NetworkBridgeMessage::SendValidationMessage( + to, + payload, + )) => { + assert_eq!(to.len(), 2); + assert!(to.contains(&peer_b)); + assert!(to.contains(&peer_c)); - assert_eq!( - payload, - statement_message(hash_b, statement.statement.clone()), - ); - } - ) - }); + assert_eq!( + payload, + statement_message(hash_b, statement.statement.clone()), + ); + } + ) + }); } #[test] fn receiving_from_one_sends_to_another_and_to_candidate_backing() { - let hash_a = Hash::repeat_byte(1); + let hash_a = Hash::repeat_byte(1); - let candidate = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c - }; + let candidate = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = hash_a; + c.descriptor.para_id = 1.into(); + c + }; - let peer_a = PeerId::random(); - let peer_b = PeerId::random(); + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - ]; + let validators = vec![ + Sr25519Keyring::Alice.pair(), + Sr25519Keyring::Bob.pair(), + Sr25519Keyring::Charlie.pair(), + ]; - let session_info = make_session_info(validators, vec![]); + let session_info = make_session_info(validators, vec![]); - let session_index = 1; + let session_index = 1; - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); + let pool = sp_core::testing::TaskExecutor::new(); + let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - let bg = async move { - let s = StatementDistribution { metrics: Default::default(), keystore: Arc::new(LocalKeystore::in_memory()) }; - s.run(ctx).await.unwrap(); - }; + let bg = async move { + let s = StatementDistribution { metrics: Default::default(), keystore: Arc::new(LocalKeystore::in_memory()) }; + s.run(ctx).await.unwrap(); + }; - let test_fut = async move { - // register our active heads. - handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: vec![ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].into(), - deactivated: vec![].into(), - }))).await; + let test_fut = async move { + // register our active heads. + handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: vec![ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].into(), + deactivated: vec![].into(), + }))).await; - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) + ) + if r == hash_a + => { + let _ = tx.send(Ok(session_index)); + } + ); - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) + ) + if r == hash_a && sess_index == session_index + => { + let _ = tx.send(Ok(Some(session_info))); + } + ); - // notify of peers and view - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected(peer_a.clone(), ObservedRole::Full, None) - ) - }).await; + // notify of peers and view + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected(peer_a.clone(), ObservedRole::Full, None) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected(peer_b.clone(), ObservedRole::Full, None) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected(peer_b.clone(), ObservedRole::Full, None) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_b.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_b.clone(), view![hash_a]) + ) + }).await; - // receive a seconded statement from peer A. it should be propagated onwards to peer B and to - // candidate backing. - let statement = { - let signing_context = SigningContext { - parent_hash: hash_a, - session_index, - }; + // receive a seconded statement from peer A. it should be propagated onwards to peer B and to + // candidate backing. + let statement = { + let signing_context = SigningContext { + parent_hash: hash_a, + session_index, + }; - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = CryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) - ).await.unwrap(); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let alice_public = CryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) + ).await.unwrap(); - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ).await.ok().flatten().expect("should be signed") - }; + SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + ).await.ok().flatten().expect("should be signed") + }; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_a.clone(), - protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()), - ) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_a.clone(), + protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()), + ) + ) + }).await; - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(p, r) - ) if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST => {} - ); + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(p, r) + ) if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST => {} + ); - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking( - CandidateBackingMessage::Statement(r, s) - ) if r == hash_a && s == statement => {} - ); + assert_matches!( + handle.recv().await, + AllMessages::CandidateBacking( + CandidateBackingMessage::Statement(r, s) + ) if r == hash_a && s == statement => {} + ); - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendValidationMessage( - recipients, - protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::Statement(r, s) - ), - ) - ) => { - assert_eq!(recipients, vec![peer_b.clone()]); - assert_eq!(r, hash_a); - assert_eq!(s, statement.into()); - } - ); - handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; - }; + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendValidationMessage( + recipients, + protocol_v1::ValidationProtocol::StatementDistribution( + protocol_v1::StatementDistributionMessage::Statement(r, s) + ), + ) + ) => { + assert_eq!(recipients, vec![peer_b.clone()]); + assert_eq!(r, hash_a); + assert_eq!(s, statement.into()); + } + ); + handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }; - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); + futures::pin_mut!(test_fut); + futures::pin_mut!(bg); - executor::block_on(future::join(test_fut, bg)); + executor::block_on(future::join(test_fut, bg)); } #[test] fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing() { - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); - let hash_b = Hash::repeat_byte(2); + sp_tracing::try_init_simple(); + let hash_a = Hash::repeat_byte(1); + let hash_b = Hash::repeat_byte(2); - let candidate = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c.commitments.new_validation_code = Some(ValidationCode(vec![1,2,3])); - c - }; + let candidate = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = hash_a; + c.descriptor.para_id = 1.into(); + c.commitments.new_validation_code = Some(ValidationCode(vec![1,2,3])); + c + }; - let peer_a = PeerId::random(); // Alice - let peer_b = PeerId::random(); // Bob - let peer_c = PeerId::random(); // Charlie - let peer_bad = PeerId::random(); // No validator + let peer_a = PeerId::random(); // Alice + let peer_b = PeerId::random(); // Bob + let peer_c = PeerId::random(); // Charlie + let peer_bad = PeerId::random(); // No validator - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; + let validators = vec![ + Sr25519Keyring::Alice.pair(), + Sr25519Keyring::Bob.pair(), + Sr25519Keyring::Charlie.pair(), + // We: + Sr25519Keyring::Ferdie.pair(), + ]; - let session_info = make_session_info( - validators, - vec![vec![0,1,2,4], vec![3]] - ); + let session_info = make_session_info( + validators, + vec![vec![0,1,2,4], vec![3]] + ); - let session_index = 1; + let session_index = 1; - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); + let pool = sp_core::testing::TaskExecutor::new(); + let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - let bg = async move { - let s = StatementDistribution { metrics: Default::default(), keystore: make_ferdie_keystore()}; - s.run(ctx).await.unwrap(); - }; + let bg = async move { + let s = StatementDistribution { metrics: Default::default(), keystore: make_ferdie_keystore()}; + s.run(ctx).await.unwrap(); + }; - let (mut tx_reqs, rx_reqs) = mpsc::channel(1); + let (mut tx_reqs, rx_reqs) = mpsc::channel(1); - let test_fut = async move { - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::StatementFetchingReceiver(rx_reqs) - }).await; + let test_fut = async move { + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::StatementFetchingReceiver(rx_reqs) + }).await; - // register our active heads. - handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: vec![ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].into(), - deactivated: vec![].into(), - }))).await; + // register our active heads. + handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: vec![ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].into(), + deactivated: vec![].into(), + }))).await; - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) + ) + if r == hash_a + => { + let _ = tx.send(Ok(session_index)); + } + ); - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) + ) + if r == hash_a && sess_index == session_index + => { + let _ = tx.send(Ok(Some(session_info))); + } + ); - // notify of peers and view - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_a.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Alice.public().into()) - ) - ) - }).await; + // notify of peers and view + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_a.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Alice.public().into()) + ) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Bob.public().into()) - ) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_c.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Charlie.public().into()) - ) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected(peer_bad.clone(), ObservedRole::Full, None) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Bob.public().into()) + ) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_c.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Charlie.public().into()) + ) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected(peer_bad.clone(), ObservedRole::Full, None) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_b.clone(), view![hash_a]) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_c.clone(), view![hash_a]) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_bad.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_b.clone(), view![hash_a]) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_c.clone(), view![hash_a]) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_bad.clone(), view![hash_a]) + ) + }).await; - // receive a seconded statement from peer A, which does not provide the request data, - // then get that data from peer C. It should be propagated onwards to peer B and to - // candidate backing. - let statement = { - let signing_context = SigningContext { - parent_hash: hash_a, - session_index, - }; + // receive a seconded statement from peer A, which does not provide the request data, + // then get that data from peer C. It should be propagated onwards to peer B and to + // candidate backing. + let statement = { + let signing_context = SigningContext { + parent_hash: hash_a, + session_index, + }; - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = CryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) - ).await.unwrap(); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let alice_public = CryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) + ).await.unwrap(); - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ).await.ok().flatten().expect("should be signed") - }; + SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate.clone()), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + ).await.ok().flatten().expect("should be signed") + }; - let metadata = - protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()).get_metadata(); + let metadata = + protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()).get_metadata(); - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_a.clone(), - protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), - ) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_a.clone(), + protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), + ) + ) + }).await; - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - // Just drop request - should trigger error. - } - ); + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); + // Just drop request - should trigger error. + } + ); - // There is a race between request handler asking for more peers and processing of the - // coming `PeerMessage`s, we want the request handler to ask first here for better test - // coverage: - Delay::new(Duration::from_millis(20)).await; + // There is a race between request handler asking for more peers and processing of the + // coming `PeerMessage`s, we want the request handler to ask first here for better test + // coverage: + Delay::new(Duration::from_millis(20)).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_c.clone(), - protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), - ) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_c.clone(), + protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), + ) + ) + }).await; - // Malicious peer: - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_bad.clone(), - protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), - ) - ) - }).await; + // Malicious peer: + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_bad.clone(), + protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), + ) + ) + }).await; - // Let c fail once too: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - } - ); + // Let c fail once too: + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); + } + ); - // a fails again: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - } - ); + // a fails again: + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + // On retry, we should have reverse order: + assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); + } + ); - // Send invalid response (all other peers have been tried now): - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_bad)); - let bad_candidate = { - let mut bad = candidate.clone(); - bad.descriptor.para_id = 0xeadbeaf.into(); - bad - }; - let response = StatementFetchingResponse::Statement(bad_candidate); - outgoing.pending_response.send(Ok(response.encode())).unwrap(); - } - ); + // Send invalid response (all other peers have been tried now): + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + assert_eq!(outgoing.peer, Recipient::Peer(peer_bad)); + let bad_candidate = { + let mut bad = candidate.clone(); + bad.descriptor.para_id = 0xeadbeaf.into(); + bad + }; + let response = StatementFetchingResponse::Statement(bad_candidate); + outgoing.pending_response.send(Ok(response.encode())).unwrap(); + } + ); - // Should get punished and never tried again: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(p, r) - ) if p == peer_bad && r == COST_WRONG_HASH => {} - ); + // Should get punished and never tried again: + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(p, r) + ) if p == peer_bad && r == COST_WRONG_HASH => {} + ); - // a is tried again (retried in reverse order): - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - } - ); + // a is tried again (retried in reverse order): + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + // On retry, we should have reverse order: + assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); + } + ); - // c succeeds now: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - let response = StatementFetchingResponse::Statement(candidate.clone()); - outgoing.pending_response.send(Ok(response.encode())).unwrap(); - } - ); + // c succeeds now: + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + // On retry, we should have reverse order: + assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); + let response = StatementFetchingResponse::Statement(candidate.clone()); + outgoing.pending_response.send(Ok(response.encode())).unwrap(); + } + ); - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(p, r) - ) if p == peer_a && r == COST_FETCH_FAIL => {} - ); + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(p, r) + ) if p == peer_a && r == COST_FETCH_FAIL => {} + ); - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(p, r) - ) if p == peer_c && r == BENEFIT_VALID_RESPONSE => {} - ); + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(p, r) + ) if p == peer_c && r == BENEFIT_VALID_RESPONSE => {} + ); - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(p, r) - ) if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST => {} - ); + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(p, r) + ) if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST => {} + ); - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking( - CandidateBackingMessage::Statement(r, s) - ) if r == hash_a && s == statement => {} - ); + assert_matches!( + handle.recv().await, + AllMessages::CandidateBacking( + CandidateBackingMessage::Statement(r, s) + ) if r == hash_a && s == statement => {} + ); - // Now messages should go out: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendValidationMessage( - mut recipients, - protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::LargeStatement(meta) - ), - ) - ) => { - tracing::debug!( - target: LOG_TARGET, - ?recipients, - "Recipients received" - ); - recipients.sort(); - let mut expected = vec![peer_b, peer_c, peer_bad]; - expected.sort(); - assert_eq!(recipients, expected); - assert_eq!(meta.relay_parent, hash_a); - assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); - assert_eq!(meta.signed_by, statement.validator_index()); - assert_eq!(&meta.signature, statement.signature()); - } - ); + // Now messages should go out: + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendValidationMessage( + mut recipients, + protocol_v1::ValidationProtocol::StatementDistribution( + protocol_v1::StatementDistributionMessage::LargeStatement(meta) + ), + ) + ) => { + tracing::debug!( + target: LOG_TARGET, + ?recipients, + "Recipients received" + ); + recipients.sort(); + let mut expected = vec![peer_b, peer_c, peer_bad]; + expected.sort(); + assert_eq!(recipients, expected); + assert_eq!(meta.relay_parent, hash_a); + assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); + assert_eq!(meta.signed_by, statement.validator_index()); + assert_eq!(&meta.signature, statement.signature()); + } + ); - // Now that it has the candidate it should answer requests accordingly (even after a - // failed request): + // Now that it has the candidate it should answer requests accordingly (even after a + // failed request): - // Failing request first (wrong relay parent hash): - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: hash_b, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_b, - payload: inner_req.encode(), - pending_response, - }; - tx_reqs.send(req).await.unwrap(); - assert_matches!( - response_rx.await.unwrap().result, - Err(()) => {} - ); + // Failing request first (wrong relay parent hash): + let (pending_response, response_rx) = oneshot::channel(); + let inner_req = StatementFetchingRequest { + relay_parent: hash_b, + candidate_hash: metadata.candidate_hash, + }; + let req = sc_network::config::IncomingRequest { + peer: peer_b, + payload: inner_req.encode(), + pending_response, + }; + tx_reqs.send(req).await.unwrap(); + assert_matches!( + response_rx.await.unwrap().result, + Err(()) => {} + ); - // Another failing request (peer_a never received a statement from us, so it is not - // allowed to request the data): - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: metadata.relay_parent, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_a, - payload: inner_req.encode(), - pending_response, - }; - tx_reqs.send(req).await.unwrap(); - assert_matches!( - response_rx.await.unwrap().result, - Err(()) => {} - ); + // Another failing request (peer_a never received a statement from us, so it is not + // allowed to request the data): + let (pending_response, response_rx) = oneshot::channel(); + let inner_req = StatementFetchingRequest { + relay_parent: metadata.relay_parent, + candidate_hash: metadata.candidate_hash, + }; + let req = sc_network::config::IncomingRequest { + peer: peer_a, + payload: inner_req.encode(), + pending_response, + }; + tx_reqs.send(req).await.unwrap(); + assert_matches!( + response_rx.await.unwrap().result, + Err(()) => {} + ); - // And now the succeding request from peer_b: - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: metadata.relay_parent, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_b, - payload: inner_req.encode(), - pending_response, - }; - tx_reqs.send(req).await.unwrap(); - let StatementFetchingResponse::Statement(committed) = - Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); - assert_eq!(committed, candidate); + // And now the succeding request from peer_b: + let (pending_response, response_rx) = oneshot::channel(); + let inner_req = StatementFetchingRequest { + relay_parent: metadata.relay_parent, + candidate_hash: metadata.candidate_hash, + }; + let req = sc_network::config::IncomingRequest { + peer: peer_b, + payload: inner_req.encode(), + pending_response, + }; + tx_reqs.send(req).await.unwrap(); + let StatementFetchingResponse::Statement(committed) = + Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); + assert_eq!(committed, candidate); - handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; - }; + handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }; - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); + futures::pin_mut!(test_fut); + futures::pin_mut!(bg); - executor::block_on(future::join(test_fut, bg)); + executor::block_on(future::join(test_fut, bg)); } #[test] fn share_prioritizes_backing_group() { - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); + sp_tracing::try_init_simple(); + let hash_a = Hash::repeat_byte(1); - let candidate = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c.commitments.new_validation_code = Some(ValidationCode(vec![1,2,3])); - c - }; + let candidate = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = hash_a; + c.descriptor.para_id = 1.into(); + c.commitments.new_validation_code = Some(ValidationCode(vec![1,2,3])); + c + }; - let peer_a = PeerId::random(); // Alice - let peer_b = PeerId::random(); // Bob - let peer_c = PeerId::random(); // Charlie - let peer_bad = PeerId::random(); // No validator - let peer_other_group = PeerId::random(); //Ferdie + let peer_a = PeerId::random(); // Alice + let peer_b = PeerId::random(); // Bob + let peer_c = PeerId::random(); // Charlie + let peer_bad = PeerId::random(); // No validator + let peer_other_group = PeerId::random(); //Ferdie - let mut validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // other group - Sr25519Keyring::Dave.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; + let mut validators = vec![ + Sr25519Keyring::Alice.pair(), + Sr25519Keyring::Bob.pair(), + Sr25519Keyring::Charlie.pair(), + // other group + Sr25519Keyring::Dave.pair(), + // We: + Sr25519Keyring::Ferdie.pair(), + ]; - // Strictly speaking we only need MIN_GOSSIP_PEERS - 3 to make sure only priority peers - // will be served, but by using a larger value we test for overflow errors: - let dummy_count = MIN_GOSSIP_PEERS; + // Strictly speaking we only need MIN_GOSSIP_PEERS - 3 to make sure only priority peers + // will be served, but by using a larger value we test for overflow errors: + let dummy_count = MIN_GOSSIP_PEERS; - // We artificially inflate our group, so there won't be any free slots for other peers. (We - // want to test that our group is prioritized): - let dummy_pairs: Vec<_> = std::iter::repeat_with(|| Pair::generate().0).take(dummy_count).collect(); - let dummy_peers: Vec<_> = std::iter::repeat_with(|| PeerId::random()).take(dummy_count).collect(); + // We artificially inflate our group, so there won't be any free slots for other peers. (We + // want to test that our group is prioritized): + let dummy_pairs: Vec<_> = std::iter::repeat_with(|| Pair::generate().0).take(dummy_count).collect(); + let dummy_peers: Vec<_> = std::iter::repeat_with(|| PeerId::random()).take(dummy_count).collect(); - validators = validators.into_iter().chain(dummy_pairs.clone()).collect(); + validators = validators.into_iter().chain(dummy_pairs.clone()).collect(); - let mut first_group = vec![0,1,2,4]; - first_group.append(&mut (0..dummy_count as u32).map(|v| v + 5).collect()); - let session_info = make_session_info( - validators, - vec![first_group, vec![3]] - ); + let mut first_group = vec![0,1,2,4]; + first_group.append(&mut (0..dummy_count as u32).map(|v| v + 5).collect()); + let session_info = make_session_info( + validators, + vec![first_group, vec![3]] + ); - let session_index = 1; + let session_index = 1; - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); + let pool = sp_core::testing::TaskExecutor::new(); + let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - let bg = async move { - let s = StatementDistribution { metrics: Default::default(), keystore: make_ferdie_keystore()}; - s.run(ctx).await.unwrap(); - }; + let bg = async move { + let s = StatementDistribution { metrics: Default::default(), keystore: make_ferdie_keystore()}; + s.run(ctx).await.unwrap(); + }; - let (mut tx_reqs, rx_reqs) = mpsc::channel(1); + let (mut tx_reqs, rx_reqs) = mpsc::channel(1); - let test_fut = async move { - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::StatementFetchingReceiver(rx_reqs) - }).await; + let test_fut = async move { + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::StatementFetchingReceiver(rx_reqs) + }).await; - // register our active heads. - handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: vec![ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].into(), - deactivated: vec![].into(), - }))).await; + // register our active heads. + handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: vec![ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].into(), + deactivated: vec![].into(), + }))).await; - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) + ) + if r == hash_a + => { + let _ = tx.send(Ok(session_index)); + } + ); - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) + ) + if r == hash_a && sess_index == session_index + => { + let _ = tx.send(Ok(Some(session_info))); + } + ); - // notify of dummy peers and view - for (peer, pair) in dummy_peers.clone().into_iter().zip(dummy_pairs) { - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer, - ObservedRole::Full, - Some(pair.public().into()), - ) - ) - }).await; + // notify of dummy peers and view + for (peer, pair) in dummy_peers.clone().into_iter().zip(dummy_pairs) { + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer, + ObservedRole::Full, + Some(pair.public().into()), + ) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer, view![hash_a]) - ) - }).await; - } + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer, view![hash_a]) + ) + }).await; + } - // notify of peers and view - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_a.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Alice.public().into()) - ) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_b.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Bob.public().into()) - ) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_c.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Charlie.public().into()) - ) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected(peer_bad.clone(), ObservedRole::Full, None) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_other_group.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Dave.public().into()) - ) - ) - }).await; + // notify of peers and view + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_a.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Alice.public().into()) + ) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_b.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Bob.public().into()) + ) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_c.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Charlie.public().into()) + ) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected(peer_bad.clone(), ObservedRole::Full, None) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_other_group.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Dave.public().into()) + ) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_b.clone(), view![hash_a]) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_c.clone(), view![hash_a]) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_bad.clone(), view![hash_a]) - ) - }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_other_group.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_b.clone(), view![hash_a]) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_c.clone(), view![hash_a]) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_bad.clone(), view![hash_a]) + ) + }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_other_group.clone(), view![hash_a]) + ) + }).await; - // receive a seconded statement from peer A, which does not provide the request data, - // then get that data from peer C. It should be propagated onwards to peer B and to - // candidate backing. - let statement = { - let signing_context = SigningContext { - parent_hash: hash_a, - session_index, - }; + // receive a seconded statement from peer A, which does not provide the request data, + // then get that data from peer C. It should be propagated onwards to peer B and to + // candidate backing. + let statement = { + let signing_context = SigningContext { + parent_hash: hash_a, + session_index, + }; - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let ferdie_public = CryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Ferdie.to_seed()) - ).await.unwrap(); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let ferdie_public = CryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Ferdie.to_seed()) + ).await.unwrap(); - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone()), - &signing_context, - ValidatorIndex(4), - &ferdie_public.into(), - ).await.ok().flatten().expect("should be signed") - }; + SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate.clone()), + &signing_context, + ValidatorIndex(4), + &ferdie_public.into(), + ).await.ok().flatten().expect("should be signed") + }; - let metadata = - protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()).get_metadata(); + let metadata = + protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()).get_metadata(); - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::Share(hash_a, statement.clone()) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::Share(hash_a, statement.clone()) + }).await; - // Messages should go out: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendValidationMessage( - mut recipients, - protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::LargeStatement(meta) - ), - ) - ) => { - tracing::debug!( - target: LOG_TARGET, - ?recipients, - "Recipients received" - ); - recipients.sort(); - // We expect only our backing group to be the recipients, du to the inflated - // test group above: - let mut expected: Vec<_> = vec![peer_a, peer_b, peer_c].into_iter().chain(dummy_peers).collect(); - expected.sort(); - assert_eq!(recipients.len(), expected.len()); - assert_eq!(recipients, expected); - assert_eq!(meta.relay_parent, hash_a); - assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); - assert_eq!(meta.signed_by, statement.validator_index()); - assert_eq!(&meta.signature, statement.signature()); - } - ); + // Messages should go out: + assert_matches!( + handle.recv().await, + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendValidationMessage( + mut recipients, + protocol_v1::ValidationProtocol::StatementDistribution( + protocol_v1::StatementDistributionMessage::LargeStatement(meta) + ), + ) + ) => { + tracing::debug!( + target: LOG_TARGET, + ?recipients, + "Recipients received" + ); + recipients.sort(); + // We expect only our backing group to be the recipients, du to the inflated + // test group above: + let mut expected: Vec<_> = vec![peer_a, peer_b, peer_c].into_iter().chain(dummy_peers).collect(); + expected.sort(); + assert_eq!(recipients.len(), expected.len()); + assert_eq!(recipients, expected); + assert_eq!(meta.relay_parent, hash_a); + assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); + assert_eq!(meta.signed_by, statement.validator_index()); + assert_eq!(&meta.signature, statement.signature()); + } + ); - // Now that it has the candidate it should answer requests accordingly: + // Now that it has the candidate it should answer requests accordingly: - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: metadata.relay_parent, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_b, - payload: inner_req.encode(), - pending_response, - }; - tx_reqs.send(req).await.unwrap(); - let StatementFetchingResponse::Statement(committed) = - Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); - assert_eq!(committed, candidate); + let (pending_response, response_rx) = oneshot::channel(); + let inner_req = StatementFetchingRequest { + relay_parent: metadata.relay_parent, + candidate_hash: metadata.candidate_hash, + }; + let req = sc_network::config::IncomingRequest { + peer: peer_b, + payload: inner_req.encode(), + pending_response, + }; + tx_reqs.send(req).await.unwrap(); + let StatementFetchingResponse::Statement(committed) = + Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); + assert_eq!(committed, candidate); - handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; - }; + handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }; - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); + futures::pin_mut!(test_fut); + futures::pin_mut!(bg); - executor::block_on(future::join(test_fut, bg)); + executor::block_on(future::join(test_fut, bg)); } #[test] fn peer_cant_flood_with_large_statements() { - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); + sp_tracing::try_init_simple(); + let hash_a = Hash::repeat_byte(1); - let candidate = { - let mut c = CommittedCandidateReceipt::default(); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c.commitments.new_validation_code = Some(ValidationCode(vec![1,2,3])); - c - }; + let candidate = { + let mut c = CommittedCandidateReceipt::default(); + c.descriptor.relay_parent = hash_a; + c.descriptor.para_id = 1.into(); + c.commitments.new_validation_code = Some(ValidationCode(vec![1,2,3])); + c + }; - let peer_a = PeerId::random(); // Alice + let peer_a = PeerId::random(); // Alice - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // other group - Sr25519Keyring::Dave.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; + let validators = vec![ + Sr25519Keyring::Alice.pair(), + Sr25519Keyring::Bob.pair(), + Sr25519Keyring::Charlie.pair(), + // other group + Sr25519Keyring::Dave.pair(), + // We: + Sr25519Keyring::Ferdie.pair(), + ]; - let first_group = vec![0,1,2,4]; - let session_info = make_session_info( - validators, - vec![first_group, vec![3]] - ); + let first_group = vec![0,1,2,4]; + let session_info = make_session_info( + validators, + vec![first_group, vec![3]] + ); - let session_index = 1; + let session_index = 1; - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); + let pool = sp_core::testing::TaskExecutor::new(); + let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - let bg = async move { - let s = StatementDistribution { metrics: Default::default(), keystore: make_ferdie_keystore()}; - s.run(ctx).await.unwrap(); - }; + let bg = async move { + let s = StatementDistribution { metrics: Default::default(), keystore: make_ferdie_keystore()}; + s.run(ctx).await.unwrap(); + }; - let (_, rx_reqs) = mpsc::channel(1); + let (_, rx_reqs) = mpsc::channel(1); - let test_fut = async move { - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::StatementFetchingReceiver(rx_reqs) - }).await; + let test_fut = async move { + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::StatementFetchingReceiver(rx_reqs) + }).await; - // register our active heads. - handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: vec![ActivatedLeaf { - hash: hash_a, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].into(), - deactivated: vec![].into(), - }))).await; + // register our active heads. + handle.send(FromOverseer::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: vec![ActivatedLeaf { + hash: hash_a, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].into(), + deactivated: vec![].into(), + }))).await; - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) + ) + if r == hash_a + => { + let _ = tx.send(Ok(session_index)); + } + ); - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) + ) + if r == hash_a && sess_index == session_index + => { + let _ = tx.send(Ok(Some(session_info))); + } + ); - // notify of peers and view - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerConnected( - peer_a.clone(), - ObservedRole::Full, - Some(Sr25519Keyring::Alice.public().into()) - ) - ) - }).await; + // notify of peers and view + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerConnected( + peer_a.clone(), + ObservedRole::Full, + Some(Sr25519Keyring::Alice.public().into()) + ) + ) + }).await; - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) - ) - }).await; + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerViewChange(peer_a.clone(), view![hash_a]) + ) + }).await; - // receive a seconded statement from peer A. - let statement = { - let signing_context = SigningContext { - parent_hash: hash_a, - session_index, - }; + // receive a seconded statement from peer A. + let statement = { + let signing_context = SigningContext { + parent_hash: hash_a, + session_index, + }; - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = CryptoStore::sr25519_generate_new( - &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) - ).await.unwrap(); + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + let alice_public = CryptoStore::sr25519_generate_new( + &*keystore, ValidatorId::ID, Some(&Sr25519Keyring::Alice.to_seed()) + ).await.unwrap(); - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ).await.ok().flatten().expect("should be signed") - }; + SignedFullStatement::sign( + &keystore, + Statement::Seconded(candidate.clone()), + &signing_context, + ValidatorIndex(0), + &alice_public.into(), + ).await.ok().flatten().expect("should be signed") + }; - let metadata = - protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()).get_metadata(); + let metadata = + protocol_v1::StatementDistributionMessage::Statement(hash_a, statement.clone().into()).get_metadata(); - for _ in 0..MAX_LARGE_STATEMENTS_PER_SENDER + 1 { - handle.send(FromOverseer::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdateV1( - NetworkBridgeEvent::PeerMessage( - peer_a.clone(), - protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), - ) - ) - }).await; - } + for _ in 0..MAX_LARGE_STATEMENTS_PER_SENDER + 1 { + handle.send(FromOverseer::Communication { + msg: StatementDistributionMessage::NetworkBridgeUpdateV1( + NetworkBridgeEvent::PeerMessage( + peer_a.clone(), + protocol_v1::StatementDistributionMessage::LargeStatement(metadata.clone()), + ) + ) + }).await; + } - // We should try to fetch the data and punish the peer (but we don't know what comes - // first): - let mut requested = false; - let mut punished = false; - for _ in 0..2 { - match handle.recv().await { - AllMessages::NetworkBridge( - NetworkBridgeMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetching(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - // Just drop request - should trigger error. - requested = true; - } + // We should try to fetch the data and punish the peer (but we don't know what comes + // first): + let mut requested = false; + let mut punished = false; + for _ in 0..2 { + match handle.recv().await { + AllMessages::NetworkBridge( + NetworkBridgeMessage::SendRequests( + mut reqs, IfDisconnected::ImmediateError + ) + ) => { + let reqs = reqs.pop().unwrap(); + let outgoing = match reqs { + Requests::StatementFetching(outgoing) => outgoing, + _ => panic!("Unexpected request"), + }; + let req = outgoing.payload; + assert_eq!(req.relay_parent, metadata.relay_parent); + assert_eq!(req.candidate_hash, metadata.candidate_hash); + assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); + // Just drop request - should trigger error. + requested = true; + } - AllMessages::NetworkBridge( - NetworkBridgeMessage::ReportPeer(p, r) - ) if p == peer_a && r == COST_APPARENT_FLOOD => { - punished = true; - } + AllMessages::NetworkBridge( + NetworkBridgeMessage::ReportPeer(p, r) + ) if p == peer_a && r == COST_APPARENT_FLOOD => { + punished = true; + } - m => panic!("Unexpected message: {:?}", m), - } - } - assert!(requested, "large data has not been requested."); - assert!(punished, "Peer should have been punished for flooding."); + m => panic!("Unexpected message: {:?}", m), + } + } + assert!(requested, "large data has not been requested."); + assert!(punished, "Peer should have been punished for flooding."); - handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; - }; + handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }; - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); + futures::pin_mut!(test_fut); + futures::pin_mut!(bg); - executor::block_on(future::join(test_fut, bg)); + executor::block_on(future::join(test_fut, bg)); } fn make_session_info(validators: Vec, groups: Vec>) -> SessionInfo { - let validator_groups: Vec> = groups - .iter().map(|g| g.into_iter().map(|v| ValidatorIndex(*v)).collect()).collect(); + let validator_groups: Vec> = groups + .iter().map(|g| g.into_iter().map(|v| ValidatorIndex(*v)).collect()).collect(); - SessionInfo { - discovery_keys: validators.iter().map(|k| k.public().into()).collect(), - // Not used: - n_cores: validator_groups.len() as u32, - validator_groups, - validators: validators.iter().map(|k| k.public().into()).collect(), - // Not used values: - assignment_keys: Vec::new(), - zeroth_delay_tranche_width: 0, - relay_vrf_modulo_samples: 0, - n_delay_tranches: 0, - no_show_slots: 0, - needed_approvals: 0, - } + SessionInfo { + discovery_keys: validators.iter().map(|k| k.public().into()).collect(), + // Not used: + n_cores: validator_groups.len() as u32, + validator_groups, + validators: validators.iter().map(|k| k.public().into()).collect(), + // Not used values: + assignment_keys: Vec::new(), + zeroth_delay_tranche_width: 0, + relay_vrf_modulo_samples: 0, + n_delay_tranches: 0, + no_show_slots: 0, + needed_approvals: 0, + } } pub fn make_ferdie_keystore() -> SyncCryptoStorePtr { - let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); - SyncCryptoStore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Ferdie.to_seed()), - ) - .expect("Insert key into keystore"); - keystore + let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::in_memory()); + SyncCryptoStore::sr25519_generate_new( + &*keystore, + ValidatorId::ID, + Some(&Sr25519Keyring::Ferdie.to_seed()), + ) + .expect("Insert key into keystore"); + keystore } diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs index 2463e545fd..8dbd22b8fc 100644 --- a/polkadot/node/overseer/src/lib.rs +++ b/polkadot/node/overseer/src/lib.rs @@ -98,6 +98,9 @@ use polkadot_node_subsystem_util::{TimeoutExt, metrics::{self, prometheus}, mete use polkadot_node_primitives::SpawnNamed; use polkadot_procmacro_overseer_subsystems_gen::AllSubsystemsGen; +#[cfg(test)] +mod tests; + // A capacity of bounded channels inside the overseer. const CHANNEL_CAPACITY: usize = 1024; // The capacity of signal channels to subsystems. @@ -2196,6 +2199,3 @@ fn spawn( instance, }) } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/overseer/src/tests.rs b/polkadot/node/overseer/src/tests.rs index 6e5383b21c..c33a01dabf 100644 --- a/polkadot/node/overseer/src/tests.rs +++ b/polkadot/node/overseer/src/tests.rs @@ -32,231 +32,231 @@ use super::*; struct TestSubsystem1(metered::MeteredSender); impl Subsystem for TestSubsystem1 - where C: SubsystemContext + where C: SubsystemContext { - fn start(self, mut ctx: C) -> SpawnedSubsystem { - let mut sender = self.0; - SpawnedSubsystem { - name: "test-subsystem-1", - future: Box::pin(async move { - let mut i = 0; - loop { - match ctx.recv().await { - Ok(FromOverseer::Communication { .. }) => { - let _ = sender.send(i).await; - i += 1; - continue; - } - Ok(FromOverseer::Signal(OverseerSignal::Conclude)) => return Ok(()), - Err(_) => return Ok(()), - _ => (), - } - } - }), - } - } + fn start(self, mut ctx: C) -> SpawnedSubsystem { + let mut sender = self.0; + SpawnedSubsystem { + name: "test-subsystem-1", + future: Box::pin(async move { + let mut i = 0; + loop { + match ctx.recv().await { + Ok(FromOverseer::Communication { .. }) => { + let _ = sender.send(i).await; + i += 1; + continue; + } + Ok(FromOverseer::Signal(OverseerSignal::Conclude)) => return Ok(()), + Err(_) => return Ok(()), + _ => (), + } + } + }), + } + } } struct TestSubsystem2(metered::MeteredSender); impl Subsystem for TestSubsystem2 - where C: SubsystemContext + where C: SubsystemContext { - fn start(self, mut ctx: C) -> SpawnedSubsystem { - let sender = self.0.clone(); - SpawnedSubsystem { - name: "test-subsystem-2", - future: Box::pin(async move { - let _sender = sender; - let mut c: usize = 0; - loop { - if c < 10 { - let (tx, _) = oneshot::channel(); - ctx.send_message( - AllMessages::CandidateValidation( - CandidateValidationMessage::ValidateFromChainState( - Default::default(), - PoV { - block_data: BlockData(Vec::new()), - }.into(), - tx, - ) - ) - ).await; - c += 1; - continue; - } - match ctx.try_recv().await { - Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => { - break; - } - Ok(Some(_)) => { - continue; - } - Err(_) => return Ok(()), - _ => (), - } - pending!(); - } + fn start(self, mut ctx: C) -> SpawnedSubsystem { + let sender = self.0.clone(); + SpawnedSubsystem { + name: "test-subsystem-2", + future: Box::pin(async move { + let _sender = sender; + let mut c: usize = 0; + loop { + if c < 10 { + let (tx, _) = oneshot::channel(); + ctx.send_message( + AllMessages::CandidateValidation( + CandidateValidationMessage::ValidateFromChainState( + Default::default(), + PoV { + block_data: BlockData(Vec::new()), + }.into(), + tx, + ) + ) + ).await; + c += 1; + continue; + } + match ctx.try_recv().await { + Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => { + break; + } + Ok(Some(_)) => { + continue; + } + Err(_) => return Ok(()), + _ => (), + } + pending!(); + } - Ok(()) - }), - } - } + Ok(()) + }), + } + } } struct ReturnOnStart; impl Subsystem for ReturnOnStart - where C: SubsystemContext + where C: SubsystemContext { - fn start(self, mut _ctx: C) -> SpawnedSubsystem { - SpawnedSubsystem { - name: "test-subsystem-4", - future: Box::pin(async move { - // Do nothing and exit. - Ok(()) - }), - } - } + fn start(self, mut _ctx: C) -> SpawnedSubsystem { + SpawnedSubsystem { + name: "test-subsystem-4", + future: Box::pin(async move { + // Do nothing and exit. + Ok(()) + }), + } + } } struct MockSupportsParachains; impl HeadSupportsParachains for MockSupportsParachains { - fn head_supports_parachains(&self, _head: &Hash) -> bool { - true - } + fn head_supports_parachains(&self, _head: &Hash) -> bool { + true + } } // Checks that a minimal configuration of two jobs can run and exchange messages. #[test] fn overseer_works() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let (s1_tx, s1_rx) = metered::channel::(64); - let (s2_tx, s2_rx) = metered::channel::(64); + executor::block_on(async move { + let (s1_tx, s1_rx) = metered::channel::(64); + let (s2_tx, s2_rx) = metered::channel::(64); - let mut s1_rx = s1_rx.fuse(); - let mut s2_rx = s2_rx.fuse(); + let mut s1_rx = s1_rx.fuse(); + let mut s2_rx = s2_rx.fuse(); - let all_subsystems = AllSubsystems::<()>::dummy() - .replace_candidate_validation(TestSubsystem1(s1_tx)) - .replace_candidate_backing(TestSubsystem2(s2_tx)); + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem1(s1_tx)) + .replace_candidate_backing(TestSubsystem2(s2_tx)); - let (overseer, mut handler) = Overseer::new( - vec![], - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); - let overseer_fut = overseer.run().fuse(); + let (overseer, mut handler) = Overseer::new( + vec![], + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); + let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + pin_mut!(overseer_fut); - let mut s1_results = Vec::new(); - let mut s2_results = Vec::new(); + let mut s1_results = Vec::new(); + let mut s2_results = Vec::new(); - loop { - select! { - _ = overseer_fut => break, - s1_next = s1_rx.next() => { - match s1_next { - Some(msg) => { - s1_results.push(msg); - if s1_results.len() == 10 { - handler.stop().await; - } - } - None => break, - } - }, - s2_next = s2_rx.next() => { - match s2_next { - Some(_) => s2_results.push(s2_next), - None => break, - } - }, - complete => break, - } - } + loop { + select! { + _ = overseer_fut => break, + s1_next = s1_rx.next() => { + match s1_next { + Some(msg) => { + s1_results.push(msg); + if s1_results.len() == 10 { + handler.stop().await; + } + } + None => break, + } + }, + s2_next = s2_rx.next() => { + match s2_next { + Some(_) => s2_results.push(s2_next), + None => break, + } + }, + complete => break, + } + } - assert_eq!(s1_results, (0..10).collect::>()); - }); + assert_eq!(s1_results, (0..10).collect::>()); + }); } // Checks activated/deactivated metrics are updated properly. #[test] fn overseer_metrics_work() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let first_block_hash = [1; 32].into(); - let second_block_hash = [2; 32].into(); - let third_block_hash = [3; 32].into(); + executor::block_on(async move { + let first_block_hash = [1; 32].into(); + let second_block_hash = [2; 32].into(); + let third_block_hash = [3; 32].into(); - let first_block = BlockInfo { - hash: first_block_hash, - parent_hash: [0; 32].into(), - number: 1, - }; - let second_block = BlockInfo { - hash: second_block_hash, - parent_hash: first_block_hash, - number: 2, - }; - let third_block = BlockInfo { - hash: third_block_hash, - parent_hash: second_block_hash, - number: 3, - }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: first_block_hash, + number: 2, + }; + let third_block = BlockInfo { + hash: third_block_hash, + parent_hash: second_block_hash, + number: 3, + }; - let all_subsystems = AllSubsystems::<()>::dummy(); - let registry = prometheus::Registry::new(); - let (overseer, mut handler) = Overseer::new( - vec![first_block], - all_subsystems, - Some(®istry), - MockSupportsParachains, - spawner, - ).unwrap(); - let overseer_fut = overseer.run().fuse(); + let all_subsystems = AllSubsystems::<()>::dummy(); + let registry = prometheus::Registry::new(); + let (overseer, mut handler) = Overseer::new( + vec![first_block], + all_subsystems, + Some(®istry), + MockSupportsParachains, + spawner, + ).unwrap(); + let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + pin_mut!(overseer_fut); - handler.block_imported(second_block).await; - handler.block_imported(third_block).await; - handler.send_msg(AllMessages::CandidateValidation(test_candidate_validation_msg())).await; - handler.stop().await; + handler.block_imported(second_block).await; + handler.block_imported(third_block).await; + handler.send_msg(AllMessages::CandidateValidation(test_candidate_validation_msg())).await; + handler.stop().await; - select! { - res = overseer_fut => { - assert!(res.is_ok()); - let metrics = extract_metrics(®istry); - assert_eq!(metrics["activated"], 3); - assert_eq!(metrics["deactivated"], 2); - assert_eq!(metrics["relayed"], 1); - }, - complete => (), - } - }); + select! { + res = overseer_fut => { + assert!(res.is_ok()); + let metrics = extract_metrics(®istry); + assert_eq!(metrics["activated"], 3); + assert_eq!(metrics["deactivated"], 2); + assert_eq!(metrics["relayed"], 1); + }, + complete => (), + } + }); } fn extract_metrics(registry: &prometheus::Registry) -> HashMap<&'static str, u64> { - let gather = registry.gather(); - assert_eq!(gather[0].get_name(), "parachain_activated_heads_total"); - assert_eq!(gather[1].get_name(), "parachain_deactivated_heads_total"); - assert_eq!(gather[2].get_name(), "parachain_messages_relayed_total"); - let activated = gather[0].get_metric()[0].get_counter().get_value() as u64; - let deactivated = gather[1].get_metric()[0].get_counter().get_value() as u64; - let relayed = gather[2].get_metric()[0].get_counter().get_value() as u64; - let mut result = HashMap::new(); - result.insert("activated", activated); - result.insert("deactivated", deactivated); - result.insert("relayed", relayed); - result + let gather = registry.gather(); + assert_eq!(gather[0].get_name(), "parachain_activated_heads_total"); + assert_eq!(gather[1].get_name(), "parachain_deactivated_heads_total"); + assert_eq!(gather[2].get_name(), "parachain_messages_relayed_total"); + let activated = gather[0].get_metric()[0].get_counter().get_value() as u64; + let deactivated = gather[1].get_metric()[0].get_counter().get_value() as u64; + let relayed = gather[2].get_metric()[0].get_counter().get_value() as u64; + let mut result = HashMap::new(); + result.insert("activated", activated); + result.insert("deactivated", deactivated); + result.insert("relayed", relayed); + result } // Spawn a subsystem that immediately exits. @@ -264,890 +264,890 @@ fn extract_metrics(registry: &prometheus::Registry) -> HashMap<&'static str, u64 // Should immediately conclude the overseer itself. #[test] fn overseer_ends_on_subsystem_exit() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let all_subsystems = AllSubsystems::<()>::dummy() - .replace_candidate_backing(ReturnOnStart); - let (overseer, _handle) = Overseer::new( - vec![], - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); + executor::block_on(async move { + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_backing(ReturnOnStart); + let (overseer, _handle) = Overseer::new( + vec![], + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); - overseer.run().await.unwrap(); - }) + overseer.run().await.unwrap(); + }) } struct TestSubsystem5(metered::MeteredSender); impl Subsystem for TestSubsystem5 - where C: SubsystemContext + where C: SubsystemContext { - fn start(self, mut ctx: C) -> SpawnedSubsystem { - let mut sender = self.0.clone(); + fn start(self, mut ctx: C) -> SpawnedSubsystem { + let mut sender = self.0.clone(); - SpawnedSubsystem { - name: "test-subsystem-5", - future: Box::pin(async move { - loop { - match ctx.try_recv().await { - Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => break, - Ok(Some(FromOverseer::Signal(s))) => { - sender.send(s).await.unwrap(); - continue; - }, - Ok(Some(_)) => continue, - Err(_) => break, - _ => (), - } - pending!(); - } + SpawnedSubsystem { + name: "test-subsystem-5", + future: Box::pin(async move { + loop { + match ctx.try_recv().await { + Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => break, + Ok(Some(FromOverseer::Signal(s))) => { + sender.send(s).await.unwrap(); + continue; + }, + Ok(Some(_)) => continue, + Err(_) => break, + _ => (), + } + pending!(); + } - Ok(()) - }), - } - } + Ok(()) + }), + } + } } struct TestSubsystem6(metered::MeteredSender); impl Subsystem for TestSubsystem6 - where C: SubsystemContext + where C: SubsystemContext { - fn start(self, mut ctx: C) -> SpawnedSubsystem { - let mut sender = self.0.clone(); + fn start(self, mut ctx: C) -> SpawnedSubsystem { + let mut sender = self.0.clone(); - SpawnedSubsystem { - name: "test-subsystem-6", - future: Box::pin(async move { - loop { - match ctx.try_recv().await { - Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => break, - Ok(Some(FromOverseer::Signal(s))) => { - sender.send(s).await.unwrap(); - continue; - }, - Ok(Some(_)) => continue, - Err(_) => break, - _ => (), - } - pending!(); - } + SpawnedSubsystem { + name: "test-subsystem-6", + future: Box::pin(async move { + loop { + match ctx.try_recv().await { + Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => break, + Ok(Some(FromOverseer::Signal(s))) => { + sender.send(s).await.unwrap(); + continue; + }, + Ok(Some(_)) => continue, + Err(_) => break, + _ => (), + } + pending!(); + } - Ok(()) - }), - } - } + Ok(()) + }), + } + } } // Tests that starting with a defined set of leaves and receiving // notifications on imported blocks triggers expected `StartWork` and `StopWork` heartbeats. #[test] fn overseer_start_stop_works() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let first_block_hash = [1; 32].into(); - let second_block_hash = [2; 32].into(); - let third_block_hash = [3; 32].into(); + executor::block_on(async move { + let first_block_hash = [1; 32].into(); + let second_block_hash = [2; 32].into(); + let third_block_hash = [3; 32].into(); - let first_block = BlockInfo { - hash: first_block_hash, - parent_hash: [0; 32].into(), - number: 1, - }; - let second_block = BlockInfo { - hash: second_block_hash, - parent_hash: first_block_hash, - number: 2, - }; - let third_block = BlockInfo { - hash: third_block_hash, - parent_hash: second_block_hash, - number: 3, - }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: first_block_hash, + number: 2, + }; + let third_block = BlockInfo { + hash: third_block_hash, + parent_hash: second_block_hash, + number: 3, + }; - let (tx_5, mut rx_5) = metered::channel(64); - let (tx_6, mut rx_6) = metered::channel(64); - let all_subsystems = AllSubsystems::<()>::dummy() - .replace_candidate_validation(TestSubsystem5(tx_5)) - .replace_candidate_backing(TestSubsystem6(tx_6)); - let (overseer, mut handler) = Overseer::new( - vec![first_block], - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); + let (tx_5, mut rx_5) = metered::channel(64); + let (tx_6, mut rx_6) = metered::channel(64); + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem5(tx_5)) + .replace_candidate_backing(TestSubsystem6(tx_6)); + let (overseer, mut handler) = Overseer::new( + vec![first_block], + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); - let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + let overseer_fut = overseer.run().fuse(); + pin_mut!(overseer_fut); - let mut ss5_results = Vec::new(); - let mut ss6_results = Vec::new(); + let mut ss5_results = Vec::new(); + let mut ss6_results = Vec::new(); - handler.block_imported(second_block).await; - handler.block_imported(third_block).await; + handler.block_imported(second_block).await; + handler.block_imported(third_block).await; - let expected_heartbeats = vec![ - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: first_block_hash, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: [ActivatedLeaf { - hash: second_block_hash, - number: 2, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].as_ref().into(), - deactivated: [first_block_hash].as_ref().into(), - }), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: [ActivatedLeaf { - hash: third_block_hash, - number: 3, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].as_ref().into(), - deactivated: [second_block_hash].as_ref().into(), - }), - ]; + let expected_heartbeats = vec![ + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: first_block_hash, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: [ActivatedLeaf { + hash: second_block_hash, + number: 2, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].as_ref().into(), + deactivated: [first_block_hash].as_ref().into(), + }), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: [ActivatedLeaf { + hash: third_block_hash, + number: 3, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].as_ref().into(), + deactivated: [second_block_hash].as_ref().into(), + }), + ]; - loop { - select! { - res = overseer_fut => { - assert!(res.is_ok()); - break; - }, - res = rx_5.next() => { - if let Some(res) = res { - ss5_results.push(res); - } - } - res = rx_6.next() => { - if let Some(res) = res { - ss6_results.push(res); - } - } - complete => break, - } + loop { + select! { + res = overseer_fut => { + assert!(res.is_ok()); + break; + }, + res = rx_5.next() => { + if let Some(res) = res { + ss5_results.push(res); + } + } + res = rx_6.next() => { + if let Some(res) = res { + ss6_results.push(res); + } + } + complete => break, + } - if ss5_results.len() == expected_heartbeats.len() && - ss6_results.len() == expected_heartbeats.len() { - handler.stop().await; - } - } + if ss5_results.len() == expected_heartbeats.len() && + ss6_results.len() == expected_heartbeats.len() { + handler.stop().await; + } + } - assert_eq!(ss5_results, expected_heartbeats); - assert_eq!(ss6_results, expected_heartbeats); - }); + assert_eq!(ss5_results, expected_heartbeats); + assert_eq!(ss6_results, expected_heartbeats); + }); } // Tests that starting with a defined set of leaves and receiving // notifications on imported blocks triggers expected `StartWork` and `StopWork` heartbeats. #[test] fn overseer_finalize_works() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let first_block_hash = [1; 32].into(); - let second_block_hash = [2; 32].into(); - let third_block_hash = [3; 32].into(); + executor::block_on(async move { + let first_block_hash = [1; 32].into(); + let second_block_hash = [2; 32].into(); + let third_block_hash = [3; 32].into(); - let first_block = BlockInfo { - hash: first_block_hash, - parent_hash: [0; 32].into(), - number: 1, - }; - let second_block = BlockInfo { - hash: second_block_hash, - parent_hash: [42; 32].into(), - number: 2, - }; - let third_block = BlockInfo { - hash: third_block_hash, - parent_hash: second_block_hash, - number: 3, - }; + let first_block = BlockInfo { + hash: first_block_hash, + parent_hash: [0; 32].into(), + number: 1, + }; + let second_block = BlockInfo { + hash: second_block_hash, + parent_hash: [42; 32].into(), + number: 2, + }; + let third_block = BlockInfo { + hash: third_block_hash, + parent_hash: second_block_hash, + number: 3, + }; - let (tx_5, mut rx_5) = metered::channel(64); - let (tx_6, mut rx_6) = metered::channel(64); + let (tx_5, mut rx_5) = metered::channel(64); + let (tx_6, mut rx_6) = metered::channel(64); - let all_subsystems = AllSubsystems::<()>::dummy() - .replace_candidate_validation(TestSubsystem5(tx_5)) - .replace_candidate_backing(TestSubsystem6(tx_6)); + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem5(tx_5)) + .replace_candidate_backing(TestSubsystem6(tx_6)); - // start with two forks of different height. - let (overseer, mut handler) = Overseer::new( - vec![first_block, second_block], - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); + // start with two forks of different height. + let (overseer, mut handler) = Overseer::new( + vec![first_block, second_block], + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); - let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + let overseer_fut = overseer.run().fuse(); + pin_mut!(overseer_fut); - let mut ss5_results = Vec::new(); - let mut ss6_results = Vec::new(); + let mut ss5_results = Vec::new(); + let mut ss6_results = Vec::new(); - // this should stop work on both forks we started with earlier. - handler.block_finalized(third_block).await; + // this should stop work on both forks we started with earlier. + handler.block_finalized(third_block).await; - let expected_heartbeats = vec![ - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: [ - ActivatedLeaf { - hash: first_block_hash, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }, - ActivatedLeaf { - hash: second_block_hash, - number: 2, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }, - ].as_ref().into(), - ..Default::default() - }), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - deactivated: [first_block_hash, second_block_hash].as_ref().into(), - ..Default::default() - }), - OverseerSignal::BlockFinalized(third_block_hash, 3), - ]; + let expected_heartbeats = vec![ + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: [ + ActivatedLeaf { + hash: first_block_hash, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }, + ActivatedLeaf { + hash: second_block_hash, + number: 2, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }, + ].as_ref().into(), + ..Default::default() + }), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + deactivated: [first_block_hash, second_block_hash].as_ref().into(), + ..Default::default() + }), + OverseerSignal::BlockFinalized(third_block_hash, 3), + ]; - loop { - select! { - res = overseer_fut => { - assert!(res.is_ok()); - break; - }, - res = rx_5.next() => { - if let Some(res) = res { - ss5_results.push(res); - } - } - res = rx_6.next() => { - if let Some(res) = res { - ss6_results.push(res); - } - } - complete => break, - } + loop { + select! { + res = overseer_fut => { + assert!(res.is_ok()); + break; + }, + res = rx_5.next() => { + if let Some(res) = res { + ss5_results.push(res); + } + } + res = rx_6.next() => { + if let Some(res) = res { + ss6_results.push(res); + } + } + complete => break, + } - if ss5_results.len() == expected_heartbeats.len() && ss6_results.len() == expected_heartbeats.len() { - handler.stop().await; - } - } + if ss5_results.len() == expected_heartbeats.len() && ss6_results.len() == expected_heartbeats.len() { + handler.stop().await; + } + } - assert_eq!(ss5_results.len(), expected_heartbeats.len()); - assert_eq!(ss6_results.len(), expected_heartbeats.len()); + assert_eq!(ss5_results.len(), expected_heartbeats.len()); + assert_eq!(ss6_results.len(), expected_heartbeats.len()); - // Notifications on finality for multiple blocks at once - // may be received in different orders. - for expected in expected_heartbeats { - assert!(ss5_results.contains(&expected)); - assert!(ss6_results.contains(&expected)); - } - }); + // Notifications on finality for multiple blocks at once + // may be received in different orders. + for expected in expected_heartbeats { + assert!(ss5_results.contains(&expected)); + assert!(ss6_results.contains(&expected)); + } + }); } #[test] fn do_not_send_empty_leaves_update_on_block_finalization() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let imported_block = BlockInfo { - hash: Hash::random(), - parent_hash: Hash::random(), - number: 1, - }; + executor::block_on(async move { + let imported_block = BlockInfo { + hash: Hash::random(), + parent_hash: Hash::random(), + number: 1, + }; - let finalized_block = BlockInfo { - hash: Hash::random(), - parent_hash: Hash::random(), - number: 1, - }; + let finalized_block = BlockInfo { + hash: Hash::random(), + parent_hash: Hash::random(), + number: 1, + }; - let (tx_5, mut rx_5) = metered::channel(64); + let (tx_5, mut rx_5) = metered::channel(64); - let all_subsystems = AllSubsystems::<()>::dummy() - .replace_candidate_backing(TestSubsystem6(tx_5)); + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_backing(TestSubsystem6(tx_5)); - let (overseer, mut handler) = Overseer::new( - Vec::new(), - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); + let (overseer, mut handler) = Overseer::new( + Vec::new(), + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); - let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + let overseer_fut = overseer.run().fuse(); + pin_mut!(overseer_fut); - let mut ss5_results = Vec::new(); + let mut ss5_results = Vec::new(); - handler.block_finalized(finalized_block.clone()).await; - handler.block_imported(imported_block.clone()).await; + handler.block_finalized(finalized_block.clone()).await; + handler.block_imported(imported_block.clone()).await; - let expected_heartbeats = vec![ - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: [ - ActivatedLeaf { - hash: imported_block.hash, - number: imported_block.number, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled) - } - ].as_ref().into(), - ..Default::default() - }), - OverseerSignal::BlockFinalized(finalized_block.hash, 1), - ]; + let expected_heartbeats = vec![ + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: [ + ActivatedLeaf { + hash: imported_block.hash, + number: imported_block.number, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled) + } + ].as_ref().into(), + ..Default::default() + }), + OverseerSignal::BlockFinalized(finalized_block.hash, 1), + ]; - loop { - select! { - res = overseer_fut => { - assert!(res.is_ok()); - break; - }, - res = rx_5.next() => { - if let Some(res) = dbg!(res) { - ss5_results.push(res); - } - } - } + loop { + select! { + res = overseer_fut => { + assert!(res.is_ok()); + break; + }, + res = rx_5.next() => { + if let Some(res) = dbg!(res) { + ss5_results.push(res); + } + } + } - if ss5_results.len() == expected_heartbeats.len() { - handler.stop().await; - } - } + if ss5_results.len() == expected_heartbeats.len() { + handler.stop().await; + } + } - assert_eq!(ss5_results.len(), expected_heartbeats.len()); + assert_eq!(ss5_results.len(), expected_heartbeats.len()); - for expected in expected_heartbeats { - assert!(ss5_results.contains(&expected)); - } - }); + for expected in expected_heartbeats { + assert!(ss5_results.contains(&expected)); + } + }); } // Tests that duplicate leaves have an attached 'Stale' status. #[test] fn overseer_stale_detection() { - let spawner = sp_core::testing::TaskExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let a1_hash = [1; 32].into(); - let b1_hash = [2; 32].into(); + executor::block_on(async move { + let a1_hash = [1; 32].into(); + let b1_hash = [2; 32].into(); - let a2_hash = [3; 32].into(); - let b2_hash = [4; 32].into(); + let a2_hash = [3; 32].into(); + let b2_hash = [4; 32].into(); - let first_block = BlockInfo { - hash: a1_hash, - parent_hash: [0; 32].into(), - number: 1, - }; - let second_block = BlockInfo { - hash: b1_hash, - parent_hash: [0; 32].into(), - number: 1, - }; + let first_block = BlockInfo { + hash: a1_hash, + parent_hash: [0; 32].into(), + number: 1, + }; + let second_block = BlockInfo { + hash: b1_hash, + parent_hash: [0; 32].into(), + number: 1, + }; - let third_block = BlockInfo { - hash: a2_hash, - parent_hash: a1_hash, - number: 2, - }; + let third_block = BlockInfo { + hash: a2_hash, + parent_hash: a1_hash, + number: 2, + }; - let fourth_block = BlockInfo { - hash: b2_hash, - parent_hash: b1_hash, - number: 2, - }; + let fourth_block = BlockInfo { + hash: b2_hash, + parent_hash: b1_hash, + number: 2, + }; - let (tx_5, mut rx_5) = metered::channel(64); - let (tx_6, mut rx_6) = metered::channel(64); - let all_subsystems = AllSubsystems::<()>::dummy() - .replace_candidate_validation(TestSubsystem5(tx_5)) - .replace_candidate_backing(TestSubsystem6(tx_6)); + let (tx_5, mut rx_5) = metered::channel(64); + let (tx_6, mut rx_6) = metered::channel(64); + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem5(tx_5)) + .replace_candidate_backing(TestSubsystem6(tx_6)); - let (overseer, mut handler) = Overseer::new( - vec![first_block.clone()], - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); + let (overseer, mut handler) = Overseer::new( + vec![first_block.clone()], + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); - let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + let overseer_fut = overseer.run().fuse(); + pin_mut!(overseer_fut); - let mut ss5_results = Vec::new(); - let mut ss6_results = Vec::new(); + let mut ss5_results = Vec::new(); + let mut ss6_results = Vec::new(); - handler.block_imported(second_block.clone()).await; + handler.block_imported(second_block.clone()).await; - // import the second block of each chain to deactivate the heads. - handler.block_imported(third_block).await; - handler.block_imported(fourth_block).await; + // import the second block of each chain to deactivate the heads. + handler.block_imported(third_block).await; + handler.block_imported(fourth_block).await; - // import the first blocks again (emulating a revert) - handler.block_imported(first_block).await; - handler.block_imported(second_block).await; + // import the first blocks again (emulating a revert) + handler.block_imported(first_block).await; + handler.block_imported(second_block).await; - let expected_heartbeats = vec![ - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: a1_hash, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: b1_hash, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - })), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: [ActivatedLeaf { - hash: a2_hash, - number: 2, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].as_ref().into(), - deactivated: [a1_hash].as_ref().into(), - }), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { - activated: [ActivatedLeaf { - hash: b2_hash, - number: 2, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }].as_ref().into(), - deactivated: [b1_hash].as_ref().into(), - }), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: a1_hash, - number: 1, - status: LeafStatus::Stale, - span: Arc::new(jaeger::Span::Disabled), - })), - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: b1_hash, - number: 1, - status: LeafStatus::Stale, - span: Arc::new(jaeger::Span::Disabled), - })), - ]; + let expected_heartbeats = vec![ + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: a1_hash, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: b1_hash, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: [ActivatedLeaf { + hash: a2_hash, + number: 2, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].as_ref().into(), + deactivated: [a1_hash].as_ref().into(), + }), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: [ActivatedLeaf { + hash: b2_hash, + number: 2, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }].as_ref().into(), + deactivated: [b1_hash].as_ref().into(), + }), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: a1_hash, + number: 1, + status: LeafStatus::Stale, + span: Arc::new(jaeger::Span::Disabled), + })), + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: b1_hash, + number: 1, + status: LeafStatus::Stale, + span: Arc::new(jaeger::Span::Disabled), + })), + ]; - loop { - select! { - res = overseer_fut => { - assert!(res.is_ok()); - break; - }, - res = rx_5.next() => { - if let Some(res) = res { - ss5_results.push(res); - } - } - res = rx_6.next() => { - if let Some(res) = res { - ss6_results.push(res); - } - } - complete => break, - } + loop { + select! { + res = overseer_fut => { + assert!(res.is_ok()); + break; + }, + res = rx_5.next() => { + if let Some(res) = res { + ss5_results.push(res); + } + } + res = rx_6.next() => { + if let Some(res) = res { + ss6_results.push(res); + } + } + complete => break, + } - if ss5_results.len() == expected_heartbeats.len() && - ss6_results.len() == expected_heartbeats.len() { - handler.stop().await; - } - } + if ss5_results.len() == expected_heartbeats.len() && + ss6_results.len() == expected_heartbeats.len() { + handler.stop().await; + } + } - assert_eq!(ss5_results, expected_heartbeats); - assert_eq!(ss6_results, expected_heartbeats); - }); + assert_eq!(ss5_results, expected_heartbeats); + assert_eq!(ss6_results, expected_heartbeats); + }); } #[derive(Clone)] struct CounterSubsystem { - stop_signals_received: Arc, - signals_received: Arc, - msgs_received: Arc, + stop_signals_received: Arc, + signals_received: Arc, + msgs_received: Arc, } impl CounterSubsystem { - fn new( - stop_signals_received: Arc, - signals_received: Arc, - msgs_received: Arc, - ) -> Self { - Self { - stop_signals_received, - signals_received, - msgs_received, - } - } + fn new( + stop_signals_received: Arc, + signals_received: Arc, + msgs_received: Arc, + ) -> Self { + Self { + stop_signals_received, + signals_received, + msgs_received, + } + } } impl Subsystem for CounterSubsystem - where - C: SubsystemContext, - M: Send, + where + C: SubsystemContext, + M: Send, { - fn start(self, mut ctx: C) -> SpawnedSubsystem { - SpawnedSubsystem { - name: "counter-subsystem", - future: Box::pin(async move { - loop { - match ctx.try_recv().await { - Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => { - self.stop_signals_received.fetch_add(1, atomic::Ordering::SeqCst); - break; - }, - Ok(Some(FromOverseer::Signal(_))) => { - self.signals_received.fetch_add(1, atomic::Ordering::SeqCst); - continue; - }, - Ok(Some(FromOverseer::Communication { .. })) => { - self.msgs_received.fetch_add(1, atomic::Ordering::SeqCst); - continue; - }, - Err(_) => (), - _ => (), - } - pending!(); - } + fn start(self, mut ctx: C) -> SpawnedSubsystem { + SpawnedSubsystem { + name: "counter-subsystem", + future: Box::pin(async move { + loop { + match ctx.try_recv().await { + Ok(Some(FromOverseer::Signal(OverseerSignal::Conclude))) => { + self.stop_signals_received.fetch_add(1, atomic::Ordering::SeqCst); + break; + }, + Ok(Some(FromOverseer::Signal(_))) => { + self.signals_received.fetch_add(1, atomic::Ordering::SeqCst); + continue; + }, + Ok(Some(FromOverseer::Communication { .. })) => { + self.msgs_received.fetch_add(1, atomic::Ordering::SeqCst); + continue; + }, + Err(_) => (), + _ => (), + } + pending!(); + } - Ok(()) - }), - } - } + Ok(()) + }), + } + } } fn test_candidate_validation_msg() -> CandidateValidationMessage { - let (sender, _) = oneshot::channel(); - let pov = Arc::new(PoV { block_data: BlockData(Vec::new()) }); - CandidateValidationMessage::ValidateFromChainState(Default::default(), pov, sender) + let (sender, _) = oneshot::channel(); + let pov = Arc::new(PoV { block_data: BlockData(Vec::new()) }); + CandidateValidationMessage::ValidateFromChainState(Default::default(), pov, sender) } fn test_candidate_backing_msg() -> CandidateBackingMessage { - let (sender, _) = oneshot::channel(); - CandidateBackingMessage::GetBackedCandidates(Default::default(), Vec::new(), sender) + let (sender, _) = oneshot::channel(); + CandidateBackingMessage::GetBackedCandidates(Default::default(), Vec::new(), sender) } fn test_chain_api_msg() -> ChainApiMessage { - let (sender, _) = oneshot::channel(); - ChainApiMessage::FinalizedBlockNumber(sender) + let (sender, _) = oneshot::channel(); + ChainApiMessage::FinalizedBlockNumber(sender) } fn test_collator_generation_msg() -> CollationGenerationMessage { - CollationGenerationMessage::Initialize(CollationGenerationConfig { - key: CollatorPair::generate().0, - collator: Box::new(|_, _| TestCollator.boxed()), - para_id: Default::default(), - }) + CollationGenerationMessage::Initialize(CollationGenerationConfig { + key: CollatorPair::generate().0, + collator: Box::new(|_, _| TestCollator.boxed()), + para_id: Default::default(), + }) } struct TestCollator; impl Future for TestCollator { - type Output = Option; + type Output = Option; - fn poll(self: Pin<&mut Self>, _cx: &mut futures::task::Context) -> Poll { - panic!("at the Disco") - } + fn poll(self: Pin<&mut Self>, _cx: &mut futures::task::Context) -> Poll { + panic!("at the Disco") + } } impl Unpin for TestCollator {} fn test_collator_protocol_msg() -> CollatorProtocolMessage { - CollatorProtocolMessage::CollateOn(Default::default()) + CollatorProtocolMessage::CollateOn(Default::default()) } fn test_network_bridge_event() -> NetworkBridgeEvent { - NetworkBridgeEvent::PeerDisconnected(PeerId::random()) + NetworkBridgeEvent::PeerDisconnected(PeerId::random()) } fn test_statement_distribution_msg() -> StatementDistributionMessage { - StatementDistributionMessage::NetworkBridgeUpdateV1(test_network_bridge_event()) + StatementDistributionMessage::NetworkBridgeUpdateV1(test_network_bridge_event()) } fn test_availability_recovery_msg() -> AvailabilityRecoveryMessage { - let (sender, _) = oneshot::channel(); - AvailabilityRecoveryMessage::RecoverAvailableData( - Default::default(), - Default::default(), - None, - sender, - ) + let (sender, _) = oneshot::channel(); + AvailabilityRecoveryMessage::RecoverAvailableData( + Default::default(), + Default::default(), + None, + sender, + ) } fn test_bitfield_distribution_msg() -> BitfieldDistributionMessage { - BitfieldDistributionMessage::NetworkBridgeUpdateV1(test_network_bridge_event()) + BitfieldDistributionMessage::NetworkBridgeUpdateV1(test_network_bridge_event()) } fn test_provisioner_msg() -> ProvisionerMessage { - let (sender, _) = oneshot::channel(); - ProvisionerMessage::RequestInherentData(Default::default(), sender) + let (sender, _) = oneshot::channel(); + ProvisionerMessage::RequestInherentData(Default::default(), sender) } fn test_runtime_api_msg() -> RuntimeApiMessage { - let (sender, _) = oneshot::channel(); - RuntimeApiMessage::Request(Default::default(), RuntimeApiRequest::Validators(sender)) + let (sender, _) = oneshot::channel(); + RuntimeApiMessage::Request(Default::default(), RuntimeApiRequest::Validators(sender)) } fn test_availability_store_msg() -> AvailabilityStoreMessage { - let (sender, _) = oneshot::channel(); - AvailabilityStoreMessage::QueryAvailableData(CandidateHash(Default::default()), sender) + let (sender, _) = oneshot::channel(); + AvailabilityStoreMessage::QueryAvailableData(CandidateHash(Default::default()), sender) } fn test_network_bridge_msg() -> NetworkBridgeMessage { - NetworkBridgeMessage::ReportPeer(PeerId::random(), UnifiedReputationChange::BenefitMinor("")) + NetworkBridgeMessage::ReportPeer(PeerId::random(), UnifiedReputationChange::BenefitMinor("")) } fn test_approval_distribution_msg() -> ApprovalDistributionMessage { - ApprovalDistributionMessage::NewBlocks(Default::default()) + ApprovalDistributionMessage::NewBlocks(Default::default()) } fn test_approval_voting_msg() -> ApprovalVotingMessage { - let (sender, _) = oneshot::channel(); - ApprovalVotingMessage::ApprovedAncestor(Default::default(), 0, sender) + let (sender, _) = oneshot::channel(); + ApprovalVotingMessage::ApprovedAncestor(Default::default(), 0, sender) } // Checks that `stop`, `broadcast_signal` and `broadcast_message` are implemented correctly. #[test] fn overseer_all_subsystems_receive_signals_and_messages() { - const NUM_SUBSYSTEMS: usize = 17; - // -3 for BitfieldSigning, GossipSupport and AvailabilityDistribution - const NUM_SUBSYSTEMS_MESSAGED: usize = NUM_SUBSYSTEMS - 3; + const NUM_SUBSYSTEMS: usize = 17; + // -3 for BitfieldSigning, GossipSupport and AvailabilityDistribution + const NUM_SUBSYSTEMS_MESSAGED: usize = NUM_SUBSYSTEMS - 3; - let spawner = sp_core::testing::TaskExecutor::new(); - executor::block_on(async move { - let stop_signals_received = Arc::new(atomic::AtomicUsize::new(0)); - let signals_received = Arc::new(atomic::AtomicUsize::new(0)); - let msgs_received = Arc::new(atomic::AtomicUsize::new(0)); + let spawner = sp_core::testing::TaskExecutor::new(); + executor::block_on(async move { + let stop_signals_received = Arc::new(atomic::AtomicUsize::new(0)); + let signals_received = Arc::new(atomic::AtomicUsize::new(0)); + let msgs_received = Arc::new(atomic::AtomicUsize::new(0)); - let subsystem = CounterSubsystem::new( - stop_signals_received.clone(), - signals_received.clone(), - msgs_received.clone(), - ); + let subsystem = CounterSubsystem::new( + stop_signals_received.clone(), + signals_received.clone(), + msgs_received.clone(), + ); - let all_subsystems = AllSubsystems { - candidate_validation: subsystem.clone(), - candidate_backing: subsystem.clone(), - collation_generation: subsystem.clone(), - collator_protocol: subsystem.clone(), - statement_distribution: subsystem.clone(), - availability_distribution: subsystem.clone(), - availability_recovery: subsystem.clone(), - bitfield_signing: subsystem.clone(), - bitfield_distribution: subsystem.clone(), - provisioner: subsystem.clone(), - runtime_api: subsystem.clone(), - availability_store: subsystem.clone(), - network_bridge: subsystem.clone(), - chain_api: subsystem.clone(), - approval_distribution: subsystem.clone(), - approval_voting: subsystem.clone(), - gossip_support: subsystem.clone(), - }; - let (overseer, mut handler) = Overseer::new( - vec![], - all_subsystems, - None, - MockSupportsParachains, - spawner, - ).unwrap(); - let overseer_fut = overseer.run().fuse(); + let all_subsystems = AllSubsystems { + candidate_validation: subsystem.clone(), + candidate_backing: subsystem.clone(), + collation_generation: subsystem.clone(), + collator_protocol: subsystem.clone(), + statement_distribution: subsystem.clone(), + availability_distribution: subsystem.clone(), + availability_recovery: subsystem.clone(), + bitfield_signing: subsystem.clone(), + bitfield_distribution: subsystem.clone(), + provisioner: subsystem.clone(), + runtime_api: subsystem.clone(), + availability_store: subsystem.clone(), + network_bridge: subsystem.clone(), + chain_api: subsystem.clone(), + approval_distribution: subsystem.clone(), + approval_voting: subsystem.clone(), + gossip_support: subsystem.clone(), + }; + let (overseer, mut handler) = Overseer::new( + vec![], + all_subsystems, + None, + MockSupportsParachains, + spawner, + ).unwrap(); + let overseer_fut = overseer.run().fuse(); - pin_mut!(overseer_fut); + pin_mut!(overseer_fut); - // send a signal to each subsystem - handler.block_imported(BlockInfo { - hash: Default::default(), - parent_hash: Default::default(), - number: Default::default(), - }).await; + // send a signal to each subsystem + handler.block_imported(BlockInfo { + hash: Default::default(), + parent_hash: Default::default(), + number: Default::default(), + }).await; - // send a msg to each subsystem - // except for BitfieldSigning and GossipSupport as the messages are not instantiable - handler.send_msg(AllMessages::CandidateValidation(test_candidate_validation_msg())).await; - handler.send_msg(AllMessages::CandidateBacking(test_candidate_backing_msg())).await; - handler.send_msg(AllMessages::CollationGeneration(test_collator_generation_msg())).await; - handler.send_msg(AllMessages::CollatorProtocol(test_collator_protocol_msg())).await; - handler.send_msg(AllMessages::StatementDistribution(test_statement_distribution_msg())).await; - handler.send_msg(AllMessages::AvailabilityRecovery(test_availability_recovery_msg())).await; - // handler.send_msg(AllMessages::BitfieldSigning(test_bitfield_signing_msg())).await; - // handler.send_msg(AllMessages::GossipSupport(test_bitfield_signing_msg())).await; - handler.send_msg(AllMessages::BitfieldDistribution(test_bitfield_distribution_msg())).await; - handler.send_msg(AllMessages::Provisioner(test_provisioner_msg())).await; - handler.send_msg(AllMessages::RuntimeApi(test_runtime_api_msg())).await; - handler.send_msg(AllMessages::AvailabilityStore(test_availability_store_msg())).await; - handler.send_msg(AllMessages::NetworkBridge(test_network_bridge_msg())).await; - handler.send_msg(AllMessages::ChainApi(test_chain_api_msg())).await; - handler.send_msg(AllMessages::ApprovalDistribution(test_approval_distribution_msg())).await; - handler.send_msg(AllMessages::ApprovalVoting(test_approval_voting_msg())).await; + // send a msg to each subsystem + // except for BitfieldSigning and GossipSupport as the messages are not instantiable + handler.send_msg(AllMessages::CandidateValidation(test_candidate_validation_msg())).await; + handler.send_msg(AllMessages::CandidateBacking(test_candidate_backing_msg())).await; + handler.send_msg(AllMessages::CollationGeneration(test_collator_generation_msg())).await; + handler.send_msg(AllMessages::CollatorProtocol(test_collator_protocol_msg())).await; + handler.send_msg(AllMessages::StatementDistribution(test_statement_distribution_msg())).await; + handler.send_msg(AllMessages::AvailabilityRecovery(test_availability_recovery_msg())).await; + // handler.send_msg(AllMessages::BitfieldSigning(test_bitfield_signing_msg())).await; + // handler.send_msg(AllMessages::GossipSupport(test_bitfield_signing_msg())).await; + handler.send_msg(AllMessages::BitfieldDistribution(test_bitfield_distribution_msg())).await; + handler.send_msg(AllMessages::Provisioner(test_provisioner_msg())).await; + handler.send_msg(AllMessages::RuntimeApi(test_runtime_api_msg())).await; + handler.send_msg(AllMessages::AvailabilityStore(test_availability_store_msg())).await; + handler.send_msg(AllMessages::NetworkBridge(test_network_bridge_msg())).await; + handler.send_msg(AllMessages::ChainApi(test_chain_api_msg())).await; + handler.send_msg(AllMessages::ApprovalDistribution(test_approval_distribution_msg())).await; + handler.send_msg(AllMessages::ApprovalVoting(test_approval_voting_msg())).await; - // Wait until all subsystems have received. Otherwise the messages might race against - // the conclude signal. - loop { - match (&mut overseer_fut).timeout(Duration::from_millis(100)).await { - None => { - let r = msgs_received.load(atomic::Ordering::SeqCst); - if r < NUM_SUBSYSTEMS_MESSAGED { - Delay::new(Duration::from_millis(100)).await; - } else if r > NUM_SUBSYSTEMS_MESSAGED { - panic!("too many messages received??"); - } else { - break - } - } - Some(_) => panic!("exited too early"), - } - } + // Wait until all subsystems have received. Otherwise the messages might race against + // the conclude signal. + loop { + match (&mut overseer_fut).timeout(Duration::from_millis(100)).await { + None => { + let r = msgs_received.load(atomic::Ordering::SeqCst); + if r < NUM_SUBSYSTEMS_MESSAGED { + Delay::new(Duration::from_millis(100)).await; + } else if r > NUM_SUBSYSTEMS_MESSAGED { + panic!("too many messages received??"); + } else { + break + } + } + Some(_) => panic!("exited too early"), + } + } - // send a stop signal to each subsystems - handler.stop().await; + // send a stop signal to each subsystems + handler.stop().await; - let res = overseer_fut.await; - assert_eq!(stop_signals_received.load(atomic::Ordering::SeqCst), NUM_SUBSYSTEMS); - assert_eq!(signals_received.load(atomic::Ordering::SeqCst), NUM_SUBSYSTEMS); - assert_eq!(msgs_received.load(atomic::Ordering::SeqCst), NUM_SUBSYSTEMS_MESSAGED); + let res = overseer_fut.await; + assert_eq!(stop_signals_received.load(atomic::Ordering::SeqCst), NUM_SUBSYSTEMS); + assert_eq!(signals_received.load(atomic::Ordering::SeqCst), NUM_SUBSYSTEMS); + assert_eq!(msgs_received.load(atomic::Ordering::SeqCst), NUM_SUBSYSTEMS_MESSAGED); - assert!(res.is_ok()); - }); + assert!(res.is_ok()); + }); } #[test] fn context_holds_onto_message_until_enough_signals_received() { - let (candidate_validation_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (candidate_backing_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (statement_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (availability_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (availability_recovery_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (bitfield_signing_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (bitfield_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (provisioner_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (runtime_api_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (availability_store_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (network_bridge_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (chain_api_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (collator_protocol_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (collation_generation_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (approval_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (approval_voting_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (gossip_support_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (candidate_validation_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (candidate_backing_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (statement_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (availability_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (availability_recovery_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (bitfield_signing_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (bitfield_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (provisioner_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (runtime_api_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (availability_store_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (network_bridge_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (chain_api_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (collator_protocol_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (collation_generation_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (approval_distribution_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (approval_voting_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); + let (gossip_support_bounded_tx, _) = metered::channel(CHANNEL_CAPACITY); - let (candidate_validation_unbounded_tx, _) = metered::unbounded(); - let (candidate_backing_unbounded_tx, _) = metered::unbounded(); - let (statement_distribution_unbounded_tx, _) = metered::unbounded(); - let (availability_distribution_unbounded_tx, _) = metered::unbounded(); - let (availability_recovery_unbounded_tx, _) = metered::unbounded(); - let (bitfield_signing_unbounded_tx, _) = metered::unbounded(); - let (bitfield_distribution_unbounded_tx, _) = metered::unbounded(); - let (provisioner_unbounded_tx, _) = metered::unbounded(); - let (runtime_api_unbounded_tx, _) = metered::unbounded(); - let (availability_store_unbounded_tx, _) = metered::unbounded(); - let (network_bridge_unbounded_tx, _) = metered::unbounded(); - let (chain_api_unbounded_tx, _) = metered::unbounded(); - let (collator_protocol_unbounded_tx, _) = metered::unbounded(); - let (collation_generation_unbounded_tx, _) = metered::unbounded(); - let (approval_distribution_unbounded_tx, _) = metered::unbounded(); - let (approval_voting_unbounded_tx, _) = metered::unbounded(); - let (gossip_support_unbounded_tx, _) = metered::unbounded(); + let (candidate_validation_unbounded_tx, _) = metered::unbounded(); + let (candidate_backing_unbounded_tx, _) = metered::unbounded(); + let (statement_distribution_unbounded_tx, _) = metered::unbounded(); + let (availability_distribution_unbounded_tx, _) = metered::unbounded(); + let (availability_recovery_unbounded_tx, _) = metered::unbounded(); + let (bitfield_signing_unbounded_tx, _) = metered::unbounded(); + let (bitfield_distribution_unbounded_tx, _) = metered::unbounded(); + let (provisioner_unbounded_tx, _) = metered::unbounded(); + let (runtime_api_unbounded_tx, _) = metered::unbounded(); + let (availability_store_unbounded_tx, _) = metered::unbounded(); + let (network_bridge_unbounded_tx, _) = metered::unbounded(); + let (chain_api_unbounded_tx, _) = metered::unbounded(); + let (collator_protocol_unbounded_tx, _) = metered::unbounded(); + let (collation_generation_unbounded_tx, _) = metered::unbounded(); + let (approval_distribution_unbounded_tx, _) = metered::unbounded(); + let (approval_voting_unbounded_tx, _) = metered::unbounded(); + let (gossip_support_unbounded_tx, _) = metered::unbounded(); - let channels_out = ChannelsOut { - candidate_validation: candidate_validation_bounded_tx.clone(), - candidate_backing: candidate_backing_bounded_tx.clone(), - statement_distribution: statement_distribution_bounded_tx.clone(), - availability_distribution: availability_distribution_bounded_tx.clone(), - availability_recovery: availability_recovery_bounded_tx.clone(), - bitfield_signing: bitfield_signing_bounded_tx.clone(), - bitfield_distribution: bitfield_distribution_bounded_tx.clone(), - provisioner: provisioner_bounded_tx.clone(), - runtime_api: runtime_api_bounded_tx.clone(), - availability_store: availability_store_bounded_tx.clone(), - network_bridge: network_bridge_bounded_tx.clone(), - chain_api: chain_api_bounded_tx.clone(), - collator_protocol: collator_protocol_bounded_tx.clone(), - collation_generation: collation_generation_bounded_tx.clone(), - approval_distribution: approval_distribution_bounded_tx.clone(), - approval_voting: approval_voting_bounded_tx.clone(), - gossip_support: gossip_support_bounded_tx.clone(), + let channels_out = ChannelsOut { + candidate_validation: candidate_validation_bounded_tx.clone(), + candidate_backing: candidate_backing_bounded_tx.clone(), + statement_distribution: statement_distribution_bounded_tx.clone(), + availability_distribution: availability_distribution_bounded_tx.clone(), + availability_recovery: availability_recovery_bounded_tx.clone(), + bitfield_signing: bitfield_signing_bounded_tx.clone(), + bitfield_distribution: bitfield_distribution_bounded_tx.clone(), + provisioner: provisioner_bounded_tx.clone(), + runtime_api: runtime_api_bounded_tx.clone(), + availability_store: availability_store_bounded_tx.clone(), + network_bridge: network_bridge_bounded_tx.clone(), + chain_api: chain_api_bounded_tx.clone(), + collator_protocol: collator_protocol_bounded_tx.clone(), + collation_generation: collation_generation_bounded_tx.clone(), + approval_distribution: approval_distribution_bounded_tx.clone(), + approval_voting: approval_voting_bounded_tx.clone(), + gossip_support: gossip_support_bounded_tx.clone(), - candidate_validation_unbounded: candidate_validation_unbounded_tx.clone(), - candidate_backing_unbounded: candidate_backing_unbounded_tx.clone(), - statement_distribution_unbounded: statement_distribution_unbounded_tx.clone(), - availability_distribution_unbounded: availability_distribution_unbounded_tx.clone(), - availability_recovery_unbounded: availability_recovery_unbounded_tx.clone(), - bitfield_signing_unbounded: bitfield_signing_unbounded_tx.clone(), - bitfield_distribution_unbounded: bitfield_distribution_unbounded_tx.clone(), - provisioner_unbounded: provisioner_unbounded_tx.clone(), - runtime_api_unbounded: runtime_api_unbounded_tx.clone(), - availability_store_unbounded: availability_store_unbounded_tx.clone(), - network_bridge_unbounded: network_bridge_unbounded_tx.clone(), - chain_api_unbounded: chain_api_unbounded_tx.clone(), - collator_protocol_unbounded: collator_protocol_unbounded_tx.clone(), - collation_generation_unbounded: collation_generation_unbounded_tx.clone(), - approval_distribution_unbounded: approval_distribution_unbounded_tx.clone(), - approval_voting_unbounded: approval_voting_unbounded_tx.clone(), - gossip_support_unbounded: gossip_support_unbounded_tx.clone(), - }; + candidate_validation_unbounded: candidate_validation_unbounded_tx.clone(), + candidate_backing_unbounded: candidate_backing_unbounded_tx.clone(), + statement_distribution_unbounded: statement_distribution_unbounded_tx.clone(), + availability_distribution_unbounded: availability_distribution_unbounded_tx.clone(), + availability_recovery_unbounded: availability_recovery_unbounded_tx.clone(), + bitfield_signing_unbounded: bitfield_signing_unbounded_tx.clone(), + bitfield_distribution_unbounded: bitfield_distribution_unbounded_tx.clone(), + provisioner_unbounded: provisioner_unbounded_tx.clone(), + runtime_api_unbounded: runtime_api_unbounded_tx.clone(), + availability_store_unbounded: availability_store_unbounded_tx.clone(), + network_bridge_unbounded: network_bridge_unbounded_tx.clone(), + chain_api_unbounded: chain_api_unbounded_tx.clone(), + collator_protocol_unbounded: collator_protocol_unbounded_tx.clone(), + collation_generation_unbounded: collation_generation_unbounded_tx.clone(), + approval_distribution_unbounded: approval_distribution_unbounded_tx.clone(), + approval_voting_unbounded: approval_voting_unbounded_tx.clone(), + gossip_support_unbounded: gossip_support_unbounded_tx.clone(), + }; - let (mut signal_tx, signal_rx) = metered::channel(CHANNEL_CAPACITY); - let (mut bounded_tx, bounded_rx) = metered::channel(CHANNEL_CAPACITY); - let (unbounded_tx, unbounded_rx) = metered::unbounded(); - let (to_overseer_tx, _to_overseer_rx) = metered::unbounded(); + let (mut signal_tx, signal_rx) = metered::channel(CHANNEL_CAPACITY); + let (mut bounded_tx, bounded_rx) = metered::channel(CHANNEL_CAPACITY); + let (unbounded_tx, unbounded_rx) = metered::unbounded(); + let (to_overseer_tx, _to_overseer_rx) = metered::unbounded(); - let mut ctx = OverseerSubsystemContext::<()>::new_unmetered( - signal_rx, - stream::select(bounded_rx, unbounded_rx), - channels_out, - to_overseer_tx, - ); + let mut ctx = OverseerSubsystemContext::<()>::new_unmetered( + signal_rx, + stream::select(bounded_rx, unbounded_rx), + channels_out, + to_overseer_tx, + ); - assert_eq!(ctx.signals_received.load(), 0); + assert_eq!(ctx.signals_received.load(), 0); - let test_fut = async move { - signal_tx.send(OverseerSignal::Conclude).await.unwrap(); - assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Signal(OverseerSignal::Conclude)); + let test_fut = async move { + signal_tx.send(OverseerSignal::Conclude).await.unwrap(); + assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Signal(OverseerSignal::Conclude)); - assert_eq!(ctx.signals_received.load(), 1); - bounded_tx.send(MessagePacket { - signals_received: 2, - message: (), - }).await.unwrap(); - unbounded_tx.unbounded_send(MessagePacket { - signals_received: 2, - message: (), - }).unwrap(); + assert_eq!(ctx.signals_received.load(), 1); + bounded_tx.send(MessagePacket { + signals_received: 2, + message: (), + }).await.unwrap(); + unbounded_tx.unbounded_send(MessagePacket { + signals_received: 2, + message: (), + }).unwrap(); - match poll!(ctx.recv()) { - Poll::Pending => {} - Poll::Ready(_) => panic!("ready too early"), - }; + match poll!(ctx.recv()) { + Poll::Pending => {} + Poll::Ready(_) => panic!("ready too early"), + }; - assert!(ctx.pending_incoming.is_some()); + assert!(ctx.pending_incoming.is_some()); - signal_tx.send(OverseerSignal::Conclude).await.unwrap(); - assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Signal(OverseerSignal::Conclude)); - assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Communication { msg: () }); - assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Communication { msg: () }); - assert!(ctx.pending_incoming.is_none()); - }; + signal_tx.send(OverseerSignal::Conclude).await.unwrap(); + assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Signal(OverseerSignal::Conclude)); + assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Communication { msg: () }); + assert_matches!(ctx.recv().await.unwrap(), FromOverseer::Communication { msg: () }); + assert!(ctx.pending_incoming.is_none()); + }; - futures::executor::block_on(test_fut); + futures::executor::block_on(test_fut); } diff --git a/polkadot/node/subsystem-util/src/lib.rs b/polkadot/node/subsystem-util/src/lib.rs index ced1aaeda3..352634767d 100644 --- a/polkadot/node/subsystem-util/src/lib.rs +++ b/polkadot/node/subsystem-util/src/lib.rs @@ -54,8 +54,6 @@ use thiserror::Error; pub use metered_channel as metered; pub use polkadot_node_network_protocol::MIN_GOSSIP_PEERS; -mod error_handling; - /// Error classification. pub use error_handling::{Fault, unwrap_non_fatal}; @@ -72,6 +70,11 @@ pub mod reexports { /// Convenient and efficient runtime info access. pub mod runtime; +mod error_handling; + +#[cfg(test)] +mod tests; + /// Duration a job will wait after sending a stop signal before hard-aborting. pub const JOB_GRACEFUL_STOP_DURATION: Duration = Duration::from_secs(1); /// Capacity of channels to and from individual jobs @@ -859,6 +862,3 @@ impl futures::Stream for Metronome Poll::Pending } } - -#[cfg(test)] -mod tests; diff --git a/polkadot/node/subsystem-util/src/tests.rs b/polkadot/node/subsystem-util/src/tests.rs index 40b87fff7c..10eb743671 100644 --- a/polkadot/node/subsystem-util/src/tests.rs +++ b/polkadot/node/subsystem-util/src/tests.rs @@ -19,8 +19,8 @@ use executor::block_on; use thiserror::Error; use polkadot_node_jaeger as jaeger; use polkadot_node_subsystem::{ - messages::{AllMessages, CollatorProtocolMessage}, ActiveLeavesUpdate, FromOverseer, OverseerSignal, - SpawnedSubsystem, ActivatedLeaf, LeafStatus, + messages::{AllMessages, CollatorProtocolMessage}, ActiveLeavesUpdate, FromOverseer, OverseerSignal, + SpawnedSubsystem, ActivatedLeaf, LeafStatus, }; use assert_matches::assert_matches; use futures::{channel::mpsc, executor, StreamExt, future, Future, FutureExt, SinkExt}; @@ -37,7 +37,7 @@ use std::{pin::Pin, sync::{Arc, atomic::{AtomicUsize, Ordering}}, time::Duration // job structs are constructed within JobTrait::run // most will want to retain the sender and receiver, as well as whatever other data they like struct FakeCollatorProtocolJob { - receiver: mpsc::Receiver, + receiver: mpsc::Receiver, } // Error will mostly be a wrapper to make the try operator more convenient; @@ -45,215 +45,215 @@ struct FakeCollatorProtocolJob { // It must implement Debug for logging. #[derive(Debug, Error)] enum Error { - #[error(transparent)] - Sending(#[from]mpsc::SendError), + #[error(transparent)] + Sending(#[from]mpsc::SendError), } impl JobTrait for FakeCollatorProtocolJob { - type ToJob = CollatorProtocolMessage; - type Error = Error; - type RunArgs = bool; - type Metrics = (); + type ToJob = CollatorProtocolMessage; + type Error = Error; + type RunArgs = bool; + type Metrics = (); - const NAME: &'static str = "FakeCollatorProtocolJob"; + const NAME: &'static str = "FakeCollatorProtocolJob"; - /// Run a job for the parent block indicated - // - // this function is in charge of creating and executing the job's main loop - fn run( - _: Hash, - _: Arc, - run_args: Self::RunArgs, - _metrics: Self::Metrics, - receiver: mpsc::Receiver, - mut sender: JobSender, - ) -> Pin> + Send>> { - async move { - let job = FakeCollatorProtocolJob { receiver }; + /// Run a job for the parent block indicated + // + // this function is in charge of creating and executing the job's main loop + fn run( + _: Hash, + _: Arc, + run_args: Self::RunArgs, + _metrics: Self::Metrics, + receiver: mpsc::Receiver, + mut sender: JobSender, + ) -> Pin> + Send>> { + async move { + let job = FakeCollatorProtocolJob { receiver }; - if run_args { - sender.send_message(CollatorProtocolMessage::Invalid( - Default::default(), - Default::default(), - ).into()).await; - } + if run_args { + sender.send_message(CollatorProtocolMessage::Invalid( + Default::default(), + Default::default(), + ).into()).await; + } - // it isn't necessary to break run_loop into its own function, - // but it's convenient to separate the concerns in this way - job.run_loop().await - } - .boxed() - } + // it isn't necessary to break run_loop into its own function, + // but it's convenient to separate the concerns in this way + job.run_loop().await + } + .boxed() + } } impl FakeCollatorProtocolJob { - async fn run_loop(mut self) -> Result<(), Error> { - loop { - match self.receiver.next().await { - Some(_csm) => { - unimplemented!("we'd report the collator to the peer set manager here, but that's not implemented yet"); - } - None => break, - } - } + async fn run_loop(mut self) -> Result<(), Error> { + loop { + match self.receiver.next().await { + Some(_csm) => { + unimplemented!("we'd report the collator to the peer set manager here, but that's not implemented yet"); + } + None => break, + } + } - Ok(()) - } + Ok(()) + } } // with the job defined, it's straightforward to get a subsystem implementation. type FakeCollatorProtocolSubsystem = - JobSubsystem; + JobSubsystem; // this type lets us pretend to be the overseer type OverseerHandle = test_helpers::TestSubsystemContextHandle; fn test_harness>( - run_args: bool, - test: impl FnOnce(OverseerHandle) -> T, + run_args: bool, + test: impl FnOnce(OverseerHandle) -> T, ) { - let _ = env_logger::builder() - .is_test(true) - .filter( - None, - log::LevelFilter::Trace, - ) - .try_init(); + let _ = env_logger::builder() + .is_test(true) + .filter( + None, + log::LevelFilter::Trace, + ) + .try_init(); - let pool = sp_core::testing::TaskExecutor::new(); - let (context, overseer_handle) = make_subsystem_context(pool.clone()); + let pool = sp_core::testing::TaskExecutor::new(); + let (context, overseer_handle) = make_subsystem_context(pool.clone()); - let subsystem = FakeCollatorProtocolSubsystem::new( - pool, - run_args, - (), - ).run(context); - let test_future = test(overseer_handle); + let subsystem = FakeCollatorProtocolSubsystem::new( + pool, + run_args, + (), + ).run(context); + let test_future = test(overseer_handle); - futures::pin_mut!(subsystem, test_future); + futures::pin_mut!(subsystem, test_future); - executor::block_on(async move { - future::join(subsystem, test_future) - .timeout(Duration::from_secs(2)) - .await - .expect("test timed out instead of completing") - }); + executor::block_on(async move { + future::join(subsystem, test_future) + .timeout(Duration::from_secs(2)) + .await + .expect("test timed out instead of completing") + }); } #[test] fn starting_and_stopping_job_works() { - let relay_parent: Hash = [0; 32].into(); + let relay_parent: Hash = [0; 32].into(); - test_harness(true, |mut overseer_handle| async move { - overseer_handle - .send(FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: relay_parent, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), - ))) - .await; - assert_matches!( - overseer_handle.recv().await, - AllMessages::CollatorProtocol(_) - ); - overseer_handle - .send(FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::stop_work(relay_parent), - ))) - .await; + test_harness(true, |mut overseer_handle| async move { + overseer_handle + .send(FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: relay_parent, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }), + ))) + .await; + assert_matches!( + overseer_handle.recv().await, + AllMessages::CollatorProtocol(_) + ); + overseer_handle + .send(FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::stop_work(relay_parent), + ))) + .await; - overseer_handle - .send(FromOverseer::Signal(OverseerSignal::Conclude)) - .await; - }); + overseer_handle + .send(FromOverseer::Signal(OverseerSignal::Conclude)) + .await; + }); } #[test] fn sending_to_a_non_running_job_do_not_stop_the_subsystem() { - let relay_parent = Hash::repeat_byte(0x01); + let relay_parent = Hash::repeat_byte(0x01); - test_harness(true, |mut overseer_handle| async move { - overseer_handle - .send(FromOverseer::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(ActivatedLeaf { - hash: relay_parent, - number: 1, - status: LeafStatus::Fresh, - span: Arc::new(jaeger::Span::Disabled), - }), - ))) - .await; + test_harness(true, |mut overseer_handle| async move { + overseer_handle + .send(FromOverseer::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::start_work(ActivatedLeaf { + hash: relay_parent, + number: 1, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }), + ))) + .await; - // send to a non running job - overseer_handle - .send(FromOverseer::Communication { - msg: Default::default(), - }) - .await; + // send to a non running job + overseer_handle + .send(FromOverseer::Communication { + msg: Default::default(), + }) + .await; - // the subsystem is still alive - assert_matches!( - overseer_handle.recv().await, - AllMessages::CollatorProtocol(_) - ); + // the subsystem is still alive + assert_matches!( + overseer_handle.recv().await, + AllMessages::CollatorProtocol(_) + ); - overseer_handle - .send(FromOverseer::Signal(OverseerSignal::Conclude)) - .await; - }); + overseer_handle + .send(FromOverseer::Signal(OverseerSignal::Conclude)) + .await; + }); } #[test] fn test_subsystem_impl_and_name_derivation() { - let pool = sp_core::testing::TaskExecutor::new(); - let (context, _) = make_subsystem_context::(pool.clone()); + let pool = sp_core::testing::TaskExecutor::new(); + let (context, _) = make_subsystem_context::(pool.clone()); - let SpawnedSubsystem { name, .. } = - FakeCollatorProtocolSubsystem::new(pool, false, ()).start(context); - assert_eq!(name, "FakeCollatorProtocol"); + let SpawnedSubsystem { name, .. } = + FakeCollatorProtocolSubsystem::new(pool, false, ()).start(context); + assert_eq!(name, "FakeCollatorProtocol"); } #[test] fn tick_tack_metronome() { - let n = Arc::new(AtomicUsize::default()); + let n = Arc::new(AtomicUsize::default()); - let (tick, mut block) = mpsc::unbounded(); + let (tick, mut block) = mpsc::unbounded(); - let metronome = { - let n = n.clone(); - let stream = Metronome::new(Duration::from_millis(137_u64)); - stream.for_each(move |_res| { - let _ = n.fetch_add(1, Ordering::Relaxed); - let mut tick = tick.clone(); - async move { - tick.send(()).await.expect("Test helper channel works. qed"); - } - }).fuse() - }; + let metronome = { + let n = n.clone(); + let stream = Metronome::new(Duration::from_millis(137_u64)); + stream.for_each(move |_res| { + let _ = n.fetch_add(1, Ordering::Relaxed); + let mut tick = tick.clone(); + async move { + tick.send(()).await.expect("Test helper channel works. qed"); + } + }).fuse() + }; - let f2 = async move { - block.next().await; - assert_eq!(n.load(Ordering::Relaxed), 1_usize); - block.next().await; - assert_eq!(n.load(Ordering::Relaxed), 2_usize); - block.next().await; - assert_eq!(n.load(Ordering::Relaxed), 3_usize); - block.next().await; - assert_eq!(n.load(Ordering::Relaxed), 4_usize); - }.fuse(); + let f2 = async move { + block.next().await; + assert_eq!(n.load(Ordering::Relaxed), 1_usize); + block.next().await; + assert_eq!(n.load(Ordering::Relaxed), 2_usize); + block.next().await; + assert_eq!(n.load(Ordering::Relaxed), 3_usize); + block.next().await; + assert_eq!(n.load(Ordering::Relaxed), 4_usize); + }.fuse(); - futures::pin_mut!(f2); - futures::pin_mut!(metronome); + futures::pin_mut!(f2); + futures::pin_mut!(metronome); - block_on(async move { - // futures::join!(metronome, f2) - futures::select!( - _ = metronome => unreachable!("Metronome never stops. qed"), - _ = f2 => (), - ) - }); + block_on(async move { + // futures::join!(metronome, f2) + futures::select!( + _ = metronome => unreachable!("Metronome never stops. qed"), + _ = f2 => (), + ) + }); }