Remove requirement on Hash = H256, make Proposer return StorageChanges and Proof (#3860)

* Extend `Proposer` to optionally generate a proof of the proposal

* Something

* Refactor sr-api to not depend on client anymore

* Fix benches

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Apply suggestions from code review

* Introduce new `into_storage_changes` function

* Switch to runtime api for `execute_block` and don't require `H256`
anywhere in the code

* Put the `StorageChanges` into the `Proposal`

* Move the runtime api error to its own trait

* Adds `StorageTransactionCache` to the runtime api

This requires that we add `type NodeBlock = ` to the
`impl_runtime_apis!` macro to work around some bugs in rustc :(

* Remove `type NodeBlock` and switch to a "better" hack

* Start using the transaction cache from the runtime api

* Make it compile

* Move `InMemory` to its own file

* Make all tests work again

* Return block, storage_changes and proof from Blockbuilder::bake()

* Make sure that we use/set `storage_changes` when possible

* Add test

* Fix deadlock

* Remove accidentally added folders

* Introduce `RecordProof` as argument type to be more explicit

* Update client/src/client.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update primitives/state-machine/src/ext.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Integrates review feedback

* Remove `unsafe` usage

* Update client/block-builder/src/lib.rs

Co-Authored-By: Benjamin Kampmann <ben@gnunicorn.org>

* Update client/src/call_executor.rs

* Bump versions

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Benjamin Kampmann <ben.kampmann@googlemail.com>
This commit is contained in:
Bastian Köcher
2020-01-10 10:48:32 +01:00
committed by GitHub
parent 74d6e660c6
commit fd6b29dd2c
140 changed files with 4860 additions and 3339 deletions
+80 -55
View File
@@ -54,15 +54,20 @@ use sp_blockchain::{
};
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification};
use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member};
use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, Zero, Member};
use sp_api::ProvideRuntimeApi;
use sp_core::crypto::Pair;
use sp_inherents::{InherentDataProviders, InherentData};
use sp_timestamp::{
TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError
};
use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO};
use sc_consensus_slots::{CheckedHeader, SlotWorker, SlotInfo, SlotCompatible};
use sc_consensus_slots::check_equivocation;
use sc_consensus_slots::{
CheckedHeader, SlotWorker, SlotInfo, SlotCompatible, StorageChanges, check_equivocation,
};
use sc_keystore::KeyStorePtr;
use sp_api::ApiExt;
@@ -91,7 +96,7 @@ impl SlotDuration {
where
A: Codec,
B: BlockT,
C: AuxStore + ProvideRuntimeApi,
C: AuxStore + ProvideRuntimeApi<B>,
C::Api: AuraApi<B, A, Error = sp_blockchain::Error>,
{
sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self)
@@ -137,7 +142,7 @@ impl SlotCompatible for AuraSlotCompatible {
}
/// Start the aura worker. The returned future should be run in a futures executor.
pub fn start_aura<B, C, SC, E, I, P, SO, CAW, Error, H>(
pub fn start_aura<B, C, SC, E, I, P, SO, CAW, Error>(
slot_duration: SlotDuration,
client: Arc<C>,
select_chain: SC,
@@ -149,19 +154,17 @@ pub fn start_aura<B, C, SC, E, I, P, SO, CAW, Error, H>(
keystore: KeyStorePtr,
can_author_with: CAW,
) -> Result<impl futures01::Future<Item = (), Error = ()>, sp_consensus::Error> where
B: BlockT<Header=H>,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B> + AuxStore + Send + Sync,
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + AuxStore + Send + Sync,
C::Api: AuraApi<B, AuthorityId<P>>,
SC: SelectChain<B>,
E: Environment<B, Error=Error> + Send + Sync + 'static,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send,
E: Environment<B, Error = Error> + Send + Sync + 'static,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
P: Pair + Send + Sync,
P::Public: Hash + Member + Encode + Decode,
P::Signature: Hash + Member + Encode + Decode,
H: Header<Hash=B::Hash>,
I: BlockImport<B> + Send + Sync + 'static,
Error: ::std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
SO: SyncOracle + Send + Sync + Clone,
CAW: CanAuthorWith<B> + Send,
{
@@ -199,20 +202,18 @@ struct AuraWorker<C, E, I, P, SO> {
_key_type: PhantomData<P>,
}
impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT<Header=H>,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B> + Sync,
impl<B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Sync,
C::Api: AuraApi<B, AuthorityId<P>>,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send,
H: Header<Hash=B::Hash>,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error>,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
P: Pair + Send + Sync,
P::Public: Member + Encode + Decode + Hash,
P::Signature: Member + Encode + Decode + Hash + Debug,
SO: SyncOracle + Send + Clone,
Error: ::std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
{
type BlockImport = I;
type SyncOracle = SO;
@@ -228,7 +229,11 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
self.block_import.clone()
}
fn epoch_data(&self, header: &B::Header, _slot_number: u64) -> Result<Self::EpochData, sp_consensus::Error> {
fn epoch_data(
&self,
header: &B::Header,
_slot_number: u64,
) -> Result<Self::EpochData, sp_consensus::Error> {
authorities(self.client.as_ref(), &BlockId::Hash(header.hash()))
}
@@ -250,7 +255,11 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
})
}
fn pre_digest_data(&self, slot_number: u64, _claim: &Self::Claim) -> Vec<sp_runtime::DigestItem<B::Hash>> {
fn pre_digest_data(
&self,
slot_number: u64,
_claim: &Self::Claim,
) -> Vec<sp_runtime::DigestItem<B::Hash>> {
vec![
<DigestItemFor<B> as CompatibleDigestItem<P>>::aura_pre_digest(slot_number),
]
@@ -260,9 +269,10 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<sp_api::TransactionFor<C, B>, B>,
Self::Claim,
) -> sp_consensus::BlockImportParams<B> + Send> {
Box::new(|header, header_hash, body, pair| {
) -> sp_consensus::BlockImportParams<B, sp_api::TransactionFor<C, B>> + Send> {
Box::new(|header, header_hash, body, storage_changes, pair| {
// sign the pre-sealed hash of the block and then
// add it to a digest item.
let signature = pair.sign(header_hash.as_ref());
@@ -274,6 +284,7 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
justification: None,
post_digests: vec![signature_digest_item],
body: Some(body),
storage_changes: Some(storage_changes),
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -324,20 +335,18 @@ impl<H, B, C, E, I, P, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for Au
}
}
impl<H, B: BlockT, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT<Header=H>,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B> + Sync + Send,
impl<B: BlockT, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Sync + Send,
C::Api: AuraApi<B, AuthorityId<P>>,
E: Environment<B, Error=Error> + Send + Sync,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
H: Header<Hash=B::Hash>,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error> + Send + Sync,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
P: Pair + Send + Sync,
P::Public: Member + Encode + Decode + Hash,
P::Signature: Member + Encode + Decode + Hash + Debug,
SO: SyncOracle + Send + Sync + Clone,
Error: ::std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
{
type OnSlot = Pin<Box<dyn Future<Output = Result<(), sp_consensus::Error>> + Send>>;
@@ -489,7 +498,7 @@ impl<C, P, T> AuraVerifier<C, P, T>
inherent_data: InherentData,
timestamp_now: u64,
) -> Result<(), Error<B>>
where C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
where C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
{
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
@@ -535,7 +544,12 @@ impl<C, P, T> AuraVerifier<C, P, T>
#[forbid(deprecated)]
impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
C: ProvideRuntimeApi + Send + Sync + sc_client_api::backend::AuxStore + ProvideCache<B> + BlockOf,
C: ProvideRuntimeApi<B> +
Send +
Sync +
sc_client_api::backend::AuxStore +
ProvideCache<B> +
BlockOf,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
DigestItemFor<B>: CompatibleDigestItem<P>,
P: Pair + Send + Sync + 'static,
@@ -549,7 +563,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
header: B::Header,
justification: Option<Justification>,
mut body: Option<Vec<B::Extrinsic>>,
) -> Result<(BlockImportParams<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
let mut inherent_data = self.inherent_data_providers
.create_inherent_data()
.map_err(|e| e.into_string())?;
@@ -623,6 +637,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
header: pre_header,
post_digests: vec![seal],
body,
storage_changes: None,
finalized: false,
justification,
auxiliary: Vec::new(),
@@ -647,7 +662,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
fn initialize_authorities_cache<A, B, C>(client: &C) -> Result<(), ConsensusError> where
A: Codec,
B: BlockT,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B>,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B>,
C::Api: AuraApi<B, A>,
{
// no cache => no initialization
@@ -681,7 +696,7 @@ fn initialize_authorities_cache<A, B, C>(client: &C) -> Result<(), ConsensusErro
fn authorities<A, B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<A>, ConsensusError> where
A: Codec,
B: BlockT,
C: ProvideRuntimeApi + BlockOf + ProvideCache<B>,
C: ProvideRuntimeApi<B> + BlockOf + ProvideCache<B>,
C::Api: AuraApi<B, A>,
{
client
@@ -695,7 +710,7 @@ fn authorities<A, B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<A>, Consensus
}
/// The Aura import queue type.
pub type AuraImportQueue<B> = BasicQueue<B>;
pub type AuraImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
/// Register the aura inherent data provider, if not registered already.
fn register_aura_inherent_data_provider(
@@ -744,14 +759,15 @@ impl<Block: BlockT, C, I: BlockImport<Block>, P> AuraBlockImport<Block, C, I, P>
}
impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I, P> where
I: BlockImport<Block> + Send + Sync,
I: BlockImport<Block, Transaction = sp_api::TransactionFor<C, Block>> + Send + Sync,
I::Error: Into<ConsensusError>,
C: HeaderBackend<Block>,
C: HeaderBackend<Block> + ProvideRuntimeApi<Block>,
P: Pair + Send + Sync + 'static,
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode,
P::Signature: Encode + Decode,
{
type Error = ConsensusError;
type Transaction = sp_api::TransactionFor<C, Block>;
fn check_block(
&mut self,
@@ -762,7 +778,7 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
fn import_block(
&mut self,
block: BlockImportParams<Block>,
block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
let hash = block.post_header().hash();
@@ -790,8 +806,7 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
);
}
self.inner.import_block(block, new_cache)
.map_err(Into::into)
self.inner.import_block(block, new_cache).map_err(Into::into)
}
}
@@ -804,11 +819,11 @@ pub fn import_queue<B, I, C, P, T>(
client: Arc<C>,
inherent_data_providers: InherentDataProviders,
transaction_pool: Option<Arc<T>>,
) -> Result<AuraImportQueue<B>, sp_consensus::Error> where
) -> Result<AuraImportQueue<B, sp_api::TransactionFor<C, B>>, sp_consensus::Error> where
B: BlockT,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
C: 'static + ProvideRuntimeApi + BlockOf + ProvideCache<B> + Send + Sync + AuxStore + HeaderBackend<B>,
I: BlockImport<B,Error=ConsensusError> + Send + Sync + 'static,
C: 'static + ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Send + Sync + AuxStore + HeaderBackend<B>,
I: BlockImport<B, Error=ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
DigestItemFor<B>: CompatibleDigestItem<P>,
P: Pair + Send + Sync + 'static,
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode,
@@ -835,7 +850,7 @@ pub fn import_queue<B, I, C, P, T>(
#[cfg(test)]
mod tests {
use super::*;
use sp_consensus::NoNetwork as DummyOracle;
use sp_consensus::{NoNetwork as DummyOracle, Proposal, RecordProof};
use sc_network_test::{Block as TestBlock, *};
use sp_runtime::traits::{Block as BlockT, DigestFor};
use sc_network::config::ProtocolConfig;
@@ -870,16 +885,26 @@ mod tests {
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = future::Ready<Result<TestBlock, Error>>;
type Transaction = sc_client_api::TransactionFor<
substrate_test_runtime_client::Backend,
TestBlock
>;
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
fn propose(
&mut self,
_: InherentData,
digests: DigestFor<TestBlock>,
_: Duration,
) -> Self::Create {
let r = self.1.new_block(digests).unwrap().bake().map_err(|e| e.into());
future::ready(r)
_: RecordProof,
) -> Self::Proposal {
let r = self.1.new_block(digests).unwrap().build().map_err(|e| e.into());
future::ready(r.map(|b| Proposal {
block: b.block,
proof: b.proof,
storage_changes: b.storage_changes,
}))
}
}
@@ -983,7 +1008,7 @@ mod tests {
&inherent_data_providers, slot_duration.get()
).expect("Registers aura inherent data provider");
let aura = start_aura::<_, _, _, _, _, AuthorityPair, _, _, _, _>(
let aura = start_aura::<_, _, _, _, _, AuthorityPair, _, _, _>(
slot_duration,
client.clone(),
select_chain,
@@ -27,7 +27,6 @@ use sp_runtime::traits::{Block as BlockT, NumberFor, One, Zero};
use codec::{Encode, Decode};
use sc_client_api::utils::is_descendent_of;
use sp_blockchain::{HeaderMetadata, HeaderBackend, Error as ClientError};
use sp_core::H256;
use std::ops::Add;
/// A builder for `is_descendent_of` functions.
@@ -57,17 +56,15 @@ pub(crate) fn descendent_query<H, Block>(client: &H) -> HeaderBackendDescendentB
/// `IsDescendentOfBuilder` for header backends.
pub(crate) struct HeaderBackendDescendentBuilder<H, Block>(H, std::marker::PhantomData<Block>);
// TODO: relying on Hash = H256 is awful.
// https://github.com/paritytech/substrate/issues/3624
impl<'a, H, Block> IsDescendentOfBuilder<H256>
impl<'a, H, Block> IsDescendentOfBuilder<Block::Hash>
for HeaderBackendDescendentBuilder<&'a H, Block> where
H: HeaderBackend<Block> + HeaderMetadata<Block, Error=ClientError>,
Block: BlockT<Hash = H256>,
Block: BlockT,
{
type Error = ClientError;
type IsDescendentOf = Box<dyn Fn(&H256, &H256) -> Result<bool, ClientError> + 'a>;
type IsDescendentOf = Box<dyn Fn(&Block::Hash, &Block::Hash) -> Result<bool, ClientError> + 'a>;
fn build_is_descendent_of(&self, current: Option<(H256, H256)>)
fn build_is_descendent_of(&self, current: Option<(Block::Hash, Block::Hash)>)
-> Self::IsDescendentOf
{
Box::new(is_descendent_of(self.0, current))
+89 -64
View File
@@ -69,14 +69,14 @@ use sp_consensus::{ImportResult, CanAuthorWith};
use sp_consensus::import_queue::{
BoxJustificationImport, BoxFinalityProofImport,
};
use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification};
use sp_runtime::traits::{
Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi,
Zero,
use sp_runtime::{
generic::{BlockId, OpaqueDigestItemId}, Justification,
traits::{Block as BlockT, Header, DigestItemFor, Zero},
};
use sp_api::ProvideRuntimeApi;
use sc_keystore::KeyStorePtr;
use parking_lot::Mutex;
use sp_core::{Blake2Hasher, H256, Pair};
use sp_core::Pair;
use sp_inherents::{InherentDataProviders, InherentData};
use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG};
use sp_consensus::{
@@ -96,10 +96,11 @@ use sc_client::Client;
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sc_consensus_slots::{CheckedHeader, check_equivocation};
use futures::prelude::*;
use log::{warn, debug, info, trace};
use sc_consensus_slots::{SlotWorker, SlotInfo, SlotCompatible};
use sc_consensus_slots::{
SlotWorker, SlotInfo, SlotCompatible, StorageChanges, CheckedHeader, check_equivocation,
};
use epoch_changes::descendent_query;
use sp_blockchain::{
Result as ClientResult, Error as ClientError,
@@ -207,7 +208,7 @@ impl Config {
/// Either fetch the slot duration from disk or compute it from the genesis
/// state.
pub fn get_or_compute<B: BlockT, C>(client: &C) -> ClientResult<Self> where
C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi<B, Error = sp_blockchain::Error>,
C: AuxStore + ProvideRuntimeApi<B>, C::Api: BabeApi<B, Error = sp_blockchain::Error>,
{
trace!(target: "babe", "Getting slot duration");
match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) {
@@ -291,16 +292,16 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, Error>(BabeParams {
impl futures01::Future<Item=(), Error=()>,
sp_consensus::Error,
> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + ProvideUncles<B> + BlockchainEvents<B>
+ HeaderBackend<B> + HeaderMetadata<B, Error=ClientError> + Send + Sync + 'static,
B: BlockT,
C: ProvideRuntimeApi<B> + ProvideCache<B> + ProvideUncles<B> + BlockchainEvents<B>
+ HeaderBackend<B> + HeaderMetadata<B, Error = ClientError> + Send + Sync + 'static,
C::Api: BabeApi<B>,
SC: SelectChain<B> + 'static,
E: Environment<B, Error=Error> + Send + Sync,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
I: BlockImport<B,Error=ConsensusError> + Send + Sync + 'static,
Error: std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
E: Environment<B, Error = Error> + Send + Sync,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Error = ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send
+ Sync + 'static,
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
SO: SyncOracle + Send + Sync + Clone,
CAW: CanAuthorWith<B> + Send,
{
@@ -349,15 +350,17 @@ struct BabeWorker<B: BlockT, C, E, I, SO> {
}
impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWorker<B, C, E, I, SO> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + HeaderBackend<B> + HeaderMetadata<B, Error=ClientError>,
B: BlockT,
C: ProvideRuntimeApi<B> +
ProvideCache<B> +
HeaderBackend<B> +
HeaderMetadata<B, Error = ClientError>,
C::Api: BabeApi<B>,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error>,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
SO: SyncOracle + Send + Clone,
Error: std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<ConsensusError> + From<I::Error> + 'static,
{
type EpochData = Epoch;
type Claim = (BabePreDigest, AuthorityPair);
@@ -373,7 +376,11 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
self.block_import.clone()
}
fn epoch_data(&self, parent: &B::Header, slot_number: u64) -> Result<Self::EpochData, sp_consensus::Error> {
fn epoch_data(
&self,
parent: &B::Header,
slot_number: u64,
) -> Result<Self::EpochData, ConsensusError> {
self.epoch_changes.lock().epoch_for_child_of(
descendent_query(&*self.client),
&parent.hash(),
@@ -411,7 +418,11 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
s
}
fn pre_digest_data(&self, _slot_number: u64, claim: &Self::Claim) -> Vec<sp_runtime::DigestItem<B::Hash>> {
fn pre_digest_data(
&self,
_slot_number: u64,
claim: &Self::Claim,
) -> Vec<sp_runtime::DigestItem<B::Hash>> {
vec![
<DigestItemFor<B> as CompatibleDigestItem>::babe_pre_digest(claim.0.clone()),
]
@@ -421,20 +432,22 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
StorageChanges<I::Transaction, B>,
Self::Claim,
) -> sp_consensus::BlockImportParams<B> + Send> {
Box::new(|header, header_hash, body, (_, pair)| {
) -> sp_consensus::BlockImportParams<B, I::Transaction> + Send> {
Box::new(|header, header_hash, body, storage_changes, (_, pair)| {
// sign the pre-sealed hash of the block and then
// add it to a digest item.
let signature = pair.sign(header_hash.as_ref());
let signature_digest_item = <DigestItemFor<B> as CompatibleDigestItem>::babe_seal(signature);
let digest_item = <DigestItemFor<B> as CompatibleDigestItem>::babe_seal(signature);
BlockImportParams {
origin: BlockOrigin::Own,
header,
justification: None,
post_digests: vec![signature_digest_item],
post_digests: vec![digest_item],
body: Some(body),
storage_changes: Some(storage_changes),
finalized: false,
auxiliary: Vec::new(), // block-weight is written in block import.
// TODO: block-import handles fork choice and this shouldn't even have the
@@ -500,15 +513,17 @@ impl<B, C, E, I, Error, SO> sc_consensus_slots::SimpleSlotWorker<B> for BabeWork
}
impl<B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<B, C, E, I, SO> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + HeaderBackend<B> + HeaderMetadata<B, Error=ClientError> + Send + Sync,
B: BlockT,
C: ProvideRuntimeApi<B> +
ProvideCache<B> +
HeaderBackend<B> +
HeaderMetadata<B, Error = ClientError> + Send + Sync,
C::Api: BabeApi<B>,
E: Environment<B, Error=Error> + Send + Sync,
E::Proposer: Proposer<B, Error=Error>,
<E::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
I: BlockImport<B> + Send + Sync + 'static,
E: Environment<B, Error = Error> + Send + Sync,
E::Proposer: Proposer<B, Error = Error, Transaction = sp_api::TransactionFor<C, B>>,
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
SO: SyncOracle + Send + Sync + Clone,
Error: std::error::Error + Send + From<::sp_consensus::Error> + From<I::Error> + 'static,
Error: std::error::Error + Send + From<sp_consensus::Error> + From<I::Error> + 'static,
{
type OnSlot = Pin<Box<dyn Future<Output = Result<(), sp_consensus::Error>> + Send>>;
@@ -603,7 +618,9 @@ impl<B, E, Block: BlockT, RA, PRA> BabeVerifier<B, E, Block, RA, PRA> {
block_id: BlockId<Block>,
inherent_data: InherentData,
) -> Result<(), Error<Block>>
where PRA: ProvideRuntimeApi, PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
where
PRA: ProvideRuntimeApi<Block>,
PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
{
let inherent_res = self.api.runtime_api().check_inherents(
&block_id,
@@ -667,11 +684,11 @@ fn median_algorithm(
}
impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA> where
Block: BlockT<Hash=H256>,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
Block: BlockT,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
RA: Send + Sync,
PRA: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache<Block>,
PRA: ProvideRuntimeApi<Block> + Send + Sync + AuxStore + ProvideCache<Block>,
PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
+ BabeApi<Block, Error = sp_blockchain::Error>,
{
@@ -681,7 +698,7 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
header: Block::Header,
justification: Option<Justification>,
mut body: Option<Vec<Block::Extrinsic>>,
) -> Result<(BlockImportParams<Block>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<Block, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
trace!(
target: "babe",
"Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}",
@@ -785,6 +802,7 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
header: pre_header,
post_digests: vec![verified_info.seal],
body,
storage_changes: None,
finalized: false,
justification,
auxiliary: Vec::new(),
@@ -810,7 +828,7 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
}
/// The BABE import queue type.
pub type BabeImportQueue<B> = BasicQueue<B>;
pub type BabeImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
/// Register the babe inherent data provider, if not registered already.
fn register_babe_inherent_data_provider(
@@ -875,20 +893,22 @@ impl<B, E, Block: BlockT, I, RA, PRA> BabeBlockImport<B, E, Block, I, RA, PRA> {
}
impl<B, E, Block, I, RA, PRA> BlockImport<Block> for BabeBlockImport<B, E, Block, I, RA, PRA> where
Block: BlockT<Hash=H256>,
I: BlockImport<Block> + Send + Sync,
Block: BlockT,
I: BlockImport<Block, Transaction = sp_api::TransactionFor<PRA, Block>> + Send + Sync,
I::Error: Into<ConsensusError>,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
B: Backend<Block> + 'static,
E: CallExecutor<Block> + 'static + Clone + Send + Sync,
Client<B, E, Block, RA>: AuxStore,
RA: Send + Sync,
PRA: ProvideRuntimeApi + ProvideCache<Block>,
PRA::Api: BabeApi<Block>,
PRA: ProvideRuntimeApi<Block> + ProvideCache<Block>,
PRA::Api: BabeApi<Block> + ApiExt<Block, StateBackend = B::State>,
{
type Error = ConsensusError;
type Transaction = sp_api::TransactionFor<PRA, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block>,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
let hash = block.post_header().hash();
@@ -1099,9 +1119,9 @@ fn prune_finalized<B, E, Block, RA>(
client: &Client<B, E, Block, RA>,
epoch_changes: &mut EpochChangesFor<Block>,
) -> Result<(), ConsensusError> where
Block: BlockT<Hash=H256>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block, Blake2Hasher>,
Block: BlockT,
E: CallExecutor<Block> + Send + Sync,
B: Backend<Block>,
RA: Send + Sync,
{
let info = client.chain_info();
@@ -1133,15 +1153,16 @@ fn prune_finalized<B, E, Block, RA>(
///
/// Also returns a link object used to correctly instantiate the import queue
/// and background worker.
pub fn block_import<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
pub fn block_import<B, E, Block: BlockT, I, RA, PRA>(
config: Config,
wrapped_block_import: I,
client: Arc<Client<B, E, Block, RA>>,
api: Arc<PRA>,
) -> ClientResult<(BabeBlockImport<B, E, Block, I, RA, PRA>, BabeLink<Block>)> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
B: Backend<Block>,
E: CallExecutor<Block> + Send + Sync,
RA: Send + Sync,
Client<B, E, Block, RA>: AuxStore,
{
let epoch_changes = aux_schema::load_epoch_changes(&*client)?;
let link = BabeLink {
@@ -1178,7 +1199,7 @@ pub fn block_import<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
///
/// The block import object provided must be the `BabeBlockImport` or a wrapper
/// of it, otherwise crucial import logic will be omitted.
pub fn import_queue<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
pub fn import_queue<B, E, Block: BlockT, I, RA, PRA>(
babe_link: BabeLink<Block>,
block_import: I,
justification_import: Option<BoxJustificationImport<Block>>,
@@ -1186,12 +1207,13 @@ pub fn import_queue<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
client: Arc<Client<B, E, Block, RA>>,
api: Arc<PRA>,
inherent_data_providers: InherentDataProviders,
) -> ClientResult<BabeImportQueue<Block>> where
B: Backend<Block, Blake2Hasher> + 'static,
I: BlockImport<Block,Error=ConsensusError> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync + 'static,
) -> ClientResult<BabeImportQueue<Block, sp_api::TransactionFor<PRA, Block>>> where
B: Backend<Block> + 'static,
I: BlockImport<Block, Error = ConsensusError, Transaction = sp_api::TransactionFor<PRA, Block>>
+ Send + Sync + 'static,
E: CallExecutor<Block> + Clone + Send + Sync + 'static,
RA: Send + Sync + 'static,
PRA: ProvideRuntimeApi + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
PRA: ProvideRuntimeApi<Block> + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
PRA::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block, Error = sp_blockchain::Error>,
{
register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?;
@@ -1227,8 +1249,11 @@ pub mod test_helpers {
keystore: &KeyStorePtr,
link: &BabeLink<B>,
) -> Option<BabePreDigest> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + ProvideCache<B> + HeaderBackend<B> + HeaderMetadata<B, Error=ClientError>,
B: BlockT,
C: ProvideRuntimeApi<B> +
ProvideCache<B> +
HeaderBackend<B> +
HeaderMetadata<B, Error = ClientError>,
C::Api: BabeApi<B>,
{
let epoch = link.epoch_changes.lock().epoch_for_child_of(
+40 -23
View File
@@ -24,16 +24,16 @@ use authorship::claim_slot;
use sp_consensus_babe::{AuthorityPair, SlotNumber};
use sc_block_builder::BlockBuilder;
use sp_consensus::NoNetwork as DummyOracle;
use sp_consensus::import_queue::{
BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport,
use sp_consensus::{
NoNetwork as DummyOracle, Proposal, RecordProof,
import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport},
};
use sc_network_test::*;
use sc_network_test::{Block as TestBlock, PeersClient};
use sc_network::config::{BoxFinalityProofRequestBuilder, ProtocolConfig};
use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}};
use tokio::runtime::current_thread;
use sc_client_api::BlockchainEvents;
use sc_client_api::{BlockchainEvents, backend::TransactionFor};
use log::debug;
use std::{time::Duration, cell::RefCell};
@@ -94,16 +94,25 @@ impl Environment<TestBlock> for DummyFactory {
impl DummyProposer {
fn propose_with(&mut self, pre_digests: DigestFor<TestBlock>)
-> future::Ready<Result<TestBlock, Error>>
-> future::Ready<
Result<
Proposal<
TestBlock,
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>
>,
Error
>
>
{
use codec::Encode;
let block_builder = self.factory.client.new_block_at(
&BlockId::Hash(self.parent_hash),
pre_digests,
false,
).unwrap();
let mut block = match block_builder.bake().map_err(|e| e.into()) {
Ok(b) => b,
let mut block = match block_builder.build().map_err(|e| e.into()) {
Ok(b) => b.block,
Err(e) => return future::ready(Err(e)),
};
@@ -142,20 +151,22 @@ impl DummyProposer {
// mutate the block header according to the mutator.
(self.factory.mutator)(&mut block.header, Stage::PreSeal);
future::ready(Ok(block))
future::ready(Ok(Proposal { block, proof: None, storage_changes: Default::default() }))
}
}
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = future::Ready<Result<TestBlock, Error>>;
type Transaction = sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>;
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
fn propose(
&mut self,
_: InherentData,
pre_digests: DigestFor<TestBlock>,
_: Duration,
) -> Self::Create {
_: RecordProof,
) -> Self::Proposal {
self.propose_with(pre_digests)
}
}
@@ -169,10 +180,11 @@ struct PanickingBlockImport<B>(B);
impl<B: BlockImport<TestBlock>> BlockImport<TestBlock> for PanickingBlockImport<B> {
type Error = B::Error;
type Transaction = B::Transaction;
fn import_block(
&mut self,
block: BlockImportParams<TestBlock>,
block: BlockImportParams<TestBlock, Self::Transaction>,
new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
Ok(self.0.import_block(block, new_cache).expect("importing block failed"))
@@ -214,7 +226,7 @@ impl Verifier<TestBlock> for TestVerifier {
mut header: TestHeader,
justification: Option<Justification>,
body: Option<Vec<TestExtrinsic>>,
) -> Result<(BlockImportParams<TestBlock>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<TestBlock, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
// apply post-sealing mutations (i.e. stripping seal, if desired).
(self.mutator)(&mut header, Stage::PostSeal);
Ok(self.inner.verify(origin, header, justification, body).expect("verification failed!"))
@@ -224,7 +236,9 @@ impl Verifier<TestBlock> for TestVerifier {
pub struct PeerData {
link: BabeLink<TestBlock>,
inherent_data_providers: InherentDataProviders,
block_import: Mutex<Option<BoxBlockImport<TestBlock>>>,
block_import: Mutex<
Option<BoxBlockImport<TestBlock, TransactionFor<substrate_test_runtime_client::Backend, TestBlock>>>
>,
}
impl TestNetFactory for BabeTestNet {
@@ -240,9 +254,9 @@ impl TestNetFactory for BabeTestNet {
}
}
fn make_block_import(&self, client: PeersClient)
fn make_block_import<Transaction>(&self, client: PeersClient)
-> (
BoxBlockImport<Block>,
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
@@ -262,9 +276,11 @@ impl TestNetFactory for BabeTestNet {
let block_import = PanickingBlockImport(block_import);
let data_block_import = Mutex::new(Some(Box::new(block_import.clone()) as BoxBlockImport<_>));
let data_block_import = Mutex::new(
Some(Box::new(block_import.clone()) as BoxBlockImport<_, _>)
);
(
Box::new(block_import),
BlockImportAdapter::new_full(block_import),
None,
None,
None,
@@ -322,8 +338,8 @@ impl TestNetFactory for BabeTestNet {
fn rejects_empty_block() {
env_logger::try_init().unwrap();
let mut net = BabeTestNet::new(3);
let block_builder = |builder: BlockBuilder<_, _>| {
builder.bake().unwrap()
let block_builder = |builder: BlockBuilder<_, _, _>| {
builder.build().unwrap().block
};
net.mut_peers(|peer| {
peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder);
@@ -525,12 +541,12 @@ fn can_author_block() {
}
// Propose and import a new BABE block on top of the given parent.
fn propose_and_import_block(
fn propose_and_import_block<Transaction>(
parent: &TestHeader,
slot_number: Option<SlotNumber>,
proposer_factory: &mut DummyFactory,
block_import: &mut BoxBlockImport<TestBlock>,
) -> H256 {
block_import: &mut BoxBlockImport<TestBlock, Transaction>,
) -> sp_core::H256 {
let mut proposer = proposer_factory.init(parent).unwrap();
let slot_number = slot_number.unwrap_or_else(|| {
@@ -549,7 +565,7 @@ fn propose_and_import_block(
],
};
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap();
let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap().block;
let seal = {
// sign the pre-sealed hash of the block and then
@@ -574,6 +590,7 @@ fn propose_and_import_block(
justification: None,
post_digests: vec![seal],
body: Some(block.extrinsics),
storage_changes: None,
finalized: false,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
@@ -10,6 +10,7 @@ codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive
sp-core = { version = "2.0.0", path = "../../../primitives/core" }
sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
sc-client-api = { version = "2.0.0", path = "../../api" }
sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" }
sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" }
+45 -36
View File
@@ -37,19 +37,19 @@ use sp_blockchain::{HeaderBackend, ProvideCache, well_known_cache_keys::Id as Ca
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sp_runtime::{Justification, RuntimeString};
use sp_runtime::generic::{BlockId, Digest, DigestItem};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi};
use sp_timestamp::{TimestampInherentData, InherentError as TIError};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use sp_api::ProvideRuntimeApi;
use sp_consensus_pow::{Seal, TotalDifficulty, POW_ENGINE_ID};
use sp_core::H256;
use sp_inherents::{InherentDataProviders, InherentData};
use sp_consensus::{
BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer,
SelectChain, Error as ConsensusError, CanAuthorWith,
SelectChain, Error as ConsensusError, CanAuthorWith, RecordProof,
};
use sp_consensus::import_queue::{BoxBlockImport, BasicQueue, Verifier};
use codec::{Encode, Decode};
use sc_client_api;
use log::*;
use sp_timestamp::{InherentError as TIError, TimestampInherentData};
#[derive(derive_more::Display, Debug)]
pub enum Error<B: BlockT> {
@@ -93,9 +93,8 @@ impl<B: BlockT> std::convert::From<Error<B>> for String {
pub const POW_AUX_PREFIX: [u8; 4] = *b"PoW:";
/// Get the auxiliary storage key used by engine to store total difficulty.
fn aux_key(hash: &H256) -> Vec<u8> {
POW_AUX_PREFIX.iter().chain(&hash[..])
.cloned().collect::<Vec<_>>()
fn aux_key<T: AsRef<[u8]>>(hash: &T) -> Vec<u8> {
POW_AUX_PREFIX.iter().chain(hash.as_ref()).copied().collect()
}
/// Auxiliary storage data for PoW.
@@ -111,12 +110,11 @@ impl<Difficulty> PowAux<Difficulty> where
Difficulty: Decode + Default,
{
/// Read the auxiliary from client.
pub fn read<C: AuxStore, B: BlockT>(client: &C, hash: &H256) -> Result<Self, Error<B>> {
let key = aux_key(hash);
pub fn read<C: AuxStore, B: BlockT>(client: &C, hash: &B::Hash) -> Result<Self, Error<B>> {
let key = aux_key(&hash);
match client.get_aux(&key).map_err(Error::Client)? {
Some(bytes) => Self::decode(&mut &bytes[..])
.map_err(Error::Codec),
Some(bytes) => Self::decode(&mut &bytes[..]).map_err(Error::Codec),
None => Ok(Self::default()),
}
}
@@ -133,7 +131,7 @@ pub trait PowAlgorithm<B: BlockT> {
fn verify(
&self,
parent: &BlockId<B>,
pre_hash: &H256,
pre_hash: &B::Hash,
seal: &Seal,
difficulty: Self::Difficulty,
) -> Result<bool, Error<B>>;
@@ -141,14 +139,14 @@ pub trait PowAlgorithm<B: BlockT> {
fn mine(
&self,
parent: &BlockId<B>,
pre_hash: &H256,
pre_hash: &B::Hash,
difficulty: Self::Difficulty,
round: u32,
) -> Result<Option<Seal>, Error<B>>;
}
/// A verifier for PoW blocks.
pub struct PowVerifier<B: BlockT<Hash=H256>, C, S, Algorithm> {
pub struct PowVerifier<B: BlockT, C, S, Algorithm> {
client: Arc<C>,
algorithm: Algorithm,
inherent_data_providers: sp_inherents::InherentDataProviders,
@@ -156,7 +154,7 @@ pub struct PowVerifier<B: BlockT<Hash=H256>, C, S, Algorithm> {
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
}
impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
impl<B: BlockT, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
pub fn new(
client: Arc<C>,
algorithm: Algorithm,
@@ -171,7 +169,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
&self,
mut header: B::Header,
parent_block_id: BlockId<B>,
) -> Result<(B::Header, Algorithm::Difficulty, DigestItem<H256>), Error<B>> where
) -> Result<(B::Header, Algorithm::Difficulty, DigestItem<B::Hash>), Error<B>> where
Algorithm: PowAlgorithm<B>,
{
let hash = header.hash();
@@ -209,7 +207,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
inherent_data: InherentData,
timestamp_now: u64,
) -> Result<(), Error<B>> where
C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
{
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
@@ -245,8 +243,8 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
}
}
impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S, Algorithm> where
C: ProvideRuntimeApi + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
impl<B: BlockT, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S, Algorithm> where
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
S: SelectChain<B>,
Algorithm: PowAlgorithm<B> + Send + Sync,
@@ -257,7 +255,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S,
header: B::Header,
justification: Option<Justification>,
mut body: Option<Vec<B::Extrinsic>>,
) -> Result<(BlockImportParams<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
) -> Result<(BlockImportParams<B, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
let inherent_data = self.inherent_data_providers
.create_inherent_data().map_err(|e| e.into_string())?;
let timestamp_now = inherent_data.timestamp_inherent_data().map_err(|e| e.into_string())?;
@@ -290,19 +288,22 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S,
timestamp_now
)?;
let (_, inner_body) = block.deconstruct();
body = Some(inner_body);
body = Some(block.deconstruct().1);
}
let key = aux_key(&hash);
let import_block = BlockImportParams {
origin,
header: checked_header,
post_digests: vec![seal],
body,
storage_changes: None,
finalized: false,
justification,
auxiliary: vec![(key, Some(aux.encode()))],
fork_choice: ForkChoiceStrategy::Custom(aux.total_difficulty > best_aux.total_difficulty),
fork_choice: ForkChoiceStrategy::Custom(
aux.total_difficulty > best_aux.total_difficulty
),
allow_missing_state: false,
import_existing: false,
};
@@ -326,19 +327,22 @@ pub fn register_pow_inherent_data_provider(
}
/// The PoW import queue type.
pub type PowImportQueue<B> = BasicQueue<B>;
pub type PowImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
/// Import queue for PoW engine.
pub fn import_queue<B, C, S, Algorithm>(
block_import: BoxBlockImport<B>,
block_import: BoxBlockImport<B, sp_api::TransactionFor<C, B>>,
client: Arc<C>,
algorithm: Algorithm,
check_inherents_after: <<B as BlockT>::Header as HeaderT>::Number,
select_chain: Option<S>,
inherent_data_providers: InherentDataProviders,
) -> Result<PowImportQueue<B>, sp_consensus::Error> where
B: BlockT<Hash=H256>,
C: ProvideRuntimeApi + HeaderBackend<B> + BlockOf + ProvideCache<B> + AuxStore,
) -> Result<
PowImportQueue<B, sp_api::TransactionFor<C, B>>,
sp_consensus::Error
> where
B: BlockT,
C: ProvideRuntimeApi<B> + HeaderBackend<B> + BlockOf + ProvideCache<B> + AuxStore,
C: Send + Sync + AuxStore + 'static,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
Algorithm: PowAlgorithm<B> + Send + Sync + 'static,
@@ -372,8 +376,8 @@ pub fn import_queue<B, C, S, Algorithm>(
/// information, or just be a graffiti. `round` is for number of rounds the
/// CPU miner runs each time. This parameter should be tweaked so that each
/// mining round is within sub-second time.
pub fn start_mine<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
mut block_import: BoxBlockImport<B>,
pub fn start_mine<B: BlockT, C, Algorithm, E, SO, S, CAW>(
mut block_import: BoxBlockImport<B, sp_api::TransactionFor<C, B>>,
client: Arc<C>,
algorithm: Algorithm,
mut env: E,
@@ -385,10 +389,11 @@ pub fn start_mine<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
inherent_data_providers: sp_inherents::InherentDataProviders,
can_author_with: CAW,
) where
C: HeaderBackend<B> + AuxStore + 'static,
C: HeaderBackend<B> + AuxStore + ProvideRuntimeApi<B> + 'static,
Algorithm: PowAlgorithm<B> + Send + Sync + 'static,
E: Environment<B> + Send + Sync + 'static,
E::Error: std::fmt::Debug,
E::Proposer: Proposer<B, Transaction = sp_api::TransactionFor<C, B>>,
SO: SyncOracle + Send + Sync + 'static,
S: SelectChain<B> + 'static,
CAW: CanAuthorWith<B> + Send + 'static,
@@ -423,8 +428,8 @@ pub fn start_mine<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
});
}
fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
block_import: &mut BoxBlockImport<B>,
fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
block_import: &mut BoxBlockImport<B, sp_api::TransactionFor<C, B>>,
client: &C,
algorithm: &Algorithm,
env: &mut E,
@@ -436,12 +441,14 @@ fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
inherent_data_providers: &sp_inherents::InherentDataProviders,
can_author_with: &CAW,
) -> Result<(), Error<B>> where
C: HeaderBackend<B> + AuxStore,
C: HeaderBackend<B> + AuxStore + ProvideRuntimeApi<B>,
Algorithm: PowAlgorithm<B>,
E: Environment<B>,
E::Proposer: Proposer<B, Transaction = sp_api::TransactionFor<C, B>>,
E::Error: std::fmt::Debug,
SO: SyncOracle,
S: SelectChain<B>,
sp_api::TransactionFor<C, B>: 'static,
CAW: CanAuthorWith<B>,
{
'outer: loop {
@@ -488,13 +495,14 @@ fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
if let Some(preruntime) = &preruntime {
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec()));
}
let block = futures::executor::block_on(proposer.propose(
let proposal = futures::executor::block_on(proposer.propose(
inherent_data,
inherent_digest,
build_time.clone(),
RecordProof::No,
)).map_err(|e| Error::BlockProposingError(format!("{:?}", e)))?;
let (header, body) = block.deconstruct();
let (header, body) = proposal.block.deconstruct();
let (difficulty, seal) = {
let difficulty = algorithm.difficulty(
&BlockId::Hash(best_hash),
@@ -546,6 +554,7 @@ fn mine_loop<B: BlockT<Hash=H256>, C, Algorithm, E, SO, S, CAW>(
justification: None,
post_digests: vec![DigestItem::Seal(POW_ENGINE_ID, seal)],
body: Some(body),
storage_changes: Some(proposal.storage_changes),
finalized: false,
auxiliary: vec![(key, Some(aux.encode()))],
fork_choice: ForkChoiceStrategy::Custom(true),
@@ -12,6 +12,8 @@ sc-client-api = { version = "2.0.0", path = "../../api" }
sp-core = { version = "2.0.0", path = "../../../primitives/core" }
sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" }
sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" }
sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" }
sp-api = { version = "2.0.0", path = "../../../primitives/api" }
sc-telemetry = { version = "2.0.0", path = "../../telemetry" }
sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" }
sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" }
+40 -19
View File
@@ -31,17 +31,23 @@ use slots::Slots;
pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND};
use codec::{Decode, Encode};
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData};
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData, RecordProof};
use futures::{prelude::*, future::{self, Either}};
use futures_timer::Delay;
use sp_inherents::{InherentData, InherentDataProviders};
use log::{debug, error, info, warn};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{ApiRef, Block as BlockT, Header, ProvideRuntimeApi};
use sp_runtime::traits::{Block as BlockT, Header, HasherFor, NumberFor};
use sp_api::{ProvideRuntimeApi, ApiRef};
use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc, time::{Instant, Duration}};
use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO};
use parking_lot::Mutex;
use sc_client_api;
/// The changes that need to applied to the storage to create the state for a block.
///
/// See [`state_machine::StorageChanges`] for more information.
pub type StorageChanges<Transaction, Block> =
sp_state_machine::StorageChanges<Transaction, HasherFor<Block>, NumberFor<Block>>;
/// A worker that should be invoked at every new slot.
pub trait SlotWorker<B: BlockT> {
@@ -58,7 +64,8 @@ pub trait SlotWorker<B: BlockT> {
/// out if block production takes too long.
pub trait SimpleSlotWorker<B: BlockT> {
/// A handle to a `BlockImport`.
type BlockImport: BlockImport<B> + Send + 'static;
type BlockImport: BlockImport<B, Transaction = <Self::Proposer as Proposer<B>>::Transaction>
+ Send + 'static;
/// A handle to a `SyncOracle`.
type SyncOracle: SyncOracle;
@@ -94,15 +101,26 @@ pub trait SimpleSlotWorker<B: BlockT> {
) -> Option<Self::Claim>;
/// Return the pre digest data to include in a block authored with the given claim.
fn pre_digest_data(&self, slot_number: u64, claim: &Self::Claim) -> Vec<sp_runtime::DigestItem<B::Hash>>;
fn pre_digest_data(
&self,
slot_number: u64,
claim: &Self::Claim,
) -> Vec<sp_runtime::DigestItem<B::Hash>>;
/// Returns a function which produces a `BlockImportParams`.
fn block_import_params(&self) -> Box<dyn Fn(
B::Header,
&B::Hash,
Vec<B::Extrinsic>,
Self::Claim,
) -> sp_consensus::BlockImportParams<B> + Send>;
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,
) -> sp_consensus::BlockImportParams<
B,
<Self::BlockImport as BlockImport<B>>::Transaction
>
+ Send
>;
/// Whether to force authoring if offline.
fn force_authoring(&self) -> bool;
@@ -136,7 +154,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo)
-> Pin<Box<dyn Future<Output = Result<(), sp_consensus::Error>> + Send>> where
Self: Send + Sync,
<Self::Proposer as Proposer<B>>::Create: Unpin + Send + 'static,
<Self::Proposer as Proposer<B>>::Proposal: Unpin + Send + 'static,
{
let (timestamp, slot_number, slot_duration) =
(slot_info.timestamp, slot_info.number, slot_info.duration);
@@ -222,6 +240,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
logs,
},
slot_remaining_duration,
RecordProof::No,
).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e)));
let delay: Box<dyn Future<Output=()> + Unpin + Send> = match proposing_remaining_duration {
Some(r) => Box::new(Delay::new(r)),
@@ -247,8 +266,8 @@ pub trait SimpleSlotWorker<B: BlockT> {
let block_import = self.block_import();
let logging_target = self.logging_target();
Box::pin(proposal_work.map_ok(move |(block, claim)| {
let (header, body) = block.deconstruct();
Box::pin(proposal_work.map_ok(move |(proposal, claim)| {
let (header, body) = proposal.block.deconstruct();
let header_num = *header.number();
let header_hash = header.hash();
let parent_hash = *header.parent_hash();
@@ -257,13 +276,15 @@ pub trait SimpleSlotWorker<B: BlockT> {
header,
&header_hash,
body,
proposal.storage_changes,
claim,
);
info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.",
header_num,
block_import_params.post_header().hash(),
header_hash,
info!(
"Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.",
header_num,
block_import_params.post_header().hash(),
header_hash,
);
telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block";
@@ -418,7 +439,7 @@ impl<T: Clone> SlotDuration<T> {
/// compile-time constant.
pub fn get_or_compute<B: BlockT, C, CB>(client: &C, cb: CB) -> sp_blockchain::Result<Self> where
C: sc_client_api::backend::AuxStore,
C: ProvideRuntimeApi,
C: ProvideRuntimeApi<B>,
CB: FnOnce(ApiRef<C::Api>, &BlockId<B>) -> sp_blockchain::Result<T>,
T: SlotData + Encode + Decode + Debug,
{