mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-23 06:11:07 +00:00
New sessions, kill consensus module (#2802)
* Draft of new sessions * Reintroduce tuple impls * Move staking module to new session API * More work on staking and grandpa. * Use iterator to avoid cloning and tuple macro * Make runtime build again * Polish the OpaqueKeys devex * Move consensus logic into system & aura. * Fix up system module * Get build mostly going. Stuck at service.rs * Building again * Update srml/staking/src/lib.rs Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> * Refactoring out Consensus module, AuthorityIdOf, &c. * Refactored out DigestItem::AuthoritiesChanged. Building. * Remove tentative code * Remove invalid comment * Make Seal opaque and introduce nice methods for handling opaque items. * Start to use proper digest for Aura authorities tracking. * Fix up grandpa, remove system::Raw/Log * Refactor Grandpa to use new logging infrastructure. Also make authorityid/sessionkey static. Switch over to storing authorities in a straight Vec. * Building again * Tidy up some AuthorityIds * Expunge most of the rest of the AuthorityKey confusion. Also, de-generify Babe and re-generify Aura. * Remove cruft * Untangle last of the `AuthorityId`s. * Sort out finality_tracker * Refactor median getting * Apply suggestions from code review Co-Authored-By: Robert Habermeier <rphmeier@gmail.com> * Session tests works * Update core/sr-primitives/src/generic/digest.rs Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> * Session tests works * Fix for staking from @dvc94ch * log an error * fix test runtime build * Some test fixes * Staking mock update to new session api. * Fix build. * Move OpaqueKeys to primitives. * Use on_initialize instead of check_rotate_session. * Update tests to new staking api. * fixup mock * Fix bond_extra_and_withdraw_unbonded_works. * Fix bond_with_little_staked_value_bounded_by_slot_stake. * Fix bond_with_no_staked_value. * Fix change_controller_works. * Fix less_than_needed_candidates_works. * Fix multi_era_reward_should_work. * Fix nominating_and_rewards_should_work. * Fix nominators_also_get_slashed. * Fix phragmen_large_scale_test. * Fix phragmen_poc_works. * Fix phragmen_score_should_be_accurate_on_large_stakes. * Fix phragmen_should_not_overflow. * Fix reward_destination_works. * Fix rewards_should_work. * Fix sessions_and_eras_should_work. * Fix slot_stake_is_least_staked_validator. * Fix too_many_unbond_calls_should_not_work. * Fix wrong_vote_is_null. * Fix runtime. * Fix wasm runtime build. * Update Cargo.lock * Fix warnings. * Fix grandpa tests. * Fix test-runtime build. * Fix template node build. * Fix stuff. * Update Cargo.lock to fix CI * Re-add missing AuRa logs Runtimes are required to know about every digest they receive ― they panic otherwise. This re-adds support for AuRa pre-runtime digests. * Update core/consensus/babe/src/digest.rs Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> * Kill log trait and all that jazz. * Refactor staking tests. * Fix ci runtime wasm check. * Line length 120. * Make tests build again * Remove trailing commas in function declarations The `extern_functions!` macro doesn’t like them, perhaps due to a bug in rustc. * Fix type error * Fix compilation errors * Fix a test * Another couple of fixes * Fix another test * More test fixes * Another test fix * Bump runtime. * Wrap long line * Fix build, remove redundant code. * Issue to track TODO * Leave the benchmark code alone. * Fix missing `std::time::{Instant, Duration}` * Indentation * Aura ConsensusLog as enum
This commit is contained in:
@@ -14,12 +14,10 @@ runtime_io = { package = "sr-io", path = "../../sr-io" }
|
||||
slots = { package = "substrate-consensus-slots", path = "../slots" }
|
||||
aura_primitives = { package = "substrate-consensus-aura-primitives", path = "primitives" }
|
||||
inherents = { package = "substrate-inherents", path = "../../inherents" }
|
||||
srml-consensus = { path = "../../../srml/consensus" }
|
||||
srml-aura = { path = "../../../srml/aura" }
|
||||
client = { package = "substrate-client", path = "../../client" }
|
||||
substrate-telemetry = { path = "../../telemetry" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../common" }
|
||||
authorities = { package = "substrate-consensus-authorities", path = "../authorities" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" }
|
||||
futures = "0.1.17"
|
||||
tokio-timer = "0.2.11"
|
||||
|
||||
@@ -6,12 +6,18 @@ description = "Primitives for Aura consensus"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
parity-codec = { version = "3.5", default-features = false }
|
||||
substrate-client = { path = "../../../client", default-features = false }
|
||||
substrate-primitives = { path = "../../../primitives", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../../sr-std", default-features = false }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"rstd/std",
|
||||
"parity-codec/std",
|
||||
"runtime_primitives/std",
|
||||
"substrate-client/std",
|
||||
"substrate-primitives/std",
|
||||
]
|
||||
|
||||
@@ -18,20 +18,32 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use parity_codec::{Encode, Decode, Codec};
|
||||
use substrate_client::decl_runtime_apis;
|
||||
use rstd::vec::Vec;
|
||||
use runtime_primitives::ConsensusEngineId;
|
||||
|
||||
/// The `ConsensusEngineId` of AuRa.
|
||||
pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a'];
|
||||
|
||||
/// An consensus log item for Aura.
|
||||
#[derive(Decode, Encode)]
|
||||
pub enum ConsensusLog<AuthorityId: Codec> {
|
||||
/// The authorities have changed.
|
||||
AuthoritiesChange(Vec<AuthorityId>),
|
||||
}
|
||||
|
||||
decl_runtime_apis! {
|
||||
/// API necessary for block authorship with aura.
|
||||
pub trait AuraApi {
|
||||
pub trait AuraApi<AuthorityId: Codec> {
|
||||
/// Return the slot duration in seconds for Aura.
|
||||
/// Currently, only the value provided by this type at genesis
|
||||
/// will be used.
|
||||
///
|
||||
/// Dynamic slot duration may be supported in the future.
|
||||
fn slot_duration() -> u64;
|
||||
|
||||
// Return the current set of authorities.
|
||||
fn authorities() -> Vec<AuthorityId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,22 @@
|
||||
//!
|
||||
//! This implements the digests for AuRa, to allow the private
|
||||
//! `CompatibleDigestItem` trait to appear in public interfaces.
|
||||
|
||||
use primitives::Pair;
|
||||
use aura_primitives::AURA_ENGINE_ID;
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use runtime_primitives::generic::{DigestItem, OpaqueDigestItemId};
|
||||
use parity_codec::{Encode, Codec};
|
||||
use std::fmt::Debug;
|
||||
|
||||
type Signature<P> = <P as Pair>::Signature;
|
||||
|
||||
/// A digest item which is usable with aura consensus.
|
||||
pub trait CompatibleDigestItem<T: Pair>: Sized {
|
||||
pub trait CompatibleDigestItem<P: Pair>: Sized {
|
||||
/// Construct a digest item which contains a signature on the hash.
|
||||
fn aura_seal(signature: Signature<T>) -> Self;
|
||||
fn aura_seal(signature: Signature<P>) -> Self;
|
||||
|
||||
/// If this item is an Aura seal, return the signature.
|
||||
fn as_aura_seal(&self) -> Option<&Signature<T>>;
|
||||
fn as_aura_seal(&self) -> Option<Signature<P>>;
|
||||
|
||||
/// Construct a digest item which contains the slot number
|
||||
fn aura_pre_digest(slot_num: u64) -> Self;
|
||||
@@ -40,18 +42,17 @@ pub trait CompatibleDigestItem<T: Pair>: Sized {
|
||||
fn as_aura_pre_digest(&self) -> Option<u64>;
|
||||
}
|
||||
|
||||
impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash, P::Public, P::Signature>
|
||||
where P: Pair, P::Signature: Clone + Encode + Decode,
|
||||
impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash> where
|
||||
P: Pair,
|
||||
Signature<P>: Codec,
|
||||
Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static
|
||||
{
|
||||
fn aura_seal(signature: Signature<P>) -> Self {
|
||||
DigestItem::Seal(AURA_ENGINE_ID, signature)
|
||||
DigestItem::Seal(AURA_ENGINE_ID, signature.encode())
|
||||
}
|
||||
|
||||
fn as_aura_seal(&self) -> Option<&Signature<P>> {
|
||||
match self {
|
||||
DigestItem::Seal(AURA_ENGINE_ID, ref sig) => Some(sig),
|
||||
_ => None,
|
||||
}
|
||||
fn as_aura_seal(&self) -> Option<Signature<P>> {
|
||||
self.try_to(OpaqueDigestItemId::Seal(&AURA_ENGINE_ID))
|
||||
}
|
||||
|
||||
fn aura_pre_digest(slot_num: u64) -> Self {
|
||||
@@ -59,9 +60,6 @@ impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash, P::Public, P::Signatu
|
||||
}
|
||||
|
||||
fn as_aura_pre_digest(&self) -> Option<u64> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(AURA_ENGINE_ID, ref buffer) => Decode::decode(&mut &buffer[..]),
|
||||
_ => None,
|
||||
}
|
||||
self.try_to(OpaqueDigestItemId::PreRuntime(&AURA_ENGINE_ID))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,15 @@
|
||||
//!
|
||||
//! Blocks from future steps will be either deferred or rejected depending on how
|
||||
//! far in the future they are.
|
||||
//!
|
||||
//! NOTE: Aura itself is designed to be generic over the crypto used.
|
||||
#![forbid(missing_docs, unsafe_code)]
|
||||
use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug};
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use consensus_common::{self, Authorities, BlockImport, Environment, Proposer,
|
||||
use parity_codec::{Encode, Decode, Codec};
|
||||
use consensus_common::{self, BlockImport, Environment, Proposer,
|
||||
ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError,
|
||||
SelectChain, well_known_cache_keys
|
||||
SelectChain, well_known_cache_keys::{self, Id as CacheKeyId}
|
||||
};
|
||||
use consensus_common::import_queue::{
|
||||
Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport, SharedFinalityProofImport,
|
||||
@@ -45,15 +47,11 @@ use client::{
|
||||
backend::AuxStore,
|
||||
};
|
||||
|
||||
use runtime_primitives::{generic::{self, BlockId}, Justification};
|
||||
use runtime_primitives::traits::{
|
||||
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor,
|
||||
Zero, Member,
|
||||
};
|
||||
use runtime_primitives::{generic::{self, BlockId, OpaqueDigestItemId}, Justification};
|
||||
use runtime_primitives::traits::{Block, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member};
|
||||
|
||||
use primitives::Pair;
|
||||
use inherents::{InherentDataProviders, InherentData};
|
||||
use authorities::AuthoritiesApi;
|
||||
|
||||
use futures::{Future, IntoFuture, future};
|
||||
use tokio_timer::Timeout;
|
||||
@@ -82,9 +80,12 @@ pub struct SlotDuration(slots::SlotDuration<u64>);
|
||||
impl SlotDuration {
|
||||
/// Either fetch the slot duration from disk or compute it from the genesis
|
||||
/// state.
|
||||
pub fn get_or_compute<B: Block, C>(client: &C) -> CResult<Self>
|
||||
pub fn get_or_compute<A, B, C>(client: &C) -> CResult<Self>
|
||||
where
|
||||
C: AuxStore, C: ProvideRuntimeApi, C::Api: AuraApi<B>,
|
||||
A: Codec,
|
||||
B: Block,
|
||||
C: AuxStore + ProvideRuntimeApi,
|
||||
C::Api: AuraApi<B, A>,
|
||||
{
|
||||
slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self)
|
||||
}
|
||||
@@ -138,19 +139,14 @@ pub fn start_aura<B, C, SC, E, I, P, SO, Error, H>(
|
||||
) -> Result<impl Future<Item=(), Error=()>, consensus_common::Error> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + AuxStore + Send + Sync,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, AuthorityId<P>>,
|
||||
SC: SelectChain<B>,
|
||||
generic::DigestItem<B::Hash, P::Public, P::Signature>: DigestItem<Hash=B::Hash>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Hash + Member + Encode + Decode,
|
||||
P::Signature: Hash + Member + Encode + Decode,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, P::Public, P::Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
E: Environment<B, Error=Error>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
@@ -189,20 +185,16 @@ struct AuraWorker<C, E, I, P, SO> {
|
||||
impl<H, B, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + Sync,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, AuthorityId<P>>,
|
||||
E: Environment<B, Error=Error>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, P::Public, P::Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Member + Encode + Decode + Hash,
|
||||
P::Signature: Member + Encode + Decode + Hash + Debug,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>, Hash=B::Hash>,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
{
|
||||
type OnSlot = Box<dyn Future<Item=(), Error=consensus_common::Error> + Send>;
|
||||
@@ -257,7 +249,7 @@ impl<H, B, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> w
|
||||
);
|
||||
|
||||
// we are the slot author. make a block and sign it.
|
||||
let proposer = match env.init(&chain_head, &authorities) {
|
||||
let proposer = match env.init(&chain_head) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
warn!("Unable to author block in slot {:?}: {:?}", slot_num, e);
|
||||
@@ -506,13 +498,12 @@ impl<C, P> AuraVerifier<C, P>
|
||||
|
||||
#[forbid(deprecated)]
|
||||
impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore,
|
||||
C::Api: BlockBuilderApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore + ProvideCache<B>,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + AsRef<P::Public> + 'static,
|
||||
P::Signature: Encode + Decode,
|
||||
Self: Authorities<B>,
|
||||
{
|
||||
fn verify(
|
||||
&self,
|
||||
@@ -520,13 +511,13 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
mut body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityId<P>>>), String> {
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?;
|
||||
let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data)
|
||||
.map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?;
|
||||
let hash = header.hash();
|
||||
let parent_hash = *header.parent_hash();
|
||||
let authorities = self.authorities(&BlockId::Hash(parent_hash))
|
||||
let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash))
|
||||
.map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?;
|
||||
|
||||
// we add one to allow for some small drift.
|
||||
@@ -569,9 +560,14 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
trace!(target: "aura", "Checked {:?}; importing.", pre_header);
|
||||
telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header);
|
||||
|
||||
let new_authorities = pre_header.digest()
|
||||
.log(DigestItem::as_authorities_change)
|
||||
.map(|digest| digest.to_vec());
|
||||
// `Consensus` is the Aura-specific authorities change log.
|
||||
let maybe_keys = pre_header.digest()
|
||||
.convert_first(|l| l.try_to::<ConsensusLog<AuthorityId<P>>>(
|
||||
OpaqueDigestItemId::Consensus(&AURA_ENGINE_ID)
|
||||
))
|
||||
.map(|ConsensusLog::AuthoritiesChange(a)|
|
||||
vec![(well_known_cache_keys::AUTHORITIES, a.encode())]
|
||||
);
|
||||
|
||||
let import_block = ImportBlock {
|
||||
origin,
|
||||
@@ -584,7 +580,7 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
fork_choice: ForkChoiceStrategy::LongestChain,
|
||||
};
|
||||
|
||||
Ok((import_block, new_authorities))
|
||||
Ok((import_block, maybe_keys))
|
||||
}
|
||||
CheckedHeader::Deferred(a, b) => {
|
||||
debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
|
||||
@@ -597,22 +593,11 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, C, P> Authorities<B> for AuraVerifier<C, P> where
|
||||
fn initialize_authorities_cache<A, B, C>(client: &C) -> Result<(), ConsensusError> where
|
||||
A: Codec,
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
{
|
||||
type Error = ConsensusError;
|
||||
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, Self::Error> {
|
||||
authorities(self.client.as_ref(), at)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, A>,
|
||||
{
|
||||
// no cache => no initialization
|
||||
let cache = match client.cache() {
|
||||
@@ -622,7 +607,7 @@ fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError>
|
||||
|
||||
// check if we already have initialized the cache
|
||||
let genesis_id = BlockId::Number(Zero::zero());
|
||||
let genesis_authorities: Option<Vec<AuthorityIdFor<B>>> = cache
|
||||
let genesis_authorities: Option<Vec<A>> = cache
|
||||
.get_at(&well_known_cache_keys::AUTHORITIES, &genesis_id)
|
||||
.and_then(|v| Decode::decode(&mut &v[..]));
|
||||
if genesis_authorities.is_some() {
|
||||
@@ -642,10 +627,11 @@ fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError>
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, ConsensusError> where
|
||||
fn authorities<A, B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<A>, ConsensusError> where
|
||||
A: Codec,
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, A>,
|
||||
{
|
||||
client
|
||||
.cache()
|
||||
@@ -653,7 +639,7 @@ fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B
|
||||
.get_at(&well_known_cache_keys::AUTHORITIES, at)
|
||||
.and_then(|v| Decode::decode(&mut &v[..]))
|
||||
)
|
||||
.or_else(|| AuthoritiesApi::authorities(&*client.runtime_api(), at).ok())
|
||||
.or_else(|| AuraApi::authorities(&*client.runtime_api(), at).ok())
|
||||
.ok_or_else(|| consensus_common::Error::InvalidAuthoritiesSet.into())
|
||||
}
|
||||
|
||||
@@ -687,8 +673,8 @@ pub fn import_queue<B, C, P>(
|
||||
) -> Result<AuraImportQueue<B>, consensus_common::Error> where
|
||||
B: Block,
|
||||
C: 'static + ProvideRuntimeApi + ProvideCache<B> + Send + Sync + AuxStore,
|
||||
C::Api: BlockBuilderApi<B> + AuthoritiesApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef<P::Public>,
|
||||
P::Signature: Encode + Decode,
|
||||
@@ -730,7 +716,12 @@ mod tests {
|
||||
|
||||
type Error = client::error::Error;
|
||||
|
||||
type TestClient = client::Client<test_client::Backend, test_client::Executor, TestBlock, test_client::runtime::RuntimeApi>;
|
||||
type TestClient = client::Client<
|
||||
test_client::Backend,
|
||||
test_client::Executor,
|
||||
TestBlock,
|
||||
test_client::runtime::RuntimeApi
|
||||
>;
|
||||
|
||||
struct DummyFactory(Arc<TestClient>);
|
||||
struct DummyProposer(u64, Arc<TestClient>);
|
||||
@@ -739,7 +730,7 @@ mod tests {
|
||||
type Proposer = DummyProposer;
|
||||
type Error = Error;
|
||||
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId<sr25519::Pair>])
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header)
|
||||
-> Result<DummyProposer, Error>
|
||||
{
|
||||
Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "substrate-consensus-authorities"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Primitives for Aura consensus"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
parity-codec = { version = "3.3", default-features = false }
|
||||
substrate-client = { path = "../../client", default-features = false }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives", default-features = false }
|
||||
runtime_support = { package = "srml-support", path = "../../../srml/support", default-features = false }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false }
|
||||
sr-version = { path = "../../sr-version", default-features = false }
|
||||
runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../sr-std", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"parity-codec/std",
|
||||
"substrate-client/std",
|
||||
"primitives/std",
|
||||
"runtime_support/std",
|
||||
"runtime_primitives/std",
|
||||
"sr-version/std",
|
||||
"runtime_io/std",
|
||||
"rstd/std"
|
||||
]
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Authorities API.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use substrate_client::decl_runtime_apis;
|
||||
use runtime_primitives::traits::AuthorityIdFor;
|
||||
use rstd::vec::Vec;
|
||||
|
||||
decl_runtime_apis! {
|
||||
/// Authorities API.
|
||||
pub trait AuthoritiesApi {
|
||||
/// Returns the authorities at the given block.
|
||||
fn authorities() -> Vec<AuthorityIdFor<Block>>;
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,10 @@ runtime_support = { package = "srml-support", path = "../../../srml/support" }
|
||||
runtime_version = { package = "sr-version", path = "../../sr-version" }
|
||||
runtime_io = { package = "sr-io", path = "../../sr-io" }
|
||||
inherents = { package = "substrate-inherents", path = "../../inherents" }
|
||||
srml-consensus = { path = "../../../srml/consensus" }
|
||||
substrate-telemetry = { path = "../../telemetry" }
|
||||
srml-babe = { path = "../../../srml/babe" }
|
||||
client = { package = "substrate-client", path = "../../client" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../common" }
|
||||
authorities = { package = "substrate-consensus-authorities", path = "../authorities" }
|
||||
slots = { package = "substrate-consensus-slots", path = "../slots" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" }
|
||||
futures = "0.1.26"
|
||||
|
||||
@@ -7,13 +7,16 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
substrate-client = { path = "../../../client", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../../sr-std", default-features = false }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false }
|
||||
substrate-primitives = { path = "../../../primitives", default-features = false }
|
||||
slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true }
|
||||
parity-codec = { version = "3.5.1", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"rstd/std",
|
||||
"runtime_primitives/std",
|
||||
"substrate-client/std",
|
||||
"parity-codec/std",
|
||||
|
||||
@@ -18,13 +18,18 @@
|
||||
#![deny(warnings, unsafe_code, missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use rstd::vec::Vec;
|
||||
use runtime_primitives::ConsensusEngineId;
|
||||
use substrate_primitives::sr25519::Public;
|
||||
use substrate_client::decl_runtime_apis;
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in
|
||||
/// the main Babe module. If that ever changes, then this must, too.
|
||||
pub type AuthorityId = Public;
|
||||
|
||||
/// The `ConsensusEngineId` of BABE.
|
||||
pub const BABE_ENGINE_ID: ConsensusEngineId = [b'b', b'a', b'b', b'e'];
|
||||
pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE";
|
||||
|
||||
/// Configuration data used by the BABE consensus engine.
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Encode, Decode)]
|
||||
@@ -69,5 +74,8 @@ decl_runtime_apis! {
|
||||
///
|
||||
/// Dynamic configuration may be supported in the future.
|
||||
fn startup_data() -> BabeConfiguration;
|
||||
|
||||
/// Get the current authorites for Babe.
|
||||
fn authorities() -> Vec<AuthorityId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Private mplementation details of BABE digests.
|
||||
|
||||
use primitives::sr25519::{Public, Signature};
|
||||
use babe_primitives::BABE_ENGINE_ID;
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use runtime_primitives::{DigestItem, generic::OpaqueDigestItemId};
|
||||
use std::fmt::Debug;
|
||||
use parity_codec::{Decode, Encode, Input};
|
||||
use log::info;
|
||||
use parity_codec::{Decode, Encode, Codec, Input};
|
||||
use schnorrkel::{
|
||||
vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH},
|
||||
PUBLIC_KEY_LENGTH,
|
||||
@@ -89,26 +89,15 @@ pub trait CompatibleDigestItem: Sized {
|
||||
fn as_babe_seal(&self) -> Option<Signature>;
|
||||
}
|
||||
|
||||
impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Vec<u8>>
|
||||
impl<Hash> CompatibleDigestItem for DigestItem<Hash> where
|
||||
Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static
|
||||
{
|
||||
fn babe_pre_digest(digest: BabePreDigest) -> Self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
|
||||
}
|
||||
|
||||
fn as_babe_pre_digest(&self) -> Option<BabePreDigest> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => {
|
||||
let decoded = Decode::decode(&mut &seal[..]);
|
||||
if decoded.is_none() {
|
||||
info!(target: "babe", "Failed to decode {:?}", seal)
|
||||
}
|
||||
decoded
|
||||
}
|
||||
_ => {
|
||||
info!(target: "babe", "Invalid consensus: {:?}!", self);
|
||||
None
|
||||
}
|
||||
}
|
||||
self.try_to(OpaqueDigestItemId::PreRuntime(&BABE_ENGINE_ID))
|
||||
}
|
||||
|
||||
fn babe_seal(signature: Signature) -> Self {
|
||||
@@ -116,34 +105,6 @@ impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Vec<u8>>
|
||||
}
|
||||
|
||||
fn as_babe_seal(&self) -> Option<Signature> {
|
||||
match self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature) => Decode::decode(&mut &signature[..]),
|
||||
_ => None,
|
||||
}
|
||||
self.try_to(OpaqueDigestItemId::Seal(&BABE_ENGINE_ID))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Signature>
|
||||
{
|
||||
fn babe_pre_digest(digest: BabePreDigest) -> Self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
|
||||
}
|
||||
|
||||
fn as_babe_pre_digest(&self) -> Option<BabePreDigest> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => Decode::decode(&mut &seal[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn babe_seal(signature: Signature) -> Self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature)
|
||||
}
|
||||
|
||||
fn as_babe_seal(&self) -> Option<Signature> {
|
||||
match self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature) => Some(signature.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,18 +31,16 @@ use digest::CompatibleDigestItem;
|
||||
pub use digest::{BabePreDigest, BABE_VRF_PREFIX};
|
||||
pub use babe_primitives::*;
|
||||
pub use consensus_common::SyncOracle;
|
||||
use runtime_primitives::{generic, generic::BlockId, Justification};
|
||||
use consensus_common::well_known_cache_keys::Id as CacheKeyId;
|
||||
use runtime_primitives::{generic, generic::{BlockId, OpaqueDigestItemId}, Justification};
|
||||
use runtime_primitives::traits::{
|
||||
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor,
|
||||
Block, Header, DigestItemFor, ProvideRuntimeApi,
|
||||
SimpleBitOps,
|
||||
};
|
||||
use std::{sync::Arc, u64, fmt::{Debug, Display}};
|
||||
use runtime_support::serde::{Serialize, Deserialize};
|
||||
use parity_codec::{Decode, Encode};
|
||||
use primitives::{
|
||||
crypto::Pair,
|
||||
sr25519::{Public, Signature, self},
|
||||
};
|
||||
use primitives::{crypto::Pair, sr25519};
|
||||
use merlin::Transcript;
|
||||
use inherents::{InherentDataProviders, InherentData};
|
||||
use substrate_telemetry::{
|
||||
@@ -58,9 +56,8 @@ use schnorrkel::{
|
||||
VRFProof, VRFProofBatchable, VRFInOut,
|
||||
},
|
||||
};
|
||||
use authorities::AuthoritiesApi;
|
||||
use consensus_common::{
|
||||
self, Authorities, BlockImport, Environment, Proposer,
|
||||
self, BlockImport, Environment, Proposer,
|
||||
ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError,
|
||||
};
|
||||
use srml_babe::{
|
||||
@@ -83,6 +80,7 @@ use log::{error, warn, debug, info, trace};
|
||||
|
||||
use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible, slot_now};
|
||||
|
||||
pub use babe_primitives::AuthorityId;
|
||||
|
||||
/// A slot duration. Create with `get_or_compute`.
|
||||
// FIXME: Once Rust has higher-kinded types, the duplication between this
|
||||
@@ -181,16 +179,11 @@ pub fn start_babe<B, C, SC, E, I, SO, Error, H>(BabeParams {
|
||||
> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
SC: SelectChain<B>,
|
||||
generic::DigestItem<B::Hash, Public, Signature>: DigestItem<Hash=B::Hash>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, Public, Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
E: Environment<B, Error=Error>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
@@ -228,17 +221,14 @@ struct BabeWorker<C, E, I, SO> {
|
||||
impl<Hash, H, B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> where
|
||||
B: Block<Header=H, Hash=Hash>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
E: Environment<B, Error=Error>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
Hash: Debug + Eq + Copy + SimpleBitOps + Encode + Decode + Serialize +
|
||||
for<'de> Deserialize<'de> + Debug + Default + AsRef<[u8]> + AsMut<[u8]> +
|
||||
std::hash::Hash + Display + Send + Sync + 'static,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, Public, Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
Error: std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
@@ -304,7 +294,7 @@ impl<Hash, H, B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> w
|
||||
);
|
||||
|
||||
// we are the slot author. make a block and sign it.
|
||||
let proposer = match env.init(&chain_head, &authorities) {
|
||||
let proposer = match env.init(&chain_head) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
warn!(target: "babe", "Unable to author block in slot {:?}: {:?}", slot_num, e);
|
||||
@@ -450,7 +440,7 @@ fn check_header<B: Block + Sized, C: AuxStore>(
|
||||
slot_now: u64,
|
||||
mut header: B::Header,
|
||||
hash: B::Hash,
|
||||
authorities: &[Public],
|
||||
authorities: &[AuthorityId],
|
||||
threshold: u64,
|
||||
) -> Result<CheckedHeader<B::Header, (DigestItemFor<B>, DigestItemFor<B>)>, String>
|
||||
where DigestItemFor<B>: CompatibleDigestItem,
|
||||
@@ -553,10 +543,9 @@ impl<C> BabeVerifier<C> {
|
||||
}
|
||||
|
||||
impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
C: ProvideRuntimeApi + Send + Sync + AuxStore,
|
||||
C::Api: BlockBuilderApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
|
||||
Self: Authorities<B>,
|
||||
C: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache<B>,
|
||||
C::Api: BlockBuilderApi<B> + BabeApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem,
|
||||
{
|
||||
fn verify(
|
||||
&self,
|
||||
@@ -564,7 +553,7 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
mut body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<Public>>), String> {
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
trace!(
|
||||
target: "babe",
|
||||
"Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}",
|
||||
@@ -583,7 +572,7 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
.map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?;
|
||||
let hash = header.hash();
|
||||
let parent_hash = *header.parent_hash();
|
||||
let authorities = self.authorities(&BlockId::Hash(parent_hash))
|
||||
let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash))
|
||||
.map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?;
|
||||
|
||||
// we add one to allow for some small drift.
|
||||
@@ -625,9 +614,12 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
"babe.checked_and_importing";
|
||||
"pre_header" => ?pre_header);
|
||||
|
||||
let new_authorities = pre_header.digest()
|
||||
.log(DigestItem::as_authorities_change)
|
||||
.map(|digest| digest.to_vec());
|
||||
// `Consensus` is the Babe-specific authorities change log.
|
||||
// It's an encoded `Vec<AuthorityId>`, the same format as is stored in the cache,
|
||||
// so no need to decode/re-encode.
|
||||
let maybe_keys = pre_header.digest()
|
||||
.log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)))
|
||||
.map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]);
|
||||
|
||||
let import_block = ImportBlock {
|
||||
origin,
|
||||
@@ -641,7 +633,7 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
};
|
||||
|
||||
// FIXME #1019 extract authorities
|
||||
Ok((import_block, new_authorities))
|
||||
Ok((import_block, maybe_keys))
|
||||
}
|
||||
CheckedHeader::Deferred(a, b) => {
|
||||
debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
|
||||
@@ -654,33 +646,21 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, C> Authorities<B> for BabeVerifier<C> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
{
|
||||
type Error = ConsensusError;
|
||||
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, Self::Error> {
|
||||
authorities(self.client.as_ref(), at)
|
||||
}
|
||||
}
|
||||
|
||||
fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<
|
||||
Vec<AuthorityIdFor<B>>,
|
||||
Vec<AuthorityId>,
|
||||
ConsensusError,
|
||||
> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
{
|
||||
client
|
||||
.cache()
|
||||
.and_then(|cache| cache.get_at(&well_known_cache_keys::AUTHORITIES, at)
|
||||
.and_then(|v| Decode::decode(&mut &v[..])))
|
||||
.or_else(|| {
|
||||
if client.runtime_api().has_api::<dyn AuthoritiesApi<B>>(at).unwrap_or(false) {
|
||||
AuthoritiesApi::authorities(&*client.runtime_api(), at).ok()
|
||||
if client.runtime_api().has_api::<dyn BabeApi<B>>(at).unwrap_or(false) {
|
||||
BabeApi::authorities(&*client.runtime_api(), at).ok()
|
||||
} else {
|
||||
panic!("We don’t support deprecated code with new consensus algorithms, \
|
||||
therefore this is unreachable; qed")
|
||||
@@ -740,7 +720,7 @@ fn claim_slot(
|
||||
slot_number: u64,
|
||||
genesis_hash: &[u8],
|
||||
epoch: u64,
|
||||
authorities: &[sr25519::Public],
|
||||
authorities: &[AuthorityId],
|
||||
key: &sr25519::Pair,
|
||||
threshold: u64,
|
||||
) -> Option<(VRFInOut, VRFProof, VRFProofBatchable)> {
|
||||
@@ -784,7 +764,7 @@ mod tests {
|
||||
use futures::stream::Stream;
|
||||
use log::debug;
|
||||
use std::time::Duration;
|
||||
type Item = generic::DigestItem<Hash, Public, Signature>;
|
||||
type Item = generic::DigestItem<Hash>;
|
||||
use test_client::AuthorityKeyring;
|
||||
|
||||
type Error = client::error::Error;
|
||||
@@ -803,7 +783,7 @@ mod tests {
|
||||
type Proposer = DummyProposer;
|
||||
type Error = Error;
|
||||
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[Public])
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header)
|
||||
-> Result<DummyProposer, Error>
|
||||
{
|
||||
Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
|
||||
@@ -977,7 +957,7 @@ mod tests {
|
||||
fn wrong_consensus_engine_id_rejected() {
|
||||
drop(env_logger::try_init());
|
||||
let sig = sr25519::Pair::generate().0.sign(b"");
|
||||
let bad_seal: Item = DigestItem::Seal([0; 4], sig);
|
||||
let bad_seal: Item = DigestItem::Seal([0; 4], sig.0.to_vec());
|
||||
assert!(bad_seal.as_babe_pre_digest().is_none());
|
||||
assert!(bad_seal.as_babe_seal().is_none())
|
||||
}
|
||||
@@ -985,7 +965,7 @@ mod tests {
|
||||
#[test]
|
||||
fn malformed_pre_digest_rejected() {
|
||||
drop(env_logger::try_init());
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, Signature([0; 64]));
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, [0; 64].to_vec());
|
||||
assert!(bad_seal.as_babe_pre_digest().is_none());
|
||||
}
|
||||
|
||||
@@ -993,7 +973,7 @@ mod tests {
|
||||
fn sig_is_not_pre_digest() {
|
||||
drop(env_logger::try_init());
|
||||
let sig = sr25519::Pair::generate().0.sign(b"");
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig);
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig.0.to_vec());
|
||||
assert!(bad_seal.as_babe_pre_digest().is_none());
|
||||
assert!(bad_seal.as_babe_seal().is_some())
|
||||
}
|
||||
|
||||
@@ -154,8 +154,6 @@ impl<Block: BlockT> ImportBlock<Block> {
|
||||
|
||||
/// Get a handle to full header (with post-digests applied).
|
||||
pub fn post_header(&self) -> Cow<Block::Header> {
|
||||
use runtime_primitives::traits::Digest;
|
||||
|
||||
if self.post_digests.is_empty() {
|
||||
Cow::Borrowed(&self.header)
|
||||
} else {
|
||||
|
||||
@@ -25,24 +25,16 @@
|
||||
//! instantiated. The `BasicQueue` and `BasicVerifier` traits allow serial
|
||||
//! queues to be instantiated simply.
|
||||
|
||||
use crate::block_import::{
|
||||
use std::{sync::Arc, thread, collections::HashMap};
|
||||
use crossbeam_channel::{self as channel, Receiver, Sender};
|
||||
use parking_lot::Mutex;
|
||||
use runtime_primitives::{Justification, traits::{
|
||||
Block as BlockT, Header as HeaderT, NumberFor,
|
||||
}};
|
||||
use crate::{error::Error as ConsensusError, well_known_cache_keys::Id as CacheKeyId, block_import::{
|
||||
BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport,
|
||||
FinalityProofImport, FinalityProofRequestBuilder,
|
||||
};
|
||||
use crossbeam_channel::{self as channel, Receiver, Sender};
|
||||
use parity_codec::Encode;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use runtime_primitives::traits::{
|
||||
AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor, Digest,
|
||||
};
|
||||
use runtime_primitives::Justification;
|
||||
|
||||
use crate::error::Error as ConsensusError;
|
||||
use parity_codec::alloc::collections::hash_map::HashMap;
|
||||
}};
|
||||
|
||||
/// Reputation change for peers which send us a block with an incomplete header.
|
||||
const INCOMPLETE_HEADER_REPUTATION_CHANGE: i32 = -(1 << 20);
|
||||
@@ -94,7 +86,7 @@ pub trait Verifier<B: BlockT>: Send + Sync {
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityIdFor<B>>>), String>;
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String>;
|
||||
}
|
||||
|
||||
/// Blocks import queue API.
|
||||
@@ -906,7 +898,7 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
|
||||
r => return Ok(r), // Any other successful result means that the block is already imported.
|
||||
}
|
||||
|
||||
let (import_block, new_authorities) = verifier.verify(block_origin, header, justification, block.body)
|
||||
let (import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body)
|
||||
.map_err(|msg| {
|
||||
if let Some(ref peer) = peer {
|
||||
trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg);
|
||||
@@ -917,8 +909,8 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
|
||||
})?;
|
||||
|
||||
let mut cache = HashMap::new();
|
||||
if let Some(authorities) = new_authorities {
|
||||
cache.insert(crate::well_known_cache_keys::AUTHORITIES, authorities.encode());
|
||||
if let Some(keys) = maybe_keys {
|
||||
cache.extend(keys.into_iter());
|
||||
}
|
||||
|
||||
import_error(import_handle.import_block(import_block, cache))
|
||||
@@ -979,7 +971,7 @@ mod tests {
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityIdFor<B>>>), String> {
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
Ok((ImportBlock {
|
||||
origin,
|
||||
header,
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{AuthorityIdFor, Block, DigestFor};
|
||||
use runtime_primitives::traits::{Block, DigestFor};
|
||||
use futures::prelude::*;
|
||||
pub use inherents::InherentData;
|
||||
|
||||
@@ -54,14 +53,6 @@ pub use block_import::{
|
||||
};
|
||||
pub use select_chain::SelectChain;
|
||||
|
||||
/// Trait for getting the authorities at a given block.
|
||||
pub trait Authorities<B: Block> {
|
||||
type Error: std::error::Error + Send + 'static;
|
||||
|
||||
/// Get the authorities at the given block.
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, Self::Error>;
|
||||
}
|
||||
|
||||
/// Environment producer for a Consensus instance. Creates proposer instance and communication streams.
|
||||
pub trait Environment<B: Block> {
|
||||
/// The proposer type this creates.
|
||||
@@ -71,7 +62,7 @@ pub trait Environment<B: Block> {
|
||||
|
||||
/// Initialize the proposal logic on top of a specific header. Provide
|
||||
/// the authorities at that header.
|
||||
fn init(&self, parent_header: &B::Header, authorities: &[AuthorityIdFor<B>])
|
||||
fn init(&self, parent_header: &B::Header)
|
||||
-> Result<Self::Proposer, Self::Error>;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,25 +112,24 @@ impl<AuthorityId: Eq + Clone + std::hash::Hash> OfflineTracker<AuthorityId> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use primitives::ed25519::Public as AuthorityId;
|
||||
|
||||
#[test]
|
||||
fn validator_offline() {
|
||||
let mut tracker = OfflineTracker::<AuthorityId>::new();
|
||||
let v = AuthorityId::from_raw([0; 32]);
|
||||
let v2 = AuthorityId::from_raw([1; 32]);
|
||||
let v3 = AuthorityId::from_raw([2; 32]);
|
||||
tracker.note_round_end(v.clone(), true);
|
||||
tracker.note_round_end(v2.clone(), true);
|
||||
tracker.note_round_end(v3.clone(), true);
|
||||
let mut tracker = OfflineTracker::<u64>::new();
|
||||
let v1 = 1;
|
||||
let v2 = 2;
|
||||
let v3 = 3;
|
||||
tracker.note_round_end(v1, true);
|
||||
tracker.note_round_end(v2, true);
|
||||
tracker.note_round_end(v3, true);
|
||||
|
||||
let slash_time = REPORT_TIME + Duration::from_secs(5);
|
||||
tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time;
|
||||
tracker.observed.get_mut(&v1).unwrap().offline_since -= slash_time;
|
||||
tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time;
|
||||
|
||||
assert_eq!(tracker.reports(&[v.clone(), v2.clone(), v3.clone()]), vec![0, 1]);
|
||||
assert_eq!(tracker.reports(&[v1, v2, v3]), vec![0, 1]);
|
||||
|
||||
tracker.note_new_block(&[v.clone(), v3.clone()]);
|
||||
assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]);
|
||||
tracker.note_new_block(&[v1, v3]);
|
||||
assert_eq!(tracker.reports(&[v1, v2, v3]), vec![0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ client = { package = "substrate-client", path = "../../client" }
|
||||
transaction_pool = { package = "substrate-transaction-pool", path = "../../transaction-pool" }
|
||||
runtime_support = { package = "srml-support", path = "../../../srml/support" }
|
||||
srml-system = { path = "../../../srml/system" }
|
||||
srml-consensus = { path = "../../../srml/consensus" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" }
|
||||
runtime_version = { package = "sr-version", path = "../../sr-version" }
|
||||
runtime_io = { package = "sr-io", path = "../../sr-io" }
|
||||
|
||||
Reference in New Issue
Block a user