Switch GrandPa to std futures (replaces #3909) (#4612)

* 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:
Ashley
2020-01-24 13:34:42 +01:00
committed by GitHub
parent 14e95f3398
commit c2c429877e
16 changed files with 468 additions and 513 deletions
@@ -16,12 +16,11 @@
//! Tests for the communication portion of the GRANDPA crate.
use futures::sync::mpsc;
use futures::channel::mpsc;
use futures::prelude::*;
use sc_network::{Event as NetworkEvent, PeerId, config::Roles};
use sc_network_test::{Block, Hash};
use sc_network_gossip::Validator;
use tokio::runtime::current_thread;
use std::sync::Arc;
use sp_keyring::Ed25519Keyring;
use parity_scale_codec::Encode;
@@ -44,11 +43,19 @@ struct TestNetwork {
sender: mpsc::UnboundedSender<Event>,
}
impl sc_network_gossip::Network<Block> for TestNetwork {
fn event_stream(&self) -> Box<dyn futures::Stream<Item = NetworkEvent, Error = ()> + Send> {
impl TestNetwork {
fn event_stream_03(&self) -> Pin<Box<dyn futures::Stream<Item = NetworkEvent> + Send>> {
let (tx, rx) = mpsc::unbounded();
let _ = self.sender.unbounded_send(Event::EventStream(tx));
Box::new(rx)
Box::pin(rx)
}
}
impl sc_network_gossip::Network<Block> for TestNetwork {
fn event_stream(&self) -> Box<dyn futures01::Stream<Item = NetworkEvent, Error = ()> + Send> {
Box::new(
self.event_stream_03().map(Ok::<_, ()>).compat()
)
}
fn report_peer(&self, who: sc_network::PeerId, cost_benefit: sc_network::ReputationChange) {
@@ -101,17 +108,17 @@ struct Tester {
}
impl Tester {
fn filter_network_events<F>(self, mut pred: F) -> impl Future<Item=Self,Error=()>
fn filter_network_events<F>(self, mut pred: F) -> impl Future<Output = Self>
where F: FnMut(Event) -> bool
{
let mut s = Some(self);
futures::future::poll_fn(move || loop {
match s.as_mut().unwrap().events.poll().expect("concluded early") {
Async::Ready(None) => panic!("concluded early"),
Async::Ready(Some(item)) => if pred(item) {
return Ok(Async::Ready(s.take().unwrap()))
futures::future::poll_fn(move |cx| loop {
match Stream::poll_next(Pin::new(&mut s.as_mut().unwrap().events), cx) {
Poll::Ready(None) => panic!("concluded early"),
Poll::Ready(Some(item)) => if pred(item) {
return Poll::Ready(s.take().unwrap())
},
Async::NotReady => return Ok(Async::NotReady),
Poll::Pending => return Poll::Pending,
}
})
}
@@ -149,8 +156,8 @@ fn voter_set_state() -> SharedVoterSetState<Block> {
}
// needs to run in a tokio runtime.
fn make_test_network(executor: &impl futures03::task::Spawn) -> (
impl Future<Item=Tester,Error=()>,
fn make_test_network(executor: &impl futures::task::Spawn) -> (
impl Future<Output = Tester>,
TestNetwork,
) {
let (tx, rx) = mpsc::unbounded();
@@ -159,7 +166,7 @@ fn make_test_network(executor: &impl futures03::task::Spawn) -> (
#[derive(Clone)]
struct Exit;
impl futures03::Future for Exit {
impl futures::Future for Exit {
type Output = ();
fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<()> {
@@ -175,7 +182,7 @@ fn make_test_network(executor: &impl futures03::task::Spawn) -> (
);
(
futures::future::ok(Tester {
futures::future::ready(Tester {
gossip_validator: bridge.validator.clone(),
net_handle: bridge,
events: rx,
@@ -245,14 +252,14 @@ fn good_commit_leads_to_relay() {
let id = sc_network::PeerId::random();
let global_topic = super::global_topic::<Block>(set_id);
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
let threads_pool = futures::executor::ThreadPool::new().unwrap();
let test = make_test_network(&threads_pool).0
.and_then(move |tester| {
.then(move |tester| {
// register a peer.
tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::FULL);
Ok((tester, id))
future::ready((tester, id))
})
.and_then(move |(tester, id)| {
.then(move |(tester, id)| {
// start round, dispatch commit, and wait for broadcast.
let (commits_in, _) = tester.net_handle.global_communication(SetId(1), voter_set, false);
@@ -305,12 +312,11 @@ fn good_commit_leads_to_relay() {
},
_ => panic!("commit expected"),
}
})
.map_err(|_| panic!("could not process commit"));
});
// once the message is sent and commit is "handled" we should have
// a repropagation event coming from the network.
send_message.join(handle_commit).and_then(move |(tester, ())| {
future::join(send_message, handle_commit).then(move |(tester, ())| {
tester.filter_network_events(move |event| match event {
Event::WriteNotification(_, data) => {
data == encoded_commit
@@ -318,11 +324,10 @@ fn good_commit_leads_to_relay() {
_ => false,
})
})
.map_err(|_| panic!("could not watch for gossip message"))
.map(|_| ())
});
current_thread::Runtime::new().unwrap().block_on(test).unwrap();
futures::executor::block_on(test);
}
#[test]
@@ -371,14 +376,14 @@ fn bad_commit_leads_to_report() {
let id = sc_network::PeerId::random();
let global_topic = super::global_topic::<Block>(set_id);
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
let threads_pool = futures::executor::ThreadPool::new().unwrap();
let test = make_test_network(&threads_pool).0
.and_then(move |tester| {
.map(move |tester| {
// register a peer.
tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::FULL);
Ok((tester, id))
(tester, id)
})
.and_then(move |(tester, id)| {
.then(move |(tester, id)| {
// start round, dispatch commit, and wait for broadcast.
let (commits_in, _) = tester.net_handle.global_communication(SetId(1), voter_set, false);
@@ -422,12 +427,11 @@ fn bad_commit_leads_to_report() {
},
_ => panic!("commit expected"),
}
})
.map_err(|_| panic!("could not process commit"));
});
// once the message is sent and commit is "handled" we should have
// a report event coming from the network.
send_message.join(handle_commit).and_then(move |(tester, ())| {
future::join(send_message, handle_commit).then(move |(tester, ())| {
tester.filter_network_events(move |event| match event {
Event::Report(who, cost_benefit) => {
who == id && cost_benefit == super::cost::INVALID_COMMIT
@@ -435,26 +439,25 @@ fn bad_commit_leads_to_report() {
_ => false,
})
})
.map_err(|_| panic!("could not watch for peer report"))
.map(|_| ())
});
current_thread::Runtime::new().unwrap().block_on(test).unwrap();
futures::executor::block_on(test);
}
#[test]
fn peer_with_higher_view_leads_to_catch_up_request() {
let id = sc_network::PeerId::random();
let threads_pool = futures03::executor::ThreadPool::new().unwrap();
let threads_pool = futures::executor::ThreadPool::new().unwrap();
let (tester, mut net) = make_test_network(&threads_pool);
let test = tester
.and_then(move |tester| {
.map(move |tester| {
// register a peer with authority role.
tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::AUTHORITY);
Ok((tester, id))
((tester, id))
})
.and_then(move |(tester, id)| {
.then(move |(tester, id)| {
// send neighbor message at round 10 and height 50
let result = tester.gossip_validator.validate(
&mut net,
@@ -494,9 +497,8 @@ fn peer_with_higher_view_leads_to_catch_up_request() {
},
_ => false,
})
.map_err(|_| panic!("could not watch for peer send message"))
.map(|_| ())
});
current_thread::Runtime::new().unwrap().block_on(test).unwrap();
futures::executor::block_on(test);
}