mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 07:01:05 +00:00
Clean up tests from runtime.block_on() and moving around Runtime and Handle (#12941)
This commit is contained in:
@@ -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
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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],
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user