mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 23:01:01 +00:00
Switch consensus crates to new futures (#3146)
* Switch consensus-common to new futures * Fix tests * More tests fixing * Fix Babe tests * Fix Babe tests
This commit is contained in:
committed by
Gavin Wood
parent
3a6a309d84
commit
b31dcdf342
@@ -32,23 +32,18 @@ pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND};
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use consensus_common::{SyncOracle, SelectChain};
|
||||
use futures::prelude::*;
|
||||
use futures::{
|
||||
future::{self, Either},
|
||||
Future, IntoFuture,
|
||||
};
|
||||
use futures::{prelude::*, future::{self, Either}, task::Poll};
|
||||
use inherents::{InherentData, InherentDataProviders};
|
||||
use log::{debug, error, info, warn};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{ApiRef, Block as BlockT, ProvideRuntimeApi};
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::{fmt::Debug, ops::Deref, panic, pin::Pin};
|
||||
|
||||
/// A worker that should be invoked at every new slot.
|
||||
pub trait SlotWorker<B: BlockT> {
|
||||
/// The type of the future that will be returned when a new slot is
|
||||
/// triggered.
|
||||
type OnSlot: IntoFuture<Item = (), Error = consensus_common::Error>;
|
||||
type OnSlot: Future<Output = Result<(), consensus_common::Error>>;
|
||||
|
||||
/// Called when a new slot is triggered.
|
||||
fn on_slot(&self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot;
|
||||
@@ -78,13 +73,14 @@ pub fn start_slot_worker<B, C, W, T, SO, SC>(
|
||||
sync_oracle: SO,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
timestamp_extractor: SC,
|
||||
) -> impl Future<Item = (), Error = ()>
|
||||
) -> impl Future<Output = ()>
|
||||
where
|
||||
B: BlockT,
|
||||
C: SelectChain<B> + Clone,
|
||||
W: SlotWorker<B>,
|
||||
W::OnSlot: Unpin,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
SC: SlotCompatible,
|
||||
SC: SlotCompatible + Unpin,
|
||||
T: SlotData + Clone,
|
||||
{
|
||||
let SlotDuration(slot_duration) = slot_duration;
|
||||
@@ -94,12 +90,12 @@ where
|
||||
slot_duration.slot_duration(),
|
||||
inherent_data_providers,
|
||||
timestamp_extractor,
|
||||
).map_err(|e| debug!(target: "slots", "Faulty timer: {:?}", e))
|
||||
.for_each(move |slot_info| {
|
||||
).inspect_err(|e| debug!(target: "slots", "Faulty timer: {:?}", e))
|
||||
.try_for_each(move |slot_info| {
|
||||
// only propose when we are not syncing.
|
||||
if sync_oracle.is_major_syncing() {
|
||||
debug!(target: "slots", "Skipping proposal slot due to sync.");
|
||||
return Either::B(future::ok(()));
|
||||
return Either::Right(future::ready(Ok(())));
|
||||
}
|
||||
|
||||
let slot_num = slot_info.number;
|
||||
@@ -108,23 +104,23 @@ where
|
||||
Err(e) => {
|
||||
warn!(target: "slots", "Unable to author block in slot {}. \
|
||||
no best block header: {:?}", slot_num, e);
|
||||
return Either::B(future::ok(()));
|
||||
return Either::Right(future::ready(Ok(())));
|
||||
}
|
||||
};
|
||||
|
||||
Either::A(worker.on_slot(chain_head, slot_info).into_future().map_err(
|
||||
|e| warn!(target: "slots", "Encountered consensus error: {:?}", e),
|
||||
Either::Left(worker.on_slot(chain_head, slot_info).map_err(
|
||||
|e| { warn!(target: "slots", "Encountered consensus error: {:?}", e); e }
|
||||
))
|
||||
});
|
||||
|
||||
future::poll_fn(move ||
|
||||
future::poll_fn(move |cx| {
|
||||
loop {
|
||||
let mut authorship = std::panic::AssertUnwindSafe(&mut authorship);
|
||||
match std::panic::catch_unwind(move || authorship.poll()) {
|
||||
Ok(Ok(Async::Ready(()))) =>
|
||||
match panic::catch_unwind(panic::AssertUnwindSafe(|| Future::poll(Pin::new(&mut authorship), cx))) {
|
||||
Ok(Poll::Ready(Ok(()))) =>
|
||||
warn!(target: "slots", "Slots stream has terminated unexpectedly."),
|
||||
Ok(Ok(Async::NotReady)) => break Ok(Async::NotReady),
|
||||
Ok(Err(())) => warn!(target: "slots", "Authorship task terminated unexpectedly. Restarting"),
|
||||
Ok(Poll::Pending) => break Poll::Pending,
|
||||
Ok(Poll::Ready(Err(_err))) =>
|
||||
warn!(target: "slots", "Authorship task terminated unexpectedly. Restarting"),
|
||||
Err(e) => {
|
||||
if let Some(s) = e.downcast_ref::<&'static str>() {
|
||||
warn!(target: "slots", "Authorship task panicked at {:?}", s);
|
||||
@@ -134,7 +130,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// A header which has been checked
|
||||
|
||||
@@ -16,16 +16,15 @@
|
||||
|
||||
//! Utility stream for yielding slots in a loop.
|
||||
//!
|
||||
//! This is used instead of `tokio_timer::Interval` because it was unreliable.
|
||||
//! This is used instead of `futures_timer::Interval` because it was unreliable.
|
||||
|
||||
use super::SlotCompatible;
|
||||
use consensus_common::Error;
|
||||
use futures::prelude::*;
|
||||
use futures::try_ready;
|
||||
use futures::{prelude::*, task::Context, task::Poll};
|
||||
use inherents::{InherentData, InherentDataProviders};
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio_timer::Delay;
|
||||
use std::{pin::Pin, time::{Duration, Instant}};
|
||||
use futures_timer::Delay;
|
||||
|
||||
/// Returns current duration since unix epoch.
|
||||
pub fn duration_now() -> Duration {
|
||||
@@ -121,47 +120,51 @@ impl<SC> Slots<SC> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<SC: SlotCompatible> Stream for Slots<SC> {
|
||||
type Item = SlotInfo;
|
||||
type Error = Error;
|
||||
impl<SC: SlotCompatible + Unpin> Stream for Slots<SC> {
|
||||
type Item = Result<SlotInfo, Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<SlotInfo>, Self::Error> {
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
loop {
|
||||
let slot_duration = self.slot_duration;
|
||||
self.inner_delay = match self.inner_delay.take() {
|
||||
None => {
|
||||
// schedule wait.
|
||||
let wait_until = Instant::now() + time_until_next(duration_now(), slot_duration);
|
||||
Some(Delay::new(wait_until))
|
||||
let wait_dur = time_until_next(duration_now(), slot_duration);
|
||||
Some(Delay::new(wait_dur))
|
||||
}
|
||||
Some(d) => Some(d),
|
||||
};
|
||||
|
||||
if let Some(ref mut inner_delay) = self.inner_delay {
|
||||
try_ready!(inner_delay
|
||||
.poll()
|
||||
.map_err(Error::FaultyTimer));
|
||||
match Future::poll(Pin::new(inner_delay), cx) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(Error::FaultyTimer(err)))),
|
||||
Poll::Ready(Ok(())) => {}
|
||||
}
|
||||
}
|
||||
|
||||
// timeout has fired.
|
||||
|
||||
let inherent_data = self
|
||||
.inherent_data_providers
|
||||
.create_inherent_data()
|
||||
.map_err(|s| consensus_common::Error::InherentData(s.into_owned()))?;
|
||||
let (timestamp, slot_num, offset) = self
|
||||
.timestamp_extractor
|
||||
.extract_timestamp_and_slot(&inherent_data)?;
|
||||
let inherent_data = match self.inherent_data_providers.create_inherent_data() {
|
||||
Ok(id) => id,
|
||||
Err(err) => return Poll::Ready(Some(Err(consensus_common::Error::InherentData(err.into_owned())))),
|
||||
};
|
||||
let result = self.timestamp_extractor.extract_timestamp_and_slot(&inherent_data);
|
||||
let (timestamp, slot_num, offset) = match result {
|
||||
Ok(v) => v,
|
||||
Err(err) => return Poll::Ready(Some(Err(err))),
|
||||
};
|
||||
// reschedule delay for next slot.
|
||||
let ends_at = Instant::now() + offset +
|
||||
let ends_in = offset +
|
||||
time_until_next(Duration::from_secs(timestamp), slot_duration);
|
||||
self.inner_delay = Some(Delay::new(ends_at));
|
||||
let ends_at = Instant::now() + ends_in;
|
||||
self.inner_delay = Some(Delay::new(ends_in));
|
||||
|
||||
// never yield the same slot twice.
|
||||
if slot_num > self.last_slot {
|
||||
self.last_slot = slot_num;
|
||||
|
||||
break Ok(Async::Ready(Some(SlotInfo {
|
||||
break Poll::Ready(Some(Ok(SlotInfo {
|
||||
number: slot_num,
|
||||
duration: self.slot_duration,
|
||||
timestamp,
|
||||
|
||||
Reference in New Issue
Block a user