Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
@@ -18,9 +18,9 @@
//! Schema for slots in the aux-db.
use codec::{Encode, Decode};
use codec::{Decode, Encode};
use sc_client_api::backend::AuxStore;
use sp_blockchain::{Result as ClientResult, Error as ClientError};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_consensus_slots::{EquivocationProof, Slot};
use sp_runtime::traits::Header;
@@ -33,17 +33,17 @@ pub const MAX_SLOT_CAPACITY: u64 = 1000;
pub const PRUNING_BOUND: u64 = 2 * MAX_SLOT_CAPACITY;
fn load_decode<C, T>(backend: &C, key: &[u8]) -> ClientResult<Option<T>>
where
C: AuxStore,
T: Decode,
where
C: AuxStore,
T: Decode,
{
match backend.get_aux(key)? {
None => Ok(None),
Some(t) => T::decode(&mut &t[..])
.map_err(
|e| ClientError::Backend(format!("Slots DB is corrupted. Decode error: {}", e)),
)
.map(Some)
.map_err(|e| {
ClientError::Backend(format!("Slots DB is corrupted. Decode error: {}", e))
})
.map(Some),
}
}
@@ -57,14 +57,14 @@ pub fn check_equivocation<C, H, P>(
header: &H,
signer: &P,
) -> ClientResult<Option<EquivocationProof<H, P>>>
where
H: Header,
C: AuxStore,
P: Clone + Encode + Decode + PartialEq,
where
H: Header,
C: AuxStore,
P: Clone + Encode + Decode + PartialEq,
{
// We don't check equivocations for old headers out of our capacity.
if slot_now.saturating_sub(*slot) > Slot::from(MAX_SLOT_CAPACITY) {
return Ok(None);
return Ok(None)
}
// Key for this slot.
@@ -72,17 +72,16 @@ pub fn check_equivocation<C, H, P>(
slot.using_encoded(|s| curr_slot_key.extend(s));
// Get headers of this slot.
let mut headers_with_sig = load_decode::<_, Vec<(H, P)>>(backend, &curr_slot_key[..])?
.unwrap_or_else(Vec::new);
let mut headers_with_sig =
load_decode::<_, Vec<(H, P)>>(backend, &curr_slot_key[..])?.unwrap_or_else(Vec::new);
// Get first slot saved.
let slot_header_start = SLOT_HEADER_START.to_vec();
let first_saved_slot = load_decode::<_, Slot>(backend, &slot_header_start[..])?
.unwrap_or(slot);
let first_saved_slot = load_decode::<_, Slot>(backend, &slot_header_start[..])?.unwrap_or(slot);
if slot_now < first_saved_slot {
// The code below assumes that slots will be visited sequentially.
return Ok(None);
return Ok(None)
}
for (prev_header, prev_signer) in headers_with_sig.iter() {
@@ -96,7 +95,7 @@ pub fn check_equivocation<C, H, P>(
offender: signer.clone(),
first_header: prev_header.clone(),
second_header: header.clone(),
}));
}))
} else {
// We don't need to continue in case of duplicated header,
// since it's already saved and a possible equivocation
@@ -135,12 +134,11 @@ pub fn check_equivocation<C, H, P>(
#[cfg(test)]
mod test {
use sp_core::{sr25519, Pair};
use sp_core::hash::H256;
use sp_runtime::testing::{Header as HeaderTest, Digest as DigestTest};
use sp_core::{hash::H256, sr25519, Pair};
use sp_runtime::testing::{Digest as DigestTest, Header as HeaderTest};
use substrate_test_runtime_client;
use super::{MAX_SLOT_CAPACITY, PRUNING_BOUND, check_equivocation};
use super::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND};
fn create_header(number: u64) -> HeaderTest {
// so that different headers for the same number get different hashes
@@ -151,7 +149,7 @@ mod test {
number,
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: DigestTest { logs: vec![], },
digest: DigestTest { logs: vec![] },
};
header
@@ -171,79 +169,55 @@ mod test {
let header6 = create_header(3); // @ slot 4
// It's ok to sign same headers.
assert!(
check_equivocation(
&client,
2.into(),
2.into(),
&header1,
&public,
).unwrap().is_none(),
);
assert!(check_equivocation(&client, 2.into(), 2.into(), &header1, &public,)
.unwrap()
.is_none(),);
assert!(
check_equivocation(
&client,
3.into(),
2.into(),
&header1,
&public,
).unwrap().is_none(),
);
assert!(check_equivocation(&client, 3.into(), 2.into(), &header1, &public,)
.unwrap()
.is_none(),);
// But not two different headers at the same slot.
assert!(
check_equivocation(
&client,
4.into(),
2.into(),
&header2,
&public,
).unwrap().is_some(),
);
assert!(check_equivocation(&client, 4.into(), 2.into(), &header2, &public,)
.unwrap()
.is_some(),);
// Different slot is ok.
assert!(
check_equivocation(
&client,
5.into(),
4.into(),
&header3,
&public,
).unwrap().is_none(),
);
assert!(check_equivocation(&client, 5.into(), 4.into(), &header3, &public,)
.unwrap()
.is_none(),);
// Here we trigger pruning and save header 4.
assert!(
check_equivocation(
&client,
(PRUNING_BOUND + 2).into(),
(MAX_SLOT_CAPACITY + 4).into(),
&header4,
&public,
).unwrap().is_none(),
);
assert!(check_equivocation(
&client,
(PRUNING_BOUND + 2).into(),
(MAX_SLOT_CAPACITY + 4).into(),
&header4,
&public,
)
.unwrap()
.is_none(),);
// This fails because header 5 is an equivocation of header 4.
assert!(
check_equivocation(
&client,
(PRUNING_BOUND + 3).into(),
(MAX_SLOT_CAPACITY + 4).into(),
&header5,
&public,
).unwrap().is_some(),
);
assert!(check_equivocation(
&client,
(PRUNING_BOUND + 3).into(),
(MAX_SLOT_CAPACITY + 4).into(),
&header5,
&public,
)
.unwrap()
.is_some(),);
// This is ok because we pruned the corresponding header. Shows that we are pruning.
assert!(
check_equivocation(
&client,
(PRUNING_BOUND + 4).into(),
4.into(),
&header6,
&public,
).unwrap().is_none(),
);
assert!(check_equivocation(
&client,
(PRUNING_BOUND + 4).into(),
4.into(),
&header6,
&public,
)
.unwrap()
.is_none(),);
}
}
+144 -175
View File
@@ -25,19 +25,19 @@
#![forbid(unsafe_code)]
#![warn(missing_docs)]
mod slots;
mod aux_schema;
mod slots;
pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND};
pub use slots::SlotInfo;
use slots::Slots;
pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND};
use std::{fmt::Debug, ops::Deref, time::Duration};
use codec::{Decode, Encode};
use futures::{future::Either, Future, TryFutureExt};
use futures_timer::Delay;
use log::{debug, error, info, warn};
use sp_api::{ProvideRuntimeApi, ApiRef};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO, CONSENSUS_WARN};
use sp_api::{ApiRef, ProvideRuntimeApi};
use sp_arithmetic::traits::BaseArithmetic;
use sp_consensus::{
BlockImport, CanAuthorWith, JustificationSyncLink, Proposer, SelectChain, SlotData, SyncOracle,
@@ -46,10 +46,10 @@ use sp_consensus_slots::Slot;
use sp_inherents::CreateInherentDataProviders;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT, HashFor, NumberFor}
traits::{Block as BlockT, HashFor, Header as HeaderT, NumberFor},
};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO};
use sp_timestamp::Timestamp;
use std::{fmt::Debug, ops::Deref, time::Duration};
/// The changes that need to applied to the storage to create the state for a block.
///
@@ -76,10 +76,7 @@ pub trait SlotWorker<B: BlockT, Proof> {
///
/// Returns a future that resolves to a [`SlotResult`] iff a block was successfully built in
/// the slot. Otherwise `None` is returned.
async fn on_slot(
&mut self,
slot_info: SlotInfo<B>,
) -> Option<SlotResult<B, Proof>>;
async fn on_slot(&mut self, slot_info: SlotInfo<B>) -> Option<SlotResult<B, Proof>>;
}
/// A skeleton implementation for `SlotWorker` which tries to claim a slot at
@@ -89,7 +86,8 @@ pub trait SlotWorker<B: BlockT, Proof> {
pub trait SimpleSlotWorker<B: BlockT> {
/// A handle to a `BlockImport`.
type BlockImport: BlockImport<B, Transaction = <Self::Proposer as Proposer<B>>::Transaction>
+ Send + 'static;
+ Send
+ 'static;
/// A handle to a `SyncOracle`.
type SyncOracle: SyncOracle;
@@ -100,7 +98,9 @@ pub trait SimpleSlotWorker<B: BlockT> {
/// The type of future resolving to the proposer.
type CreateProposer: Future<Output = Result<Self::Proposer, sp_consensus::Error>>
+ Send + Unpin + 'static;
+ Send
+ Unpin
+ 'static;
/// The type of proposer to use to build blocks.
type Proposer: Proposer<B> + Send;
@@ -139,12 +139,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
/// Notifies the given slot. Similar to `claim_slot`, but will be called no matter whether we
/// need to author blocks or not.
fn notify_slot(
&self,
_header: &B::Header,
_slot: Slot,
_epoch_data: &Self::EpochData,
) {}
fn notify_slot(&self, _header: &B::Header, _slot: Slot, _epoch_data: &Self::EpochData) {}
/// Return the pre digest data to include in a block authored with the given claim.
fn pre_digest_data(
@@ -154,18 +149,24 @@ pub trait SimpleSlotWorker<B: BlockT> {
) -> Vec<sp_runtime::DigestItem<B::Hash>>;
/// Returns a function which produces a `BlockImportParams`.
fn block_import_params(&self) -> Box<
fn block_import_params(
&self,
) -> Box<
dyn Fn(
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<<Self::BlockImport as BlockImport<B>>::Transaction, B>,
Self::Claim,
Self::EpochData,
) -> Result<
sp_consensus::BlockImportParams<B, <Self::BlockImport as BlockImport<B>>::Transaction>,
sp_consensus::Error
> + Send + 'static
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<<Self::BlockImport as BlockImport<B>>::Transaction, B>,
Self::Claim,
Self::EpochData,
) -> Result<
sp_consensus::BlockImportParams<
B,
<Self::BlockImport as BlockImport<B>>::Transaction,
>,
sp_consensus::Error,
> + Send
+ 'static,
>;
/// Whether to force authoring if offline.
@@ -194,10 +195,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
fn telemetry(&self) -> Option<TelemetryHandle>;
/// Remaining duration for proposing.
fn proposing_remaining_duration(
&self,
slot_info: &SlotInfo<B>,
) -> Duration;
fn proposing_remaining_duration(&self, slot_info: &SlotInfo<B>) -> Duration;
/// Implements [`SlotWorker::on_slot`].
async fn on_slot(
@@ -213,8 +211,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
let proposing_remaining = if proposing_remaining_duration == Duration::default() {
debug!(
target: logging_target,
"Skipping proposal slot {} since there's no time left to propose",
slot,
"Skipping proposal slot {} since there's no time left to propose", slot,
);
return None
@@ -240,8 +237,8 @@ pub trait SimpleSlotWorker<B: BlockT> {
"err" => ?err,
);
return None;
}
return None
},
};
self.notify_slot(&slot_info.chain_head, slot, &epoch_data);
@@ -260,13 +257,13 @@ pub trait SimpleSlotWorker<B: BlockT> {
"authorities_len" => authorities_len,
);
return None;
return None
}
let claim = self.claim_slot(&slot_info.chain_head, slot, &epoch_data)?;
if self.should_backoff(slot, &slot_info.chain_head) {
return None;
return None
}
debug!(
@@ -289,9 +286,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
Err(err) => {
warn!(
target: logging_target,
"Unable to author block in slot {:?}: {:?}",
slot,
err,
"Unable to author block in slot {:?}: {:?}", slot, err,
);
telemetry!(
@@ -303,7 +298,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
);
return None
}
},
};
let logs = self.pre_digest_data(slot, &claim);
@@ -311,34 +306,29 @@ pub trait SimpleSlotWorker<B: BlockT> {
// deadline our production to 98% of the total time left for proposing. As we deadline
// the proposing below to the same total time left, the 2% margin should be enough for
// the result to be returned.
let proposing = proposer.propose(
slot_info.inherent_data,
sp_runtime::generic::Digest {
logs,
},
proposing_remaining_duration.mul_f32(0.98),
None,
).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e)));
let proposing = proposer
.propose(
slot_info.inherent_data,
sp_runtime::generic::Digest { logs },
proposing_remaining_duration.mul_f32(0.98),
None,
)
.map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e)));
let proposal = match futures::future::select(proposing, proposing_remaining).await {
Either::Left((Ok(p), _)) => p,
Either::Left((Err(err), _)) => {
warn!(
target: logging_target,
"Proposing failed: {:?}",
err,
);
warn!(target: logging_target, "Proposing failed: {:?}", err,);
return None
},
Either::Right(_) => {
info!(
target: logging_target,
"⌛️ Discarding proposal for slot {}; block production took too long",
slot,
"⌛️ Discarding proposal for slot {}; block production took too long", slot,
);
// If the node was compiled with debug, tell the user to use release optimizations.
#[cfg(build_type="debug")]
#[cfg(build_type = "debug")]
info!(
target: logging_target,
"👉 Recompile your node in `--release` mode to mitigate this problem.",
@@ -373,14 +363,10 @@ pub trait SimpleSlotWorker<B: BlockT> {
) {
Ok(bi) => bi,
Err(err) => {
warn!(
target: logging_target,
"Failed to create block import params: {:?}",
err,
);
warn!(target: logging_target, "Failed to create block import params: {:?}", err,);
return None
}
},
};
info!(
@@ -401,17 +387,14 @@ pub trait SimpleSlotWorker<B: BlockT> {
);
let header = block_import_params.post_header();
match block_import
.import_block(block_import_params, Default::default())
.await
{
match block_import.import_block(block_import_params, Default::default()).await {
Ok(res) => {
res.handle_justification(
&header.hash(),
*header.number(),
self.justification_sync_link(),
);
}
},
Err(err) => {
warn!(
target: logging_target,
@@ -425,18 +408,17 @@ pub trait SimpleSlotWorker<B: BlockT> {
"hash" => ?parent_hash,
"err" => ?err,
);
}
},
}
Some(SlotResult {
block: B::new(header, body),
storage_proof,
})
Some(SlotResult { block: B::new(header, body), storage_proof })
}
}
#[async_trait::async_trait]
impl<B: BlockT, T: SimpleSlotWorker<B> + Send> SlotWorker<B, <T::Proposer as Proposer<B>>::Proof> for T {
impl<B: BlockT, T: SimpleSlotWorker<B> + Send> SlotWorker<B, <T::Proposer as Proposer<B>>::Proof>
for T
{
async fn on_slot(
&mut self,
slot_info: SlotInfo<B>,
@@ -496,8 +478,7 @@ pub async fn start_slot_worker<B, C, W, T, SO, CIDP, CAW, Proof>(
mut sync_oracle: SO,
create_inherent_data_providers: CIDP,
can_author_with: CAW,
)
where
) where
B: BlockT,
C: SelectChain<B>,
W: SlotWorker<B, Proof>,
@@ -509,28 +490,25 @@ where
{
let SlotDuration(slot_duration) = slot_duration;
let mut slots = Slots::new(
slot_duration.slot_duration(),
create_inherent_data_providers,
client,
);
let mut slots =
Slots::new(slot_duration.slot_duration(), create_inherent_data_providers, client);
loop {
let slot_info = match slots.next_slot().await {
Ok(r) => r,
Err(e) => {
warn!(target: "slots", "Error while polling for next slot: {:?}", e);
return;
}
return
},
};
if sync_oracle.is_major_syncing() {
debug!(target: "slots", "Skipping proposal slot due to sync.");
continue;
continue
}
if let Err(err) = can_author_with
.can_author_with(&BlockId::Hash(slot_info.chain_head.hash()))
if let Err(err) =
can_author_with.can_author_with(&BlockId::Hash(slot_info.chain_head.hash()))
{
warn!(
target: "slots",
@@ -559,7 +537,10 @@ pub enum CheckedHeader<H, S> {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error<T> where T: Debug {
pub enum Error<T>
where
T: Debug,
{
#[error("Slot duration is invalid: {0:?}")]
SlotDurationInvalid(SlotDuration<T>),
}
@@ -591,25 +572,23 @@ impl<T: Clone + Send + Sync + 'static> SlotDuration<T> {
///
/// `slot_key` is marked as `'static`, as it should really be a
/// compile-time constant.
pub fn get_or_compute<B: BlockT, C, CB>(client: &C, cb: CB) -> sp_blockchain::Result<Self> where
pub fn get_or_compute<B: BlockT, C, CB>(client: &C, cb: CB) -> sp_blockchain::Result<Self>
where
C: sc_client_api::backend::AuxStore + sc_client_api::UsageProvider<B>,
C: ProvideRuntimeApi<B>,
CB: FnOnce(ApiRef<C::Api>, &BlockId<B>) -> sp_blockchain::Result<T>,
T: SlotData + Encode + Decode + Debug,
{
let slot_duration = match client.get_aux(T::SLOT_KEY)? {
Some(v) => <T as codec::Decode>::decode(&mut &v[..])
.map(SlotDuration)
.map_err(|_| {
sp_blockchain::Error::Backend({
error!(target: "slots", "slot duration kept in invalid format");
"slot duration kept in invalid format".to_string()
})
}),
Some(v) => <T as codec::Decode>::decode(&mut &v[..]).map(SlotDuration).map_err(|_| {
sp_blockchain::Error::Backend({
error!(target: "slots", "slot duration kept in invalid format");
"slot duration kept in invalid format".to_string()
})
}),
None => {
let best_hash = client.usage_info().chain.best_hash;
let slot_duration =
cb(client.runtime_api(), &BlockId::hash(best_hash))?;
let slot_duration = cb(client.runtime_api(), &BlockId::hash(best_hash))?;
info!(
"⏱ Loaded block-time = {:?} from block {:?}",
@@ -621,11 +600,13 @@ impl<T: Clone + Send + Sync + 'static> SlotDuration<T> {
.using_encoded(|s| client.insert_aux(&[(T::SLOT_KEY, &s[..])], &[]))?;
Ok(SlotDuration(slot_duration))
}
},
}?;
if slot_duration.slot_duration() == Default::default() {
return Err(sp_blockchain::Error::Application(Box::new(Error::SlotDurationInvalid(slot_duration))))
return Err(sp_blockchain::Error::Application(Box::new(Error::SlotDurationInvalid(
slot_duration,
))))
}
Ok(slot_duration)
@@ -687,9 +668,7 @@ pub fn proposing_remaining_duration<Block: BlockT>(
) -> Duration {
use sp_runtime::traits::Zero;
let proposing_duration = slot_info
.duration
.mul_f32(block_proposal_slot_portion.get());
let proposing_duration = slot_info.duration.mul_f32(block_proposal_slot_portion.get());
let slot_remaining = slot_info
.ends_at
@@ -700,7 +679,7 @@ pub fn proposing_remaining_duration<Block: BlockT>(
// If parent is genesis block, we don't require any lenience factor.
if slot_info.chain_head.number().is_zero() {
return proposing_duration;
return proposing_duration
}
let parent_slot = match parent_slot {
@@ -723,9 +702,7 @@ pub fn proposing_remaining_duration<Block: BlockT>(
if let Some(ref max_block_proposal_slot_portion) = max_block_proposal_slot_portion {
std::cmp::min(
lenient_proposing_duration,
slot_info
.duration
.mul_f32(max_block_proposal_slot_portion.get()),
slot_info.duration.mul_f32(max_block_proposal_slot_portion.get()),
)
} else {
lenient_proposing_duration
@@ -853,7 +830,7 @@ impl<N: BaseArithmetic> Default for BackoffAuthoringOnFinalizedHeadLagging<N> {
impl<N> BackoffAuthoringBlocksStrategy<N> for BackoffAuthoringOnFinalizedHeadLagging<N>
where
N: BaseArithmetic + Copy
N: BaseArithmetic + Copy,
{
fn should_backoff(
&self,
@@ -865,12 +842,12 @@ where
) -> bool {
// This should not happen, but we want to keep the previous behaviour if it does.
if slot_now <= chain_head_slot {
return false;
return false
}
let unfinalized_block_length = chain_head_number - finalized_number;
let interval = unfinalized_block_length.saturating_sub(self.unfinalized_slack)
/ self.authoring_bias;
let interval =
unfinalized_block_length.saturating_sub(self.unfinalized_slack) / self.authoring_bias;
let interval = interval.min(self.max_interval);
// We're doing arithmetic between block and slot numbers.
@@ -906,9 +883,9 @@ impl<N> BackoffAuthoringBlocksStrategy<N> for () {
#[cfg(test)]
mod test {
use super::*;
use sp_api::NumberFor;
use std::time::{Duration, Instant};
use substrate_test_runtime_client::runtime::{Block, Header};
use sp_api::NumberFor;
const SLOT_DURATION: Duration = Duration::from_millis(6000);
@@ -945,10 +922,7 @@ mod test {
}
// but we cap it to a maximum of 20 slots
assert_eq!(
super::slot_lenience_linear(1u64.into(), &slot(23)),
Some(SLOT_DURATION * 20),
);
assert_eq!(super::slot_lenience_linear(1u64.into(), &slot(23)), Some(SLOT_DURATION * 20),);
}
#[test]
@@ -1041,7 +1015,15 @@ mod test {
let slot_now = 2;
let should_backoff: Vec<bool> = (slot_now..1000)
.map(|s| strategy.should_backoff(head_number, head_slot.into(), finalized_number, s.into(), "slots"))
.map(|s| {
strategy.should_backoff(
head_number,
head_slot.into(),
finalized_number,
s.into(),
"slots",
)
})
.collect();
// Should always be false, since the head isn't advancing
@@ -1105,7 +1087,15 @@ mod test {
let max_interval = strategy.max_interval;
let should_backoff: Vec<bool> = (slot_now..200)
.map(|s| strategy.should_backoff(head_number, head_slot.into(), finalized_number, s.into(), "slots"))
.map(|s| {
strategy.should_backoff(
head_number,
head_slot.into(),
finalized_number,
s.into(),
"slots",
)
})
.collect();
// Should backoff (true) until we are `max_interval` number of slots ahead of the chain
@@ -1123,11 +1113,7 @@ mod test {
};
let finalized_number = 2;
let mut head_state = HeadState {
head_number: 4,
head_slot: 10,
slot_now: 11,
};
let mut head_state = HeadState { head_number: 4, head_slot: 10, slot_now: 11 };
let should_backoff = |head_state: &HeadState| -> bool {
<dyn BackoffAuthoringBlocksStrategy<NumberFor<Block>>>::should_backoff(
@@ -1155,32 +1141,27 @@ mod test {
// Gradually start to backoff more and more frequently
let expected = [
false, false, false, false, false, // no effect
true, false,
true, false, // 1:1
true, true, false,
true, true, false, // 2:1
true, true, true, false,
true, true, true, false, // 3:1
true, true, true, true, false,
true, true, true, true, false, // 4:1
true, true, true, true, true, false,
true, true, true, true, true, false, // 5:1
true, true, true, true, true, true, false,
true, true, true, true, true, true, false, // 6:1
true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, false, // 7:1
true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, false, // 8:1
true, true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, true, false, // 9:1
true, true, true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, true, true, false, // 10:1
true, true, true, true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, true, true, true, false, // 11:1
true, true, true, true, true, true, true, true, true, true, true, true, false,
true, true, true, true, true, true, true, true, true, true, true, true, false, // 12:1
true, false, true, false, // 1:1
true, true, false, true, true, false, // 2:1
true, true, true, false, true, true, true, false, // 3:1
true, true, true, true, false, true, true, true, true, false, // 4:1
true, true, true, true, true, false, true, true, true, true, true, false, // 5:1
true, true, true, true, true, true, false, true, true, true, true, true, true,
false, // 6:1
true, true, true, true, true, true, true, false, true, true, true, true, true, true,
true, false, // 7:1
true, true, true, true, true, true, true, true, false, true, true, true, true, true,
true, true, true, false, // 8:1
true, true, true, true, true, true, true, true, true, false, true, true, true, true,
true, true, true, true, true, false, // 9:1
true, true, true, true, true, true, true, true, true, true, false, true, true, true,
true, true, true, true, true, true, true, false, // 10:1
true, true, true, true, true, true, true, true, true, true, true, false, true, true,
true, true, true, true, true, true, true, true, true, false, // 11:1
true, true, true, true, true, true, true, true, true, true, true, true, false, true,
true, true, true, true, true, true, true, true, true, true, true, false, // 12:1
true, true, true, true,
];
];
assert_eq!(backoff.as_slice(), &expected[..]);
}
@@ -1195,11 +1176,7 @@ mod test {
let finalized_number = 2;
let starting_slot = 11;
let mut head_state = HeadState {
head_number: 4,
head_slot: 10,
slot_now: starting_slot,
};
let mut head_state = HeadState { head_number: 4, head_slot: 10, slot_now: starting_slot };
let should_backoff = |head_state: &HeadState| -> bool {
<dyn BackoffAuthoringBlocksStrategy<NumberFor<Block>>>::should_backoff(
@@ -1240,30 +1217,22 @@ mod test {
assert_eq!(last_slot - last_two_claimed.next().unwrap(), 92);
assert_eq!(last_slot - last_two_claimed.next().unwrap(), 92 + expected_distance);
let intervals: Vec<_> = slots_claimed
.windows(2)
.map(|x| x[1] - x[0])
.collect();
let intervals: Vec<_> = slots_claimed.windows(2).map(|x| x[1] - x[0]).collect();
// The key thing is that the distance between claimed slots is capped to `max_interval + 1`
// assert_eq!(max_observed_interval, Some(&expected_distance));
assert_eq!(intervals.iter().max(), Some(&expected_distance));
// But lets assert all distances, which we expect to grow linearly until `max_interval + 1`
let expected_intervals: Vec<_> = (0..497)
.map(|i| (i/2).max(1).min(expected_distance) )
.collect();
let expected_intervals: Vec<_> =
(0..497).map(|i| (i / 2).max(1).min(expected_distance)).collect();
assert_eq!(intervals, expected_intervals);
}
fn run_until_max_interval(param: BackoffAuthoringOnFinalizedHeadLagging<u64>) -> (u64, u64) {
let finalized_number = 0;
let mut head_state = HeadState {
head_number: 0,
head_slot: 0,
slot_now: 1,
};
let mut head_state = HeadState { head_number: 0, head_slot: 0, slot_now: 1 };
let should_backoff = |head_state: &HeadState| -> bool {
<dyn BackoffAuthoringBlocksStrategy<NumberFor<Block>>>::should_backoff(
@@ -1277,8 +1246,8 @@ mod test {
};
// Number of blocks until we reach the max interval
let block_for_max_interval
= param.max_interval * param.authoring_bias + param.unfinalized_slack;
let block_for_max_interval =
param.max_interval * param.authoring_bias + param.unfinalized_slack;
while head_state.head_number < block_for_max_interval {
if should_backoff(&head_state) {
@@ -1294,15 +1263,15 @@ mod test {
}
// Denoting
// C: unfinalized_slack
// M: authoring_bias
// X: max_interval
// C: unfinalized_slack
// M: authoring_bias
// X: max_interval
// then the number of slots to reach the max interval can be computed from
// (start_slot + C) + M * sum(n, 1, X)
// (start_slot + C) + M * sum(n, 1, X)
// or
// (start_slot + C) + M * X*(X+1)/2
// (start_slot + C) + M * X*(X+1)/2
fn expected_time_to_reach_max_interval(
param: &BackoffAuthoringOnFinalizedHeadLagging<u64>
param: &BackoffAuthoringOnFinalizedHeadLagging<u64>,
) -> (u64, u64) {
let c = param.unfinalized_slack;
let m = param.authoring_bias;
+12 -17
View File
@@ -20,23 +20,21 @@
//!
//! This is used instead of `futures_timer::Interval` because it was unreliable.
use super::{Slot, InherentDataProviderExt};
use super::{InherentDataProviderExt, Slot};
use sp_consensus::{Error, SelectChain};
use sp_inherents::{InherentData, CreateInherentDataProviders, InherentDataProvider};
use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use std::time::{Duration, Instant};
use futures_timer::Delay;
use std::time::{Duration, Instant};
/// Returns current duration since unix epoch.
pub fn duration_now() -> Duration {
use std::time::SystemTime;
let now = SystemTime::now();
now.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| panic!(
"Current time {:?} is before unix epoch. Something is wrong: {:?}",
now,
e,
))
now.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| {
panic!("Current time {:?} is before unix epoch. Something is wrong: {:?}", now, e,)
})
}
/// Returns the duration until the next slot from now.
@@ -104,11 +102,7 @@ pub(crate) struct Slots<Block, C, IDP> {
impl<Block, C, IDP> Slots<Block, C, IDP> {
/// Create a new `Slots` stream.
pub fn new(
slot_duration: Duration,
create_inherent_data_providers: IDP,
client: C,
) -> Self {
pub fn new(slot_duration: Duration, create_inherent_data_providers: IDP, client: C) -> Self {
Slots {
last_slot: 0.into(),
slot_duration,
@@ -135,7 +129,7 @@ where
// schedule wait.
let wait_dur = time_until_next_slot(self.slot_duration);
Some(Delay::new(wait_dur))
}
},
Some(d) => Some(d),
};
@@ -161,11 +155,12 @@ where
);
// Let's try at the next slot..
self.inner_delay.take();
continue;
}
continue
},
};
let inherent_data_providers = self.create_inherent_data_providers
let inherent_data_providers = self
.create_inherent_data_providers
.create_inherent_data_providers(chain_head.hash(), ())
.await?;