Clean up tests from runtime.block_on() and moving around Runtime and Handle (#12941)

This commit is contained in:
Dmitry Markin
2022-12-16 16:29:39 +03:00
committed by GitHub
parent a5cab922a5
commit e14d6a5c4e
13 changed files with 996 additions and 1148 deletions
+3 -5
View File
@@ -77,7 +77,6 @@ pub(crate) mod tests {
use super::*; use super::*;
use crate::tests::BeefyTestNet; use crate::tests::BeefyTestNet;
use sc_network_test::TestNetFactory; use sc_network_test::TestNetFactory;
use tokio::runtime::Runtime;
// also used in tests.rs // also used in tests.rs
pub fn verify_persisted_version<B: BlockT, BE: Backend<B>>(backend: &BE) -> bool { pub fn verify_persisted_version<B: BlockT, BE: Backend<B>>(backend: &BE) -> bool {
@@ -85,10 +84,9 @@ pub(crate) mod tests {
version == CURRENT_VERSION version == CURRENT_VERSION
} }
#[test] #[tokio::test]
fn should_load_persistent_sanity_checks() { async fn should_load_persistent_sanity_checks() {
let runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let backend = net.peer(0).client().as_backend(); let backend = net.peer(0).client().as_backend();
// version not available in db -> None // version not available in db -> None
+117 -152
View File
@@ -47,7 +47,7 @@ use sc_consensus::{
use sc_network::{config::RequestResponseConfig, ProtocolName}; use sc_network::{config::RequestResponseConfig, ProtocolName};
use sc_network_test::{ use sc_network_test::{
Block, BlockImportAdapter, FullPeerConfig, PassThroughVerifier, Peer, PeersClient, Block, BlockImportAdapter, FullPeerConfig, PassThroughVerifier, Peer, PeersClient,
PeersFullClient, TestNetFactory, WithRuntime, PeersFullClient, TestNetFactory,
}; };
use sc_utils::notification::NotificationReceiver; use sc_utils::notification::NotificationReceiver;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -64,10 +64,7 @@ use sp_runtime::{
}; };
use std::{collections::HashMap, marker::PhantomData, sync::Arc, task::Poll}; use std::{collections::HashMap, marker::PhantomData, sync::Arc, task::Poll};
use substrate_test_runtime_client::{runtime::Header, ClientExt}; use substrate_test_runtime_client::{runtime::Header, ClientExt};
use tokio::{ use tokio::time::Duration;
runtime::{Handle, Runtime},
time::Duration,
};
const GENESIS_HASH: H256 = H256::zero(); const GENESIS_HASH: H256 = H256::zero();
fn beefy_gossip_proto_name() -> ProtocolName { fn beefy_gossip_proto_name() -> ProtocolName {
@@ -106,23 +103,14 @@ pub(crate) struct PeerData {
Mutex<Option<BeefyJustifsRequestHandler<Block, PeersFullClient>>>, Mutex<Option<BeefyJustifsRequestHandler<Block, PeersFullClient>>>,
} }
#[derive(Default)]
pub(crate) struct BeefyTestNet { pub(crate) struct BeefyTestNet {
rt_handle: Handle,
peers: Vec<BeefyPeer>, peers: Vec<BeefyPeer>,
} }
impl WithRuntime for BeefyTestNet {
fn with_runtime(rt_handle: Handle) -> Self {
BeefyTestNet { rt_handle, peers: Vec::new() }
}
fn rt_handle(&self) -> &Handle {
&self.rt_handle
}
}
impl BeefyTestNet { impl BeefyTestNet {
pub(crate) fn new(rt_handle: Handle, n_authority: usize) -> Self { pub(crate) fn new(n_authority: usize) -> Self {
let mut net = BeefyTestNet::with_runtime(rt_handle); let mut net = BeefyTestNet { peers: Vec::with_capacity(n_authority) };
for i in 0..n_authority { for i in 0..n_authority {
let (rx, cfg) = on_demand_justifications_protocol_config(GENESIS_HASH, None); let (rx, cfg) = on_demand_justifications_protocol_config(GENESIS_HASH, None);
@@ -151,13 +139,12 @@ impl BeefyTestNet {
}); });
} }
pub(crate) fn generate_blocks_and_sync( pub(crate) async fn generate_blocks_and_sync(
&mut self, &mut self,
count: usize, count: usize,
session_length: u64, session_length: u64,
validator_set: &BeefyValidatorSet, validator_set: &BeefyValidatorSet,
include_mmr_digest: bool, include_mmr_digest: bool,
runtime: &mut Runtime,
) { ) {
self.peer(0).generate_blocks(count, BlockOrigin::File, |builder| { self.peer(0).generate_blocks(count, BlockOrigin::File, |builder| {
let mut block = builder.build().unwrap().block; let mut block = builder.build().unwrap().block;
@@ -175,7 +162,7 @@ impl BeefyTestNet {
block block
}); });
runtime.block_on(self.wait_until_sync()); self.run_until_sync().await;
} }
} }
@@ -404,17 +391,16 @@ where
tasks.for_each(|_| async move {}) tasks.for_each(|_| async move {})
} }
fn block_until(future: impl Future + Unpin, net: &Arc<Mutex<BeefyTestNet>>, runtime: &mut Runtime) { async fn run_until(future: impl Future + Unpin, net: &Arc<Mutex<BeefyTestNet>>) {
let drive_to_completion = futures::future::poll_fn(|cx| { let drive_to_completion = futures::future::poll_fn(|cx| {
net.lock().poll(cx); net.lock().poll(cx);
Poll::<()>::Pending Poll::<()>::Pending
}); });
runtime.block_on(future::select(future, drive_to_completion)); let _ = future::select(future, drive_to_completion).await;
} }
fn run_for(duration: Duration, net: &Arc<Mutex<BeefyTestNet>>, runtime: &mut Runtime) { async fn run_for(duration: Duration, net: &Arc<Mutex<BeefyTestNet>>) {
let sleep = runtime.spawn(async move { tokio::time::sleep(duration).await }); run_until(Box::pin(tokio::time::sleep(duration)), net).await;
block_until(sleep, net, runtime);
} }
pub(crate) fn get_beefy_streams( pub(crate) fn get_beefy_streams(
@@ -435,10 +421,9 @@ pub(crate) fn get_beefy_streams(
(best_block_streams, versioned_finality_proof_streams) (best_block_streams, versioned_finality_proof_streams)
} }
fn wait_for_best_beefy_blocks( async fn wait_for_best_beefy_blocks(
streams: Vec<NotificationReceiver<H256>>, streams: Vec<NotificationReceiver<H256>>,
net: &Arc<Mutex<BeefyTestNet>>, net: &Arc<Mutex<BeefyTestNet>>,
runtime: &mut Runtime,
expected_beefy_blocks: &[u64], expected_beefy_blocks: &[u64],
) { ) {
let mut wait_for = Vec::new(); let mut wait_for = Vec::new();
@@ -458,13 +443,12 @@ fn wait_for_best_beefy_blocks(
}))); })));
}); });
let wait_for = futures::future::join_all(wait_for); let wait_for = futures::future::join_all(wait_for);
block_until(wait_for, net, runtime); run_until(wait_for, net).await;
} }
fn wait_for_beefy_signed_commitments( async fn wait_for_beefy_signed_commitments(
streams: Vec<NotificationReceiver<BeefyVersionedFinalityProof<Block>>>, streams: Vec<NotificationReceiver<BeefyVersionedFinalityProof<Block>>>,
net: &Arc<Mutex<BeefyTestNet>>, net: &Arc<Mutex<BeefyTestNet>>,
runtime: &mut Runtime,
expected_commitment_block_nums: &[u64], expected_commitment_block_nums: &[u64],
) { ) {
let mut wait_for = Vec::new(); let mut wait_for = Vec::new();
@@ -484,34 +468,33 @@ fn wait_for_beefy_signed_commitments(
}))); })));
}); });
let wait_for = futures::future::join_all(wait_for); let wait_for = futures::future::join_all(wait_for);
block_until(wait_for, net, runtime); run_until(wait_for, net).await;
} }
fn streams_empty_after_timeout<T>( async fn streams_empty_after_timeout<T>(
streams: Vec<NotificationReceiver<T>>, streams: Vec<NotificationReceiver<T>>,
net: &Arc<Mutex<BeefyTestNet>>, net: &Arc<Mutex<BeefyTestNet>>,
runtime: &mut Runtime,
timeout: Option<Duration>, timeout: Option<Duration>,
) where ) where
T: std::fmt::Debug, T: std::fmt::Debug,
T: std::cmp::PartialEq, T: std::cmp::PartialEq,
{ {
if let Some(timeout) = timeout { if let Some(timeout) = timeout {
run_for(timeout, net, runtime); run_for(timeout, net).await;
} }
streams.into_iter().for_each(|mut stream| { for mut stream in streams.into_iter() {
runtime.block_on(future::poll_fn(move |cx| { future::poll_fn(move |cx| {
assert_eq!(stream.poll_next_unpin(cx), Poll::Pending); assert_eq!(stream.poll_next_unpin(cx), Poll::Pending);
Poll::Ready(()) Poll::Ready(())
})); })
}); .await;
}
} }
fn finalize_block_and_wait_for_beefy( async fn finalize_block_and_wait_for_beefy(
net: &Arc<Mutex<BeefyTestNet>>, net: &Arc<Mutex<BeefyTestNet>>,
// peer index and key // peer index and key
peers: impl Iterator<Item = (usize, BeefyKeyring)> + Clone, peers: impl Iterator<Item = (usize, BeefyKeyring)> + Clone,
runtime: &mut Runtime,
finalize_targets: &[u64], finalize_targets: &[u64],
expected_beefy: &[u64], expected_beefy: &[u64],
) { ) {
@@ -528,33 +511,32 @@ fn finalize_block_and_wait_for_beefy(
if expected_beefy.is_empty() { if expected_beefy.is_empty() {
// run for quarter second then verify no new best beefy block available // run for quarter second then verify no new best beefy block available
let timeout = Some(Duration::from_millis(250)); let timeout = Some(Duration::from_millis(250));
streams_empty_after_timeout(best_blocks, &net, runtime, timeout); streams_empty_after_timeout(best_blocks, &net, timeout).await;
streams_empty_after_timeout(versioned_finality_proof, &net, runtime, None); streams_empty_after_timeout(versioned_finality_proof, &net, None).await;
} else { } else {
// run until expected beefy blocks are received // run until expected beefy blocks are received
wait_for_best_beefy_blocks(best_blocks, &net, runtime, expected_beefy); wait_for_best_beefy_blocks(best_blocks, &net, expected_beefy).await;
wait_for_beefy_signed_commitments(versioned_finality_proof, &net, runtime, expected_beefy); wait_for_beefy_signed_commitments(versioned_finality_proof, &net, expected_beefy).await;
} }
} }
#[test] #[tokio::test]
fn beefy_finalizing_blocks() { async fn beefy_finalizing_blocks() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob]; let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob];
let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap();
let session_len = 10; let session_len = 10;
let min_block_delta = 4; let min_block_delta = 4;
let mut net = BeefyTestNet::new(runtime.handle().clone(), 2); let mut net = BeefyTestNet::new(2);
let api = Arc::new(two_validators::TestApi {}); let api = Arc::new(two_validators::TestApi {});
let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect(); let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect();
runtime.spawn(initialize_beefy(&mut net, beefy_peers, min_block_delta)); tokio::spawn(initialize_beefy(&mut net, beefy_peers, min_block_delta));
// push 42 blocks including `AuthorityChange` digests every 10 blocks. // push 42 blocks including `AuthorityChange` digests every 10 blocks.
net.generate_blocks_and_sync(42, session_len, &validator_set, true, &mut runtime); net.generate_blocks_and_sync(42, session_len, &validator_set, true).await;
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
@@ -562,51 +544,44 @@ fn beefy_finalizing_blocks() {
let peers = peers.into_iter().enumerate(); let peers = peers.into_iter().enumerate();
// finalize block #5 -> BEEFY should finalize #1 (mandatory) and #5 from diff-power-of-two rule. // finalize block #5 -> BEEFY should finalize #1 (mandatory) and #5 from diff-power-of-two rule.
finalize_block_and_wait_for_beefy(&net, peers.clone(), &mut runtime, &[1, 5], &[1, 5]); finalize_block_and_wait_for_beefy(&net, peers.clone(), &[1, 5], &[1, 5]).await;
// GRANDPA finalize #10 -> BEEFY finalize #10 (mandatory) // GRANDPA finalize #10 -> BEEFY finalize #10 (mandatory)
finalize_block_and_wait_for_beefy(&net, peers.clone(), &mut runtime, &[10], &[10]); finalize_block_and_wait_for_beefy(&net, peers.clone(), &[10], &[10]).await;
// GRANDPA finalize #18 -> BEEFY finalize #14, then #18 (diff-power-of-two rule) // GRANDPA finalize #18 -> BEEFY finalize #14, then #18 (diff-power-of-two rule)
finalize_block_and_wait_for_beefy(&net, peers.clone(), &mut runtime, &[18], &[14, 18]); finalize_block_and_wait_for_beefy(&net, peers.clone(), &[18], &[14, 18]).await;
// GRANDPA finalize #20 -> BEEFY finalize #20 (mandatory) // GRANDPA finalize #20 -> BEEFY finalize #20 (mandatory)
finalize_block_and_wait_for_beefy(&net, peers.clone(), &mut runtime, &[20], &[20]); finalize_block_and_wait_for_beefy(&net, peers.clone(), &[20], &[20]).await;
// GRANDPA finalize #21 -> BEEFY finalize nothing (yet) because min delta is 4 // GRANDPA finalize #21 -> BEEFY finalize nothing (yet) because min delta is 4
finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[21], &[]); finalize_block_and_wait_for_beefy(&net, peers, &[21], &[]).await;
} }
#[test] #[tokio::test]
fn lagging_validators() { async fn lagging_validators() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob]; let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob];
let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap();
let session_len = 30; let session_len = 30;
let min_block_delta = 1; let min_block_delta = 1;
let mut net = BeefyTestNet::new(runtime.handle().clone(), 2); let mut net = BeefyTestNet::new(2);
let api = Arc::new(two_validators::TestApi {}); let api = Arc::new(two_validators::TestApi {});
let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect(); let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect();
runtime.spawn(initialize_beefy(&mut net, beefy_peers, min_block_delta)); tokio::spawn(initialize_beefy(&mut net, beefy_peers, min_block_delta));
// push 62 blocks including `AuthorityChange` digests every 30 blocks. // push 62 blocks including `AuthorityChange` digests every 30 blocks.
net.generate_blocks_and_sync(62, session_len, &validator_set, true, &mut runtime); net.generate_blocks_and_sync(62, session_len, &validator_set, true).await;
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
let peers = peers.into_iter().enumerate(); let peers = peers.into_iter().enumerate();
// finalize block #15 -> BEEFY should finalize #1 (mandatory) and #9, #13, #14, #15 from // finalize block #15 -> BEEFY should finalize #1 (mandatory) and #9, #13, #14, #15 from
// diff-power-of-two rule. // diff-power-of-two rule.
finalize_block_and_wait_for_beefy( finalize_block_and_wait_for_beefy(&net, peers.clone(), &[1, 15], &[1, 9, 13, 14, 15]).await;
&net,
peers.clone(),
&mut runtime,
&[1, 15],
&[1, 9, 13, 14, 15],
);
// Alice finalizes #25, Bob lags behind // Alice finalizes #25, Bob lags behind
let finalize = net let finalize = net
@@ -620,18 +595,18 @@ fn lagging_validators() {
net.lock().peer(0).client().as_client().finalize_block(finalize, None).unwrap(); net.lock().peer(0).client().as_client().finalize_block(finalize, None).unwrap();
// verify nothing gets finalized by BEEFY // verify nothing gets finalized by BEEFY
let timeout = Some(Duration::from_millis(250)); let timeout = Some(Duration::from_millis(250));
streams_empty_after_timeout(best_blocks, &net, &mut runtime, timeout); streams_empty_after_timeout(best_blocks, &net, timeout).await;
streams_empty_after_timeout(versioned_finality_proof, &net, &mut runtime, None); streams_empty_after_timeout(versioned_finality_proof, &net, None).await;
// Bob catches up and also finalizes #25 // Bob catches up and also finalizes #25
let (best_blocks, versioned_finality_proof) = get_beefy_streams(&mut net.lock(), peers.clone()); let (best_blocks, versioned_finality_proof) = get_beefy_streams(&mut net.lock(), peers.clone());
net.lock().peer(1).client().as_client().finalize_block(finalize, None).unwrap(); net.lock().peer(1).client().as_client().finalize_block(finalize, None).unwrap();
// expected beefy finalizes block #17 from diff-power-of-two // expected beefy finalizes block #17 from diff-power-of-two
wait_for_best_beefy_blocks(best_blocks, &net, &mut runtime, &[23, 24, 25]); wait_for_best_beefy_blocks(best_blocks, &net, &[23, 24, 25]).await;
wait_for_beefy_signed_commitments(versioned_finality_proof, &net, &mut runtime, &[23, 24, 25]); wait_for_beefy_signed_commitments(versioned_finality_proof, &net, &[23, 24, 25]).await;
// Both finalize #30 (mandatory session) and #32 -> BEEFY finalize #30 (mandatory), #31, #32 // Both finalize #30 (mandatory session) and #32 -> BEEFY finalize #30 (mandatory), #31, #32
finalize_block_and_wait_for_beefy(&net, peers.clone(), &mut runtime, &[30, 32], &[30, 31, 32]); finalize_block_and_wait_for_beefy(&net, peers.clone(), &[30, 32], &[30, 31, 32]).await;
// Verify that session-boundary votes get buffered by client and only processed once // Verify that session-boundary votes get buffered by client and only processed once
// session-boundary block is GRANDPA-finalized (this guarantees authenticity for the new session // session-boundary block is GRANDPA-finalized (this guarantees authenticity for the new session
@@ -649,28 +624,27 @@ fn lagging_validators() {
net.lock().peer(0).client().as_client().finalize_block(finalize, None).unwrap(); net.lock().peer(0).client().as_client().finalize_block(finalize, None).unwrap();
// verify nothing gets finalized by BEEFY // verify nothing gets finalized by BEEFY
let timeout = Some(Duration::from_millis(250)); let timeout = Some(Duration::from_millis(250));
streams_empty_after_timeout(best_blocks, &net, &mut runtime, timeout); streams_empty_after_timeout(best_blocks, &net, timeout).await;
streams_empty_after_timeout(versioned_finality_proof, &net, &mut runtime, None); streams_empty_after_timeout(versioned_finality_proof, &net, None).await;
// Bob catches up and also finalizes #60 (and should have buffered Alice's vote on #60) // Bob catches up and also finalizes #60 (and should have buffered Alice's vote on #60)
let (best_blocks, versioned_finality_proof) = get_beefy_streams(&mut net.lock(), peers); let (best_blocks, versioned_finality_proof) = get_beefy_streams(&mut net.lock(), peers);
net.lock().peer(1).client().as_client().finalize_block(finalize, None).unwrap(); net.lock().peer(1).client().as_client().finalize_block(finalize, None).unwrap();
// verify beefy skips intermediary votes, and successfully finalizes mandatory block #60 // verify beefy skips intermediary votes, and successfully finalizes mandatory block #60
wait_for_best_beefy_blocks(best_blocks, &net, &mut runtime, &[60]); wait_for_best_beefy_blocks(best_blocks, &net, &[60]).await;
wait_for_beefy_signed_commitments(versioned_finality_proof, &net, &mut runtime, &[60]); wait_for_beefy_signed_commitments(versioned_finality_proof, &net, &[60]).await;
} }
#[test] #[tokio::test]
fn correct_beefy_payload() { async fn correct_beefy_payload() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie, BeefyKeyring::Dave]; let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie, BeefyKeyring::Dave];
let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap();
let session_len = 20; let session_len = 20;
let min_block_delta = 2; let min_block_delta = 2;
let mut net = BeefyTestNet::new(runtime.handle().clone(), 4); let mut net = BeefyTestNet::new(4);
// Alice, Bob, Charlie will vote on good payloads // Alice, Bob, Charlie will vote on good payloads
let good_api = Arc::new(four_validators::TestApi {}); let good_api = Arc::new(four_validators::TestApi {});
@@ -679,20 +653,20 @@ fn correct_beefy_payload() {
.enumerate() .enumerate()
.map(|(id, key)| (id, key, good_api.clone())) .map(|(id, key)| (id, key, good_api.clone()))
.collect(); .collect();
runtime.spawn(initialize_beefy(&mut net, good_peers, min_block_delta)); tokio::spawn(initialize_beefy(&mut net, good_peers, min_block_delta));
// Dave will vote on bad mmr roots // Dave will vote on bad mmr roots
let bad_api = Arc::new(bad_four_validators::TestApi {}); let bad_api = Arc::new(bad_four_validators::TestApi {});
let bad_peers = vec![(3, &BeefyKeyring::Dave, bad_api)]; let bad_peers = vec![(3, &BeefyKeyring::Dave, bad_api)];
runtime.spawn(initialize_beefy(&mut net, bad_peers, min_block_delta)); tokio::spawn(initialize_beefy(&mut net, bad_peers, min_block_delta));
// push 12 blocks // push 12 blocks
net.generate_blocks_and_sync(12, session_len, &validator_set, false, &mut runtime); net.generate_blocks_and_sync(12, session_len, &validator_set, false).await;
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
let peers = peers.into_iter().enumerate(); let peers = peers.into_iter().enumerate();
// with 3 good voters and 1 bad one, consensus should happen and best blocks produced. // with 3 good voters and 1 bad one, consensus should happen and best blocks produced.
finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[1, 10], &[1, 9]); finalize_block_and_wait_for_beefy(&net, peers, &[1, 10], &[1, 9]).await;
let (best_blocks, versioned_finality_proof) = let (best_blocks, versioned_finality_proof) =
get_beefy_streams(&mut net.lock(), [(0, BeefyKeyring::Alice)].into_iter()); get_beefy_streams(&mut net.lock(), [(0, BeefyKeyring::Alice)].into_iter());
@@ -711,8 +685,8 @@ fn correct_beefy_payload() {
// verify consensus is _not_ reached // verify consensus is _not_ reached
let timeout = Some(Duration::from_millis(250)); let timeout = Some(Duration::from_millis(250));
streams_empty_after_timeout(best_blocks, &net, &mut runtime, timeout); streams_empty_after_timeout(best_blocks, &net, timeout).await;
streams_empty_after_timeout(versioned_finality_proof, &net, &mut runtime, None); streams_empty_after_timeout(versioned_finality_proof, &net, None).await;
// 3rd good validator catches up and votes as well // 3rd good validator catches up and votes as well
let (best_blocks, versioned_finality_proof) = let (best_blocks, versioned_finality_proof) =
@@ -720,21 +694,19 @@ fn correct_beefy_payload() {
net.lock().peer(2).client().as_client().finalize_block(hashof11, None).unwrap(); net.lock().peer(2).client().as_client().finalize_block(hashof11, None).unwrap();
// verify consensus is reached // verify consensus is reached
wait_for_best_beefy_blocks(best_blocks, &net, &mut runtime, &[11]); wait_for_best_beefy_blocks(best_blocks, &net, &[11]).await;
wait_for_beefy_signed_commitments(versioned_finality_proof, &net, &mut runtime, &[11]); wait_for_beefy_signed_commitments(versioned_finality_proof, &net, &[11]).await;
} }
#[test] #[tokio::test]
fn beefy_importing_blocks() { async fn beefy_importing_blocks() {
use futures::{future::poll_fn, task::Poll}; use futures::{future::poll_fn, task::Poll};
use sc_block_builder::BlockBuilderProvider; use sc_block_builder::BlockBuilderProvider;
use sc_client_api::BlockBackend; use sc_client_api::BlockBackend;
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(2);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 2);
let client = net.peer(0).client().clone(); let client = net.peer(0).client().clone();
let (mut block_import, _, peer_data) = net.make_block_import(client.clone()); let (mut block_import, _, peer_data) = net.make_block_import(client.clone());
@@ -759,16 +731,15 @@ fn beefy_importing_blocks() {
// Import without justifications. // Import without justifications.
let mut justif_recv = justif_stream.subscribe(); let mut justif_recv = justif_stream.subscribe();
assert_eq!( assert_eq!(
runtime block_import
.block_on(block_import.import_block(params(block.clone(), None), HashMap::new())) .import_block(params(block.clone(), None), HashMap::new())
.await
.unwrap(), .unwrap(),
ImportResult::Imported(ImportedAux { is_new_best: true, ..Default::default() }), ImportResult::Imported(ImportedAux { is_new_best: true, ..Default::default() }),
); );
assert_eq!( assert_eq!(
runtime block_import.import_block(params(block, None), HashMap::new()).await.unwrap(),
.block_on(block_import.import_block(params(block, None), HashMap::new())) ImportResult::AlreadyInChain,
.unwrap(),
ImportResult::AlreadyInChain
); );
// Verify no BEEFY justifications present: // Verify no BEEFY justifications present:
{ {
@@ -781,10 +752,11 @@ fn beefy_importing_blocks() {
None None
); );
// and none sent to BEEFY worker. // and none sent to BEEFY worker.
runtime.block_on(poll_fn(move |cx| { poll_fn(move |cx| {
assert_eq!(justif_recv.poll_next_unpin(cx), Poll::Pending); assert_eq!(justif_recv.poll_next_unpin(cx), Poll::Pending);
Poll::Ready(()) Poll::Ready(())
})); })
.await;
} }
// Import with valid justification. // Import with valid justification.
@@ -802,9 +774,7 @@ fn beefy_importing_blocks() {
let hashof2 = block.header.hash(); let hashof2 = block.header.hash();
let mut justif_recv = justif_stream.subscribe(); let mut justif_recv = justif_stream.subscribe();
assert_eq!( assert_eq!(
runtime block_import.import_block(params(block, justif), HashMap::new()).await.unwrap(),
.block_on(block_import.import_block(params(block, justif), HashMap::new()))
.unwrap(),
ImportResult::Imported(ImportedAux { ImportResult::Imported(ImportedAux {
bad_justification: false, bad_justification: false,
is_new_best: true, is_new_best: true,
@@ -823,13 +793,14 @@ fn beefy_importing_blocks() {
); );
// but sent to BEEFY worker // but sent to BEEFY worker
// (worker will append it to backend when all previous mandatory justifs are there as well). // (worker will append it to backend when all previous mandatory justifs are there as well).
runtime.block_on(poll_fn(move |cx| { poll_fn(move |cx| {
match justif_recv.poll_next_unpin(cx) { match justif_recv.poll_next_unpin(cx) {
Poll::Ready(Some(_justification)) => (), Poll::Ready(Some(_justification)) => (),
v => panic!("unexpected value: {:?}", v), v => panic!("unexpected value: {:?}", v),
} }
Poll::Ready(()) Poll::Ready(())
})); })
.await;
} }
// Import with invalid justification (incorrect validator set). // Import with invalid justification (incorrect validator set).
@@ -847,9 +818,7 @@ fn beefy_importing_blocks() {
let hashof3 = block.header.hash(); let hashof3 = block.header.hash();
let mut justif_recv = justif_stream.subscribe(); let mut justif_recv = justif_stream.subscribe();
assert_eq!( assert_eq!(
runtime block_import.import_block(params(block, justif), HashMap::new()).await.unwrap(),
.block_on(block_import.import_block(params(block, justif), HashMap::new()))
.unwrap(),
ImportResult::Imported(ImportedAux { ImportResult::Imported(ImportedAux {
// Still `false` because we don't want to fail import on bad BEEFY justifications. // Still `false` because we don't want to fail import on bad BEEFY justifications.
bad_justification: false, bad_justification: false,
@@ -868,33 +837,33 @@ fn beefy_importing_blocks() {
None None
); );
// and none sent to BEEFY worker. // and none sent to BEEFY worker.
runtime.block_on(poll_fn(move |cx| { poll_fn(move |cx| {
assert_eq!(justif_recv.poll_next_unpin(cx), Poll::Pending); assert_eq!(justif_recv.poll_next_unpin(cx), Poll::Pending);
Poll::Ready(()) Poll::Ready(())
})); })
.await;
} }
} }
#[test] #[tokio::test]
fn voter_initialization() { async fn voter_initialization() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
// Regression test for voter initialization where finality notifications were dropped // Regression test for voter initialization where finality notifications were dropped
// after waiting for BEEFY pallet availability. // after waiting for BEEFY pallet availability.
let mut runtime = Runtime::new().unwrap();
let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob]; let peers = [BeefyKeyring::Alice, BeefyKeyring::Bob];
let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(&peers), 0).unwrap();
let session_len = 5; let session_len = 5;
// Should vote on all mandatory blocks no matter the `min_block_delta`. // Should vote on all mandatory blocks no matter the `min_block_delta`.
let min_block_delta = 10; let min_block_delta = 10;
let mut net = BeefyTestNet::new(runtime.handle().clone(), 2); let mut net = BeefyTestNet::new(2);
let api = Arc::new(two_validators::TestApi {}); let api = Arc::new(two_validators::TestApi {});
let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect(); let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect();
runtime.spawn(initialize_beefy(&mut net, beefy_peers, min_block_delta)); tokio::spawn(initialize_beefy(&mut net, beefy_peers, min_block_delta));
// push 26 blocks // push 26 blocks
net.generate_blocks_and_sync(26, session_len, &validator_set, false, &mut runtime); net.generate_blocks_and_sync(26, session_len, &validator_set, false).await;
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
// Finalize multiple blocks at once to get a burst of finality notifications right from start. // Finalize multiple blocks at once to get a burst of finality notifications right from start.
@@ -903,31 +872,30 @@ fn voter_initialization() {
finalize_block_and_wait_for_beefy( finalize_block_and_wait_for_beefy(
&net, &net,
peers.into_iter().enumerate(), peers.into_iter().enumerate(),
&mut runtime,
&[1, 6, 10, 17, 24, 26], &[1, 6, 10, 17, 24, 26],
&[1, 5, 10, 15, 20, 25], &[1, 5, 10, 15, 20, 25],
); )
.await;
} }
#[test] #[tokio::test]
fn on_demand_beefy_justification_sync() { async fn on_demand_beefy_justification_sync() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let all_peers = let all_peers =
[BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie, BeefyKeyring::Dave]; [BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie, BeefyKeyring::Dave];
let validator_set = ValidatorSet::new(make_beefy_ids(&all_peers), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(&all_peers), 0).unwrap();
let session_len = 5; let session_len = 5;
let min_block_delta = 5; let min_block_delta = 5;
let mut net = BeefyTestNet::new(runtime.handle().clone(), 4); let mut net = BeefyTestNet::new(4);
// Alice, Bob, Charlie start first and make progress through voting. // Alice, Bob, Charlie start first and make progress through voting.
let api = Arc::new(four_validators::TestApi {}); let api = Arc::new(four_validators::TestApi {});
let fast_peers = [BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie]; let fast_peers = [BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie];
let voting_peers = let voting_peers =
fast_peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect(); fast_peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect();
runtime.spawn(initialize_beefy(&mut net, voting_peers, min_block_delta)); tokio::spawn(initialize_beefy(&mut net, voting_peers, min_block_delta));
// Dave will start late and have to catch up using on-demand justification requests (since // Dave will start late and have to catch up using on-demand justification requests (since
// in this test there is no block import queue to automatically import justifications). // in this test there is no block import queue to automatically import justifications).
@@ -937,7 +905,7 @@ fn on_demand_beefy_justification_sync() {
let dave_index = 3; let dave_index = 3;
// push 30 blocks // push 30 blocks
net.generate_blocks_and_sync(30, session_len, &validator_set, false, &mut runtime); net.generate_blocks_and_sync(30, session_len, &validator_set, false).await;
let fast_peers = fast_peers.into_iter().enumerate(); let fast_peers = fast_peers.into_iter().enumerate();
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
@@ -946,15 +914,15 @@ fn on_demand_beefy_justification_sync() {
finalize_block_and_wait_for_beefy( finalize_block_and_wait_for_beefy(
&net, &net,
fast_peers.clone(), fast_peers.clone(),
&mut runtime,
&[1, 6, 10, 17, 24], &[1, 6, 10, 17, 24],
&[1, 5, 10, 15, 20], &[1, 5, 10, 15, 20],
); )
.await;
// Spawn Dave, he's now way behind voting and can only catch up through on-demand justif sync. // Spawn Dave, he's now way behind voting and can only catch up through on-demand justif sync.
runtime.spawn(dave_task); tokio::spawn(dave_task);
// give Dave a chance to spawn and init. // give Dave a chance to spawn and init.
run_for(Duration::from_millis(400), &net, &mut runtime); run_for(Duration::from_millis(400), &net).await;
let (dave_best_blocks, _) = let (dave_best_blocks, _) =
get_beefy_streams(&mut net.lock(), [(dave_index, BeefyKeyring::Dave)].into_iter()); get_beefy_streams(&mut net.lock(), [(dave_index, BeefyKeyring::Dave)].into_iter());
@@ -962,41 +930,40 @@ fn on_demand_beefy_justification_sync() {
let hashof1 = client.expect_block_hash_from_id(&BlockId::number(1)).unwrap(); let hashof1 = client.expect_block_hash_from_id(&BlockId::number(1)).unwrap();
client.finalize_block(hashof1, None).unwrap(); client.finalize_block(hashof1, None).unwrap();
// Give Dave task some cpu cycles to process the finality notification, // Give Dave task some cpu cycles to process the finality notification,
run_for(Duration::from_millis(100), &net, &mut runtime); run_for(Duration::from_millis(100), &net).await;
// freshly spun up Dave now needs to listen for gossip to figure out the state of his peers. // freshly spun up Dave now needs to listen for gossip to figure out the state of his peers.
// Have the other peers do some gossip so Dave finds out about their progress. // Have the other peers do some gossip so Dave finds out about their progress.
finalize_block_and_wait_for_beefy(&net, fast_peers, &mut runtime, &[25], &[25]); finalize_block_and_wait_for_beefy(&net, fast_peers, &[25], &[25]).await;
// Now verify Dave successfully finalized #1 (through on-demand justification request). // Now verify Dave successfully finalized #1 (through on-demand justification request).
wait_for_best_beefy_blocks(dave_best_blocks, &net, &mut runtime, &[1]); wait_for_best_beefy_blocks(dave_best_blocks, &net, &[1]).await;
// Give Dave all tasks some cpu cycles to burn through their events queues, // Give Dave all tasks some cpu cycles to burn through their events queues,
run_for(Duration::from_millis(100), &net, &mut runtime); run_for(Duration::from_millis(100), &net).await;
// then verify Dave catches up through on-demand justification requests. // then verify Dave catches up through on-demand justification requests.
finalize_block_and_wait_for_beefy( finalize_block_and_wait_for_beefy(
&net, &net,
[(dave_index, BeefyKeyring::Dave)].into_iter(), [(dave_index, BeefyKeyring::Dave)].into_iter(),
&mut runtime,
&[6, 10, 17, 24, 26], &[6, 10, 17, 24, 26],
&[5, 10, 15, 20, 25], &[5, 10, 15, 20, 25],
); )
.await;
let all_peers = all_peers.into_iter().enumerate(); let all_peers = all_peers.into_iter().enumerate();
// Now that Dave has caught up, sanity check voting works for all of them. // Now that Dave has caught up, sanity check voting works for all of them.
finalize_block_and_wait_for_beefy(&net, all_peers, &mut runtime, &[30], &[30]); finalize_block_and_wait_for_beefy(&net, all_peers, &[30], &[30]).await;
} }
#[test] #[tokio::test]
fn should_initialize_voter_at_genesis() { async fn should_initialize_voter_at_genesis() {
let keys = &[BeefyKeyring::Alice]; let keys = &[BeefyKeyring::Alice];
let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
let mut runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let backend = net.peer(0).client().as_backend(); let backend = net.peer(0).client().as_backend();
// push 15 blocks with `AuthorityChange` digests every 10 blocks // push 15 blocks with `AuthorityChange` digests every 10 blocks
net.generate_blocks_and_sync(15, 10, &validator_set, false, &mut runtime); net.generate_blocks_and_sync(15, 10, &validator_set, false).await;
let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse(); let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse();
@@ -1033,16 +1000,15 @@ fn should_initialize_voter_at_genesis() {
assert_eq!(state, persisted_state); assert_eq!(state, persisted_state);
} }
#[test] #[tokio::test]
fn should_initialize_voter_when_last_final_is_session_boundary() { async fn should_initialize_voter_when_last_final_is_session_boundary() {
let keys = &[BeefyKeyring::Alice]; let keys = &[BeefyKeyring::Alice];
let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
let mut runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let backend = net.peer(0).client().as_backend(); let backend = net.peer(0).client().as_backend();
// push 15 blocks with `AuthorityChange` digests every 10 blocks // push 15 blocks with `AuthorityChange` digests every 10 blocks
net.generate_blocks_and_sync(15, 10, &validator_set, false, &mut runtime); net.generate_blocks_and_sync(15, 10, &validator_set, false).await;
let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse(); let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse();
@@ -1094,16 +1060,15 @@ fn should_initialize_voter_when_last_final_is_session_boundary() {
assert_eq!(state, persisted_state); assert_eq!(state, persisted_state);
} }
#[test] #[tokio::test]
fn should_initialize_voter_at_latest_finalized() { async fn should_initialize_voter_at_latest_finalized() {
let keys = &[BeefyKeyring::Alice]; let keys = &[BeefyKeyring::Alice];
let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
let mut runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let backend = net.peer(0).client().as_backend(); let backend = net.peer(0).client().as_backend();
// push 15 blocks with `AuthorityChange` digests every 10 blocks // push 15 blocks with `AuthorityChange` digests every 10 blocks
net.generate_blocks_and_sync(15, 10, &validator_set, false, &mut runtime); net.generate_blocks_and_sync(15, 10, &validator_set, false).await;
let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse(); let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse();
+21 -23
View File
@@ -983,7 +983,6 @@ pub(crate) mod tests {
runtime::{Block, Digest, DigestItem, Header, H256}, runtime::{Block, Digest, DigestItem, Header, H256},
Backend, Backend,
}; };
use tokio::runtime::Runtime;
impl<B: super::Block> PersistedState<B> { impl<B: super::Block> PersistedState<B> {
pub fn voting_oracle(&self) -> &VoterOracle<B> { pub fn voting_oracle(&self) -> &VoterOracle<B> {
@@ -1295,12 +1294,11 @@ pub(crate) mod tests {
assert_eq!(extracted, Some(validator_set)); assert_eq!(extracted, Some(validator_set));
} }
#[test] #[tokio::test]
fn keystore_vs_validator_set() { async fn keystore_vs_validator_set() {
let keys = &[Keyring::Alice]; let keys = &[Keyring::Alice];
let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
let runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone()); let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone());
// keystore doesn't contain other keys than validators' // keystore doesn't contain other keys than validators'
@@ -1319,12 +1317,11 @@ pub(crate) mod tests {
assert_eq!(worker.verify_validator_set(&1, &validator_set), expected_err); assert_eq!(worker.verify_validator_set(&1, &validator_set), expected_err);
} }
#[test] #[tokio::test]
fn should_finalize_correctly() { async fn should_finalize_correctly() {
let keys = [Keyring::Alice]; let keys = [Keyring::Alice];
let validator_set = ValidatorSet::new(make_beefy_ids(&keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(&keys), 0).unwrap();
let runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let backend = net.peer(0).client().as_backend(); let backend = net.peer(0).client().as_backend();
let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone()); let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone());
// remove default session, will manually add custom one. // remove default session, will manually add custom one.
@@ -1347,11 +1344,12 @@ pub(crate) mod tests {
// no 'best beefy block' or finality proofs // no 'best beefy block' or finality proofs
assert_eq!(worker.best_beefy_block(), 0); assert_eq!(worker.best_beefy_block(), 0);
runtime.block_on(poll_fn(move |cx| { poll_fn(move |cx| {
assert_eq!(best_block_stream.poll_next_unpin(cx), Poll::Pending); assert_eq!(best_block_stream.poll_next_unpin(cx), Poll::Pending);
assert_eq!(finality_proof.poll_next_unpin(cx), Poll::Pending); assert_eq!(finality_proof.poll_next_unpin(cx), Poll::Pending);
Poll::Ready(()) Poll::Ready(())
})); })
.await;
// unknown hash for block #1 // unknown hash for block #1
let (mut best_block_streams, mut finality_proofs) = let (mut best_block_streams, mut finality_proofs) =
@@ -1368,7 +1366,7 @@ pub(crate) mod tests {
worker.finalize(justif.clone()).unwrap(); worker.finalize(justif.clone()).unwrap();
// verify block finalized // verify block finalized
assert_eq!(worker.best_beefy_block(), 1); assert_eq!(worker.best_beefy_block(), 1);
runtime.block_on(poll_fn(move |cx| { poll_fn(move |cx| {
// unknown hash -> nothing streamed // unknown hash -> nothing streamed
assert_eq!(best_block_stream.poll_next_unpin(cx), Poll::Pending); assert_eq!(best_block_stream.poll_next_unpin(cx), Poll::Pending);
// commitment streamed // commitment streamed
@@ -1378,7 +1376,8 @@ pub(crate) mod tests {
v => panic!("unexpected value: {:?}", v), v => panic!("unexpected value: {:?}", v),
} }
Poll::Ready(()) Poll::Ready(())
})); })
.await;
// generate 2 blocks, try again expect success // generate 2 blocks, try again expect success
let (mut best_block_streams, _) = get_beefy_streams(&mut net, keys); let (mut best_block_streams, _) = get_beefy_streams(&mut net, keys);
@@ -1400,7 +1399,7 @@ pub(crate) mod tests {
assert_eq!(worker.active_rounds().unwrap().session_start(), 2); assert_eq!(worker.active_rounds().unwrap().session_start(), 2);
// verify block finalized // verify block finalized
assert_eq!(worker.best_beefy_block(), 2); assert_eq!(worker.best_beefy_block(), 2);
runtime.block_on(poll_fn(move |cx| { poll_fn(move |cx| {
match best_block_stream.poll_next_unpin(cx) { match best_block_stream.poll_next_unpin(cx) {
// expect Some(hash-of-block-2) // expect Some(hash-of-block-2)
Poll::Ready(Some(hash)) => { Poll::Ready(Some(hash)) => {
@@ -1410,19 +1409,19 @@ pub(crate) mod tests {
v => panic!("unexpected value: {:?}", v), v => panic!("unexpected value: {:?}", v),
} }
Poll::Ready(()) Poll::Ready(())
})); })
.await;
// check BEEFY justifications are also appended to backend // check BEEFY justifications are also appended to backend
let justifs = backend.blockchain().justifications(hashof2).unwrap().unwrap(); let justifs = backend.blockchain().justifications(hashof2).unwrap().unwrap();
assert!(justifs.get(BEEFY_ENGINE_ID).is_some()) assert!(justifs.get(BEEFY_ENGINE_ID).is_some())
} }
#[test] #[tokio::test]
fn should_init_session() { async fn should_init_session() {
let keys = &[Keyring::Alice, Keyring::Bob]; let keys = &[Keyring::Alice, Keyring::Bob];
let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
let runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone()); let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone());
let worker_rounds = worker.active_rounds().unwrap(); let worker_rounds = worker.active_rounds().unwrap();
@@ -1449,12 +1448,11 @@ pub(crate) mod tests {
assert_eq!(rounds.validator_set_id(), new_validator_set.id()); assert_eq!(rounds.validator_set_id(), new_validator_set.id());
} }
#[test] #[tokio::test]
fn should_triage_votes_and_process_later() { async fn should_triage_votes_and_process_later() {
let keys = &[Keyring::Alice, Keyring::Bob]; let keys = &[Keyring::Alice, Keyring::Bob];
let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
let runtime = Runtime::new().unwrap(); let mut net = BeefyTestNet::new(1);
let mut net = BeefyTestNet::new(runtime.handle().clone(), 1);
let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone()); let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1, validator_set.clone());
// remove default session, will manually add custom one. // remove default session, will manually add custom one.
worker.persisted_state.voting_oracle.sessions.clear(); worker.persisted_state.voting_oracle.sessions.clear();
+25 -36
View File
@@ -660,7 +660,6 @@ mod tests {
runtime::{Header, H256}, runtime::{Header, H256},
TestClient, TestClient,
}; };
use tokio::runtime::{Handle, Runtime};
const SLOT_DURATION_MS: u64 = 1000; const SLOT_DURATION_MS: u64 = 1000;
@@ -718,20 +717,11 @@ mod tests {
>; >;
type AuraPeer = Peer<(), PeersClient>; type AuraPeer = Peer<(), PeersClient>;
#[derive(Default)]
pub struct AuraTestNet { pub struct AuraTestNet {
rt_handle: Handle,
peers: Vec<AuraPeer>, peers: Vec<AuraPeer>,
} }
impl WithRuntime for AuraTestNet {
fn with_runtime(rt_handle: Handle) -> Self {
AuraTestNet { rt_handle, peers: Vec::new() }
}
fn rt_handle(&self) -> &Handle {
&self.rt_handle
}
}
impl TestNetFactory for AuraTestNet { impl TestNetFactory for AuraTestNet {
type Verifier = AuraVerifier; type Verifier = AuraVerifier;
type PeerData = (); type PeerData = ();
@@ -780,11 +770,10 @@ mod tests {
} }
} }
#[test] #[tokio::test]
fn authoring_blocks() { async fn authoring_blocks() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let runtime = Runtime::new().unwrap(); let net = AuraTestNet::new(3);
let net = AuraTestNet::new(runtime.handle().clone(), 3);
let peers = &[(0, Keyring::Alice), (1, Keyring::Bob), (2, Keyring::Charlie)]; let peers = &[(0, Keyring::Alice), (1, Keyring::Bob), (2, Keyring::Charlie)];
@@ -850,13 +839,14 @@ mod tests {
); );
} }
runtime.block_on(future::select( future::select(
future::poll_fn(move |cx| { future::poll_fn(move |cx| {
net.lock().poll(cx); net.lock().poll(cx);
Poll::<()>::Pending Poll::<()>::Pending
}), }),
future::select(future::join_all(aura_futures), future::join_all(import_notifications)), future::select(future::join_all(aura_futures), future::join_all(import_notifications)),
)); )
.await;
} }
#[test] #[test]
@@ -875,10 +865,9 @@ mod tests {
); );
} }
#[test] #[tokio::test]
fn current_node_authority_should_claim_slot() { async fn current_node_authority_should_claim_slot() {
let runtime = Runtime::new().unwrap(); let net = AuraTestNet::new(4);
let net = AuraTestNet::new(runtime.handle().clone(), 4);
let mut authorities = vec![ let mut authorities = vec![
Keyring::Alice.public().into(), Keyring::Alice.public().into(),
@@ -922,20 +911,19 @@ mod tests {
Default::default(), Default::default(),
Default::default(), Default::default(),
); );
assert!(runtime.block_on(worker.claim_slot(&head, 0.into(), &authorities)).is_none()); assert!(worker.claim_slot(&head, 0.into(), &authorities).await.is_none());
assert!(runtime.block_on(worker.claim_slot(&head, 1.into(), &authorities)).is_none()); assert!(worker.claim_slot(&head, 1.into(), &authorities).await.is_none());
assert!(runtime.block_on(worker.claim_slot(&head, 2.into(), &authorities)).is_none()); assert!(worker.claim_slot(&head, 2.into(), &authorities).await.is_none());
assert!(runtime.block_on(worker.claim_slot(&head, 3.into(), &authorities)).is_some()); assert!(worker.claim_slot(&head, 3.into(), &authorities).await.is_some());
assert!(runtime.block_on(worker.claim_slot(&head, 4.into(), &authorities)).is_none()); assert!(worker.claim_slot(&head, 4.into(), &authorities).await.is_none());
assert!(runtime.block_on(worker.claim_slot(&head, 5.into(), &authorities)).is_none()); assert!(worker.claim_slot(&head, 5.into(), &authorities).await.is_none());
assert!(runtime.block_on(worker.claim_slot(&head, 6.into(), &authorities)).is_none()); assert!(worker.claim_slot(&head, 6.into(), &authorities).await.is_none());
assert!(runtime.block_on(worker.claim_slot(&head, 7.into(), &authorities)).is_some()); assert!(worker.claim_slot(&head, 7.into(), &authorities).await.is_some());
} }
#[test] #[tokio::test]
fn on_slot_returns_correct_block() { async fn on_slot_returns_correct_block() {
let runtime = Runtime::new().unwrap(); let net = AuraTestNet::new(4);
let net = AuraTestNet::new(runtime.handle().clone(), 4);
let keystore_path = tempfile::tempdir().expect("Creates keystore path"); let keystore_path = tempfile::tempdir().expect("Creates keystore path");
let keystore = LocalKeystore::open(keystore_path.path(), None).expect("Creates keystore."); let keystore = LocalKeystore::open(keystore_path.path(), None).expect("Creates keystore.");
@@ -971,15 +959,16 @@ mod tests {
let head = client.header(&BlockId::Number(0)).unwrap().unwrap(); let head = client.header(&BlockId::Number(0)).unwrap().unwrap();
let res = runtime let res = worker
.block_on(worker.on_slot(SlotInfo { .on_slot(SlotInfo {
slot: 0.into(), slot: 0.into(),
ends_at: Instant::now() + Duration::from_secs(100), ends_at: Instant::now() + Duration::from_secs(100),
create_inherent_data: Box::new(()), create_inherent_data: Box::new(()),
duration: Duration::from_millis(1000), duration: Duration::from_millis(1000),
chain_head: head, chain_head: head,
block_size_limit: None, block_size_limit: None,
})) })
.await
.unwrap(); .unwrap();
// The returned block should be imported and we should be able to get its header by now. // The returned block should be imported and we should be able to get its header by now.
+163 -132
View File
@@ -49,7 +49,6 @@ use sp_runtime::{
}; };
use sp_timestamp::Timestamp; use sp_timestamp::Timestamp;
use std::{cell::RefCell, task::Poll, time::Duration}; use std::{cell::RefCell, task::Poll, time::Duration};
use tokio::runtime::{Handle, Runtime};
type Item = DigestItem; type Item = DigestItem;
@@ -227,20 +226,11 @@ where
type BabePeer = Peer<Option<PeerData>, BabeBlockImport>; type BabePeer = Peer<Option<PeerData>, BabeBlockImport>;
#[derive(Default)]
pub struct BabeTestNet { pub struct BabeTestNet {
rt_handle: Handle,
peers: Vec<BabePeer>, peers: Vec<BabePeer>,
} }
impl WithRuntime for BabeTestNet {
fn with_runtime(rt_handle: Handle) -> Self {
BabeTestNet { rt_handle, peers: Vec::new() }
}
fn rt_handle(&self) -> &Handle {
&self.rt_handle
}
}
type TestHeader = <TestBlock as BlockT>::Header; type TestHeader = <TestBlock as BlockT>::Header;
type TestSelectChain = type TestSelectChain =
@@ -366,12 +356,11 @@ impl TestNetFactory for BabeTestNet {
} }
} }
#[test] #[tokio::test]
#[should_panic] #[should_panic]
fn rejects_empty_block() { async fn rejects_empty_block() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(3);
let mut net = BabeTestNet::new(runtime.handle().clone(), 3);
let block_builder = |builder: BlockBuilder<_, _, _>| builder.build().unwrap().block; let block_builder = |builder: BlockBuilder<_, _, _>| builder.build().unwrap().block;
net.mut_peers(|peer| { net.mut_peers(|peer| {
peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder); peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder);
@@ -385,14 +374,13 @@ fn create_keystore(authority: Sr25519Keyring) -> SyncCryptoStorePtr {
keystore keystore
} }
fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static) { async fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static) {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mutator = Arc::new(mutator) as Mutator; let mutator = Arc::new(mutator) as Mutator;
MUTATOR.with(|m| *m.borrow_mut() = mutator.clone()); MUTATOR.with(|m| *m.borrow_mut() = mutator.clone());
let runtime = Runtime::new().unwrap(); let net = BabeTestNet::new(3);
let net = BabeTestNet::new(runtime.handle().clone(), 3);
let peers = [Sr25519Keyring::Alice, Sr25519Keyring::Bob, Sr25519Keyring::Charlie]; let peers = [Sr25519Keyring::Alice, Sr25519Keyring::Bob, Sr25519Keyring::Charlie];
@@ -469,7 +457,7 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static
.expect("Starts babe"), .expect("Starts babe"),
); );
} }
runtime.block_on(future::select( future::select(
futures::future::poll_fn(move |cx| { futures::future::poll_fn(move |cx| {
let mut net = net.lock(); let mut net = net.lock();
net.poll(cx); net.poll(cx);
@@ -482,17 +470,18 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static
Poll::<()>::Pending Poll::<()>::Pending
}), }),
future::select(future::join_all(import_notifications), future::join_all(babe_futures)), future::select(future::join_all(import_notifications), future::join_all(babe_futures)),
)); )
.await;
} }
#[test] #[tokio::test]
fn authoring_blocks() { async fn authoring_blocks() {
run_one_test(|_, _| ()) run_one_test(|_, _| ()).await;
} }
#[test] #[tokio::test]
#[should_panic] #[should_panic]
fn rejects_missing_inherent_digest() { async fn rejects_missing_inherent_digest() {
run_one_test(|header: &mut TestHeader, stage| { run_one_test(|header: &mut TestHeader, stage| {
let v = std::mem::take(&mut header.digest_mut().logs); let v = std::mem::take(&mut header.digest_mut().logs);
header.digest_mut().logs = v header.digest_mut().logs = v
@@ -500,11 +489,12 @@ fn rejects_missing_inherent_digest() {
.filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none()) .filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none())
.collect() .collect()
}) })
.await;
} }
#[test] #[tokio::test]
#[should_panic] #[should_panic]
fn rejects_missing_seals() { async fn rejects_missing_seals() {
run_one_test(|header: &mut TestHeader, stage| { run_one_test(|header: &mut TestHeader, stage| {
let v = std::mem::take(&mut header.digest_mut().logs); let v = std::mem::take(&mut header.digest_mut().logs);
header.digest_mut().logs = v header.digest_mut().logs = v
@@ -512,18 +502,20 @@ fn rejects_missing_seals() {
.filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none()) .filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none())
.collect() .collect()
}) })
.await;
} }
#[test] #[tokio::test]
#[should_panic] #[should_panic]
fn rejects_missing_consensus_digests() { async fn rejects_missing_consensus_digests() {
run_one_test(|header: &mut TestHeader, stage| { run_one_test(|header: &mut TestHeader, stage| {
let v = std::mem::take(&mut header.digest_mut().logs); let v = std::mem::take(&mut header.digest_mut().logs);
header.digest_mut().logs = v header.digest_mut().logs = v
.into_iter() .into_iter()
.filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none()) .filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none())
.collect() .collect()
}); })
.await;
} }
#[test] #[test]
@@ -601,14 +593,13 @@ fn can_author_block() {
} }
// Propose and import a new BABE block on top of the given parent. // Propose and import a new BABE block on top of the given parent.
fn propose_and_import_block<Transaction: Send + 'static>( async fn propose_and_import_block<Transaction: Send + 'static>(
parent: &TestHeader, parent: &TestHeader,
slot: Option<Slot>, slot: Option<Slot>,
proposer_factory: &mut DummyFactory, proposer_factory: &mut DummyFactory,
block_import: &mut BoxBlockImport<TestBlock, Transaction>, block_import: &mut BoxBlockImport<TestBlock, Transaction>,
runtime: &Runtime,
) -> Hash { ) -> Hash {
let mut proposer = runtime.block_on(proposer_factory.init(parent)).unwrap(); let mut proposer = proposer_factory.init(parent).await.unwrap();
let slot = slot.unwrap_or_else(|| { let slot = slot.unwrap_or_else(|| {
let parent_pre_digest = find_pre_digest::<TestBlock>(parent).unwrap(); let parent_pre_digest = find_pre_digest::<TestBlock>(parent).unwrap();
@@ -624,7 +615,7 @@ fn propose_and_import_block<Transaction: Send + 'static>(
let parent_hash = parent.hash(); let parent_hash = parent.hash();
let mut block = runtime.block_on(proposer.propose_with(pre_digest)).unwrap().block; let mut block = proposer.propose_with(pre_digest).await.unwrap().block;
let epoch_descriptor = proposer_factory let epoch_descriptor = proposer_factory
.epoch_changes .epoch_changes
@@ -660,8 +651,7 @@ fn propose_and_import_block<Transaction: Send + 'static>(
import import
.insert_intermediate(INTERMEDIATE_KEY, BabeIntermediate::<TestBlock> { epoch_descriptor }); .insert_intermediate(INTERMEDIATE_KEY, BabeIntermediate::<TestBlock> { epoch_descriptor });
import.fork_choice = Some(ForkChoiceStrategy::LongestChain); import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
let import_result = let import_result = block_import.import_block(import, Default::default()).await.unwrap();
runtime.block_on(block_import.import_block(import, Default::default())).unwrap();
match import_result { match import_result {
ImportResult::Imported(_) => {}, ImportResult::Imported(_) => {},
@@ -674,20 +664,19 @@ fn propose_and_import_block<Transaction: Send + 'static>(
// Propose and import n valid BABE blocks that are built on top of the given parent. // Propose and import n valid BABE blocks that are built on top of the given parent.
// The proposer takes care of producing epoch change digests according to the epoch // The proposer takes care of producing epoch change digests according to the epoch
// duration (which is set to 6 slots in the test runtime). // duration (which is set to 6 slots in the test runtime).
fn propose_and_import_blocks<Transaction: Send + 'static>( async fn propose_and_import_blocks<Transaction: Send + 'static>(
client: &PeersFullClient, client: &PeersFullClient,
proposer_factory: &mut DummyFactory, proposer_factory: &mut DummyFactory,
block_import: &mut BoxBlockImport<TestBlock, Transaction>, block_import: &mut BoxBlockImport<TestBlock, Transaction>,
parent_id: BlockId<TestBlock>, parent_id: BlockId<TestBlock>,
n: usize, n: usize,
runtime: &Runtime,
) -> Vec<Hash> { ) -> Vec<Hash> {
let mut hashes = Vec::with_capacity(n); let mut hashes = Vec::with_capacity(n);
let mut parent_header = client.header(&parent_id).unwrap().unwrap(); let mut parent_header = client.header(&parent_id).unwrap().unwrap();
for _ in 0..n { for _ in 0..n {
let block_hash = let block_hash =
propose_and_import_block(&parent_header, None, proposer_factory, block_import, runtime); propose_and_import_block(&parent_header, None, proposer_factory, block_import).await;
hashes.push(block_hash); hashes.push(block_hash);
parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap(); parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap();
} }
@@ -695,10 +684,9 @@ fn propose_and_import_blocks<Transaction: Send + 'static>(
hashes hashes
} }
#[test] #[tokio::test]
fn importing_block_one_sets_genesis_epoch() { async fn importing_block_one_sets_genesis_epoch() {
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(1);
let mut net = BabeTestNet::new(runtime.handle().clone(), 1);
let peer = net.peer(0); let peer = net.peer(0);
let data = peer.data.as_ref().expect("babe link set up during initialization"); let data = peer.data.as_ref().expect("babe link set up during initialization");
@@ -720,8 +708,8 @@ fn importing_block_one_sets_genesis_epoch() {
Some(999.into()), Some(999.into()),
&mut proposer_factory, &mut proposer_factory,
&mut block_import, &mut block_import,
&runtime, )
); .await;
let genesis_epoch = Epoch::genesis(&data.link.config, 999.into()); let genesis_epoch = Epoch::genesis(&data.link.config, 999.into());
@@ -736,10 +724,9 @@ fn importing_block_one_sets_genesis_epoch() {
assert_eq!(epoch_for_second_block, genesis_epoch); assert_eq!(epoch_for_second_block, genesis_epoch);
} }
#[test] #[tokio::test]
fn revert_prunes_epoch_changes_and_removes_weights() { async fn revert_prunes_epoch_changes_and_removes_weights() {
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(1);
let mut net = BabeTestNet::new(runtime.handle().clone(), 1);
let peer = net.peer(0); let peer = net.peer(0);
let data = peer.data.as_ref().expect("babe link set up during initialization"); let data = peer.data.as_ref().expect("babe link set up during initialization");
@@ -756,17 +743,6 @@ fn revert_prunes_epoch_changes_and_removes_weights() {
mutator: Arc::new(|_, _| ()), mutator: Arc::new(|_, _| ()),
}; };
let mut propose_and_import_blocks_wrap = |parent_id, n| {
propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
parent_id,
n,
&runtime,
)
};
// Test scenario. // Test scenario.
// Information for epoch 19 is produced on three different forks at block #13. // Information for epoch 19 is produced on three different forks at block #13.
// One branch starts before the revert point (epoch data should be maintained). // One branch starts before the revert point (epoch data should be maintained).
@@ -779,10 +755,38 @@ fn revert_prunes_epoch_changes_and_removes_weights() {
// \ revert *---- G(#13) ---- H(#19) ---#20 < fork #3 // \ revert *---- G(#13) ---- H(#19) ---#20 < fork #3
// \ to #10 // \ to #10
// *-----E(#7)---#11 < fork #1 // *-----E(#7)---#11 < fork #1
let canon = propose_and_import_blocks_wrap(BlockId::Number(0), 21); let canon = propose_and_import_blocks(
let fork1 = propose_and_import_blocks_wrap(BlockId::Hash(canon[0]), 10); &client,
let fork2 = propose_and_import_blocks_wrap(BlockId::Hash(canon[7]), 10); &mut proposer_factory,
let fork3 = propose_and_import_blocks_wrap(BlockId::Hash(canon[11]), 8); &mut block_import,
BlockId::Number(0),
21,
)
.await;
let fork1 = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(canon[0]),
10,
)
.await;
let fork2 = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(canon[7]),
10,
)
.await;
let fork3 = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(canon[11]),
8,
)
.await;
// We should be tracking a total of 9 epochs in the fork tree // We should be tracking a total of 9 epochs in the fork tree
assert_eq!(epoch_changes.shared_data().tree().iter().count(), 8); assert_eq!(epoch_changes.shared_data().tree().iter().count(), 8);
@@ -824,10 +828,9 @@ fn revert_prunes_epoch_changes_and_removes_weights() {
assert!(weight_data_check(&fork3, false)); assert!(weight_data_check(&fork3, false));
} }
#[test] #[tokio::test]
fn revert_not_allowed_for_finalized() { async fn revert_not_allowed_for_finalized() {
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(1);
let mut net = BabeTestNet::new(runtime.handle().clone(), 1);
let peer = net.peer(0); let peer = net.peer(0);
let data = peer.data.as_ref().expect("babe link set up during initialization"); let data = peer.data.as_ref().expect("babe link set up during initialization");
@@ -843,18 +846,14 @@ fn revert_not_allowed_for_finalized() {
mutator: Arc::new(|_, _| ()), mutator: Arc::new(|_, _| ()),
}; };
let mut propose_and_import_blocks_wrap = |parent_id, n| { let canon = propose_and_import_blocks(
propose_and_import_blocks( &client,
&client, &mut proposer_factory,
&mut proposer_factory, &mut block_import,
&mut block_import, BlockId::Number(0),
parent_id, 3,
n, )
&runtime, .await;
)
};
let canon = propose_and_import_blocks_wrap(BlockId::Number(0), 3);
// Finalize best block // Finalize best block
client.finalize_block(canon[2], None, false).unwrap(); client.finalize_block(canon[2], None, false).unwrap();
@@ -870,10 +869,9 @@ fn revert_not_allowed_for_finalized() {
assert!(weight_data_check(&canon, true)); assert!(weight_data_check(&canon, true));
} }
#[test] #[tokio::test]
fn importing_epoch_change_block_prunes_tree() { async fn importing_epoch_change_block_prunes_tree() {
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(1);
let mut net = BabeTestNet::new(runtime.handle().clone(), 1);
let peer = net.peer(0); let peer = net.peer(0);
let data = peer.data.as_ref().expect("babe link set up during initialization"); let data = peer.data.as_ref().expect("babe link set up during initialization");
@@ -889,17 +887,6 @@ fn importing_epoch_change_block_prunes_tree() {
mutator: Arc::new(|_, _| ()), mutator: Arc::new(|_, _| ()),
}; };
let mut propose_and_import_blocks_wrap = |parent_id, n| {
propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
parent_id,
n,
&runtime,
)
};
// This is the block tree that we're going to use in this test. Each node // This is the block tree that we're going to use in this test. Each node
// represents an epoch change block, the epoch duration is 6 slots. // represents an epoch change block, the epoch duration is 6 slots.
// //
@@ -912,12 +899,40 @@ fn importing_epoch_change_block_prunes_tree() {
// Create and import the canon chain and keep track of fork blocks (A, C, D) // Create and import the canon chain and keep track of fork blocks (A, C, D)
// from the diagram above. // from the diagram above.
let canon = propose_and_import_blocks_wrap(BlockId::Number(0), 30); let canon = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Number(0),
30,
)
.await;
// Create the forks // Create the forks
let fork_1 = propose_and_import_blocks_wrap(BlockId::Hash(canon[0]), 10); let fork_1 = propose_and_import_blocks(
let fork_2 = propose_and_import_blocks_wrap(BlockId::Hash(canon[12]), 15); &client,
let fork_3 = propose_and_import_blocks_wrap(BlockId::Hash(canon[18]), 10); &mut proposer_factory,
&mut block_import,
BlockId::Hash(canon[0]),
10,
)
.await;
let fork_2 = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(canon[12]),
15,
)
.await;
let fork_3 = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(canon[18]),
10,
)
.await;
// We should be tracking a total of 9 epochs in the fork tree // We should be tracking a total of 9 epochs in the fork tree
assert_eq!(epoch_changes.shared_data().tree().iter().count(), 9); assert_eq!(epoch_changes.shared_data().tree().iter().count(), 9);
@@ -928,7 +943,14 @@ fn importing_epoch_change_block_prunes_tree() {
// We finalize block #13 from the canon chain, so on the next epoch // We finalize block #13 from the canon chain, so on the next epoch
// change the tree should be pruned, to not contain F (#7). // change the tree should be pruned, to not contain F (#7).
client.finalize_block(canon[12], None, false).unwrap(); client.finalize_block(canon[12], None, false).unwrap();
propose_and_import_blocks_wrap(BlockId::Hash(client.chain_info().best_hash), 7); propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(client.chain_info().best_hash),
7,
)
.await;
let nodes: Vec<_> = epoch_changes.shared_data().tree().iter().map(|(h, _, _)| *h).collect(); let nodes: Vec<_> = epoch_changes.shared_data().tree().iter().map(|(h, _, _)| *h).collect();
@@ -941,7 +963,14 @@ fn importing_epoch_change_block_prunes_tree() {
// finalizing block #25 from the canon chain should prune out the second fork // finalizing block #25 from the canon chain should prune out the second fork
client.finalize_block(canon[24], None, false).unwrap(); client.finalize_block(canon[24], None, false).unwrap();
propose_and_import_blocks_wrap(BlockId::Hash(client.chain_info().best_hash), 8); propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Hash(client.chain_info().best_hash),
8,
)
.await;
let nodes: Vec<_> = epoch_changes.shared_data().tree().iter().map(|(h, _, _)| *h).collect(); let nodes: Vec<_> = epoch_changes.shared_data().tree().iter().map(|(h, _, _)| *h).collect();
@@ -954,11 +983,10 @@ fn importing_epoch_change_block_prunes_tree() {
assert!(nodes.iter().any(|h| *h == canon[24])); assert!(nodes.iter().any(|h| *h == canon[24]));
} }
#[test] #[tokio::test]
#[should_panic] #[should_panic]
fn verify_slots_are_strictly_increasing() { async fn verify_slots_are_strictly_increasing() {
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(1);
let mut net = BabeTestNet::new(runtime.handle().clone(), 1);
let peer = net.peer(0); let peer = net.peer(0);
let data = peer.data.as_ref().expect("babe link set up during initialization"); let data = peer.data.as_ref().expect("babe link set up during initialization");
@@ -981,20 +1009,14 @@ fn verify_slots_are_strictly_increasing() {
Some(999.into()), Some(999.into()),
&mut proposer_factory, &mut proposer_factory,
&mut block_import, &mut block_import,
&runtime, )
); .await;
let b1 = client.header(&BlockId::Hash(b1)).unwrap().unwrap(); let b1 = client.header(&BlockId::Hash(b1)).unwrap().unwrap();
// we should fail to import this block since the slot number didn't increase. // we should fail to import this block since the slot number didn't increase.
// we will panic due to the `PanickingBlockImport` defined above. // we will panic due to the `PanickingBlockImport` defined above.
propose_and_import_block( propose_and_import_block(&b1, Some(999.into()), &mut proposer_factory, &mut block_import).await;
&b1,
Some(999.into()),
&mut proposer_factory,
&mut block_import,
&runtime,
);
} }
#[test] #[test]
@@ -1027,10 +1049,9 @@ fn babe_transcript_generation_match() {
debug_assert!(test(orig_transcript) == test(transcript_from_data(new_transcript))); debug_assert!(test(orig_transcript) == test(transcript_from_data(new_transcript)));
} }
#[test] #[tokio::test]
fn obsolete_blocks_aux_data_cleanup() { async fn obsolete_blocks_aux_data_cleanup() {
let runtime = Runtime::new().unwrap(); let mut net = BabeTestNet::new(1);
let mut net = BabeTestNet::new(runtime.handle().clone(), 1);
let peer = net.peer(0); let peer = net.peer(0);
let data = peer.data.as_ref().expect("babe link set up during initialization"); let data = peer.data.as_ref().expect("babe link set up during initialization");
@@ -1052,17 +1073,6 @@ fn obsolete_blocks_aux_data_cleanup() {
let mut block_import = data.block_import.lock().take().expect("import set up during init"); let mut block_import = data.block_import.lock().take().expect("import set up during init");
let mut propose_and_import_blocks_wrap = |parent_id, n| {
propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
parent_id,
n,
&runtime,
)
};
let aux_data_check = |hashes: &[Hash], expected: bool| { let aux_data_check = |hashes: &[Hash], expected: bool| {
hashes.iter().all(|hash| { hashes.iter().all(|hash| {
aux_schema::load_block_weight(&*peer.client().as_backend(), hash) aux_schema::load_block_weight(&*peer.client().as_backend(), hash)
@@ -1077,9 +1087,30 @@ fn obsolete_blocks_aux_data_cleanup() {
// G --- A1 --- A2 --- A3 --- A4 ( < fork1 ) // G --- A1 --- A2 --- A3 --- A4 ( < fork1 )
// \-----C4 --- C5 ( < fork3 ) // \-----C4 --- C5 ( < fork3 )
let fork1_hashes = propose_and_import_blocks_wrap(BlockId::Number(0), 4); let fork1_hashes = propose_and_import_blocks(
let fork2_hashes = propose_and_import_blocks_wrap(BlockId::Number(0), 2); &client,
let fork3_hashes = propose_and_import_blocks_wrap(BlockId::Number(3), 2); &mut proposer_factory,
&mut block_import,
BlockId::Number(0),
4,
)
.await;
let fork2_hashes = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Number(0),
2,
)
.await;
let fork3_hashes = propose_and_import_blocks(
&client,
&mut proposer_factory,
&mut block_import,
BlockId::Number(3),
2,
)
.await;
// Check that aux data is present for all but the genesis block. // Check that aux data is present for all but the genesis block.
assert!(aux_data_check(&[client.chain_info().genesis_hash], false)); assert!(aux_data_check(&[client.chain_info().genesis_hash], false));
+130 -162
View File
@@ -30,7 +30,7 @@ use sc_consensus::{
use sc_network::config::Role; use sc_network::config::Role;
use sc_network_test::{ use sc_network_test::{
Block, BlockImportAdapter, FullPeerConfig, Hash, PassThroughVerifier, Peer, PeersClient, Block, BlockImportAdapter, FullPeerConfig, Hash, PassThroughVerifier, Peer, PeersClient,
PeersFullClient, TestClient, TestNetFactory, WithRuntime, PeersFullClient, TestClient, TestNetFactory,
}; };
use sp_api::{ApiRef, ProvideRuntimeApi}; use sp_api::{ApiRef, ProvideRuntimeApi};
use sp_blockchain::Result; use sp_blockchain::Result;
@@ -52,7 +52,7 @@ use std::{
pin::Pin, pin::Pin,
}; };
use substrate_test_runtime_client::runtime::BlockNumber; use substrate_test_runtime_client::runtime::BlockNumber;
use tokio::runtime::{Handle, Runtime}; use tokio::runtime::Handle;
use authorities::AuthoritySet; use authorities::AuthoritySet;
use communication::grandpa_protocol_name; use communication::grandpa_protocol_name;
@@ -71,26 +71,16 @@ type GrandpaBlockImport = crate::GrandpaBlockImport<
LongestChain<substrate_test_runtime_client::Backend, Block>, LongestChain<substrate_test_runtime_client::Backend, Block>,
>; >;
#[derive(Default)]
struct GrandpaTestNet { struct GrandpaTestNet {
peers: Vec<GrandpaPeer>, peers: Vec<GrandpaPeer>,
test_config: TestApi, test_config: TestApi,
rt_handle: Handle,
}
impl WithRuntime for GrandpaTestNet {
fn with_runtime(rt_handle: Handle) -> Self {
GrandpaTestNet { peers: Vec::new(), test_config: TestApi::default(), rt_handle }
}
fn rt_handle(&self) -> &Handle {
&self.rt_handle
}
} }
impl GrandpaTestNet { impl GrandpaTestNet {
fn new(test_config: TestApi, n_authority: usize, n_full: usize, rt_handle: Handle) -> Self { fn new(test_config: TestApi, n_authority: usize, n_full: usize) -> Self {
let mut net = GrandpaTestNet::with_runtime(rt_handle); let mut net =
net.peers = Vec::with_capacity(n_authority + n_full); GrandpaTestNet { peers: Vec::with_capacity(n_authority + n_full), test_config };
net.test_config = test_config;
for _ in 0..n_authority { for _ in 0..n_authority {
net.add_authority_peer(); net.add_authority_peer();
@@ -228,16 +218,12 @@ fn create_keystore(authority: Ed25519Keyring) -> SyncCryptoStorePtr {
keystore keystore
} }
fn block_until_complete( async fn run_until_complete(future: impl Future + Unpin, net: &Arc<Mutex<GrandpaTestNet>>) {
future: impl Future + Unpin,
net: &Arc<Mutex<GrandpaTestNet>>,
runtime: &mut Runtime,
) {
let drive_to_completion = futures::future::poll_fn(|cx| { let drive_to_completion = futures::future::poll_fn(|cx| {
net.lock().poll(cx); net.lock().poll(cx);
Poll::<()>::Pending Poll::<()>::Pending
}); });
runtime.block_on(future::select(future, drive_to_completion)); future::select(future, drive_to_completion).await;
} }
// Spawns grandpa voters. Returns a future to spawn on the runtime. // Spawns grandpa voters. Returns a future to spawn on the runtime.
@@ -289,8 +275,7 @@ fn initialize_grandpa(
// run the voters to completion. provide a closure to be invoked after // run the voters to completion. provide a closure to be invoked after
// the voters are spawned but before blocking on them. // the voters are spawned but before blocking on them.
fn run_to_completion_with<F>( async fn run_to_completion_with<F>(
runtime: &mut Runtime,
blocks: u64, blocks: u64,
net: Arc<Mutex<GrandpaTestNet>>, net: Arc<Mutex<GrandpaTestNet>>,
peers: &[Ed25519Keyring], peers: &[Ed25519Keyring],
@@ -303,7 +288,7 @@ where
let highest_finalized = Arc::new(RwLock::new(0)); let highest_finalized = Arc::new(RwLock::new(0));
if let Some(f) = (with)(runtime.handle().clone()) { if let Some(f) = (with)(Handle::current()) {
wait_for.push(f); wait_for.push(f);
}; };
@@ -329,18 +314,17 @@ where
// wait for all finalized on each. // wait for all finalized on each.
let wait_for = ::futures::future::join_all(wait_for); let wait_for = ::futures::future::join_all(wait_for);
block_until_complete(wait_for, &net, runtime); run_until_complete(wait_for, &net).await;
let highest_finalized = *highest_finalized.read(); let highest_finalized = *highest_finalized.read();
highest_finalized highest_finalized
} }
fn run_to_completion( async fn run_to_completion(
runtime: &mut Runtime,
blocks: u64, blocks: u64,
net: Arc<Mutex<GrandpaTestNet>>, net: Arc<Mutex<GrandpaTestNet>>,
peers: &[Ed25519Keyring], peers: &[Ed25519Keyring],
) -> u64 { ) -> u64 {
run_to_completion_with(runtime, blocks, net, peers, |_| None) run_to_completion_with(blocks, net, peers, |_| None).await
} }
fn add_scheduled_change(block: &mut Block, change: ScheduledChange<BlockNumber>) { fn add_scheduled_change(block: &mut Block, change: ScheduledChange<BlockNumber>) {
@@ -361,17 +345,16 @@ fn add_forced_change(
)); ));
} }
#[test] #[tokio::test]
fn finalize_3_voters_no_observers() { async fn finalize_3_voters_no_observers() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let voters = make_ids(peers); let voters = make_ids(peers);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 0);
runtime.spawn(initialize_grandpa(&mut net, peers)); tokio::spawn(initialize_grandpa(&mut net, peers));
net.peer(0).push_blocks(20, false); net.peer(0).push_blocks(20, false);
runtime.block_on(net.wait_until_sync()); net.run_until_sync().await;
let hashof20 = net.peer(0).client().info().best_hash; let hashof20 = net.peer(0).client().info().best_hash;
for i in 0..3 { for i in 0..3 {
@@ -380,7 +363,7 @@ fn finalize_3_voters_no_observers() {
} }
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
run_to_completion(&mut runtime, 20, net.clone(), peers); run_to_completion(20, net.clone(), peers).await;
// normally there's no justification for finalized blocks // normally there's no justification for finalized blocks
assert!( assert!(
@@ -389,17 +372,15 @@ fn finalize_3_voters_no_observers() {
); );
} }
#[test] #[tokio::test]
fn finalize_3_voters_1_full_observer() { async fn finalize_3_voters_1_full_observer() {
let mut runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let voters = make_ids(peers); let voters = make_ids(peers);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 1, runtime.handle().clone()); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 1);
runtime.spawn(initialize_grandpa(&mut net, peers)); tokio::spawn(initialize_grandpa(&mut net, peers));
runtime.spawn({ tokio::spawn({
let peer_id = 3; let peer_id = 3;
let net_service = net.peers[peer_id].network_service().clone(); let net_service = net.peers[peer_id].network_service().clone();
let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed"); let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed");
@@ -444,7 +425,7 @@ fn finalize_3_voters_1_full_observer() {
// wait for all finalized on each. // wait for all finalized on each.
let wait_for = futures::future::join_all(finality_notifications).map(|_| ()); let wait_for = futures::future::join_all(finality_notifications).map(|_| ());
block_until_complete(wait_for, &net, &mut runtime); run_until_complete(wait_for, &net).await;
// all peers should have stored the justification for the best finalized block #20 // all peers should have stored the justification for the best finalized block #20
for peer_id in 0..4 { for peer_id in 0..4 {
@@ -456,8 +437,8 @@ fn finalize_3_voters_1_full_observer() {
} }
} }
#[test] #[tokio::test]
fn transition_3_voters_twice_1_full_observer() { async fn transition_3_voters_twice_1_full_observer() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
@@ -478,8 +459,7 @@ fn transition_3_voters_twice_1_full_observer() {
let genesis_voters = make_ids(peers_a); let genesis_voters = make_ids(peers_a);
let api = TestApi::new(genesis_voters); let api = TestApi::new(genesis_voters);
let mut runtime = Runtime::new().unwrap(); let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8, 1)));
let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8, 1, runtime.handle().clone())));
let mut voters = Vec::new(); let mut voters = Vec::new();
for (peer_id, local_key) in all_peers.clone().into_iter().enumerate() { for (peer_id, local_key) in all_peers.clone().into_iter().enumerate() {
@@ -516,7 +496,7 @@ fn transition_3_voters_twice_1_full_observer() {
} }
net.lock().peer(0).push_blocks(1, false); net.lock().peer(0).push_blocks(1, false);
runtime.block_on(net.lock().wait_until_sync()); net.lock().run_until_sync().await;
for (i, peer) in net.lock().peers().iter().enumerate() { for (i, peer) in net.lock().peers().iter().enumerate() {
let full_client = peer.client().as_client(); let full_client = peer.client().as_client();
@@ -577,13 +557,13 @@ fn transition_3_voters_twice_1_full_observer() {
future::ready(()) future::ready(())
}); });
runtime.spawn(block_production); tokio::spawn(block_production);
} }
let mut finality_notifications = Vec::new(); let mut finality_notifications = Vec::new();
for voter in voters { for voter in voters {
runtime.spawn(voter); tokio::spawn(voter);
} }
for (peer_id, _) in all_peers.into_iter().enumerate() { for (peer_id, _) in all_peers.into_iter().enumerate() {
@@ -607,24 +587,23 @@ fn transition_3_voters_twice_1_full_observer() {
// wait for all finalized on each. // wait for all finalized on each.
let wait_for = ::futures::future::join_all(finality_notifications); let wait_for = ::futures::future::join_all(finality_notifications);
block_until_complete(wait_for, &net, &mut runtime); run_until_complete(wait_for, &net).await;
} }
#[test] #[tokio::test]
fn justification_is_generated_periodically() { async fn justification_is_generated_periodically() {
let mut runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let voters = make_ids(peers); let voters = make_ids(peers);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 0);
runtime.spawn(initialize_grandpa(&mut net, peers)); tokio::spawn(initialize_grandpa(&mut net, peers));
net.peer(0).push_blocks(32, false); net.peer(0).push_blocks(32, false);
runtime.block_on(net.wait_until_sync()); net.run_until_sync().await;
let hashof32 = net.peer(0).client().info().best_hash; let hashof32 = net.peer(0).client().info().best_hash;
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
run_to_completion(&mut runtime, 32, net.clone(), peers); run_to_completion(32, net.clone(), peers).await;
// when block#32 (justification_period) is finalized, justification // when block#32 (justification_period) is finalized, justification
// is required => generated // is required => generated
@@ -633,16 +612,15 @@ fn justification_is_generated_periodically() {
} }
} }
#[test] #[tokio::test]
fn sync_justifications_on_change_blocks() { async fn sync_justifications_on_change_blocks() {
let mut runtime = Runtime::new().unwrap();
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob];
let voters = make_ids(peers_b); let voters = make_ids(peers_b);
// 4 peers, 3 of them are authorities and participate in grandpa // 4 peers, 3 of them are authorities and participate in grandpa
let api = TestApi::new(voters); let api = TestApi::new(voters);
let mut net = GrandpaTestNet::new(api, 3, 1, runtime.handle().clone()); let mut net = GrandpaTestNet::new(api, 3, 1);
let voters = initialize_grandpa(&mut net, peers_a); let voters = initialize_grandpa(&mut net, peers_a);
// add 20 blocks // add 20 blocks
@@ -660,15 +638,15 @@ fn sync_justifications_on_change_blocks() {
// add more blocks on top of it (until we have 25) // add more blocks on top of it (until we have 25)
net.peer(0).push_blocks(4, false); net.peer(0).push_blocks(4, false);
runtime.block_on(net.wait_until_sync()); net.run_until_sync().await;
for i in 0..4 { for i in 0..4 {
assert_eq!(net.peer(i).client().info().best_number, 25, "Peer #{} failed to sync", i); assert_eq!(net.peer(i).client().info().best_number, 25, "Peer #{} failed to sync", i);
} }
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
runtime.spawn(voters); tokio::spawn(voters);
run_to_completion(&mut runtime, 25, net.clone(), peers_a); run_to_completion(25, net.clone(), peers_a).await;
// the first 3 peers are grandpa voters and therefore have already finalized // the first 3 peers are grandpa voters and therefore have already finalized
// block 21 and stored a justification // block 21 and stored a justification
@@ -677,20 +655,20 @@ fn sync_justifications_on_change_blocks() {
} }
// the last peer should get the justification by syncing from other peers // the last peer should get the justification by syncing from other peers
futures::executor::block_on(futures::future::poll_fn(move |cx| { futures::future::poll_fn(move |cx| {
if net.lock().peer(3).client().justifications(hashof21).unwrap().is_none() { if net.lock().peer(3).client().justifications(hashof21).unwrap().is_none() {
net.lock().poll(cx); net.lock().poll(cx);
Poll::Pending Poll::Pending
} else { } else {
Poll::Ready(()) Poll::Ready(())
} }
})) })
.await;
} }
#[test] #[tokio::test]
fn finalizes_multiple_pending_changes_in_order() { async fn finalizes_multiple_pending_changes_in_order() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let peers_b = &[Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::Ferdie]; let peers_b = &[Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::Ferdie];
@@ -710,8 +688,8 @@ fn finalizes_multiple_pending_changes_in_order() {
// but all of them will be part of the voter set eventually so they should be // but all of them will be part of the voter set eventually so they should be
// all added to the network as authorities // all added to the network as authorities
let api = TestApi::new(genesis_voters); let api = TestApi::new(genesis_voters);
let mut net = GrandpaTestNet::new(api, 6, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(api, 6, 0);
runtime.spawn(initialize_grandpa(&mut net, all_peers)); tokio::spawn(initialize_grandpa(&mut net, all_peers));
// add 20 blocks // add 20 blocks
net.peer(0).push_blocks(20, false); net.peer(0).push_blocks(20, false);
@@ -742,7 +720,7 @@ fn finalizes_multiple_pending_changes_in_order() {
// add more blocks on top of it (until we have 30) // add more blocks on top of it (until we have 30)
net.peer(0).push_blocks(4, false); net.peer(0).push_blocks(4, false);
runtime.block_on(net.wait_until_sync()); net.run_until_sync().await;
// all peers imported both change blocks // all peers imported both change blocks
for i in 0..6 { for i in 0..6 {
@@ -750,13 +728,12 @@ fn finalizes_multiple_pending_changes_in_order() {
} }
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
run_to_completion(&mut runtime, 30, net.clone(), all_peers); run_to_completion(30, net.clone(), all_peers).await;
} }
#[test] #[tokio::test]
fn force_change_to_new_set() { async fn force_change_to_new_set() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
// two of these guys are offline. // two of these guys are offline.
let genesis_authorities = &[ let genesis_authorities = &[
Ed25519Keyring::Alice, Ed25519Keyring::Alice,
@@ -769,7 +746,7 @@ fn force_change_to_new_set() {
let api = TestApi::new(make_ids(genesis_authorities)); let api = TestApi::new(make_ids(genesis_authorities));
let voters = make_ids(peers_a); let voters = make_ids(peers_a);
let mut net = GrandpaTestNet::new(api, 3, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(api, 3, 0);
let voters_future = initialize_grandpa(&mut net, peers_a); let voters_future = initialize_grandpa(&mut net, peers_a);
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
@@ -793,7 +770,7 @@ fn force_change_to_new_set() {
}); });
net.lock().peer(0).push_blocks(25, false); net.lock().peer(0).push_blocks(25, false);
runtime.block_on(net.lock().wait_until_sync()); net.lock().run_until_sync().await;
for (i, peer) in net.lock().peers().iter().enumerate() { for (i, peer) in net.lock().peers().iter().enumerate() {
assert_eq!(peer.client().info().best_number, 26, "Peer #{} failed to sync", i); assert_eq!(peer.client().info().best_number, 26, "Peer #{} failed to sync", i);
@@ -809,18 +786,17 @@ fn force_change_to_new_set() {
// it will only finalize if the forced transition happens. // it will only finalize if the forced transition happens.
// we add_blocks after the voters are spawned because otherwise // we add_blocks after the voters are spawned because otherwise
// the link-halves have the wrong AuthoritySet // the link-halves have the wrong AuthoritySet
runtime.spawn(voters_future); tokio::spawn(voters_future);
run_to_completion(&mut runtime, 25, net, peers_a); run_to_completion(25, net, peers_a).await;
} }
#[test] #[tokio::test]
fn allows_reimporting_change_blocks() { async fn allows_reimporting_change_blocks() {
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob];
let voters = make_ids(peers_a); let voters = make_ids(peers_a);
let api = TestApi::new(voters); let api = TestApi::new(voters);
let runtime = Runtime::new().unwrap(); let mut net = GrandpaTestNet::new(api.clone(), 3, 0);
let mut net = GrandpaTestNet::new(api.clone(), 3, 0, runtime.handle().clone());
let client = net.peer(0).client().clone(); let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone()); let (mut block_import, ..) = net.make_block_import(client.clone());
@@ -845,7 +821,7 @@ fn allows_reimporting_change_blocks() {
}; };
assert_eq!( assert_eq!(
runtime.block_on(block_import.import_block(block(), HashMap::new())).unwrap(), block_import.import_block(block(), HashMap::new()).await.unwrap(),
ImportResult::Imported(ImportedAux { ImportResult::Imported(ImportedAux {
needs_justification: true, needs_justification: true,
clear_justification_requests: false, clear_justification_requests: false,
@@ -856,19 +832,18 @@ fn allows_reimporting_change_blocks() {
); );
assert_eq!( assert_eq!(
runtime.block_on(block_import.import_block(block(), HashMap::new())).unwrap(), block_import.import_block(block(), HashMap::new()).await.unwrap(),
ImportResult::AlreadyInChain ImportResult::AlreadyInChain
); );
} }
#[test] #[tokio::test]
fn test_bad_justification() { async fn test_bad_justification() {
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob];
let voters = make_ids(peers_a); let voters = make_ids(peers_a);
let api = TestApi::new(voters); let api = TestApi::new(voters);
let runtime = Runtime::new().unwrap(); let mut net = GrandpaTestNet::new(api.clone(), 3, 0);
let mut net = GrandpaTestNet::new(api.clone(), 3, 0, runtime.handle().clone());
let client = net.peer(0).client().clone(); let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone()); let (mut block_import, ..) = net.make_block_import(client.clone());
@@ -895,7 +870,7 @@ fn test_bad_justification() {
}; };
assert_eq!( assert_eq!(
runtime.block_on(block_import.import_block(block(), HashMap::new())).unwrap(), block_import.import_block(block(), HashMap::new()).await.unwrap(),
ImportResult::Imported(ImportedAux { ImportResult::Imported(ImportedAux {
needs_justification: true, needs_justification: true,
clear_justification_requests: false, clear_justification_requests: false,
@@ -906,18 +881,17 @@ fn test_bad_justification() {
); );
assert_eq!( assert_eq!(
runtime.block_on(block_import.import_block(block(), HashMap::new())).unwrap(), block_import.import_block(block(), HashMap::new()).await.unwrap(),
ImportResult::AlreadyInChain ImportResult::AlreadyInChain
); );
} }
#[test] #[tokio::test]
fn voter_persists_its_votes() { async fn voter_persists_its_votes() {
use futures::future; use futures::future;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
// we have two authorities but we'll only be running the voter for alice // we have two authorities but we'll only be running the voter for alice
// we are going to be listening for the prevotes it casts // we are going to be listening for the prevotes it casts
@@ -925,7 +899,7 @@ fn voter_persists_its_votes() {
let voters = make_ids(peers); let voters = make_ids(peers);
// alice has a chain with 20 blocks // alice has a chain with 20 blocks
let mut net = GrandpaTestNet::new(TestApi::new(voters.clone()), 2, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(TestApi::new(voters.clone()), 2, 0);
// create the communication layer for bob, but don't start any // create the communication layer for bob, but don't start any
// voter. instead we'll listen for the prevote that alice casts // voter. instead we'll listen for the prevote that alice casts
@@ -1042,10 +1016,10 @@ fn voter_persists_its_votes() {
}) })
} }
runtime.spawn(alice_voter1); tokio::spawn(alice_voter1);
net.peer(0).push_blocks(20, false); net.peer(0).push_blocks(20, false);
runtime.block_on(net.wait_until_sync()); net.run_until_sync().await;
assert_eq!(net.peer(0).client().info().best_number, 20, "Peer #{} failed to sync", 0); assert_eq!(net.peer(0).client().info().best_number, 20, "Peer #{} failed to sync", 0);
@@ -1062,7 +1036,7 @@ fn voter_persists_its_votes() {
HasVoted::No, HasVoted::No,
); );
runtime.spawn(bob_network); tokio::spawn(bob_network);
let round_tx = Arc::new(Mutex::new(round_tx)); let round_tx = Arc::new(Mutex::new(round_tx));
let exit_tx = Arc::new(Mutex::new(Some(exit_tx))); let exit_tx = Arc::new(Mutex::new(Some(exit_tx)));
@@ -1070,15 +1044,13 @@ fn voter_persists_its_votes() {
let net = net.clone(); let net = net.clone();
let state = Arc::new(AtomicUsize::new(0)); let state = Arc::new(AtomicUsize::new(0));
let runtime_handle = runtime.handle().clone(); tokio::spawn(round_rx.for_each(move |signed| {
runtime.spawn(round_rx.for_each(move |signed| {
let net2 = net.clone(); let net2 = net.clone();
let net = net.clone(); let net = net.clone();
let abort = abort.clone(); let abort = abort.clone();
let round_tx = round_tx.clone(); let round_tx = round_tx.clone();
let state = state.clone(); let state = state.clone();
let exit_tx = exit_tx.clone(); let exit_tx = exit_tx.clone();
let runtime_handle = runtime_handle.clone();
async move { async move {
if state.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst).unwrap() == 0 { if state.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst).unwrap() == 0 {
@@ -1115,7 +1087,7 @@ fn voter_persists_its_votes() {
// we restart alice's voter // we restart alice's voter
abort.abort(); abort.abort();
runtime_handle.spawn(alice_voter2(peers, net.clone())); tokio::spawn(alice_voter2(peers, net.clone()));
// and we push our own prevote for block 30 // and we push our own prevote for block 30
let prevote = let prevote =
@@ -1164,17 +1136,16 @@ fn voter_persists_its_votes() {
})); }));
} }
block_until_complete(exit_rx.into_future(), &net, &mut runtime); run_until_complete(exit_rx.into_future(), &net).await;
} }
#[test] #[tokio::test]
fn finalize_3_voters_1_light_observer() { async fn finalize_3_voters_1_light_observer() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let authorities = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let authorities = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let voters = make_ids(authorities); let voters = make_ids(authorities);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 1, runtime.handle().clone()); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3, 1);
let voters = initialize_grandpa(&mut net, authorities); let voters = initialize_grandpa(&mut net, authorities);
let observer = observer::run_grandpa_observer( let observer = observer::run_grandpa_observer(
Config { Config {
@@ -1192,7 +1163,7 @@ fn finalize_3_voters_1_light_observer() {
) )
.unwrap(); .unwrap();
net.peer(0).push_blocks(20, false); net.peer(0).push_blocks(20, false);
runtime.block_on(net.wait_until_sync()); net.run_until_sync().await;
for i in 0..4 { for i in 0..4 {
assert_eq!(net.peer(i).client().info().best_number, 20, "Peer #{} failed to sync", i); assert_eq!(net.peer(i).client().info().best_number, 20, "Peer #{} failed to sync", i);
@@ -1200,20 +1171,19 @@ fn finalize_3_voters_1_light_observer() {
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
runtime.spawn(voters); tokio::spawn(voters);
runtime.spawn(observer); tokio::spawn(observer);
run_to_completion(&mut runtime, 20, net.clone(), authorities); run_to_completion(20, net.clone(), authorities).await;
} }
#[test] #[tokio::test]
fn voter_catches_up_to_latest_round_when_behind() { async fn voter_catches_up_to_latest_round_when_behind() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob];
let voters = make_ids(peers); let voters = make_ids(peers);
let net = GrandpaTestNet::new(TestApi::new(voters), 2, 0, runtime.handle().clone()); let net = GrandpaTestNet::new(TestApi::new(voters), 2, 0);
let net = Arc::new(Mutex::new(net)); let net = Arc::new(Mutex::new(net));
let mut finality_notifications = Vec::new(); let mut finality_notifications = Vec::new();
@@ -1265,11 +1235,11 @@ fn voter_catches_up_to_latest_round_when_behind() {
let voter = voter(Some(keystore), peer_id, link, net.clone()); let voter = voter(Some(keystore), peer_id, link, net.clone());
runtime.spawn(voter); tokio::spawn(voter);
} }
net.lock().peer(0).push_blocks(50, false); net.lock().peer(0).push_blocks(50, false);
runtime.block_on(net.lock().wait_until_sync()); net.lock().run_until_sync().await;
// wait for them to finalize block 50. since they'll vote on 3/4 of the // wait for them to finalize block 50. since they'll vote on 3/4 of the
// unfinalized chain it will take at least 4 rounds to do it. // unfinalized chain it will take at least 4 rounds to do it.
@@ -1279,7 +1249,6 @@ fn voter_catches_up_to_latest_round_when_behind() {
// able to catch up to the latest round // able to catch up to the latest round
let test = { let test = {
let net = net.clone(); let net = net.clone();
let runtime = runtime.handle().clone();
wait_for_finality.then(move |_| { wait_for_finality.then(move |_| {
net.lock().add_authority_peer(); net.lock().add_authority_peer();
@@ -1290,7 +1259,7 @@ fn voter_catches_up_to_latest_round_when_behind() {
link.take().expect("link initialized at startup; qed") link.take().expect("link initialized at startup; qed")
}; };
let set_state = link.persistent_data.set_state.clone(); let set_state = link.persistent_data.set_state.clone();
runtime.spawn(voter(None, 2, link, net.clone())); tokio::spawn(voter(None, 2, link, net.clone()));
let start_time = std::time::Instant::now(); let start_time = std::time::Instant::now();
let timeout = Duration::from_secs(5 * 60); let timeout = Duration::from_secs(5 * 60);
@@ -1315,7 +1284,7 @@ fn voter_catches_up_to_latest_round_when_behind() {
net.lock().poll(cx); net.lock().poll(cx);
Poll::<()>::Pending Poll::<()>::Pending
}); });
runtime.block_on(future::select(test, drive_to_completion)); future::select(test, drive_to_completion).await;
} }
type TestEnvironment<N, VR> = Environment< type TestEnvironment<N, VR> = Environment<
@@ -1370,15 +1339,14 @@ where
} }
} }
#[test] #[tokio::test]
fn grandpa_environment_respects_voting_rules() { async fn grandpa_environment_respects_voting_rules() {
use finality_grandpa::voter::Environment; use finality_grandpa::voter::Environment;
let peers = &[Ed25519Keyring::Alice]; let peers = &[Ed25519Keyring::Alice];
let voters = make_ids(peers); let voters = make_ids(peers);
let runtime = Runtime::new().unwrap(); let mut net = GrandpaTestNet::new(TestApi::new(voters), 1, 0);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 1, 0, runtime.handle().clone());
let peer = net.peer(0); let peer = net.peer(0);
let network_service = peer.network_service().clone(); let network_service = peer.network_service().clone();
let link = peer.data.lock().take().unwrap(); let link = peer.data.lock().take().unwrap();
@@ -1408,8 +1376,9 @@ fn grandpa_environment_respects_voting_rules() {
// the unrestricted environment should just return the best block // the unrestricted environment should just return the best block
assert_eq!( assert_eq!(
runtime unrestricted_env
.block_on(unrestricted_env.best_chain_containing(peer.client().info().finalized_hash)) .best_chain_containing(peer.client().info().finalized_hash)
.await
.unwrap() .unwrap()
.unwrap() .unwrap()
.1, .1,
@@ -1419,8 +1388,9 @@ fn grandpa_environment_respects_voting_rules() {
// both the other environments should return block 16, which is 3/4 of the // both the other environments should return block 16, which is 3/4 of the
// way in the unfinalized chain // way in the unfinalized chain
assert_eq!( assert_eq!(
runtime three_quarters_env
.block_on(three_quarters_env.best_chain_containing(peer.client().info().finalized_hash)) .best_chain_containing(peer.client().info().finalized_hash)
.await
.unwrap() .unwrap()
.unwrap() .unwrap()
.1, .1,
@@ -1428,8 +1398,9 @@ fn grandpa_environment_respects_voting_rules() {
); );
assert_eq!( assert_eq!(
runtime default_env
.block_on(default_env.best_chain_containing(peer.client().info().finalized_hash)) .best_chain_containing(peer.client().info().finalized_hash)
.await
.unwrap() .unwrap()
.unwrap() .unwrap()
.1, .1,
@@ -1446,8 +1417,9 @@ fn grandpa_environment_respects_voting_rules() {
// the 3/4 environment should propose block 21 for voting // the 3/4 environment should propose block 21 for voting
assert_eq!( assert_eq!(
runtime three_quarters_env
.block_on(three_quarters_env.best_chain_containing(peer.client().info().finalized_hash)) .best_chain_containing(peer.client().info().finalized_hash)
.await
.unwrap() .unwrap()
.unwrap() .unwrap()
.1, .1,
@@ -1457,8 +1429,9 @@ fn grandpa_environment_respects_voting_rules() {
// while the default environment will always still make sure we don't vote // while the default environment will always still make sure we don't vote
// on the best block (2 behind) // on the best block (2 behind)
assert_eq!( assert_eq!(
runtime default_env
.block_on(default_env.best_chain_containing(peer.client().info().finalized_hash)) .best_chain_containing(peer.client().info().finalized_hash)
.await
.unwrap() .unwrap()
.unwrap() .unwrap()
.1, .1,
@@ -1477,8 +1450,9 @@ fn grandpa_environment_respects_voting_rules() {
// best block, there's a hard rule that we can't cast any votes lower than // best block, there's a hard rule that we can't cast any votes lower than
// the given base (#21). // the given base (#21).
assert_eq!( assert_eq!(
runtime default_env
.block_on(default_env.best_chain_containing(peer.client().info().finalized_hash)) .best_chain_containing(peer.client().info().finalized_hash)
.await
.unwrap() .unwrap()
.unwrap() .unwrap()
.1, .1,
@@ -1486,15 +1460,14 @@ fn grandpa_environment_respects_voting_rules() {
); );
} }
#[test] #[tokio::test]
fn grandpa_environment_never_overwrites_round_voter_state() { async fn grandpa_environment_never_overwrites_round_voter_state() {
use finality_grandpa::voter::Environment; use finality_grandpa::voter::Environment;
let peers = &[Ed25519Keyring::Alice]; let peers = &[Ed25519Keyring::Alice];
let voters = make_ids(peers); let voters = make_ids(peers);
let runtime = Runtime::new().unwrap(); let mut net = GrandpaTestNet::new(TestApi::new(voters), 1, 0);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 1, 0, runtime.handle().clone());
let peer = net.peer(0); let peer = net.peer(0);
let network_service = peer.network_service().clone(); let network_service = peer.network_service().clone();
let link = peer.data.lock().take().unwrap(); let link = peer.data.lock().take().unwrap();
@@ -1549,16 +1522,15 @@ fn grandpa_environment_never_overwrites_round_voter_state() {
assert_matches!(get_current_round(2).unwrap(), HasVoted::Yes(_, _)); assert_matches!(get_current_round(2).unwrap(), HasVoted::Yes(_, _));
} }
#[test] #[tokio::test]
fn justification_with_equivocation() { async fn justification_with_equivocation() {
use sp_application_crypto::Pair; use sp_application_crypto::Pair;
// we have 100 authorities // we have 100 authorities
let pairs = (0..100).map(|n| AuthorityPair::from_seed(&[n; 32])).collect::<Vec<_>>(); let pairs = (0..100).map(|n| AuthorityPair::from_seed(&[n; 32])).collect::<Vec<_>>();
let voters = pairs.iter().map(AuthorityPair::public).map(|id| (id, 1)).collect::<Vec<_>>(); let voters = pairs.iter().map(AuthorityPair::public).map(|id| (id, 1)).collect::<Vec<_>>();
let api = TestApi::new(voters.clone()); let api = TestApi::new(voters.clone());
let runtime = Runtime::new().unwrap(); let mut net = GrandpaTestNet::new(api.clone(), 1, 0);
let mut net = GrandpaTestNet::new(api.clone(), 1, 0, runtime.handle().clone());
// we create a basic chain with 3 blocks (no forks) // we create a basic chain with 3 blocks (no forks)
net.peer(0).push_blocks(3, false); net.peer(0).push_blocks(3, false);
@@ -1617,16 +1589,15 @@ fn justification_with_equivocation() {
assert!(justification.verify(set_id, &voters).is_ok()); assert!(justification.verify(set_id, &voters).is_ok());
} }
#[test] #[tokio::test]
fn imports_justification_for_regular_blocks_on_import() { async fn imports_justification_for_regular_blocks_on_import() {
// NOTE: this is a regression test since initially we would only import // NOTE: this is a regression test since initially we would only import
// justifications for authority change blocks, and would discard any // justifications for authority change blocks, and would discard any
// existing justification otherwise. // existing justification otherwise.
let peers = &[Ed25519Keyring::Alice]; let peers = &[Ed25519Keyring::Alice];
let voters = make_ids(peers); let voters = make_ids(peers);
let api = TestApi::new(voters); let api = TestApi::new(voters);
let runtime = Runtime::new().unwrap(); let mut net = GrandpaTestNet::new(api.clone(), 1, 0);
let mut net = GrandpaTestNet::new(api.clone(), 1, 0, runtime.handle().clone());
let client = net.peer(0).client().clone(); let client = net.peer(0).client().clone();
let (mut block_import, ..) = net.make_block_import(client.clone()); let (mut block_import, ..) = net.make_block_import(client.clone());
@@ -1675,7 +1646,7 @@ fn imports_justification_for_regular_blocks_on_import() {
import.fork_choice = Some(ForkChoiceStrategy::LongestChain); import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
assert_eq!( assert_eq!(
runtime.block_on(block_import.import_block(import, HashMap::new())).unwrap(), block_import.import_block(import, HashMap::new()).await.unwrap(),
ImportResult::Imported(ImportedAux { ImportResult::Imported(ImportedAux {
needs_justification: false, needs_justification: false,
clear_justification_requests: false, clear_justification_requests: false,
@@ -1689,17 +1660,15 @@ fn imports_justification_for_regular_blocks_on_import() {
assert!(client.justifications(block_hash).unwrap().is_some()); assert!(client.justifications(block_hash).unwrap().is_some());
} }
#[test] #[tokio::test]
fn grandpa_environment_doesnt_send_equivocation_reports_for_itself() { async fn grandpa_environment_doesnt_send_equivocation_reports_for_itself() {
use finality_grandpa::voter::Environment; use finality_grandpa::voter::Environment;
let alice = Ed25519Keyring::Alice; let alice = Ed25519Keyring::Alice;
let voters = make_ids(&[alice]); let voters = make_ids(&[alice]);
let runtime = Runtime::new().unwrap();
let environment = { let environment = {
let mut net = GrandpaTestNet::new(TestApi::new(voters), 1, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(TestApi::new(voters), 1, 0);
let peer = net.peer(0); let peer = net.peer(0);
let network_service = peer.network_service().clone(); let network_service = peer.network_service().clone();
let link = peer.data.lock().take().unwrap(); let link = peer.data.lock().take().unwrap();
@@ -1737,10 +1706,9 @@ fn grandpa_environment_doesnt_send_equivocation_reports_for_itself() {
assert!(environment.report_equivocation(equivocation_proof).is_ok()); assert!(environment.report_equivocation(equivocation_proof).is_ok());
} }
#[test] #[tokio::test]
fn revert_prunes_authority_changes() { async fn revert_prunes_authority_changes() {
sp_tracing::try_init_simple(); sp_tracing::try_init_simple();
let runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
@@ -1757,8 +1725,8 @@ fn revert_prunes_authority_changes() {
let api = TestApi::new(make_ids(peers)); let api = TestApi::new(make_ids(peers));
let mut net = GrandpaTestNet::new(api, 3, 0, runtime.handle().clone()); let mut net = GrandpaTestNet::new(api, 3, 0);
runtime.spawn(initialize_grandpa(&mut net, peers)); tokio::spawn(initialize_grandpa(&mut net, peers));
let peer = net.peer(0); let peer = net.peer(0);
let client = peer.client().as_client(); let client = peer.client().as_client();
@@ -489,7 +489,7 @@ mod tests {
})) }))
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn keeps_multiple_subscribers_per_topic_updated_with_both_old_and_new_messages() { async fn keeps_multiple_subscribers_per_topic_updated_with_both_old_and_new_messages() {
let topic = H256::default(); let topic = H256::default();
let protocol = ProtocolName::from("/my_protocol"); let protocol = ProtocolName::from("/my_protocol");
@@ -483,20 +483,15 @@ mod tests {
use super::{NotificationsIn, NotificationsInOpen, NotificationsOut, NotificationsOutOpen}; use super::{NotificationsIn, NotificationsInOpen, NotificationsOut, NotificationsOutOpen};
use futures::{channel::oneshot, prelude::*}; use futures::{channel::oneshot, prelude::*};
use libp2p::core::upgrade; use libp2p::core::upgrade;
use tokio::{ use tokio::net::{TcpListener, TcpStream};
net::{TcpListener, TcpStream},
runtime::Runtime,
};
use tokio_util::compat::TokioAsyncReadCompatExt; use tokio_util::compat::TokioAsyncReadCompatExt;
#[test] #[tokio::test]
fn basic_works() { async fn basic_works() {
const PROTO_NAME: &str = "/test/proto/1"; const PROTO_NAME: &str = "/test/proto/1";
let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let (listener_addr_tx, listener_addr_rx) = oneshot::channel();
let runtime = Runtime::new().unwrap(); let client = tokio::spawn(async move {
let client = runtime.spawn(async move {
let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap();
let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound( let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound(
socket.compat(), socket.compat(),
@@ -510,38 +505,34 @@ mod tests {
substream.send(b"test message".to_vec()).await.unwrap(); substream.send(b"test message".to_vec()).await.unwrap();
}); });
runtime.block_on(async move { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
let (socket, _) = listener.accept().await.unwrap(); let (socket, _) = listener.accept().await.unwrap();
let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound(
socket.compat(), socket.compat(),
NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024),
) )
.await .await
.unwrap(); .unwrap();
assert_eq!(handshake, b"initial message"); assert_eq!(handshake, b"initial message");
substream.send_handshake(&b"hello world"[..]); substream.send_handshake(&b"hello world"[..]);
let msg = substream.next().await.unwrap().unwrap(); let msg = substream.next().await.unwrap().unwrap();
assert_eq!(msg.as_ref(), b"test message"); assert_eq!(msg.as_ref(), b"test message");
});
runtime.block_on(client).unwrap(); client.await.unwrap();
} }
#[test] #[tokio::test]
fn empty_handshake() { async fn empty_handshake() {
// Check that everything still works when the handshake messages are empty. // Check that everything still works when the handshake messages are empty.
const PROTO_NAME: &str = "/test/proto/1"; const PROTO_NAME: &str = "/test/proto/1";
let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let (listener_addr_tx, listener_addr_rx) = oneshot::channel();
let runtime = Runtime::new().unwrap(); let client = tokio::spawn(async move {
let client = runtime.spawn(async move {
let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap();
let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound( let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound(
socket.compat(), socket.compat(),
@@ -555,36 +546,32 @@ mod tests {
substream.send(Default::default()).await.unwrap(); substream.send(Default::default()).await.unwrap();
}); });
runtime.block_on(async move { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
let (socket, _) = listener.accept().await.unwrap(); let (socket, _) = listener.accept().await.unwrap();
let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound(
socket.compat(), socket.compat(),
NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024),
) )
.await .await
.unwrap(); .unwrap();
assert!(handshake.is_empty()); assert!(handshake.is_empty());
substream.send_handshake(vec![]); substream.send_handshake(vec![]);
let msg = substream.next().await.unwrap().unwrap(); let msg = substream.next().await.unwrap().unwrap();
assert!(msg.as_ref().is_empty()); assert!(msg.as_ref().is_empty());
});
runtime.block_on(client).unwrap(); client.await.unwrap();
} }
#[test] #[tokio::test]
fn refused() { async fn refused() {
const PROTO_NAME: &str = "/test/proto/1"; const PROTO_NAME: &str = "/test/proto/1";
let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let (listener_addr_tx, listener_addr_rx) = oneshot::channel();
let runtime = Runtime::new().unwrap(); let client = tokio::spawn(async move {
let client = runtime.spawn(async move {
let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap();
let outcome = upgrade::apply_outbound( let outcome = upgrade::apply_outbound(
socket.compat(), socket.compat(),
@@ -599,35 +586,31 @@ mod tests {
assert!(outcome.is_err()); assert!(outcome.is_err());
}); });
runtime.block_on(async move { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
let (socket, _) = listener.accept().await.unwrap(); let (socket, _) = listener.accept().await.unwrap();
let NotificationsInOpen { handshake, substream, .. } = upgrade::apply_inbound( let NotificationsInOpen { handshake, substream, .. } = upgrade::apply_inbound(
socket.compat(), socket.compat(),
NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024),
) )
.await .await
.unwrap(); .unwrap();
assert_eq!(handshake, b"hello"); assert_eq!(handshake, b"hello");
// We successfully upgrade to the protocol, but then close the substream. // We successfully upgrade to the protocol, but then close the substream.
drop(substream); drop(substream);
});
runtime.block_on(client).unwrap(); client.await.unwrap();
} }
#[test] #[tokio::test]
fn large_initial_message_refused() { async fn large_initial_message_refused() {
const PROTO_NAME: &str = "/test/proto/1"; const PROTO_NAME: &str = "/test/proto/1";
let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let (listener_addr_tx, listener_addr_rx) = oneshot::channel();
let runtime = Runtime::new().unwrap(); let client = tokio::spawn(async move {
let client = runtime.spawn(async move {
let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap();
let ret = upgrade::apply_outbound( let ret = upgrade::apply_outbound(
socket.compat(), socket.compat(),
@@ -644,30 +627,26 @@ mod tests {
assert!(ret.is_err()); assert!(ret.is_err());
}); });
runtime.block_on(async move { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
let (socket, _) = listener.accept().await.unwrap(); let (socket, _) = listener.accept().await.unwrap();
let ret = upgrade::apply_inbound( let ret = upgrade::apply_inbound(
socket.compat(), socket.compat(),
NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024),
) )
.await; .await;
assert!(ret.is_err()); assert!(ret.is_err());
});
runtime.block_on(client).unwrap(); client.await.unwrap();
} }
#[test] #[tokio::test]
fn large_handshake_refused() { async fn large_handshake_refused() {
const PROTO_NAME: &str = "/test/proto/1"; const PROTO_NAME: &str = "/test/proto/1";
let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let (listener_addr_tx, listener_addr_rx) = oneshot::channel();
let runtime = Runtime::new().unwrap(); let client = tokio::spawn(async move {
let client = runtime.spawn(async move {
let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap();
let ret = upgrade::apply_outbound( let ret = upgrade::apply_outbound(
socket.compat(), socket.compat(),
@@ -678,24 +657,22 @@ mod tests {
assert!(ret.is_err()); assert!(ret.is_err());
}); });
runtime.block_on(async move { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
listener_addr_tx.send(listener.local_addr().unwrap()).unwrap();
let (socket, _) = listener.accept().await.unwrap(); let (socket, _) = listener.accept().await.unwrap();
let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound(
socket.compat(), socket.compat(),
NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024),
) )
.await .await
.unwrap(); .unwrap();
assert_eq!(handshake, b"initial message"); assert_eq!(handshake, b"initial message");
// We check that a handshake that is too large gets refused. // We check that a handshake that is too large gets refused.
substream.send_handshake((0..32768).map(|_| 0).collect::<Vec<_>>()); substream.send_handshake((0..32768).map(|_| 0).collect::<Vec<_>>());
let _ = substream.next().await; let _ = substream.next().await;
});
runtime.block_on(client).unwrap(); client.await.unwrap();
} }
} }
@@ -44,7 +44,6 @@ use std::{
time::Duration, time::Duration,
}; };
use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _}; use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _};
use tokio::runtime::Handle;
fn set_default_expecations_no_peers( fn set_default_expecations_no_peers(
chain_sync: &mut MockChainSync<substrate_test_runtime_client::runtime::Block>, chain_sync: &mut MockChainSync<substrate_test_runtime_client::runtime::Block>,
@@ -72,7 +71,7 @@ async fn normal_network_poll_no_peers() {
let chain_sync_service = let chain_sync_service =
Box::new(MockChainSyncInterface::<substrate_test_runtime_client::runtime::Block>::new()); Box::new(MockChainSyncInterface::<substrate_test_runtime_client::runtime::Block>::new());
let mut network = TestNetworkBuilder::new(Handle::current()) let mut network = TestNetworkBuilder::new()
.with_chain_sync((chain_sync, chain_sync_service)) .with_chain_sync((chain_sync, chain_sync_service))
.build(); .build();
@@ -104,7 +103,7 @@ async fn request_justification() {
let mut chain_sync = MockChainSync::<substrate_test_runtime_client::runtime::Block>::new(); let mut chain_sync = MockChainSync::<substrate_test_runtime_client::runtime::Block>::new();
set_default_expecations_no_peers(&mut chain_sync); set_default_expecations_no_peers(&mut chain_sync);
let mut network = TestNetworkBuilder::new(Handle::current()) let mut network = TestNetworkBuilder::new()
.with_chain_sync((Box::new(chain_sync), chain_sync_service)) .with_chain_sync((Box::new(chain_sync), chain_sync_service))
.build(); .build();
@@ -135,7 +134,7 @@ async fn clear_justification_requests() {
Box::new(MockChainSync::<substrate_test_runtime_client::runtime::Block>::new()); Box::new(MockChainSync::<substrate_test_runtime_client::runtime::Block>::new());
set_default_expecations_no_peers(&mut chain_sync); set_default_expecations_no_peers(&mut chain_sync);
let mut network = TestNetworkBuilder::new(Handle::current()) let mut network = TestNetworkBuilder::new()
.with_chain_sync((chain_sync, chain_sync_service)) .with_chain_sync((chain_sync, chain_sync_service))
.build(); .build();
@@ -174,7 +173,7 @@ async fn set_sync_fork_request() {
.once() .once()
.returning(|_, _, _| ()); .returning(|_, _, _| ());
let mut network = TestNetworkBuilder::new(Handle::current()) let mut network = TestNetworkBuilder::new()
.with_chain_sync((chain_sync, Box::new(chain_sync_service))) .with_chain_sync((chain_sync, Box::new(chain_sync_service)))
.build(); .build();
@@ -218,7 +217,7 @@ async fn on_block_finalized() {
.returning(|_, _| ()); .returning(|_, _| ());
set_default_expecations_no_peers(&mut chain_sync); set_default_expecations_no_peers(&mut chain_sync);
let mut network = TestNetworkBuilder::new(Handle::current()) let mut network = TestNetworkBuilder::new()
.with_client(client) .with_client(client)
.with_chain_sync((chain_sync, chain_sync_service)) .with_chain_sync((chain_sync, chain_sync_service))
.build(); .build();
@@ -316,7 +315,7 @@ async fn invalid_justification_imported() {
let justification_info = Arc::new(RwLock::new(None)); let justification_info = Arc::new(RwLock::new(None));
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let (service1, mut event_stream1) = TestNetworkBuilder::new(Handle::current()) let (service1, mut event_stream1) = TestNetworkBuilder::new()
.with_import_queue(Box::new(DummyImportQueue( .with_import_queue(Box::new(DummyImportQueue(
justification_info.clone(), justification_info.clone(),
DummyImportQueueHandle {}, DummyImportQueueHandle {},
@@ -325,7 +324,7 @@ async fn invalid_justification_imported() {
.build() .build()
.start_network(); .start_network();
let (service2, mut event_stream2) = TestNetworkBuilder::new(Handle::current()) let (service2, mut event_stream2) = TestNetworkBuilder::new()
.with_set_config(SetConfig { .with_set_config(SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr, multiaddr: listen_addr,
@@ -393,7 +392,7 @@ async fn disconnect_peer_using_chain_sync_handle() {
) )
.unwrap(); .unwrap();
let (node1, mut event_stream1) = TestNetworkBuilder::new(Handle::current()) let (node1, mut event_stream1) = TestNetworkBuilder::new()
.with_listen_addresses(vec![listen_addr.clone()]) .with_listen_addresses(vec![listen_addr.clone()])
.with_chain_sync((Box::new(chain_sync), Box::new(chain_sync_service))) .with_chain_sync((Box::new(chain_sync), Box::new(chain_sync_service)))
.with_chain_sync_network((chain_sync_network_provider, chain_sync_network_handle)) .with_chain_sync_network((chain_sync_network_provider, chain_sync_network_handle))
@@ -401,7 +400,7 @@ async fn disconnect_peer_using_chain_sync_handle() {
.build() .build()
.start_network(); .start_network();
let (node2, mut event_stream2) = TestNetworkBuilder::new(Handle::current()) let (node2, mut event_stream2) = TestNetworkBuilder::new()
.with_set_config(SetConfig { .with_set_config(SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr, multiaddr: listen_addr,
@@ -44,7 +44,6 @@ use substrate_test_runtime_client::{
runtime::{Block as TestBlock, Hash as TestHash}, runtime::{Block as TestBlock, Hash as TestHash},
TestClient, TestClientBuilder, TestClientBuilderExt as _, TestClient, TestClientBuilder, TestClientBuilderExt as _,
}; };
use tokio::runtime::Handle;
#[cfg(test)] #[cfg(test)]
mod chain_sync; mod chain_sync;
@@ -59,12 +58,11 @@ const PROTOCOL_NAME: &str = "/foo";
struct TestNetwork { struct TestNetwork {
network: TestNetworkWorker, network: TestNetworkWorker,
rt_handle: Handle,
} }
impl TestNetwork { impl TestNetwork {
pub fn new(network: TestNetworkWorker, rt_handle: Handle) -> Self { pub fn new(network: TestNetworkWorker) -> Self {
Self { network, rt_handle } Self { network }
} }
pub fn service(&self) -> &Arc<TestNetworkService> { pub fn service(&self) -> &Arc<TestNetworkService> {
@@ -82,7 +80,7 @@ impl TestNetwork {
let service = worker.service().clone(); let service = worker.service().clone();
let event_stream = service.event_stream("test"); let event_stream = service.event_stream("test");
self.rt_handle.spawn(async move { tokio::spawn(async move {
futures::pin_mut!(worker); futures::pin_mut!(worker);
let _ = worker.await; let _ = worker.await;
}); });
@@ -100,11 +98,10 @@ struct TestNetworkBuilder {
chain_sync: Option<(Box<dyn ChainSyncT<TestBlock>>, Box<dyn ChainSyncInterface<TestBlock>>)>, chain_sync: Option<(Box<dyn ChainSyncT<TestBlock>>, Box<dyn ChainSyncInterface<TestBlock>>)>,
chain_sync_network: Option<(NetworkServiceProvider, NetworkServiceHandle)>, chain_sync_network: Option<(NetworkServiceProvider, NetworkServiceHandle)>,
config: Option<config::NetworkConfiguration>, config: Option<config::NetworkConfiguration>,
rt_handle: Handle,
} }
impl TestNetworkBuilder { impl TestNetworkBuilder {
pub fn new(rt_handle: Handle) -> Self { pub fn new() -> Self {
Self { Self {
import_queue: None, import_queue: None,
link: None, link: None,
@@ -114,7 +111,6 @@ impl TestNetworkBuilder {
chain_sync: None, chain_sync: None,
chain_sync_network: None, chain_sync_network: None,
config: None, config: None,
rt_handle,
} }
} }
@@ -229,21 +225,21 @@ impl TestNetworkBuilder {
let block_request_protocol_config = { let block_request_protocol_config = {
let (handler, protocol_config) = let (handler, protocol_config) =
BlockRequestHandler::new(&protocol_id, None, client.clone(), 50); BlockRequestHandler::new(&protocol_id, None, client.clone(), 50);
self.rt_handle.spawn(handler.run().boxed()); tokio::spawn(handler.run().boxed());
protocol_config protocol_config
}; };
let state_request_protocol_config = { let state_request_protocol_config = {
let (handler, protocol_config) = let (handler, protocol_config) =
StateRequestHandler::new(&protocol_id, None, client.clone(), 50); StateRequestHandler::new(&protocol_id, None, client.clone(), 50);
self.rt_handle.spawn(handler.run().boxed()); tokio::spawn(handler.run().boxed());
protocol_config protocol_config
}; };
let light_client_request_protocol_config = { let light_client_request_protocol_config = {
let (handler, protocol_config) = let (handler, protocol_config) =
LightClientRequestHandler::new(&protocol_id, None, client.clone()); LightClientRequestHandler::new(&protocol_id, None, client.clone());
self.rt_handle.spawn(handler.run().boxed()); tokio::spawn(handler.run().boxed());
protocol_config protocol_config
}; };
@@ -310,11 +306,6 @@ impl TestNetworkBuilder {
.link .link
.unwrap_or(Box::new(sc_network_sync::service::mock::MockChainSyncInterface::new())); .unwrap_or(Box::new(sc_network_sync::service::mock::MockChainSyncInterface::new()));
let handle = self.rt_handle.clone();
let executor = move |f| {
handle.spawn(f);
};
let worker = NetworkWorker::< let worker = NetworkWorker::<
substrate_test_runtime_client::runtime::Block, substrate_test_runtime_client::runtime::Block,
substrate_test_runtime_client::runtime::Hash, substrate_test_runtime_client::runtime::Hash,
@@ -322,7 +313,9 @@ impl TestNetworkBuilder {
>::new(config::Params { >::new(config::Params {
block_announce_config, block_announce_config,
role: config::Role::Full, role: config::Role::Full,
executor: Box::new(executor), executor: Box::new(|f| {
tokio::spawn(f);
}),
network_config, network_config,
chain: client.clone(), chain: client.clone(),
protocol_id, protocol_id,
@@ -340,10 +333,10 @@ impl TestNetworkBuilder {
.unwrap(); .unwrap();
let service = worker.service().clone(); let service = worker.service().clone();
self.rt_handle.spawn(async move { tokio::spawn(async move {
let _ = chain_sync_network_provider.run(service).await; let _ = chain_sync_network_provider.run(service).await;
}); });
self.rt_handle.spawn(async move { tokio::spawn(async move {
loop { loop {
futures::future::poll_fn(|cx| { futures::future::poll_fn(|cx| {
import_queue.poll_actions(cx, &mut *link); import_queue.poll_actions(cx, &mut *link);
@@ -354,6 +347,6 @@ impl TestNetworkBuilder {
} }
}); });
TestNetwork::new(worker, self.rt_handle) TestNetwork::new(worker)
} }
} }
@@ -26,7 +26,6 @@ use sc_network_common::{
service::{NetworkNotification, NetworkPeers, NetworkStateInfo}, service::{NetworkNotification, NetworkPeers, NetworkStateInfo},
}; };
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tokio::runtime::Handle;
type TestNetworkService = NetworkService< type TestNetworkService = NetworkService<
substrate_test_runtime_client::runtime::Block, substrate_test_runtime_client::runtime::Block,
@@ -38,9 +37,7 @@ const PROTOCOL_NAME: &str = "/foo";
/// Builds two nodes and their associated events stream. /// Builds two nodes and their associated events stream.
/// The nodes are connected together and have the `PROTOCOL_NAME` protocol registered. /// The nodes are connected together and have the `PROTOCOL_NAME` protocol registered.
fn build_nodes_one_proto( fn build_nodes_one_proto() -> (
rt_handle: &Handle,
) -> (
Arc<TestNetworkService>, Arc<TestNetworkService>,
impl Stream<Item = Event>, impl Stream<Item = Event>,
Arc<TestNetworkService>, Arc<TestNetworkService>,
@@ -48,12 +45,12 @@ fn build_nodes_one_proto(
) { ) {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let (node1, events_stream1) = TestNetworkBuilder::new(rt_handle.clone()) let (node1, events_stream1) = TestNetworkBuilder::new()
.with_listen_addresses(vec![listen_addr.clone()]) .with_listen_addresses(vec![listen_addr.clone()])
.build() .build()
.start_network(); .start_network();
let (node2, events_stream2) = TestNetworkBuilder::new(rt_handle.clone()) let (node2, events_stream2) = TestNetworkBuilder::new()
.with_set_config(SetConfig { .with_set_config(SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr, multiaddr: listen_addr,
@@ -67,15 +64,12 @@ fn build_nodes_one_proto(
(node1, events_stream1, node2, events_stream2) (node1, events_stream1, node2, events_stream2)
} }
#[test] #[tokio::test]
fn notifications_state_consistent() { async fn notifications_state_consistent() {
// Runs two nodes and ensures that events are propagated out of the API in a consistent // Runs two nodes and ensures that events are propagated out of the API in a consistent
// correct order, which means no notification received on a closed substream. // correct order, which means no notification received on a closed substream.
let runtime = tokio::runtime::Runtime::new().unwrap(); let (node1, mut events_stream1, node2, mut events_stream2) = build_nodes_one_proto();
let (node1, mut events_stream1, node2, mut events_stream2) =
build_nodes_one_proto(runtime.handle());
// Write some initial notifications that shouldn't get through. // Write some initial notifications that shouldn't get through.
for _ in 0..(rand::random::<u8>() % 5) { for _ in 0..(rand::random::<u8>() % 5) {
@@ -93,140 +87,130 @@ fn notifications_state_consistent() {
); );
} }
runtime.block_on(async move { // True if we have an active substream from node1 to node2.
// True if we have an active substream from node1 to node2. let mut node1_to_node2_open = false;
let mut node1_to_node2_open = false; // True if we have an active substream from node2 to node1.
// True if we have an active substream from node2 to node1. let mut node2_to_node1_open = false;
let mut node2_to_node1_open = false; // We stop the test after a certain number of iterations.
// We stop the test after a certain number of iterations. let mut iterations = 0;
let mut iterations = 0; // Safe guard because we don't want the test to pass if no substream has been open.
// Safe guard because we don't want the test to pass if no substream has been open. let mut something_happened = false;
let mut something_happened = false;
loop { loop {
iterations += 1; iterations += 1;
if iterations >= 1_000 { if iterations >= 1_000 {
assert!(something_happened); assert!(something_happened);
break break
}
// Start by sending a notification from node1 to node2 and vice-versa. Part of the
// test consists in ensuring that notifications get ignored if the stream isn't open.
if rand::random::<u8>() % 5 >= 3 {
node1.write_notification(
node2.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
if rand::random::<u8>() % 5 >= 3 {
node2.write_notification(
node1.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
// Also randomly disconnect the two nodes from time to time.
if rand::random::<u8>() % 20 == 0 {
node1.disconnect_peer(node2.local_peer_id(), PROTOCOL_NAME.into());
}
if rand::random::<u8>() % 20 == 0 {
node2.disconnect_peer(node1.local_peer_id(), PROTOCOL_NAME.into());
}
// Grab next event from either `events_stream1` or `events_stream2`.
let next_event = {
let next1 = events_stream1.next();
let next2 = events_stream2.next();
// We also await on a small timer, otherwise it is possible for the test to wait
// forever while nothing at all happens on the network.
let continue_test = futures_timer::Delay::new(Duration::from_millis(20));
match future::select(future::select(next1, next2), continue_test).await {
future::Either::Left((future::Either::Left((Some(ev), _)), _)) =>
future::Either::Left(ev),
future::Either::Left((future::Either::Right((Some(ev), _)), _)) =>
future::Either::Right(ev),
future::Either::Right(_) => continue,
_ => break,
}
};
match next_event {
future::Either::Left(Event::NotificationStreamOpened {
remote, protocol, ..
}) =>
if protocol == PROTOCOL_NAME.into() {
something_happened = true;
assert!(!node1_to_node2_open);
node1_to_node2_open = true;
assert_eq!(remote, node2.local_peer_id());
},
future::Either::Right(Event::NotificationStreamOpened {
remote, protocol, ..
}) =>
if protocol == PROTOCOL_NAME.into() {
something_happened = true;
assert!(!node2_to_node1_open);
node2_to_node1_open = true;
assert_eq!(remote, node1.local_peer_id());
},
future::Either::Left(Event::NotificationStreamClosed {
remote, protocol, ..
}) =>
if protocol == PROTOCOL_NAME.into() {
assert!(node1_to_node2_open);
node1_to_node2_open = false;
assert_eq!(remote, node2.local_peer_id());
},
future::Either::Right(Event::NotificationStreamClosed {
remote, protocol, ..
}) =>
if protocol == PROTOCOL_NAME.into() {
assert!(node2_to_node1_open);
node2_to_node1_open = false;
assert_eq!(remote, node1.local_peer_id());
},
future::Either::Left(Event::NotificationsReceived { remote, .. }) => {
assert!(node1_to_node2_open);
assert_eq!(remote, node2.local_peer_id());
if rand::random::<u8>() % 5 >= 4 {
node1.write_notification(
node2.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
},
future::Either::Right(Event::NotificationsReceived { remote, .. }) => {
assert!(node2_to_node1_open);
assert_eq!(remote, node1.local_peer_id());
if rand::random::<u8>() % 5 >= 4 {
node2.write_notification(
node1.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
},
// Add new events here.
future::Either::Left(Event::SyncConnected { .. }) => {},
future::Either::Right(Event::SyncConnected { .. }) => {},
future::Either::Left(Event::SyncDisconnected { .. }) => {},
future::Either::Right(Event::SyncDisconnected { .. }) => {},
future::Either::Left(Event::Dht(_)) => {},
future::Either::Right(Event::Dht(_)) => {},
};
} }
});
// Start by sending a notification from node1 to node2 and vice-versa. Part of the
// test consists in ensuring that notifications get ignored if the stream isn't open.
if rand::random::<u8>() % 5 >= 3 {
node1.write_notification(
node2.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
if rand::random::<u8>() % 5 >= 3 {
node2.write_notification(
node1.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
// Also randomly disconnect the two nodes from time to time.
if rand::random::<u8>() % 20 == 0 {
node1.disconnect_peer(node2.local_peer_id(), PROTOCOL_NAME.into());
}
if rand::random::<u8>() % 20 == 0 {
node2.disconnect_peer(node1.local_peer_id(), PROTOCOL_NAME.into());
}
// Grab next event from either `events_stream1` or `events_stream2`.
let next_event = {
let next1 = events_stream1.next();
let next2 = events_stream2.next();
// We also await on a small timer, otherwise it is possible for the test to wait
// forever while nothing at all happens on the network.
let continue_test = futures_timer::Delay::new(Duration::from_millis(20));
match future::select(future::select(next1, next2), continue_test).await {
future::Either::Left((future::Either::Left((Some(ev), _)), _)) =>
future::Either::Left(ev),
future::Either::Left((future::Either::Right((Some(ev), _)), _)) =>
future::Either::Right(ev),
future::Either::Right(_) => continue,
_ => break,
}
};
match next_event {
future::Either::Left(Event::NotificationStreamOpened { remote, protocol, .. }) =>
if protocol == PROTOCOL_NAME.into() {
something_happened = true;
assert!(!node1_to_node2_open);
node1_to_node2_open = true;
assert_eq!(remote, node2.local_peer_id());
},
future::Either::Right(Event::NotificationStreamOpened { remote, protocol, .. }) =>
if protocol == PROTOCOL_NAME.into() {
something_happened = true;
assert!(!node2_to_node1_open);
node2_to_node1_open = true;
assert_eq!(remote, node1.local_peer_id());
},
future::Either::Left(Event::NotificationStreamClosed { remote, protocol, .. }) =>
if protocol == PROTOCOL_NAME.into() {
assert!(node1_to_node2_open);
node1_to_node2_open = false;
assert_eq!(remote, node2.local_peer_id());
},
future::Either::Right(Event::NotificationStreamClosed { remote, protocol, .. }) =>
if protocol == PROTOCOL_NAME.into() {
assert!(node2_to_node1_open);
node2_to_node1_open = false;
assert_eq!(remote, node1.local_peer_id());
},
future::Either::Left(Event::NotificationsReceived { remote, .. }) => {
assert!(node1_to_node2_open);
assert_eq!(remote, node2.local_peer_id());
if rand::random::<u8>() % 5 >= 4 {
node1.write_notification(
node2.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
},
future::Either::Right(Event::NotificationsReceived { remote, .. }) => {
assert!(node2_to_node1_open);
assert_eq!(remote, node1.local_peer_id());
if rand::random::<u8>() % 5 >= 4 {
node2.write_notification(
node1.local_peer_id(),
PROTOCOL_NAME.into(),
b"hello world".to_vec(),
);
}
},
// Add new events here.
future::Either::Left(Event::SyncConnected { .. }) => {},
future::Either::Right(Event::SyncConnected { .. }) => {},
future::Either::Left(Event::SyncDisconnected { .. }) => {},
future::Either::Right(Event::SyncDisconnected { .. }) => {},
future::Either::Left(Event::Dht(_)) => {},
future::Either::Right(Event::Dht(_)) => {},
};
}
} }
#[tokio::test] #[tokio::test]
async fn lots_of_incoming_peers_works() { async fn lots_of_incoming_peers_works() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let (main_node, _) = TestNetworkBuilder::new(Handle::current()) let (main_node, _) = TestNetworkBuilder::new()
.with_listen_addresses(vec![listen_addr.clone()]) .with_listen_addresses(vec![listen_addr.clone()])
.with_set_config(SetConfig { in_peers: u32::MAX, ..Default::default() }) .with_set_config(SetConfig { in_peers: u32::MAX, ..Default::default() })
.build() .build()
@@ -239,7 +223,7 @@ async fn lots_of_incoming_peers_works() {
let mut background_tasks_to_wait = Vec::new(); let mut background_tasks_to_wait = Vec::new();
for _ in 0..32 { for _ in 0..32 {
let (_dialing_node, event_stream) = TestNetworkBuilder::new(Handle::current()) let (_dialing_node, event_stream) = TestNetworkBuilder::new()
.with_set_config(SetConfig { .with_set_config(SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr.clone(), multiaddr: listen_addr.clone(),
@@ -286,20 +270,17 @@ async fn lots_of_incoming_peers_works() {
future::join_all(background_tasks_to_wait).await; future::join_all(background_tasks_to_wait).await;
} }
#[test] #[tokio::test]
fn notifications_back_pressure() { async fn notifications_back_pressure() {
// Node 1 floods node 2 with notifications. Random sleeps are done on node 2 to simulate the // Node 1 floods node 2 with notifications. Random sleeps are done on node 2 to simulate the
// node being busy. We make sure that all notifications are received. // node being busy. We make sure that all notifications are received.
const TOTAL_NOTIFS: usize = 10_000; const TOTAL_NOTIFS: usize = 10_000;
let runtime = tokio::runtime::Runtime::new().unwrap(); let (node1, mut events_stream1, node2, mut events_stream2) = build_nodes_one_proto();
let (node1, mut events_stream1, node2, mut events_stream2) =
build_nodes_one_proto(runtime.handle());
let node2_id = node2.local_peer_id(); let node2_id = node2.local_peer_id();
let receiver = runtime.spawn(async move { let receiver = tokio::spawn(async move {
let mut received_notifications = 0; let mut received_notifications = 0;
while received_notifications < TOTAL_NOTIFS { while received_notifications < TOTAL_NOTIFS {
@@ -320,40 +301,36 @@ fn notifications_back_pressure() {
} }
}); });
runtime.block_on(async move { // Wait for the `NotificationStreamOpened`.
// Wait for the `NotificationStreamOpened`. loop {
loop { match events_stream1.next().await.unwrap() {
match events_stream1.next().await.unwrap() { Event::NotificationStreamOpened { .. } => break,
Event::NotificationStreamOpened { .. } => break, _ => {},
_ => {}, };
}; }
}
// Sending! // Sending!
for num in 0..TOTAL_NOTIFS { for num in 0..TOTAL_NOTIFS {
let notif = node1.notification_sender(node2_id, PROTOCOL_NAME.into()).unwrap(); let notif = node1.notification_sender(node2_id, PROTOCOL_NAME.into()).unwrap();
notif notif
.ready() .ready()
.await .await
.unwrap() .unwrap()
.send(format!("hello #{}", num).into_bytes()) .send(format!("hello #{}", num).into_bytes())
.unwrap(); .unwrap();
} }
receiver.await.unwrap(); receiver.await.unwrap();
});
} }
#[test] #[tokio::test]
fn fallback_name_working() { async fn fallback_name_working() {
// Node 1 supports the protocols "new" and "old". Node 2 only supports "old". Checks whether // Node 1 supports the protocols "new" and "old". Node 2 only supports "old". Checks whether
// they can connect. // they can connect.
const NEW_PROTOCOL_NAME: &str = "/new-shiny-protocol-that-isnt-PROTOCOL_NAME"; const NEW_PROTOCOL_NAME: &str = "/new-shiny-protocol-that-isnt-PROTOCOL_NAME";
let runtime = tokio::runtime::Runtime::new().unwrap();
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let (node1, mut events_stream1) = TestNetworkBuilder::new(runtime.handle().clone()) let (node1, mut events_stream1) = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
extra_sets: vec![NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: NEW_PROTOCOL_NAME.into(), notifications_protocol: NEW_PROTOCOL_NAME.into(),
@@ -369,7 +346,7 @@ fn fallback_name_working() {
.build() .build()
.start_network(); .start_network();
let (_, mut events_stream2) = TestNetworkBuilder::new(runtime.handle().clone()) let (_, mut events_stream2) = TestNetworkBuilder::new()
.with_set_config(SetConfig { .with_set_config(SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr, multiaddr: listen_addr,
@@ -380,7 +357,7 @@ fn fallback_name_working() {
.build() .build()
.start_network(); .start_network();
let receiver = runtime.spawn(async move { let receiver = tokio::spawn(async move {
// Wait for the `NotificationStreamOpened`. // Wait for the `NotificationStreamOpened`.
loop { loop {
match events_stream2.next().await.unwrap() { match events_stream2.next().await.unwrap() {
@@ -394,30 +371,27 @@ fn fallback_name_working() {
} }
}); });
runtime.block_on(async move { // Wait for the `NotificationStreamOpened`.
// Wait for the `NotificationStreamOpened`. loop {
loop { match events_stream1.next().await.unwrap() {
match events_stream1.next().await.unwrap() { Event::NotificationStreamOpened { protocol, negotiated_fallback, .. }
Event::NotificationStreamOpened { protocol, negotiated_fallback, .. } if protocol == NEW_PROTOCOL_NAME.into() =>
if protocol == NEW_PROTOCOL_NAME.into() => {
{ assert_eq!(negotiated_fallback, Some(PROTOCOL_NAME.into()));
assert_eq!(negotiated_fallback, Some(PROTOCOL_NAME.into())); break
break },
}, _ => {},
_ => {}, };
}; }
}
receiver.await.unwrap(); receiver.await.unwrap();
});
} }
// Disconnect peer by calling `Protocol::disconnect_peer()` with the supplied block announcement // Disconnect peer by calling `Protocol::disconnect_peer()` with the supplied block announcement
// protocol name and verify that `SyncDisconnected` event is emitted // protocol name and verify that `SyncDisconnected` event is emitted
#[tokio::test] #[tokio::test]
async fn disconnect_sync_peer_using_block_announcement_protocol_name() { async fn disconnect_sync_peer_using_block_announcement_protocol_name() {
let (node1, mut events_stream1, node2, mut events_stream2) = let (node1, mut events_stream1, node2, mut events_stream2) = build_nodes_one_proto();
build_nodes_one_proto(&Handle::current());
async fn wait_for_events(stream: &mut (impl Stream<Item = Event> + std::marker::Unpin)) { async fn wait_for_events(stream: &mut (impl Stream<Item = Event> + std::marker::Unpin)) {
let mut notif_received = false; let mut notif_received = false;
@@ -454,7 +428,7 @@ async fn disconnect_sync_peer_using_block_announcement_protocol_name() {
async fn ensure_listen_addresses_consistent_with_transport_memory() { async fn ensure_listen_addresses_consistent_with_transport_memory() {
let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
@@ -474,7 +448,7 @@ async fn ensure_listen_addresses_consistent_with_transport_memory() {
async fn ensure_listen_addresses_consistent_with_transport_not_memory() { async fn ensure_listen_addresses_consistent_with_transport_not_memory() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
..config::NetworkConfiguration::new( ..config::NetworkConfiguration::new(
@@ -497,7 +471,7 @@ async fn ensure_boot_node_addresses_consistent_with_transport_memory() {
peer_id: PeerId::random(), peer_id: PeerId::random(),
}; };
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
@@ -522,7 +496,7 @@ async fn ensure_boot_node_addresses_consistent_with_transport_not_memory() {
peer_id: PeerId::random(), peer_id: PeerId::random(),
}; };
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
boot_nodes: vec![boot_node], boot_nodes: vec![boot_node],
@@ -546,7 +520,7 @@ async fn ensure_reserved_node_addresses_consistent_with_transport_memory() {
peer_id: PeerId::random(), peer_id: PeerId::random(),
}; };
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
@@ -574,7 +548,7 @@ async fn ensure_reserved_node_addresses_consistent_with_transport_not_memory() {
peer_id: PeerId::random(), peer_id: PeerId::random(),
}; };
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
default_peers_set: SetConfig { default_peers_set: SetConfig {
@@ -598,7 +572,7 @@ async fn ensure_public_addresses_consistent_with_transport_memory() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let public_address = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; let public_address = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
@@ -620,7 +594,7 @@ async fn ensure_public_addresses_consistent_with_transport_not_memory() {
let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)]; let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];
let public_address = config::build_multiaddr![Memory(rand::random::<u64>())]; let public_address = config::build_multiaddr![Memory(rand::random::<u64>())];
let _ = TestNetworkBuilder::new(Handle::current()) let _ = TestNetworkBuilder::new()
.with_config(config::NetworkConfiguration { .with_config(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
public_addresses: vec![public_address], public_addresses: vec![public_address],
+18 -45
View File
@@ -708,16 +708,8 @@ pub struct FullPeerConfig {
pub storage_chain: bool, pub storage_chain: bool,
} }
/// Trait for text fixtures with tokio runtime.
pub trait WithRuntime {
/// Construct with runtime handle.
fn with_runtime(rt_handle: tokio::runtime::Handle) -> Self;
/// Get runtime handle.
fn rt_handle(&self) -> &tokio::runtime::Handle;
}
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait TestNetFactory: WithRuntime + Sized pub trait TestNetFactory: Default + Sized
where where
<Self::BlockImport as BlockImport<Block>>::Transaction: Send, <Self::BlockImport as BlockImport<Block>>::Transaction: Send,
{ {
@@ -747,9 +739,9 @@ where
); );
/// Create new test network with this many peers. /// Create new test network with this many peers.
fn new(rt_handle: tokio::runtime::Handle, n: usize) -> Self { fn new(n: usize) -> Self {
trace!(target: "test_network", "Creating test network"); trace!(target: "test_network", "Creating test network");
let mut net = Self::with_runtime(rt_handle); let mut net = Self::default();
for i in 0..n { for i in 0..n {
trace!(target: "test_network", "Adding peer {}", i); trace!(target: "test_network", "Adding peer {}", i);
@@ -905,14 +897,11 @@ where
) )
.unwrap(); .unwrap();
let handle = self.rt_handle().clone();
let executor = move |f| {
handle.spawn(f);
};
let network = NetworkWorker::new(sc_network::config::Params { let network = NetworkWorker::new(sc_network::config::Params {
role: if config.is_authority { Role::Authority } else { Role::Full }, role: if config.is_authority { Role::Authority } else { Role::Full },
executor: Box::new(executor), executor: Box::new(|f| {
tokio::spawn(f);
}),
network_config, network_config,
chain: client.clone(), chain: client.clone(),
protocol_id, protocol_id,
@@ -934,10 +923,10 @@ where
trace!(target: "test_network", "Peer identifier: {}", network.service().local_peer_id()); trace!(target: "test_network", "Peer identifier: {}", network.service().local_peer_id());
let service = network.service().clone(); let service = network.service().clone();
self.rt_handle().spawn(async move { tokio::spawn(async move {
chain_sync_network_provider.run(service).await; chain_sync_network_provider.run(service).await;
}); });
self.rt_handle().spawn(async move { tokio::spawn(async move {
import_queue.run(Box::new(chain_sync_service)).await; import_queue.run(Box::new(chain_sync_service)).await;
}); });
@@ -968,7 +957,7 @@ where
/// Used to spawn background tasks, e.g. the block request protocol handler. /// Used to spawn background tasks, e.g. the block request protocol handler.
fn spawn_task(&self, f: BoxFuture<'static, ()>) { fn spawn_task(&self, f: BoxFuture<'static, ()>) {
self.rt_handle().spawn(f); tokio::spawn(f);
} }
/// Polls the testnet until all nodes are in sync. /// Polls the testnet until all nodes are in sync.
@@ -1027,11 +1016,11 @@ where
Poll::Pending Poll::Pending
} }
/// Wait until we are sync'ed. /// Run the network until we are sync'ed.
/// ///
/// Calls `poll_until_sync` repeatedly. /// Calls `poll_until_sync` repeatedly.
/// (If we've not synced within 10 mins then panic rather than hang.) /// (If we've not synced within 10 mins then panic rather than hang.)
async fn wait_until_sync(&mut self) { async fn run_until_sync(&mut self) {
timeout( timeout(
Duration::from_secs(10 * 60), Duration::from_secs(10 * 60),
futures::future::poll_fn::<(), _>(|cx| self.poll_until_sync(cx)), futures::future::poll_fn::<(), _>(|cx| self.poll_until_sync(cx)),
@@ -1040,17 +1029,17 @@ where
.expect("sync didn't happen within 10 mins"); .expect("sync didn't happen within 10 mins");
} }
/// Wait until there are no pending packets. /// Run the network until there are no pending packets.
/// ///
/// Calls `poll_until_idle` repeatedly with the runtime passed as parameter. /// Calls `poll_until_idle` repeatedly with the runtime passed as parameter.
async fn wait_until_idle(&mut self) { async fn run_until_idle(&mut self) {
futures::future::poll_fn::<(), _>(|cx| self.poll_until_idle(cx)).await; futures::future::poll_fn::<(), _>(|cx| self.poll_until_idle(cx)).await;
} }
/// Wait until all peers are connected to each other. /// Run the network until all peers are connected to each other.
/// ///
/// Calls `poll_until_connected` repeatedly with the runtime passed as parameter. /// Calls `poll_until_connected` repeatedly with the runtime passed as parameter.
async fn wait_until_connected(&mut self) { async fn run_until_connected(&mut self) {
futures::future::poll_fn::<(), _>(|cx| self.poll_until_connected(cx)).await; futures::future::poll_fn::<(), _>(|cx| self.poll_until_connected(cx)).await;
} }
@@ -1082,20 +1071,11 @@ where
} }
} }
#[derive(Default)]
pub struct TestNet { pub struct TestNet {
rt_handle: tokio::runtime::Handle,
peers: Vec<Peer<(), PeersClient>>, peers: Vec<Peer<(), PeersClient>>,
} }
impl WithRuntime for TestNet {
fn with_runtime(rt_handle: tokio::runtime::Handle) -> Self {
TestNet { rt_handle, peers: Vec::new() }
}
fn rt_handle(&self) -> &tokio::runtime::Handle {
&self.rt_handle
}
}
impl TestNetFactory for TestNet { impl TestNetFactory for TestNet {
type Verifier = PassThroughVerifier; type Verifier = PassThroughVerifier;
type PeerData = (); type PeerData = ();
@@ -1150,16 +1130,9 @@ impl JustificationImport<Block> for ForceFinalized {
.map_err(|_| ConsensusError::InvalidJustification) .map_err(|_| ConsensusError::InvalidJustification)
} }
} }
pub struct JustificationTestNet(TestNet);
impl WithRuntime for JustificationTestNet { #[derive(Default)]
fn with_runtime(rt_handle: tokio::runtime::Handle) -> Self { pub struct JustificationTestNet(TestNet);
JustificationTestNet(TestNet::with_runtime(rt_handle))
}
fn rt_handle(&self) -> &tokio::runtime::Handle {
&self.0.rt_handle()
}
}
impl TestNetFactory for JustificationTestNet { impl TestNetFactory for JustificationTestNet {
type Verifier = PassThroughVerifier; type Verifier = PassThroughVerifier;
File diff suppressed because it is too large Load Diff