mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-01 02:11:01 +00:00
* Switch GrandPa to new futures * Work on making tests work * until_imported tests working again * Work on switching tests to stable futures * Modifications * Re-add test as #[ignore] * Don't ignore * Add manual unpins * Remove Header import * Return concrete Sink type * Switch to crates.io finality-grandpa version * Remove use statement that slipped in * Fix some nitpicks * Remove unpin from i * Fixed typo * Move futures01 to dev-deps * Fix nitpicks * Update client/finality-grandpa/src/communication/mod.rs Co-Authored-By: André Silva <andre.beat@gmail.com> * nitpicking Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com> Co-authored-by: André Silva <andre.beat@gmail.com>
This commit is contained in:
@@ -25,7 +25,6 @@ use sc_network_test::{
|
||||
use sc_network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder};
|
||||
use parking_lot::Mutex;
|
||||
use futures_timer::Delay;
|
||||
use futures03::TryStreamExt as _;
|
||||
use tokio::runtime::current_thread;
|
||||
use sp_keyring::Ed25519Keyring;
|
||||
use sc_client::LongestChain;
|
||||
@@ -48,6 +47,8 @@ use sp_runtime::generic::{BlockId, DigestItem};
|
||||
use sp_core::{H256, NativeOrEncoded, ExecutionContext, crypto::Public};
|
||||
use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, GrandpaApi};
|
||||
use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check};
|
||||
use futures01::Async;
|
||||
use futures::compat::Future01CompatExt;
|
||||
|
||||
use authorities::AuthoritySet;
|
||||
use finality_proof::{
|
||||
@@ -196,7 +197,7 @@ impl TestNetFactory for GrandpaTestNet {
|
||||
#[derive(Clone)]
|
||||
struct Exit;
|
||||
|
||||
impl futures03::Future for Exit {
|
||||
impl futures::Future for Exit {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, _: &mut task::Context) -> task::Poll<()> {
|
||||
@@ -371,17 +372,28 @@ fn create_keystore(authority: Ed25519Keyring) -> (KeyStorePtr, tempfile::TempDir
|
||||
(keystore, keystore_path)
|
||||
}
|
||||
|
||||
fn block_until_complete(future: impl Future + Unpin, net: &Arc<Mutex<GrandpaTestNet>>, runtime: &mut current_thread::Runtime) {
|
||||
let drive_to_completion = futures01::future::poll_fn(|| {
|
||||
net.lock().poll(); Ok::<Async<()>, ()>(Async::NotReady)
|
||||
});
|
||||
runtime.block_on(
|
||||
future::select(future, drive_to_completion.compat())
|
||||
.map(|_| Ok::<(), ()>(()))
|
||||
.compat()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// run the voters to completion. provide a closure to be invoked after
|
||||
// the voters are spawned but before blocking on them.
|
||||
fn run_to_completion_with<F>(
|
||||
runtime: &mut current_thread::Runtime,
|
||||
threads_pool: &futures03::executor::ThreadPool,
|
||||
threads_pool: &futures::executor::ThreadPool,
|
||||
blocks: u64,
|
||||
net: Arc<Mutex<GrandpaTestNet>>,
|
||||
peers: &[Ed25519Keyring],
|
||||
with: F,
|
||||
) -> u64 where
|
||||
F: FnOnce(current_thread::Handle) -> Option<Box<dyn Future<Item=(), Error=()>>>
|
||||
F: FnOnce(current_thread::Handle) -> Option<Pin<Box<dyn Future<Output = ()>>>>
|
||||
{
|
||||
use parking_lot::RwLock;
|
||||
|
||||
@@ -411,17 +423,16 @@ fn run_to_completion_with<F>(
|
||||
};
|
||||
|
||||
wait_for.push(
|
||||
Box::new(
|
||||
Box::pin(
|
||||
client.finality_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
.take_while(move |n| {
|
||||
let mut highest_finalized = highest_finalized.write();
|
||||
if *n.header.number() > *highest_finalized {
|
||||
*highest_finalized = *n.header.number();
|
||||
}
|
||||
Ok(n.header.number() < &blocks)
|
||||
future::ready(n.header.number() < &blocks)
|
||||
})
|
||||
.collect()
|
||||
.collect::<Vec<_>>()
|
||||
.map(|_| ())
|
||||
)
|
||||
);
|
||||
@@ -449,24 +460,20 @@ fn run_to_completion_with<F>(
|
||||
|
||||
assert_send(&voter);
|
||||
|
||||
runtime.spawn(voter);
|
||||
runtime.spawn(voter.unit_error().compat());
|
||||
}
|
||||
|
||||
// wait for all finalized on each.
|
||||
let wait_for = ::futures::future::join_all(wait_for)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ());
|
||||
|
||||
let drive_to_completion = futures::future::poll_fn(|| { net.lock().poll(); Ok(Async::NotReady) });
|
||||
let _ = runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
let wait_for = ::futures::future::join_all(wait_for);
|
||||
|
||||
block_until_complete(wait_for, &net, runtime);
|
||||
let highest_finalized = *highest_finalized.read();
|
||||
highest_finalized
|
||||
}
|
||||
|
||||
fn run_to_completion(
|
||||
runtime: &mut current_thread::Runtime,
|
||||
threads_pool: &futures03::executor::ThreadPool,
|
||||
threads_pool: &futures::executor::ThreadPool,
|
||||
blocks: u64,
|
||||
net: Arc<Mutex<GrandpaTestNet>>,
|
||||
peers: &[Ed25519Keyring]
|
||||
@@ -496,7 +503,7 @@ fn add_forced_change(
|
||||
fn finalize_3_voters_no_observers() {
|
||||
let _ = env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
@@ -522,7 +529,7 @@ fn finalize_3_voters_no_observers() {
|
||||
#[test]
|
||||
fn finalize_3_voters_1_full_observer() {
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let voters = make_ids(peers);
|
||||
@@ -555,9 +562,8 @@ fn finalize_3_voters_1_full_observer() {
|
||||
};
|
||||
finality_notifications.push(
|
||||
client.finality_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
.take_while(|n| Ok(n.header.number() < &20))
|
||||
.for_each(move |_| Ok(()))
|
||||
.take_while(|n| future::ready(n.header.number() < &20))
|
||||
.for_each(move |_| future::ready(()))
|
||||
);
|
||||
|
||||
let keystore = if let Some(local_key) = local_key {
|
||||
@@ -590,16 +596,14 @@ fn finalize_3_voters_1_full_observer() {
|
||||
}
|
||||
|
||||
for voter in voters {
|
||||
runtime.spawn(voter);
|
||||
runtime.spawn(voter.unit_error().compat());
|
||||
}
|
||||
|
||||
// wait for all finalized on each.
|
||||
let wait_for = futures::future::join_all(finality_notifications)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ());
|
||||
.map(|_| ());
|
||||
|
||||
let drive_to_completion = futures::future::poll_fn(|| { net.lock().poll(); Ok(Async::NotReady) });
|
||||
let _ = runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
block_until_complete(wait_for, &net, &mut runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -631,7 +635,7 @@ fn transition_3_voters_twice_1_full_observer() {
|
||||
let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8)));
|
||||
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
net.lock().peer(0).push_blocks(1, false);
|
||||
net.lock().block_until_sync(&mut runtime);
|
||||
@@ -654,8 +658,7 @@ fn transition_3_voters_twice_1_full_observer() {
|
||||
|
||||
// wait for blocks to be finalized before generating new ones
|
||||
let block_production = client.finality_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
.take_while(|n| Ok(n.header.number() < &30))
|
||||
.take_while(|n| future::ready(n.header.number() < &30))
|
||||
.for_each(move |n| {
|
||||
match n.header.number() {
|
||||
1 => {
|
||||
@@ -692,10 +695,10 @@ fn transition_3_voters_twice_1_full_observer() {
|
||||
_ => {},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
future::ready(())
|
||||
});
|
||||
|
||||
runtime.spawn(block_production);
|
||||
runtime.spawn(block_production.unit_error().compat());
|
||||
}
|
||||
|
||||
let mut finality_notifications = Vec::new();
|
||||
@@ -725,9 +728,8 @@ fn transition_3_voters_twice_1_full_observer() {
|
||||
|
||||
finality_notifications.push(
|
||||
client.finality_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
.take_while(|n| Ok(n.header.number() < &30))
|
||||
.for_each(move |_| Ok(()))
|
||||
.take_while(|n| future::ready(n.header.number() < &30))
|
||||
.for_each(move |_| future::ready(()))
|
||||
.map(move |()| {
|
||||
let full_client = client.as_full().expect("only full clients are used in test");
|
||||
let set: AuthoritySet<Hash, BlockNumber> = crate::aux_schema::load_authorities(&*full_client).unwrap();
|
||||
@@ -756,22 +758,19 @@ fn transition_3_voters_twice_1_full_observer() {
|
||||
};
|
||||
let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network");
|
||||
|
||||
runtime.spawn(voter);
|
||||
runtime.spawn(voter.unit_error().compat());
|
||||
}
|
||||
|
||||
// wait for all finalized on each.
|
||||
let wait_for = ::futures::future::join_all(finality_notifications)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ());
|
||||
let wait_for = ::futures::future::join_all(finality_notifications);
|
||||
|
||||
let drive_to_completion = futures::future::poll_fn(|| { net.lock().poll(); Ok(Async::NotReady) });
|
||||
let _ = runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
block_until_complete(wait_for, &net, &mut runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn justification_is_emitted_when_consensus_data_changes() {
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3);
|
||||
|
||||
@@ -790,7 +789,7 @@ fn justification_is_emitted_when_consensus_data_changes() {
|
||||
#[test]
|
||||
fn justification_is_generated_periodically() {
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
@@ -830,7 +829,7 @@ fn consensus_changes_works() {
|
||||
#[test]
|
||||
fn sync_justifications_on_change_blocks() {
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob];
|
||||
let voters = make_ids(peers_b);
|
||||
@@ -871,21 +870,21 @@ fn sync_justifications_on_change_blocks() {
|
||||
}
|
||||
|
||||
// the last peer should get the justification by syncing from other peers
|
||||
runtime.block_on(futures::future::poll_fn(move || -> std::result::Result<_, ()> {
|
||||
futures::executor::block_on(futures::future::poll_fn(move |_| {
|
||||
if net.lock().peer(3).client().justification(&BlockId::Number(21)).unwrap().is_none() {
|
||||
net.lock().poll();
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
} else {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(())
|
||||
}
|
||||
})).unwrap()
|
||||
}))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finalizes_multiple_pending_changes_in_order() {
|
||||
let _ = env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let peers_b = &[Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::Ferdie];
|
||||
@@ -946,7 +945,7 @@ fn finalizes_multiple_pending_changes_in_order() {
|
||||
fn force_change_to_new_set() {
|
||||
let _ = env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
// two of these guys are offline.
|
||||
let genesis_authorities = &[
|
||||
Ed25519Keyring::Alice,
|
||||
@@ -1123,11 +1122,11 @@ fn voter_persists_its_votes() {
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use futures::future;
|
||||
use futures::sync::mpsc;
|
||||
use futures::channel::mpsc;
|
||||
|
||||
let _ = env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
// 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
|
||||
@@ -1161,56 +1160,56 @@ fn voter_persists_its_votes() {
|
||||
keystore_paths.push(keystore_path);
|
||||
|
||||
struct ResettableVoter {
|
||||
voter: Box<dyn Future<Item = (), Error = ()> + Send>,
|
||||
voter: Pin<Box<dyn Future<Output = ()> + Send + Unpin>>,
|
||||
voter_rx: mpsc::UnboundedReceiver<()>,
|
||||
net: Arc<Mutex<GrandpaTestNet>>,
|
||||
client: PeersClient,
|
||||
keystore: KeyStorePtr,
|
||||
threads_pool: futures03::executor::ThreadPool,
|
||||
threads_pool: futures::executor::ThreadPool,
|
||||
}
|
||||
|
||||
impl Future for ResettableVoter {
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
type Output = ();
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
match self.voter.poll() {
|
||||
Ok(Async::Ready(())) | Err(_) => panic!("error in the voter"),
|
||||
Ok(Async::NotReady) => {},
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = Pin::into_inner(self);
|
||||
|
||||
if let Poll::Ready(()) = Pin::new(&mut this.voter).poll(cx) {
|
||||
panic!("error in the voter");
|
||||
}
|
||||
|
||||
match self.voter_rx.poll() {
|
||||
Err(_) | Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
|
||||
Ok(Async::NotReady) => {}
|
||||
Ok(Async::Ready(Some(()))) => {
|
||||
match Pin::new(&mut this.voter_rx).poll_next(cx) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(None) => return Poll::Ready(()),
|
||||
Poll::Ready(Some(())) => {
|
||||
let (_block_import, _, _, _, link) =
|
||||
self.net.lock()
|
||||
this.net.lock()
|
||||
.make_block_import::<
|
||||
TransactionFor<substrate_test_runtime_client::Backend, Block>
|
||||
>(self.client.clone());
|
||||
>(this.client.clone());
|
||||
let link = link.lock().take().unwrap();
|
||||
|
||||
let grandpa_params = GrandpaParams {
|
||||
config: Config {
|
||||
gossip_duration: TEST_GOSSIP_DURATION,
|
||||
justification_period: 32,
|
||||
keystore: Some(self.keystore.clone()),
|
||||
keystore: Some(this.keystore.clone()),
|
||||
name: Some(format!("peer#{}", 0)),
|
||||
is_authority: true,
|
||||
observer_enabled: true,
|
||||
},
|
||||
link,
|
||||
network: self.net.lock().peers[0].network_service().clone(),
|
||||
network: this.net.lock().peers[0].network_service().clone(),
|
||||
inherent_data_providers: InherentDataProviders::new(),
|
||||
on_exit: Exit,
|
||||
telemetry_on_connect: None,
|
||||
voting_rule: VotingRulesBuilder::default().build(),
|
||||
executor: self.threads_pool.clone(),
|
||||
executor: this.threads_pool.clone(),
|
||||
};
|
||||
|
||||
let voter = run_grandpa_voter(grandpa_params)
|
||||
.expect("all in order with client and network")
|
||||
.then(move |r| {
|
||||
.map(move |r| {
|
||||
// we need to keep the block_import alive since it owns the
|
||||
// sender for the voter commands channel, if that gets dropped
|
||||
// then the voter will stop
|
||||
@@ -1218,30 +1217,30 @@ fn voter_persists_its_votes() {
|
||||
r
|
||||
});
|
||||
|
||||
self.voter = Box::new(voter);
|
||||
this.voter = Box::pin(voter);
|
||||
// notify current task in order to poll the voter
|
||||
futures::task::current().notify();
|
||||
cx.waker().wake_by_ref();
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
// we create a "dummy" voter by setting it to `empty` and triggering the `tx`.
|
||||
// we create a "dummy" voter by setting it to `pending` and triggering the `tx`.
|
||||
// this way, the `ResettableVoter` will reset its `voter` field to a value ASAP.
|
||||
voter_tx.unbounded_send(()).unwrap();
|
||||
runtime.spawn(ResettableVoter {
|
||||
voter: Box::new(futures::future::empty()),
|
||||
voter: Box::pin(futures::future::pending()),
|
||||
voter_rx,
|
||||
net: net.clone(),
|
||||
client: client.clone(),
|
||||
keystore,
|
||||
threads_pool: threads_pool.clone(),
|
||||
});
|
||||
}.unit_error().compat());
|
||||
}
|
||||
|
||||
let (exit_tx, exit_rx) = futures::sync::oneshot::channel::<()>();
|
||||
let (exit_tx, exit_rx) = futures::channel::oneshot::channel::<()>();
|
||||
|
||||
// create the communication layer for bob, but don't start any
|
||||
// voter. instead we'll listen for the prevote that alice casts
|
||||
@@ -1284,122 +1283,107 @@ fn voter_persists_its_votes() {
|
||||
HasVoted::No,
|
||||
);
|
||||
|
||||
let round_rx = futures03::compat::Compat::new(round_rx.map(|item| Ok::<_, Error>(item)));
|
||||
let round_tx = futures03::compat::CompatSink::new(round_tx);
|
||||
|
||||
let round_tx = Arc::new(Mutex::new(round_tx));
|
||||
let exit_tx = Arc::new(Mutex::new(Some(exit_tx)));
|
||||
|
||||
let net = net.clone();
|
||||
let state = AtomicUsize::new(0);
|
||||
let state = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
runtime.spawn(round_rx.for_each(move |signed| {
|
||||
if state.compare_and_swap(0, 1, Ordering::SeqCst) == 0 {
|
||||
// the first message we receive should be a prevote from alice.
|
||||
let prevote = match signed.message {
|
||||
finality_grandpa::Message::Prevote(prevote) => prevote,
|
||||
_ => panic!("voter should prevote."),
|
||||
};
|
||||
let net2 = net.clone();
|
||||
let net = net.clone();
|
||||
let voter_tx = voter_tx.clone();
|
||||
let round_tx = round_tx.clone();
|
||||
let state = state.clone();
|
||||
let exit_tx = exit_tx.clone();
|
||||
|
||||
// its chain has 20 blocks and the voter targets 3/4 of the
|
||||
// unfinalized chain, so the vote should be for block 15
|
||||
assert!(prevote.target_number == 15);
|
||||
async move {
|
||||
if state.compare_and_swap(0, 1, Ordering::SeqCst) == 0 {
|
||||
// the first message we receive should be a prevote from alice.
|
||||
let prevote = match signed.message {
|
||||
finality_grandpa::Message::Prevote(prevote) => prevote,
|
||||
_ => panic!("voter should prevote."),
|
||||
};
|
||||
|
||||
// we push 20 more blocks to alice's chain
|
||||
net.lock().peer(0).push_blocks(20, false);
|
||||
// its chain has 20 blocks and the voter targets 3/4 of the
|
||||
// unfinalized chain, so the vote should be for block 15
|
||||
assert!(prevote.target_number == 15);
|
||||
|
||||
let net2 = net.clone();
|
||||
let net = net.clone();
|
||||
let voter_tx = voter_tx.clone();
|
||||
let round_tx = round_tx.clone();
|
||||
// we push 20 more blocks to alice's chain
|
||||
net.lock().peer(0).push_blocks(20, false);
|
||||
|
||||
let interval = futures03::stream::unfold(Delay::new(Duration::from_millis(200)), |delay|
|
||||
Box::pin(async move {
|
||||
delay.await;
|
||||
Some(((), Delay::new(Duration::from_millis(200))))
|
||||
})).map(Ok::<_, ()>).compat();
|
||||
let interval = futures::stream::unfold(Delay::new(Duration::from_millis(200)), |delay|
|
||||
Box::pin(async move {
|
||||
delay.await;
|
||||
Some(((), Delay::new(Duration::from_millis(200))))
|
||||
})
|
||||
);
|
||||
|
||||
future::Either::A(interval
|
||||
.take_while(move |_| {
|
||||
Ok(net2.lock().peer(1).client().info().best_number != 40)
|
||||
})
|
||||
.for_each(|_| Ok(()))
|
||||
.and_then(move |_| {
|
||||
let block_30_hash =
|
||||
net.lock().peer(0).client().as_full().unwrap().hash(30).unwrap().unwrap();
|
||||
interval
|
||||
.take_while(move |_| {
|
||||
future::ready(net2.lock().peer(1).client().info().best_number != 40)
|
||||
})
|
||||
.for_each(|_| future::ready(()))
|
||||
.await;
|
||||
|
||||
// we restart alice's voter
|
||||
voter_tx.unbounded_send(()).unwrap();
|
||||
let block_30_hash =
|
||||
net.lock().peer(0).client().as_full().unwrap().hash(30).unwrap().unwrap();
|
||||
|
||||
// and we push our own prevote for block 30
|
||||
let prevote = finality_grandpa::Prevote {
|
||||
target_number: 30,
|
||||
target_hash: block_30_hash,
|
||||
};
|
||||
// we restart alice's voter
|
||||
voter_tx.unbounded_send(()).unwrap();
|
||||
|
||||
// One should either be calling `Sink::send` or `Sink::start_send` followed
|
||||
// by `Sink::poll_complete` to make sure items are being flushed. Given that
|
||||
// we send in a loop including a delay until items are received, this can be
|
||||
// ignored for the sake of reduced complexity.
|
||||
if !round_tx.lock()
|
||||
.start_send(finality_grandpa::Message::Prevote(prevote))
|
||||
.unwrap()
|
||||
.is_ready() {
|
||||
panic!("expected sink to be ready to write to.");
|
||||
}
|
||||
// and we push our own prevote for block 30
|
||||
let prevote = finality_grandpa::Prevote {
|
||||
target_number: 30,
|
||||
target_hash: block_30_hash,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}).map_err(|_| panic!()))
|
||||
// One should either be calling `Sink::send` or `Sink::start_send` followed
|
||||
// by `Sink::poll_complete` to make sure items are being flushed. Given that
|
||||
// we send in a loop including a delay until items are received, this can be
|
||||
// ignored for the sake of reduced complexity.
|
||||
Pin::new(&mut *round_tx.lock()).start_send(finality_grandpa::Message::Prevote(prevote)).unwrap();
|
||||
} else if state.compare_and_swap(1, 2, Ordering::SeqCst) == 1 {
|
||||
// the next message we receive should be our own prevote
|
||||
let prevote = match signed.message {
|
||||
finality_grandpa::Message::Prevote(prevote) => prevote,
|
||||
_ => panic!("We should receive our own prevote."),
|
||||
};
|
||||
|
||||
} else if state.compare_and_swap(1, 2, Ordering::SeqCst) == 1 {
|
||||
// the next message we receive should be our own prevote
|
||||
let prevote = match signed.message {
|
||||
finality_grandpa::Message::Prevote(prevote) => prevote,
|
||||
_ => panic!("We should receive our own prevote."),
|
||||
};
|
||||
// targeting block 30
|
||||
assert!(prevote.target_number == 30);
|
||||
|
||||
// targeting block 30
|
||||
assert!(prevote.target_number == 30);
|
||||
// after alice restarts it should send its previous prevote
|
||||
// therefore we won't ever receive it again since it will be a
|
||||
// known message on the gossip layer
|
||||
|
||||
// after alice restarts it should send its previous prevote
|
||||
// therefore we won't ever receive it again since it will be a
|
||||
// known message on the gossip layer
|
||||
} else if state.compare_and_swap(2, 3, Ordering::SeqCst) == 2 {
|
||||
// we then receive a precommit from alice for block 15
|
||||
// even though we casted a prevote for block 30
|
||||
let precommit = match signed.message {
|
||||
finality_grandpa::Message::Precommit(precommit) => precommit,
|
||||
_ => panic!("voter should precommit."),
|
||||
};
|
||||
|
||||
future::Either::B(future::ok(()))
|
||||
assert!(precommit.target_number == 15);
|
||||
|
||||
} else if state.compare_and_swap(2, 3, Ordering::SeqCst) == 2 {
|
||||
// we then receive a precommit from alice for block 15
|
||||
// even though we casted a prevote for block 30
|
||||
let precommit = match signed.message {
|
||||
finality_grandpa::Message::Precommit(precommit) => precommit,
|
||||
_ => panic!("voter should precommit."),
|
||||
};
|
||||
|
||||
assert!(precommit.target_number == 15);
|
||||
|
||||
// signal exit
|
||||
exit_tx.clone().lock().take().unwrap().send(()).unwrap();
|
||||
|
||||
future::Either::B(future::ok(()))
|
||||
|
||||
} else {
|
||||
panic!()
|
||||
// signal exit
|
||||
exit_tx.clone().lock().take().unwrap().send(()).unwrap();
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
}).map_err(|_| ()));
|
||||
}).map(Ok).boxed().compat());
|
||||
}
|
||||
|
||||
let drive_to_completion = futures::future::poll_fn(|| { net.lock().poll(); Ok(Async::NotReady) });
|
||||
let exit = exit_rx.into_future().map(|_| ()).map_err(|_| ());
|
||||
|
||||
runtime.block_on(drive_to_completion.select(exit).map(|_| ()).map_err(|_| ())).unwrap();
|
||||
block_until_complete(exit_rx.into_future(), &net, &mut runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finalize_3_voters_1_light_observer() {
|
||||
let _ = env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
let authorities = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let voters = make_ids(authorities);
|
||||
|
||||
@@ -1416,9 +1400,8 @@ fn finalize_3_voters_1_light_observer() {
|
||||
let link = net.lock().peer(3).data.lock().take().expect("link initialized on startup; qed");
|
||||
|
||||
let finality_notifications = net.lock().peer(3).client().finality_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
.take_while(|n| Ok(n.header.number() < &20))
|
||||
.collect();
|
||||
.take_while(|n| future::ready(n.header.number() < &20))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
run_to_completion_with(&mut runtime, &threads_pool, 20, net.clone(), authorities, |executor| {
|
||||
executor.spawn(
|
||||
@@ -1435,10 +1418,10 @@ fn finalize_3_voters_1_light_observer() {
|
||||
net.lock().peers[3].network_service().clone(),
|
||||
Exit,
|
||||
threads_pool.clone(),
|
||||
).unwrap()
|
||||
).unwrap().unit_error().compat()
|
||||
).unwrap();
|
||||
|
||||
Some(Box::new(finality_notifications.map(|_| ())))
|
||||
Some(Box::pin(finality_notifications.map(|_| ())))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1446,7 +1429,7 @@ fn finalize_3_voters_1_light_observer() {
|
||||
fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() {
|
||||
let _ = ::env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
let peers = &[Ed25519Keyring::Alice];
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1);
|
||||
@@ -1460,14 +1443,15 @@ fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() {
|
||||
net.lock().block_until_sync(&mut runtime);
|
||||
|
||||
// check that the block#1 is finalized on light client
|
||||
runtime.block_on(futures::future::poll_fn(move || -> std::result::Result<_, ()> {
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let _ = runtime.block_on(futures::future::poll_fn(move |_| {
|
||||
if net.lock().peer(1).client().info().finalized_number == 1 {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
net.lock().poll();
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
})).unwrap()
|
||||
}).unit_error().compat());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1477,7 +1461,7 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ
|
||||
|
||||
let _ = ::env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
// two of these guys are offline.
|
||||
let genesis_authorities = if FORCE_CHANGE {
|
||||
@@ -1542,7 +1526,7 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ
|
||||
fn voter_catches_up_to_latest_round_when_behind() {
|
||||
let _ = env_logger::try_init();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob];
|
||||
let voters = make_ids(peers);
|
||||
@@ -1554,7 +1538,7 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
let mut finality_notifications = Vec::new();
|
||||
|
||||
let voter = |keystore, peer_id, link, net: Arc<Mutex<GrandpaTestNet>>| -> Box<dyn Future<Item=(), Error=()> + Send> {
|
||||
let voter = |keystore, peer_id, link, net: Arc<Mutex<GrandpaTestNet>>| -> Pin<Box<dyn Future<Output = ()> + Send>> {
|
||||
let grandpa_params = GrandpaParams {
|
||||
config: Config {
|
||||
gossip_duration: TEST_GOSSIP_DURATION,
|
||||
@@ -1573,7 +1557,7 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
executor: threads_pool.clone(),
|
||||
};
|
||||
|
||||
Box::new(run_grandpa_voter(grandpa_params).expect("all in order with client and network"))
|
||||
Box::pin(run_grandpa_voter(grandpa_params).expect("all in order with client and network"))
|
||||
};
|
||||
|
||||
let mut keystore_paths = Vec::new();
|
||||
@@ -1591,9 +1575,8 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
|
||||
finality_notifications.push(
|
||||
client.finality_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
.take_while(|n| Ok(n.header.number() < &50))
|
||||
.for_each(move |_| Ok(()))
|
||||
.take_while(|n| future::ready(n.header.number() < &50))
|
||||
.for_each(move |_| future::ready(()))
|
||||
);
|
||||
|
||||
let (keystore, keystore_path) = create_keystore(*key);
|
||||
@@ -1601,14 +1584,13 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
|
||||
let voter = voter(Some(keystore), peer_id, link, net.clone());
|
||||
|
||||
runtime.spawn(voter);
|
||||
runtime.spawn(voter.unit_error().compat());
|
||||
}
|
||||
|
||||
// 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.
|
||||
let wait_for_finality = ::futures::future::join_all(finality_notifications)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ());
|
||||
.map(|_| ());
|
||||
|
||||
// spawn a new voter, it should be behind by at least 4 rounds and should be
|
||||
// able to catch up to the latest round
|
||||
@@ -1616,7 +1598,7 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
let net = net.clone();
|
||||
let runtime = runtime.handle();
|
||||
|
||||
wait_for_finality.and_then(move |_| {
|
||||
wait_for_finality.then(move |_| {
|
||||
let peer_id = 2;
|
||||
let link = {
|
||||
let net = net.lock();
|
||||
@@ -1628,20 +1610,20 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
|
||||
let voter = voter(None, peer_id, link, net);
|
||||
|
||||
runtime.spawn(voter).unwrap();
|
||||
runtime.spawn(voter.unit_error().compat()).unwrap();
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let timeout = Duration::from_secs(5 * 60);
|
||||
let wait_for_catch_up = futures::future::poll_fn(move || {
|
||||
let wait_for_catch_up = futures::future::poll_fn(move |_| {
|
||||
// The voter will start at round 1 and since everyone else is
|
||||
// already at a later round the only way to get to round 4 (or
|
||||
// later) is by issuing a catch up request.
|
||||
if set_state.read().last_completed_round().number >= 4 {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(())
|
||||
} else if start_time.elapsed() > timeout {
|
||||
panic!("Timed out while waiting for catch up to happen")
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1649,8 +1631,14 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
})
|
||||
};
|
||||
|
||||
let drive_to_completion = futures::future::poll_fn(|| { net.lock().poll(); Ok(Async::NotReady) });
|
||||
let _ = runtime.block_on(test.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
let drive_to_completion = futures01::future::poll_fn(|| {
|
||||
net.lock().poll(); Ok::<Async<()>, ()>(Async::NotReady)
|
||||
});
|
||||
runtime.block_on(
|
||||
future::select(test, drive_to_completion.compat())
|
||||
.map(|_| Ok::<(), ()>(()))
|
||||
.compat()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1658,7 +1646,7 @@ fn grandpa_environment_respects_voting_rules() {
|
||||
use finality_grandpa::Chain;
|
||||
use sc_network_test::TestClient;
|
||||
|
||||
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
|
||||
let threads_pool = futures::executor::ThreadPool::new().unwrap();
|
||||
|
||||
let peers = &[Ed25519Keyring::Alice];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
Reference in New Issue
Block a user