mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 14:47:55 +00:00
Aura consensus for parachains (#371)
* Update polkadot * Migrate all uses of MQC heads to merkle proofs * Mass rename `relay_parent_storage_root` * Restore parachain-system tests * Update polkadot and libp2p swarm for testing * Collapse match into an if let Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Start with something * Update Substrate & Polkadot * Start to make it compile * Make it compile * Begin with something * Yep * I'm a hacker * Bring back the builder * Make it work in some way * Compile * Parachains use their own "slot" * Adds cumulus-pallet-aura * Wrap AuRa import queue to disable equivocation checking by default * Pass slot duration * Check the seal when validating a block * Adds missing file * Try to make the seal working * Fix it * Some fixes * Bring in the latest features to cleanup the code * Update and make it compile * Improve the import * Start fixing * More work * Fix fix fix * Make everything compile * Small cleanups * Rename and more docs * Docs * Fixes fixes fixes * Update rococo-parachains/src/chain_spec.rs * Update client/consensus/aura/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update client/consensus/aura/src/lib.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update primitives/parachain-inherent/Cargo.toml Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update primitives/parachain-inherent/Cargo.toml * Update primitives/parachain-inherent/Cargo.toml * Update primitives/parachain-inherent/Cargo.toml Co-authored-by: Sergei Shulepov <sergei@parity.io> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus 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.
|
||||
|
||||
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Parachain specific wrapper for the AuRa import queue.
|
||||
|
||||
use codec::Codec;
|
||||
use sc_client_api::{backend::AuxStore, BlockOf};
|
||||
use sc_consensus_slots::InherentDataProviderExt;
|
||||
use sp_api::{ApiExt, ProvideRuntimeApi};
|
||||
use sp_block_builder::BlockBuilder as BlockBuilderApi;
|
||||
use sp_blockchain::{HeaderBackend, ProvideCache};
|
||||
use sp_consensus::{
|
||||
import_queue::DefaultImportQueue, BlockImport, CanAuthorWith, Error as ConsensusError,
|
||||
};
|
||||
use sp_consensus_aura::{digests::CompatibleDigestItem, AuraApi};
|
||||
use sp_core::crypto::Pair;
|
||||
use sp_inherents::CreateInherentDataProviders;
|
||||
use sp_runtime::traits::{Block as BlockT, DigestItemFor};
|
||||
use std::{fmt::Debug, hash::Hash, sync::Arc};
|
||||
use substrate_prometheus_endpoint::Registry;
|
||||
use sc_telemetry::TelemetryHandle;
|
||||
|
||||
/// Parameters of [`import_queue`].
|
||||
pub struct ImportQueueParams<'a, I, C, IDP, S, CAW> {
|
||||
/// The block import to use.
|
||||
pub block_import: I,
|
||||
/// The client to interact with the chain.
|
||||
pub client: Arc<C>,
|
||||
/// The inherent data providers, to create the inherent data.
|
||||
pub create_inherent_data_providers: IDP,
|
||||
/// The spawner to spawn background tasks.
|
||||
pub spawner: &'a S,
|
||||
/// The prometheus registry.
|
||||
pub registry: Option<&'a Registry>,
|
||||
/// Can we author with the current node?
|
||||
pub can_author_with: CAW,
|
||||
/// The telemetry handle.
|
||||
pub telemetry: Option<TelemetryHandle>,
|
||||
}
|
||||
|
||||
/// Start an import queue for the Aura consensus algorithm.
|
||||
pub fn import_queue<'a, P, Block, I, C, S, CAW, IDP>(
|
||||
ImportQueueParams {
|
||||
block_import,
|
||||
client,
|
||||
create_inherent_data_providers,
|
||||
spawner,
|
||||
registry,
|
||||
can_author_with,
|
||||
telemetry,
|
||||
}: ImportQueueParams<'a, I, C, IDP, S, CAW>,
|
||||
) -> Result<DefaultImportQueue<Block, C>, sp_consensus::Error>
|
||||
where
|
||||
Block: BlockT,
|
||||
C::Api: BlockBuilderApi<Block> + AuraApi<Block, P::Public> + ApiExt<Block>,
|
||||
C: 'static
|
||||
+ ProvideRuntimeApi<Block>
|
||||
+ BlockOf
|
||||
+ ProvideCache<Block>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ AuxStore
|
||||
+ HeaderBackend<Block>,
|
||||
I: BlockImport<Block, Error = ConsensusError, Transaction = sp_api::TransactionFor<C, Block>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
DigestItemFor<Block>: CompatibleDigestItem<P::Signature>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Codec,
|
||||
P::Signature: Codec,
|
||||
S: sp_core::traits::SpawnEssentialNamed,
|
||||
CAW: CanAuthorWith<Block> + Send + Sync + 'static,
|
||||
IDP: CreateInherentDataProviders<Block, ()> + Sync + Send + 'static,
|
||||
IDP::InherentDataProviders: InherentDataProviderExt + Send + Sync,
|
||||
{
|
||||
sc_consensus_aura::import_queue::<P, _, _, _, _, _, _>(sc_consensus_aura::ImportQueueParams {
|
||||
block_import: crate::ParachainBlockImport(block_import),
|
||||
justification_import: None,
|
||||
client,
|
||||
create_inherent_data_providers,
|
||||
spawner,
|
||||
registry,
|
||||
can_author_with,
|
||||
check_for_equivocation: sc_consensus_aura::CheckForEquivocation::No,
|
||||
telemetry,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus 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.
|
||||
|
||||
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! The AuRa consensus algoritm for parachains.
|
||||
//!
|
||||
//! This extends the Substrate provided AuRa consensus implementation to make it compatible for
|
||||
//! parachains. The main entry points for of this consensus algorithm are [`build_aura_consensus`]
|
||||
//! and [`import_queue`].
|
||||
//!
|
||||
//! For more information about AuRa, the Substrate crate should be checked.
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use cumulus_client_consensus_common::{ParachainCandidate, ParachainConsensus};
|
||||
use cumulus_primitives_core::{
|
||||
relay_chain::v1::{Block as PBlock, Hash as PHash, ParachainHost},
|
||||
PersistedValidationData,
|
||||
};
|
||||
use futures::lock::Mutex;
|
||||
use polkadot_service::ClientHandle;
|
||||
use sc_client_api::{backend::AuxStore, Backend, BlockOf};
|
||||
use sc_consensus_slots::{BackoffAuthoringBlocksStrategy, SlotInfo};
|
||||
use sc_telemetry::TelemetryHandle;
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_application_crypto::AppPublic;
|
||||
use sp_blockchain::{HeaderBackend, ProvideCache};
|
||||
use sp_consensus::{
|
||||
BlockImport, EnableProofRecording, Environment, ProofRecording, Proposer, SlotData, SyncOracle,
|
||||
};
|
||||
use sp_consensus_aura::AuraApi;
|
||||
use sp_core::crypto::Pair;
|
||||
use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider};
|
||||
use sp_keystore::SyncCryptoStorePtr;
|
||||
use sp_runtime::traits::{Block as BlockT, HashFor, Header as HeaderT, Member, NumberFor};
|
||||
use std::{convert::TryFrom, hash::Hash, marker::PhantomData, sync::Arc};
|
||||
|
||||
mod import_queue;
|
||||
|
||||
pub use import_queue::{import_queue, ImportQueueParams};
|
||||
pub use sc_consensus_aura::{
|
||||
slot_duration, AuraBlockImport, BuildAuraWorkerParams, SlotDuration, SlotProportion,
|
||||
};
|
||||
pub use sc_consensus_slots::InherentDataProviderExt;
|
||||
|
||||
const LOG_TARGET: &str = "aura::cumulus";
|
||||
|
||||
/// The implementation of the AURA consensus for parachains.
|
||||
pub struct AuraConsensus<B, RClient, RBackend, CIDP> {
|
||||
create_inherent_data_providers: Arc<CIDP>,
|
||||
relay_chain_client: Arc<RClient>,
|
||||
relay_chain_backend: Arc<RBackend>,
|
||||
aura_worker: Arc<
|
||||
Mutex<
|
||||
dyn sc_consensus_slots::SlotWorker<B, <EnableProofRecording as ProofRecording>::Proof>
|
||||
+ Send
|
||||
+ 'static,
|
||||
>,
|
||||
>,
|
||||
slot_duration: SlotDuration,
|
||||
}
|
||||
|
||||
impl<B, RClient, RBackend, CIDP> Clone for AuraConsensus<B, RClient, RBackend, CIDP> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
create_inherent_data_providers: self.create_inherent_data_providers.clone(),
|
||||
relay_chain_backend: self.relay_chain_backend.clone(),
|
||||
relay_chain_client: self.relay_chain_client.clone(),
|
||||
aura_worker: self.aura_worker.clone(),
|
||||
slot_duration: self.slot_duration,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, RClient, RBackend, CIDP> AuraConsensus<B, RClient, RBackend, CIDP>
|
||||
where
|
||||
B: BlockT,
|
||||
RClient: ProvideRuntimeApi<PBlock>,
|
||||
RClient::Api: ParachainHost<PBlock>,
|
||||
RBackend: Backend<PBlock>,
|
||||
CIDP: CreateInherentDataProviders<B, (PHash, PersistedValidationData)>,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt,
|
||||
{
|
||||
/// Create a new instance of AURA consensus.
|
||||
pub fn new<P, Client, BI, SO, PF, BS, Error>(
|
||||
para_client: Arc<Client>,
|
||||
block_import: BI,
|
||||
sync_oracle: SO,
|
||||
proposer_factory: PF,
|
||||
force_authoring: bool,
|
||||
backoff_authoring_blocks: Option<BS>,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
create_inherent_data_providers: CIDP,
|
||||
polkadot_client: Arc<RClient>,
|
||||
polkadot_backend: Arc<RBackend>,
|
||||
slot_duration: SlotDuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
block_proposal_slot_portion: SlotProportion,
|
||||
) -> Self
|
||||
where
|
||||
Client: ProvideRuntimeApi<B>
|
||||
+ BlockOf
|
||||
+ ProvideCache<B>
|
||||
+ AuxStore
|
||||
+ HeaderBackend<B>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
Client::Api: AuraApi<B, P::Public>,
|
||||
BI: BlockImport<B, Transaction = sp_api::TransactionFor<Client, B>> + Send + Sync + 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone + 'static,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + 'static,
|
||||
PF: Environment<B, Error = Error> + Send + Sync + 'static,
|
||||
PF::Proposer: Proposer<
|
||||
B,
|
||||
Error = Error,
|
||||
Transaction = sp_api::TransactionFor<Client, B>,
|
||||
ProofRecording = EnableProofRecording,
|
||||
Proof = <EnableProofRecording as ProofRecording>::Proof,
|
||||
>,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
P: Pair + Send + Sync,
|
||||
P::Public: AppPublic + Hash + Member + Encode + Decode,
|
||||
P::Signature: TryFrom<Vec<u8>> + Hash + Member + Encode + Decode,
|
||||
{
|
||||
let worker =
|
||||
sc_consensus_aura::build_aura_worker::<P, _, _, _, _, _, _, _>(BuildAuraWorkerParams {
|
||||
client: para_client,
|
||||
block_import: ParachainBlockImport(block_import),
|
||||
proposer_factory,
|
||||
sync_oracle,
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
keystore,
|
||||
telemetry,
|
||||
block_proposal_slot_portion,
|
||||
});
|
||||
|
||||
Self {
|
||||
create_inherent_data_providers: Arc::new(create_inherent_data_providers),
|
||||
relay_chain_backend: polkadot_backend,
|
||||
relay_chain_client: polkadot_client,
|
||||
aura_worker: Arc::new(Mutex::new(worker)),
|
||||
slot_duration,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the inherent data.
|
||||
///
|
||||
/// Returns the created inherent data and the inherent data providers used.
|
||||
async fn inherent_data(
|
||||
&self,
|
||||
parent: B::Hash,
|
||||
validation_data: &PersistedValidationData,
|
||||
relay_parent: PHash,
|
||||
) -> Option<(InherentData, CIDP::InherentDataProviders)> {
|
||||
let inherent_data_providers = self
|
||||
.create_inherent_data_providers
|
||||
.create_inherent_data_providers(parent, (relay_parent, validation_data.clone()))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Failed to create inherent data providers.",
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
inherent_data_providers
|
||||
.create_inherent_data()
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Failed to create inherent data.",
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
.map(|d| (d, inherent_data_providers))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<B, RClient, RBackend, CIDP> ParachainConsensus<B> for AuraConsensus<B, RClient, RBackend, CIDP>
|
||||
where
|
||||
B: BlockT,
|
||||
RClient: ProvideRuntimeApi<PBlock> + Send + Sync,
|
||||
RClient::Api: ParachainHost<PBlock>,
|
||||
RBackend: Backend<PBlock>,
|
||||
CIDP: CreateInherentDataProviders<B, (PHash, PersistedValidationData)> + Send + Sync,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
{
|
||||
async fn produce_candidate(
|
||||
&mut self,
|
||||
parent: &B::Header,
|
||||
relay_parent: PHash,
|
||||
validation_data: &PersistedValidationData,
|
||||
) -> Option<ParachainCandidate<B>> {
|
||||
let (inherent_data, inherent_data_providers) = self
|
||||
.inherent_data(parent.hash(), validation_data, relay_parent)
|
||||
.await?;
|
||||
|
||||
let info = SlotInfo::new(
|
||||
inherent_data_providers.slot(),
|
||||
inherent_data_providers.timestamp(),
|
||||
inherent_data,
|
||||
self.slot_duration.slot_duration(),
|
||||
parent.clone(),
|
||||
// Set the block limit to 50% of the maximum PoV size.
|
||||
//
|
||||
// TODO: If we got benchmarking that includes the proof size,
|
||||
// we should be able to use the maximum pov size.
|
||||
Some((validation_data.max_pov_size / 2) as usize),
|
||||
);
|
||||
|
||||
let res = self.aura_worker.lock().await.on_slot(info).await?;
|
||||
|
||||
Some(ParachainCandidate {
|
||||
block: res.block,
|
||||
proof: res.storage_proof,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Parachain specific block import.
|
||||
///
|
||||
/// This is used to set `block_import_params.fork_choice` to `false` as long as the block origin is
|
||||
/// not `NetworkInitialSync`. The best block for parachains is determined by the relay chain. Meaning
|
||||
/// we will update the best block, as it is included by the relay-chain.
|
||||
struct ParachainBlockImport<I>(I);
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<Block, I> BlockImport<Block> for ParachainBlockImport<I>
|
||||
where
|
||||
Block: BlockT,
|
||||
I: BlockImport<Block> + Send,
|
||||
{
|
||||
type Error = I::Error;
|
||||
type Transaction = I::Transaction;
|
||||
|
||||
async fn check_block(
|
||||
&mut self,
|
||||
block: sp_consensus::BlockCheckParams<Block>,
|
||||
) -> Result<sp_consensus::ImportResult, Self::Error> {
|
||||
self.0.check_block(block).await
|
||||
}
|
||||
|
||||
async fn import_block(
|
||||
&mut self,
|
||||
mut block_import_params: sp_consensus::BlockImportParams<Block, Self::Transaction>,
|
||||
cache: std::collections::HashMap<sp_consensus::import_queue::CacheKeyId, Vec<u8>>,
|
||||
) -> Result<sp_consensus::ImportResult, Self::Error> {
|
||||
// Best block is determined by the relay chain, or if we are doing the intial sync
|
||||
// we import all blocks as new best.
|
||||
block_import_params.fork_choice = Some(sp_consensus::ForkChoiceStrategy::Custom(
|
||||
block_import_params.origin == sp_consensus::BlockOrigin::NetworkInitialSync,
|
||||
));
|
||||
self.0.import_block(block_import_params, cache).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Paramaters of [`build_aura_consensus`].
|
||||
pub struct BuildAuraConsensusParams<PF, BI, RBackend, CIDP, Client, BS, SO> {
|
||||
pub proposer_factory: PF,
|
||||
pub create_inherent_data_providers: CIDP,
|
||||
pub block_import: BI,
|
||||
pub relay_chain_client: polkadot_service::Client,
|
||||
pub relay_chain_backend: Arc<RBackend>,
|
||||
pub para_client: Arc<Client>,
|
||||
pub backoff_authoring_blocks: Option<BS>,
|
||||
pub sync_oracle: SO,
|
||||
pub keystore: SyncCryptoStorePtr,
|
||||
pub force_authoring: bool,
|
||||
pub slot_duration: SlotDuration,
|
||||
pub telemetry: Option<TelemetryHandle>,
|
||||
pub block_proposal_slot_portion: SlotProportion,
|
||||
}
|
||||
|
||||
/// Build the [`AuraConsensus`].
|
||||
///
|
||||
/// Returns a boxed [`ParachainConsensus`].
|
||||
pub fn build_aura_consensus<P, Block, PF, BI, RBackend, CIDP, Client, SO, BS, Error>(
|
||||
BuildAuraConsensusParams {
|
||||
proposer_factory,
|
||||
create_inherent_data_providers,
|
||||
block_import,
|
||||
relay_chain_client,
|
||||
relay_chain_backend,
|
||||
para_client,
|
||||
backoff_authoring_blocks,
|
||||
sync_oracle,
|
||||
keystore,
|
||||
force_authoring,
|
||||
slot_duration,
|
||||
telemetry,
|
||||
block_proposal_slot_portion,
|
||||
}: BuildAuraConsensusParams<PF, BI, RBackend, CIDP, Client, BS, SO>,
|
||||
) -> Box<dyn ParachainConsensus<Block>>
|
||||
where
|
||||
Block: BlockT,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
sc_client_api::StateBackendFor<RBackend, PBlock>: sc_client_api::StateBackend<HashFor<PBlock>>,
|
||||
RBackend: Backend<PBlock> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, (PHash, PersistedValidationData)>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
Client: ProvideRuntimeApi<Block>
|
||||
+ BlockOf
|
||||
+ ProvideCache<Block>
|
||||
+ AuxStore
|
||||
+ HeaderBackend<Block>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
Client::Api: AuraApi<Block, P::Public>,
|
||||
BI: BlockImport<Block, Transaction = sp_api::TransactionFor<Client, Block>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone + 'static,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<Block>> + Send + 'static,
|
||||
PF: Environment<Block, Error = Error> + Send + Sync + 'static,
|
||||
PF::Proposer: Proposer<
|
||||
Block,
|
||||
Error = Error,
|
||||
Transaction = sp_api::TransactionFor<Client, Block>,
|
||||
ProofRecording = EnableProofRecording,
|
||||
Proof = <EnableProofRecording as ProofRecording>::Proof,
|
||||
>,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
P: Pair + Send + Sync,
|
||||
P::Public: AppPublic + Hash + Member + Encode + Decode,
|
||||
P::Signature: TryFrom<Vec<u8>> + Hash + Member + Encode + Decode,
|
||||
{
|
||||
AuraConsensusBuilder::<P, _, _, _, _, _, _, _, _, _>::new(
|
||||
proposer_factory,
|
||||
block_import,
|
||||
create_inherent_data_providers,
|
||||
relay_chain_client,
|
||||
relay_chain_backend,
|
||||
para_client,
|
||||
backoff_authoring_blocks,
|
||||
sync_oracle,
|
||||
force_authoring,
|
||||
keystore,
|
||||
slot_duration,
|
||||
telemetry,
|
||||
block_proposal_slot_portion,
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
/// Aura consensus builder.
|
||||
///
|
||||
/// Builds a [`AuraConsensus`] for a parachain. As this requires
|
||||
/// a concrete relay chain client instance, the builder takes a [`polkadot_service::Client`]
|
||||
/// that wraps this concrete instance. By using [`polkadot_service::ExecuteWithClient`]
|
||||
/// the builder gets access to this concrete instance.
|
||||
struct AuraConsensusBuilder<P, Block, PF, BI, RBackend, CIDP, Client, SO, BS, Error> {
|
||||
_phantom: PhantomData<(Block, Error, P)>,
|
||||
proposer_factory: PF,
|
||||
create_inherent_data_providers: CIDP,
|
||||
block_import: BI,
|
||||
relay_chain_backend: Arc<RBackend>,
|
||||
relay_chain_client: polkadot_service::Client,
|
||||
para_client: Arc<Client>,
|
||||
backoff_authoring_blocks: Option<BS>,
|
||||
sync_oracle: SO,
|
||||
force_authoring: bool,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
slot_duration: SlotDuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
block_proposal_slot_portion: SlotProportion,
|
||||
}
|
||||
|
||||
impl<Block, PF, BI, RBackend, CIDP, Client, SO, BS, P, Error>
|
||||
AuraConsensusBuilder<P, Block, PF, BI, RBackend, CIDP, Client, SO, BS, Error>
|
||||
where
|
||||
Block: BlockT,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
sc_client_api::StateBackendFor<RBackend, PBlock>: sc_client_api::StateBackend<HashFor<PBlock>>,
|
||||
RBackend: Backend<PBlock> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, (PHash, PersistedValidationData)>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
Client: ProvideRuntimeApi<Block>
|
||||
+ BlockOf
|
||||
+ ProvideCache<Block>
|
||||
+ AuxStore
|
||||
+ HeaderBackend<Block>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
Client::Api: AuraApi<Block, P::Public>,
|
||||
BI: BlockImport<Block, Transaction = sp_api::TransactionFor<Client, Block>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone + 'static,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<Block>> + Send + 'static,
|
||||
PF: Environment<Block, Error = Error> + Send + Sync + 'static,
|
||||
PF::Proposer: Proposer<
|
||||
Block,
|
||||
Error = Error,
|
||||
Transaction = sp_api::TransactionFor<Client, Block>,
|
||||
ProofRecording = EnableProofRecording,
|
||||
Proof = <EnableProofRecording as ProofRecording>::Proof,
|
||||
>,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
P: Pair + Send + Sync,
|
||||
P::Public: AppPublic + Hash + Member + Encode + Decode,
|
||||
P::Signature: TryFrom<Vec<u8>> + Hash + Member + Encode + Decode,
|
||||
{
|
||||
/// Create a new instance of the builder.
|
||||
fn new(
|
||||
proposer_factory: PF,
|
||||
block_import: BI,
|
||||
create_inherent_data_providers: CIDP,
|
||||
relay_chain_client: polkadot_service::Client,
|
||||
relay_chain_backend: Arc<RBackend>,
|
||||
para_client: Arc<Client>,
|
||||
backoff_authoring_blocks: Option<BS>,
|
||||
sync_oracle: SO,
|
||||
force_authoring: bool,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
slot_duration: SlotDuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
block_proposal_slot_portion: SlotProportion,
|
||||
) -> Self {
|
||||
Self {
|
||||
_phantom: PhantomData,
|
||||
proposer_factory,
|
||||
block_import,
|
||||
create_inherent_data_providers,
|
||||
relay_chain_backend,
|
||||
relay_chain_client,
|
||||
para_client,
|
||||
backoff_authoring_blocks,
|
||||
sync_oracle,
|
||||
force_authoring,
|
||||
keystore,
|
||||
slot_duration,
|
||||
telemetry,
|
||||
block_proposal_slot_portion,
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the relay chain consensus.
|
||||
fn build(self) -> Box<dyn ParachainConsensus<Block>> {
|
||||
self.relay_chain_client.clone().execute_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block, PF, BI, RBackend, CIDP, Client, SO, BS, P, Error> polkadot_service::ExecuteWithClient
|
||||
for AuraConsensusBuilder<P, Block, PF, BI, RBackend, CIDP, Client, SO, BS, Error>
|
||||
where
|
||||
Block: BlockT,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
sc_client_api::StateBackendFor<RBackend, PBlock>: sc_client_api::StateBackend<HashFor<PBlock>>,
|
||||
RBackend: Backend<PBlock> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, (PHash, PersistedValidationData)>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
|
||||
Client: ProvideRuntimeApi<Block>
|
||||
+ BlockOf
|
||||
+ ProvideCache<Block>
|
||||
+ AuxStore
|
||||
+ HeaderBackend<Block>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
Client::Api: AuraApi<Block, P::Public>,
|
||||
BI: BlockImport<Block, Transaction = sp_api::TransactionFor<Client, Block>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
SO: SyncOracle + Send + Sync + Clone + 'static,
|
||||
BS: BackoffAuthoringBlocksStrategy<NumberFor<Block>> + Send + 'static,
|
||||
PF: Environment<Block, Error = Error> + Send + Sync + 'static,
|
||||
PF::Proposer: Proposer<
|
||||
Block,
|
||||
Error = Error,
|
||||
Transaction = sp_api::TransactionFor<Client, Block>,
|
||||
ProofRecording = EnableProofRecording,
|
||||
Proof = <EnableProofRecording as ProofRecording>::Proof,
|
||||
>,
|
||||
Error: std::error::Error + Send + From<sp_consensus::Error> + 'static,
|
||||
P: Pair + Send + Sync,
|
||||
P::Public: AppPublic + Hash + Member + Encode + Decode,
|
||||
P::Signature: TryFrom<Vec<u8>> + Hash + Member + Encode + Decode,
|
||||
{
|
||||
type Output = Box<dyn ParachainConsensus<Block>>;
|
||||
|
||||
fn execute_with_client<PClient, Api, PBackend>(self, client: Arc<PClient>) -> Self::Output
|
||||
where
|
||||
<Api as sp_api::ApiExt<PBlock>>::StateBackend: sp_api::StateBackend<HashFor<PBlock>>,
|
||||
PBackend: Backend<PBlock>,
|
||||
PBackend::State: sp_api::StateBackend<sp_runtime::traits::BlakeTwo256>,
|
||||
Api: polkadot_service::RuntimeApiCollection<StateBackend = PBackend::State>,
|
||||
PClient: polkadot_service::AbstractClient<PBlock, PBackend, Api = Api> + 'static,
|
||||
{
|
||||
Box::new(AuraConsensus::new::<P, _, _, _, _, _, _>(
|
||||
self.para_client,
|
||||
self.block_import,
|
||||
self.sync_oracle,
|
||||
self.proposer_factory,
|
||||
self.force_authoring,
|
||||
self.backoff_authoring_blocks,
|
||||
self.keystore,
|
||||
self.create_inherent_data_providers,
|
||||
client.clone(),
|
||||
self.relay_chain_backend,
|
||||
self.slot_duration,
|
||||
self.telemetry,
|
||||
self.block_proposal_slot_portion,
|
||||
))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user