mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 04:27:57 +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:
Generated
+339
-206
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,12 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"client/cli",
|
||||
"client/consensus/aura",
|
||||
"client/consensus/common",
|
||||
"client/consensus/relay-chain",
|
||||
"client/network",
|
||||
"client/service",
|
||||
"pallets/aura-ext",
|
||||
"pallets/dmp-queue",
|
||||
"pallets/parachain-system",
|
||||
"pallets/xcm",
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
[package]
|
||||
name = "cumulus-client-consensus-aura"
|
||||
description = "AURA consensus algorithm for parachains"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# Substrate dependencies
|
||||
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
|
||||
# Cumulus dependencies
|
||||
cumulus-client-consensus-common = { path = "../common" }
|
||||
cumulus-primitives-core = { path = "../../../primitives/core" }
|
||||
|
||||
# Other deps
|
||||
futures = { version = "0.3.8", features = ["compat"] }
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] }
|
||||
tracing = "0.1.22"
|
||||
async-trait = "0.1.42"
|
||||
parking_lot = "0.9"
|
||||
@@ -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,
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "m
|
||||
# Cumulus dependencies
|
||||
cumulus-client-consensus-common = { path = "../common" }
|
||||
cumulus-primitives-core = { path = "../../../primitives/core" }
|
||||
cumulus-primitives-parachain-inherent = { path = "../../../primitives/parachain-inherent" }
|
||||
|
||||
# Other deps
|
||||
futures = { version = "0.3.8", features = ["compat"] }
|
||||
|
||||
@@ -64,7 +64,7 @@ where
|
||||
.create_inherent_data_providers
|
||||
.create_inherent_data_providers(*header.parent_hash(), ())
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let inherent_data = inherent_data_providers
|
||||
.create_inherent_data()
|
||||
|
||||
@@ -38,7 +38,6 @@ use cumulus_primitives_core::{
|
||||
relay_chain::v1::{Block as PBlock, Hash as PHash, ParachainHost},
|
||||
ParaId, PersistedValidationData,
|
||||
};
|
||||
use cumulus_primitives_parachain_inherent::ParachainInherentData;
|
||||
use parking_lot::Mutex;
|
||||
use polkadot_service::ClientHandle;
|
||||
use sc_client_api::Backend;
|
||||
@@ -89,7 +88,7 @@ where
|
||||
RClient: ProvideRuntimeApi<PBlock>,
|
||||
RClient::Api: ParachainHost<PBlock>,
|
||||
RBackend: Backend<PBlock>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
CIDP: CreateInherentDataProviders<B, (PHash, PersistedValidationData)>,
|
||||
{
|
||||
/// Create a new instance of relay-chain provided consensus.
|
||||
pub fn new(
|
||||
@@ -120,18 +119,18 @@ where
|
||||
) -> Option<InherentData> {
|
||||
let inherent_data_providers = self
|
||||
.create_inherent_data_providers
|
||||
.create_inherent_data_providers(parent, ())
|
||||
.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",
|
||||
"Failed to create inherent data providers.",
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let mut inherent_data = inherent_data_providers
|
||||
inherent_data_providers
|
||||
.create_inherent_data()
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
@@ -140,31 +139,7 @@ where
|
||||
"Failed to create inherent data.",
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let parachain_inherent_data = ParachainInherentData::create_at(
|
||||
relay_parent,
|
||||
&*self.relay_chain_client,
|
||||
&*self.relay_chain_backend,
|
||||
validation_data,
|
||||
self.para_id,
|
||||
)?;
|
||||
|
||||
inherent_data
|
||||
.put_data(
|
||||
cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER,
|
||||
¶chain_inherent_data,
|
||||
)
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Failed to put the system inherent into inherent data.",
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
Some(inherent_data)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +159,7 @@ where
|
||||
ProofRecording = EnableProofRecording,
|
||||
Proof = <EnableProofRecording as ProofRecording>::Proof,
|
||||
>,
|
||||
CIDP: CreateInherentDataProviders<B, ()>,
|
||||
CIDP: CreateInherentDataProviders<B, (PHash, PersistedValidationData)>,
|
||||
{
|
||||
async fn produce_candidate(
|
||||
&mut self,
|
||||
@@ -201,7 +176,9 @@ where
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
let inherent_data = self.inherent_data(parent.hash(), &validation_data, relay_parent).await?;
|
||||
let inherent_data = self
|
||||
.inherent_data(parent.hash(), &validation_data, relay_parent)
|
||||
.await?;
|
||||
|
||||
let Proposal {
|
||||
block,
|
||||
@@ -288,7 +265,7 @@ where
|
||||
RBackend: Backend<PBlock> + 'static,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
sc_client_api::StateBackendFor<RBackend, PBlock>: sc_client_api::StateBackend<HashFor<PBlock>>,
|
||||
CIDP: CreateInherentDataProviders<Block, ()> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, (PHash, PersistedValidationData)> + 'static,
|
||||
{
|
||||
RelayChainConsensusBuilder::new(
|
||||
para_id,
|
||||
@@ -331,7 +308,7 @@ where
|
||||
>,
|
||||
BI: BlockImport<Block> + Send + Sync + 'static,
|
||||
RBackend: Backend<PBlock> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, ()> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, (PHash, PersistedValidationData)> + 'static,
|
||||
{
|
||||
/// Create a new instance of the builder.
|
||||
fn new(
|
||||
@@ -374,7 +351,7 @@ where
|
||||
>,
|
||||
BI: BlockImport<Block> + Send + Sync + 'static,
|
||||
RBackend: Backend<PBlock> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, ()> + 'static,
|
||||
CIDP: CreateInherentDataProviders<Block, (PHash, PersistedValidationData)> + 'static,
|
||||
{
|
||||
type Output = Box<dyn ParachainConsensus<Block>>;
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
[package]
|
||||
name = "cumulus-pallet-aura-ext"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
description = "AURA consensus extension pallet for parachains"
|
||||
|
||||
[dependencies]
|
||||
# Substrate dependencies
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
|
||||
# Other Dependencies
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"]}
|
||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
cumulus-pallet-parachain-system = { path = "../parachain-system" }
|
||||
|
||||
[features]
|
||||
default = [ "std" ]
|
||||
std = [
|
||||
"codec/std",
|
||||
"serde",
|
||||
"frame-support/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
"frame-system/std",
|
||||
"frame-executive/std",
|
||||
"pallet-aura/std",
|
||||
"sp-consensus-aura/std",
|
||||
"sp-application-crypto/std",
|
||||
]
|
||||
@@ -0,0 +1,161 @@
|
||||
// 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/>.
|
||||
|
||||
//! Cumulus extension pallet for AuRa
|
||||
//!
|
||||
//! This pallets extends the Substrate AuRa pallet to make it compatible with parachains. It
|
||||
//! provides the [`Pallet`], the [`Config`] and the [`GenesisConfig`].
|
||||
//!
|
||||
//! It is also required that the parachain runtime uses the provided [`BlockExecutor`] to properly
|
||||
//! check the constructed block on the relay chain.
|
||||
//!
|
||||
//! ```
|
||||
//!# struct Runtime;
|
||||
//!# struct Executive;
|
||||
//! cumulus_pallet_parachain_system::register_validate_block!(
|
||||
//! Runtime,
|
||||
//! cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
|
||||
//! );
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use frame_support::traits::{ExecuteBlock, FindAuthor};
|
||||
use sp_application_crypto::RuntimeAppPublic;
|
||||
use sp_consensus_aura::digests::CompatibleDigestItem;
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
type Aura<T> = pallet_aura::Pallet<T>;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
/// The configuration trait.
|
||||
#[pallet::config]
|
||||
pub trait Config: pallet_aura::Config + frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn on_finalize(_: BlockNumberFor<T>) {
|
||||
// Update to the latest AuRa authorities.
|
||||
Authorities::<T>::put(Aura::<T>::authorities());
|
||||
}
|
||||
|
||||
fn on_initialize(_: BlockNumberFor<T>) -> Weight {
|
||||
// Fetch the authorities once to get them into the storage proof of the PoV.
|
||||
Authorities::<T>::get();
|
||||
|
||||
T::DbWeight::get().reads_writes(2, 1)
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {}
|
||||
|
||||
/// Serves as cache for the authorities.
|
||||
///
|
||||
/// The authorities in AuRa are overwritten in `on_initialize` when we switch to a new session,
|
||||
/// but we require the old authorities to verify the seal when validating a PoV. This will always
|
||||
/// be updated to the latest AuRa authorities in `on_finalize`.
|
||||
#[pallet::storage]
|
||||
pub(crate) type Authorities<T: Config> = StorageValue<_, Vec<T::AuthorityId>, ValueQuery>;
|
||||
|
||||
#[pallet::genesis_config]
|
||||
#[derive(Default)]
|
||||
pub struct GenesisConfig;
|
||||
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> GenesisBuild<T> for GenesisConfig {
|
||||
fn build(&self) {
|
||||
let authorities = Aura::<T>::authorities();
|
||||
|
||||
assert!(
|
||||
!authorities.is_empty(),
|
||||
"AuRa authorities empty, maybe wrong order in `construct_runtime!`?",
|
||||
);
|
||||
|
||||
Authorities::<T>::put(authorities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The block executor used when validating a PoV at the relay chain.
|
||||
///
|
||||
/// When executing the block it will verify the block seal to ensure that the correct author created
|
||||
/// the block.
|
||||
pub struct BlockExecutor<T, I>(sp_std::marker::PhantomData<(T, I)>);
|
||||
|
||||
impl<Block, T, I> ExecuteBlock<Block> for BlockExecutor<T, I>
|
||||
where
|
||||
Block: BlockT,
|
||||
T: Config,
|
||||
I: ExecuteBlock<Block>,
|
||||
{
|
||||
fn execute_block(block: Block) {
|
||||
let (mut header, extrinsics) = block.deconstruct();
|
||||
// We need to fetch the authorities before we execute the block, to get the authorities
|
||||
// before any potential update.
|
||||
let authorities = Authorities::<T>::get();
|
||||
|
||||
let mut seal = None;
|
||||
header.digest_mut().logs.retain(|s| {
|
||||
let s =
|
||||
CompatibleDigestItem::<<T::AuthorityId as RuntimeAppPublic>::Signature>::as_aura_seal(s);
|
||||
match (s, seal.is_some()) {
|
||||
(Some(_), true) => panic!("Found multiple AuRa seal digests"),
|
||||
(None, _) => true,
|
||||
(Some(s), false) => {
|
||||
seal = Some(s);
|
||||
false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let seal = seal.expect("Could not find an AuRa seal digest!");
|
||||
|
||||
let author = Aura::<T>::find_author(
|
||||
header
|
||||
.digest()
|
||||
.logs()
|
||||
.iter()
|
||||
.filter_map(|d| d.as_pre_runtime()),
|
||||
)
|
||||
.expect("Could not find AuRa author index!");
|
||||
|
||||
let pre_hash = header.hash();
|
||||
|
||||
if !authorities
|
||||
.get(author as usize)
|
||||
.unwrap_or_else(||
|
||||
panic!("Invalid AuRa author index {} for authorities: {:?}", author, authorities)
|
||||
)
|
||||
.verify(&pre_hash, &seal)
|
||||
{
|
||||
panic!("Invalid AuRa seal");
|
||||
}
|
||||
|
||||
I::execute_block(Block::new(header, extrinsics));
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ fn set_and_run_with_validation_params<R>(mut params: ValidationParams, f: impl F
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! register_validate_block {
|
||||
($runtime:ty, $block_executor:ty) => {
|
||||
($runtime:ty, $block_executor:ty $( , )? ) => {
|
||||
$crate::register_validate_block_impl!($runtime, $block_executor);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,16 +15,21 @@ sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-service = { git = "https://github.com/paritytech/polkadot", optional = true, branch = "master" }
|
||||
|
||||
# Cumulus dependencies
|
||||
cumulus-primitives-core = { path = "../core", default-features = false }
|
||||
|
||||
# Other dependencies
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] }
|
||||
tracing = { version = "0.1.22", optional = true }
|
||||
async-trait = { version = "0.1.42", optional = true }
|
||||
|
||||
[features]
|
||||
default = [ "std" ]
|
||||
std = [
|
||||
"async-trait",
|
||||
"codec/std",
|
||||
"cumulus-primitives-core/std",
|
||||
"sp-inherents/std",
|
||||
@@ -36,4 +41,5 @@ std = [
|
||||
"sp-runtime",
|
||||
"sc-client-api",
|
||||
"sp-api",
|
||||
"polkadot-service",
|
||||
]
|
||||
|
||||
@@ -26,6 +26,7 @@ use cumulus_primitives_core::{
|
||||
},
|
||||
InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData,
|
||||
};
|
||||
use polkadot_service::{Client, ClientHandle, ExecuteWithClient};
|
||||
use sc_client_api::Backend;
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_runtime::generic::BlockId;
|
||||
@@ -210,7 +211,8 @@ impl ParachainInherentData {
|
||||
PClient: ProvideRuntimeApi<PBlock>,
|
||||
PClient::Api: ParachainHost<PBlock>,
|
||||
{
|
||||
let relay_chain_state = collect_relay_storage_proof(polkadot_backend, para_id, relay_parent)?;
|
||||
let relay_chain_state =
|
||||
collect_relay_storage_proof(polkadot_backend, para_id, relay_parent)?;
|
||||
let downward_messages = retrieve_dmq_contents(polkadot_client, para_id, relay_parent)?;
|
||||
let horizontal_messages =
|
||||
retrieve_all_inbound_hrmp_channel_contents(polkadot_client, para_id, relay_parent)?;
|
||||
@@ -222,4 +224,68 @@ impl ParachainInherentData {
|
||||
relay_chain_state,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create the [`ParachainInherentData`] at the given `relay_parent`.
|
||||
///
|
||||
/// Returns `None` if the creation failed.
|
||||
pub fn create_at_with_client(
|
||||
relay_parent: PHash,
|
||||
polkadot_client: &Client,
|
||||
relay_chain_backend: &impl Backend<PBlock>,
|
||||
validation_data: &PersistedValidationData,
|
||||
para_id: ParaId,
|
||||
) -> Option<ParachainInherentData> {
|
||||
polkadot_client.execute_with(CreateAtWithClient {
|
||||
relay_chain_backend,
|
||||
validation_data,
|
||||
para_id,
|
||||
relay_parent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl sp_inherents::InherentDataProvider for ParachainInherentData {
|
||||
fn provide_inherent_data(
|
||||
&self,
|
||||
inherent_data: &mut sp_inherents::InherentData,
|
||||
) -> Result<(), sp_inherents::Error> {
|
||||
inherent_data.put_data(crate::INHERENT_IDENTIFIER, &self)
|
||||
}
|
||||
|
||||
async fn try_handle_error(
|
||||
&self,
|
||||
_: &sp_inherents::InherentIdentifier,
|
||||
_: &[u8],
|
||||
) -> Option<Result<(), sp_inherents::Error>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Special structure to run [`ParachainInherentData::create_at`] with a [`Client`].
|
||||
struct CreateAtWithClient<'a, B> {
|
||||
relay_parent: PHash,
|
||||
relay_chain_backend: &'a B,
|
||||
validation_data: &'a PersistedValidationData,
|
||||
para_id: ParaId,
|
||||
}
|
||||
|
||||
impl<'a, B> ExecuteWithClient for CreateAtWithClient<'a, B>
|
||||
where
|
||||
B: Backend<PBlock>,
|
||||
{
|
||||
type Output = Option<ParachainInherentData>;
|
||||
|
||||
fn execute_with_client<Client, Api, Backend>(
|
||||
self,
|
||||
client: std::sync::Arc<Client>,
|
||||
) -> Self::Output where Client: ProvideRuntimeApi<PBlock>, Client::Api: ParachainHost<PBlock> {
|
||||
ParachainInherentData::create_at(
|
||||
self.relay_parent,
|
||||
&*client,
|
||||
self.relay_chain_backend,
|
||||
self.validation_data,
|
||||
self.para_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,24 +46,29 @@ sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch
|
||||
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
# RPC related dependencies
|
||||
jsonrpc-core = "15.1.0"
|
||||
|
||||
# Cumulus dependencies
|
||||
cumulus-client-cli = { path = "../client/cli" }
|
||||
cumulus-client-consensus-aura = { path = "../client/consensus/aura" }
|
||||
cumulus-client-consensus-relay-chain = { path = "../client/consensus/relay-chain" }
|
||||
cumulus-client-consensus-common = { path = "../client/consensus/common" }
|
||||
cumulus-client-collator = { path = "../client/collator" }
|
||||
cumulus-client-service = { path = "../client/service" }
|
||||
cumulus-client-network = { path = "../client/network" }
|
||||
cumulus-primitives-core = { path = "../primitives/core" }
|
||||
cumulus-primitives-parachain-inherent = { path = "../primitives/parachain-inherent" }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
|
||||
@@ -23,6 +23,7 @@ sp-offchain = { git = "https://github.com/paritytech/substrate", default-feature
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
@@ -33,8 +34,10 @@ pallet-randomness-collective-flip = { git = "https://github.com/paritytech/subst
|
||||
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
|
||||
# Cumulus dependencies
|
||||
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
|
||||
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
|
||||
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
|
||||
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
|
||||
@@ -85,6 +88,7 @@ std = [
|
||||
"pallet-transaction-payment/std",
|
||||
"parachain-info/std",
|
||||
"rococo-parachain-primitives/std",
|
||||
"cumulus-pallet-aura-ext/std",
|
||||
"cumulus-pallet-dmp-queue/std",
|
||||
"cumulus-pallet-parachain-system/std",
|
||||
"cumulus-pallet-xcmp-queue/std",
|
||||
@@ -95,4 +99,6 @@ std = [
|
||||
"xcm/std",
|
||||
"xcm-builder/std",
|
||||
"xcm-executor/std",
|
||||
"pallet-aura/std",
|
||||
"sp-consensus-aura/std",
|
||||
]
|
||||
|
||||
@@ -52,6 +52,7 @@ pub use pallet_timestamp::Call as TimestampCall;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub use sp_runtime::BuildStorage;
|
||||
pub use sp_runtime::{Perbill, Permill};
|
||||
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
|
||||
|
||||
// XCM imports
|
||||
use polkadot_parachain::primitives::Sibling;
|
||||
@@ -71,7 +72,9 @@ use frame_support::traits::Contains;
|
||||
pub type SessionHandlers = ();
|
||||
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {}
|
||||
pub struct SessionKeys {
|
||||
pub aura: Aura,
|
||||
}
|
||||
}
|
||||
|
||||
/// This runtime version.
|
||||
@@ -85,7 +88,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
transaction_version: 1,
|
||||
};
|
||||
|
||||
pub const MILLISECS_PER_BLOCK: u64 = 6000;
|
||||
pub const MILLISECS_PER_BLOCK: u64 = 12000;
|
||||
|
||||
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
||||
|
||||
@@ -248,6 +251,8 @@ impl cumulus_pallet_parachain_system::Config for Runtime {
|
||||
|
||||
impl parachain_info::Config for Runtime {}
|
||||
|
||||
impl cumulus_pallet_aura_ext::Config for Runtime {}
|
||||
|
||||
parameter_types! {
|
||||
pub const RocLocation: MultiLocation = X1(Parent);
|
||||
pub const RococoNetwork: NetworkId = NetworkId::Polkadot;
|
||||
@@ -419,14 +424,8 @@ impl pallet_assets::Config for Runtime {
|
||||
type WeightInfo = pallet_assets::weights::SubstrateWeight<Runtime>;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_call() {
|
||||
let hash = hex_literal::hex!["0af9fef6f950ca3ac8ac4766200454b1039ffb7b2d0827fffd5e47bd43761437"].into();
|
||||
let call = Call::ParachainSystem(cumulus_pallet_parachain_system::Call::authorize_upgrade(hash));
|
||||
assert_eq!(
|
||||
hex::encode(codec::Encode::encode(&call)),
|
||||
"14030af9fef6f950ca3ac8ac4766200454b1039ffb7b2d0827fffd5e47bd43761437",
|
||||
);
|
||||
impl pallet_aura::Config for Runtime {
|
||||
type AuthorityId = AuraId;
|
||||
}
|
||||
|
||||
construct_runtime! {
|
||||
@@ -447,6 +446,9 @@ construct_runtime! {
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
|
||||
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>} = 31,
|
||||
|
||||
Aura: pallet_aura::{Pallet, Config<T>},
|
||||
AuraExt: cumulus_pallet_aura_ext::{Pallet, Config},
|
||||
|
||||
// XCM helpers.
|
||||
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
|
||||
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
|
||||
@@ -496,7 +498,7 @@ impl_runtime_apis! {
|
||||
}
|
||||
|
||||
fn execute_block(block: Block) {
|
||||
Executive::execute_block(block)
|
||||
Executive::execute_block(block);
|
||||
}
|
||||
|
||||
fn initialize_block(header: &<Block as BlockT>::Header) {
|
||||
@@ -556,6 +558,19 @@ impl_runtime_apis! {
|
||||
SessionKeys::generate(seed)
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> sp_consensus_aura::SlotDuration {
|
||||
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
|
||||
}
|
||||
|
||||
fn authorities() -> Vec<AuraId> {
|
||||
Aura::authorities()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cumulus_pallet_parachain_system::register_validate_block!(Runtime, Executive);
|
||||
cumulus_pallet_parachain_system::register_validate_block!(
|
||||
Runtime,
|
||||
cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
|
||||
);
|
||||
|
||||
@@ -209,8 +209,8 @@ impl Config for XcmConfig {
|
||||
type IsTeleporter = (); // balances not supported
|
||||
type LocationInverter = LocationInverter<Ancestry>;
|
||||
type Barrier = AllowUnpaidExecutionFrom<JustTheParent>;
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, Call>; // balances not supported
|
||||
type Trader = (); // balances not supported
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, Call>; // balances not supported
|
||||
type Trader = (); // balances not supported
|
||||
type ResponseHandler = (); // Don't handle responses for now.
|
||||
}
|
||||
|
||||
@@ -219,16 +219,6 @@ impl cumulus_pallet_xcm::Config for Runtime {
|
||||
type XcmExecutor = XcmExecutor<XcmConfig>;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_call() {
|
||||
let hash = hex_literal::hex!["0af9fef6f950ca3ac8ac4766200454b1039ffb7b2d0827fffd5e47bd43761437"].into();
|
||||
let call = Call::ParachainSystem(cumulus_pallet_parachain_system::Call::authorize_upgrade(hash));
|
||||
assert_eq!(
|
||||
hex::encode(codec::Encode::encode(&call)),
|
||||
"01030af9fef6f950ca3ac8ac4766200454b1039ffb7b2d0827fffd5e47bd43761437",
|
||||
);
|
||||
}
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use hex_literal::hex;
|
||||
use parachain_runtime::AuraId;
|
||||
use rococo_parachain_primitives::{AccountId, Signature};
|
||||
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
|
||||
use sc_service::ChainType;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_core::{sr25519, Pair, Public};
|
||||
use sp_core::{sr25519, Pair, Public, crypto::UncheckedInto};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
/// Specialized `ChainSpec` for the normal parachain runtime.
|
||||
@@ -71,6 +72,10 @@ pub fn get_chain_spec(id: ParaId) -> ChainSpec {
|
||||
move || {
|
||||
testnet_genesis(
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
vec![
|
||||
get_from_seed::<AuraId>("Alice"),
|
||||
get_from_seed::<AuraId>("Bob"),
|
||||
],
|
||||
vec![
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob"),
|
||||
@@ -124,6 +129,12 @@ pub fn staging_test_net(id: ParaId) -> ChainSpec {
|
||||
move || {
|
||||
testnet_genesis(
|
||||
hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into(),
|
||||
vec![
|
||||
// $secret//one
|
||||
hex!["aad9fa2249f87a210a0f93400b7f90e47b810c6d65caa0ca3f5af982904c2a33"].unchecked_into(),
|
||||
// $secret//two
|
||||
hex!["d47753f0cca9dd8da00c70e82ec4fc5501a69c49a5952a643d18802837c88212"].unchecked_into(),
|
||||
],
|
||||
vec![
|
||||
hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into(),
|
||||
],
|
||||
@@ -143,6 +154,7 @@ pub fn staging_test_net(id: ParaId) -> ChainSpec {
|
||||
|
||||
fn testnet_genesis(
|
||||
root_key: AccountId,
|
||||
initial_authorities: Vec<AuraId>,
|
||||
endowed_accounts: Vec<AccountId>,
|
||||
id: ParaId,
|
||||
) -> parachain_runtime::GenesisConfig {
|
||||
@@ -162,6 +174,10 @@ fn testnet_genesis(
|
||||
},
|
||||
pallet_sudo: parachain_runtime::SudoConfig { key: root_key },
|
||||
parachain_info: parachain_runtime::ParachainInfoConfig { parachain_id: id },
|
||||
pallet_aura: parachain_runtime::AuraConfig {
|
||||
authorities: initial_authorities,
|
||||
},
|
||||
cumulus_pallet_aura_ext: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ use crate::{
|
||||
cli::{Cli, RelayChainCli, Subcommand},
|
||||
};
|
||||
use codec::Encode;
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use cumulus_client_service::genesis::generate_genesis_block;
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use log::info;
|
||||
use parachain_runtime::Block;
|
||||
use polkadot_parachain::primitives::AccountIdConversion;
|
||||
@@ -28,9 +28,7 @@ use sc_cli::{
|
||||
ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
|
||||
NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli,
|
||||
};
|
||||
use sc_service::{
|
||||
config::{BasePath, PrometheusConfig},
|
||||
};
|
||||
use sc_service::config::{BasePath, PrometheusConfig};
|
||||
use sp_core::hexdisplay::HexDisplay;
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use std::{io::Write, net::SocketAddr};
|
||||
@@ -157,13 +155,19 @@ macro_rules! construct_async_run {
|
||||
let runner = $cli.create_runner($cmd)?;
|
||||
if use_shell_runtime(&runner.config().chain_spec) {
|
||||
runner.async_run(|$config| {
|
||||
let $components = new_partial::<shell_runtime::RuntimeApi, ShellRuntimeExecutor>(&$config)?;
|
||||
let $components = new_partial::<shell_runtime::RuntimeApi, ShellRuntimeExecutor, _>(
|
||||
&$config,
|
||||
crate::service::shell_build_import_queue,
|
||||
)?;
|
||||
let task_manager = $components.task_manager;
|
||||
{ $( $code )* }.map(|v| (v, task_manager))
|
||||
})
|
||||
} else {
|
||||
runner.async_run(|$config| {
|
||||
let $components = new_partial::<parachain_runtime::RuntimeApi, RuntimeExecutor>(&$config)?;
|
||||
let $components = new_partial::<parachain_runtime::RuntimeApi, RuntimeExecutor, _>(
|
||||
&$config,
|
||||
crate::service::build_import_queue,
|
||||
)?;
|
||||
let task_manager = $components.task_manager;
|
||||
{ $( $code )* }.map(|v| (v, task_manager))
|
||||
})
|
||||
@@ -180,18 +184,26 @@ pub fn run() -> Result<()> {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
|
||||
}
|
||||
Some(Subcommand::CheckBlock(cmd)) => construct_async_run! (|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, components.import_queue))
|
||||
}),
|
||||
Some(Subcommand::ExportBlocks(cmd)) => construct_async_run! (|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, config.database))
|
||||
}),
|
||||
Some(Subcommand::ExportState(cmd)) => construct_async_run! (|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, config.chain_spec))
|
||||
}),
|
||||
Some(Subcommand::ImportBlocks(cmd)) => construct_async_run! (|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, components.import_queue))
|
||||
}),
|
||||
Some(Subcommand::CheckBlock(cmd)) => {
|
||||
construct_async_run!(|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, components.import_queue))
|
||||
})
|
||||
}
|
||||
Some(Subcommand::ExportBlocks(cmd)) => {
|
||||
construct_async_run!(|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, config.database))
|
||||
})
|
||||
}
|
||||
Some(Subcommand::ExportState(cmd)) => {
|
||||
construct_async_run!(|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, config.chain_spec))
|
||||
})
|
||||
}
|
||||
Some(Subcommand::ImportBlocks(cmd)) => {
|
||||
construct_async_run!(|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, components.import_queue))
|
||||
})
|
||||
}
|
||||
Some(Subcommand::PurgeChain(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
|
||||
@@ -213,7 +225,7 @@ pub fn run() -> Result<()> {
|
||||
cmd.run(config, polkadot_config)
|
||||
})
|
||||
}
|
||||
Some(Subcommand::Revert(cmd)) => construct_async_run! (|components, cli, cmd, config| {
|
||||
Some(Subcommand::Revert(cmd)) => construct_async_run!(|components, cli, cmd, config| {
|
||||
Ok(cmd.run(components.client, components.backend))
|
||||
}),
|
||||
Some(Subcommand::ExportGenesisState(params)) => {
|
||||
|
||||
@@ -14,24 +14,31 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use cumulus_client_consensus_relay_chain::{
|
||||
build_relay_chain_consensus, BuildRelayChainConsensusParams,
|
||||
use cumulus_client_consensus_aura::{
|
||||
build_aura_consensus, BuildAuraConsensusParams, SlotProportion,
|
||||
};
|
||||
use cumulus_client_consensus_common::ParachainConsensus;
|
||||
use cumulus_client_network::build_block_announce_validator;
|
||||
use cumulus_client_service::{
|
||||
prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,
|
||||
};
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use polkadot_primitives::v0::CollatorPair;
|
||||
use rococo_parachain_primitives::Block;
|
||||
use rococo_parachain_primitives::{Block, Hash};
|
||||
|
||||
use sc_client_api::ExecutorProvider;
|
||||
use sc_executor::native_executor_instance;
|
||||
pub use sc_executor::NativeExecutor;
|
||||
use sc_network::NetworkService;
|
||||
use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager};
|
||||
use sc_telemetry::{Telemetry, TelemetryWorker, TelemetryWorkerHandle};
|
||||
use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
|
||||
use sp_api::ConstructRuntimeApi;
|
||||
use sp_consensus::SlotData;
|
||||
use sp_keystore::SyncCryptoStorePtr;
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use sp_trie::PrefixedMemoryDB;
|
||||
use std::sync::Arc;
|
||||
use substrate_prometheus_endpoint::Registry;
|
||||
|
||||
pub use sc_executor::NativeExecutor;
|
||||
|
||||
// Native executor instance.
|
||||
native_executor_instance!(
|
||||
@@ -51,14 +58,15 @@ native_executor_instance!(
|
||||
///
|
||||
/// Use this macro if you don't actually need the full service, but just the builder in order to
|
||||
/// be able to perform chain operations.
|
||||
pub fn new_partial<RuntimeApi, Executor>(
|
||||
pub fn new_partial<RuntimeApi, Executor, BIQ>(
|
||||
config: &Configuration,
|
||||
build_import_queue: BIQ,
|
||||
) -> Result<
|
||||
PartialComponents<
|
||||
TFullClient<Block, RuntimeApi, Executor>,
|
||||
TFullBackend<Block>,
|
||||
(),
|
||||
sp_consensus::import_queue::BasicQueue<Block, PrefixedMemoryDB<BlakeTwo256>>,
|
||||
sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,
|
||||
sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>,
|
||||
(Option<Telemetry>, Option<TelemetryWorkerHandle>),
|
||||
>,
|
||||
@@ -79,6 +87,15 @@ where
|
||||
+ sp_block_builder::BlockBuilder<Block>,
|
||||
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
|
||||
Executor: sc_executor::NativeExecutionDispatch + 'static,
|
||||
BIQ: FnOnce(
|
||||
Arc<TFullClient<Block, RuntimeApi, Executor>>,
|
||||
&Configuration,
|
||||
Option<TelemetryHandle>,
|
||||
&TaskManager,
|
||||
) -> Result<
|
||||
sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,
|
||||
sc_service::Error,
|
||||
>,
|
||||
{
|
||||
let telemetry = config
|
||||
.telemetry_endpoints
|
||||
@@ -105,8 +122,6 @@ where
|
||||
telemetry
|
||||
});
|
||||
|
||||
let registry = config.prometheus_registry();
|
||||
|
||||
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
|
||||
config.transaction_pool.clone(),
|
||||
config.role.is_authority().into(),
|
||||
@@ -115,12 +130,11 @@ where
|
||||
client.clone(),
|
||||
);
|
||||
|
||||
let import_queue = cumulus_client_consensus_relay_chain::import_queue(
|
||||
let import_queue = build_import_queue(
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
|_, _| async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) },
|
||||
&task_manager.spawn_essential_handle(),
|
||||
registry.clone(),
|
||||
config,
|
||||
telemetry.as_ref().map(|telemetry| telemetry.handle()),
|
||||
&task_manager,
|
||||
)?;
|
||||
|
||||
let params = PartialComponents {
|
||||
@@ -141,12 +155,14 @@ where
|
||||
///
|
||||
/// This is the actual implementation that is abstract over the executor and the runtime api.
|
||||
#[sc_tracing::logging::prefix_logs_with("Parachain")]
|
||||
async fn start_node_impl<RuntimeApi, Executor, RB>(
|
||||
async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(
|
||||
parachain_config: Configuration,
|
||||
collator_key: CollatorPair,
|
||||
polkadot_config: Configuration,
|
||||
id: ParaId,
|
||||
rpc_ext_builder: RB,
|
||||
build_import_queue: BIQ,
|
||||
build_consensus: BIC,
|
||||
) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, Executor>>)>
|
||||
where
|
||||
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>
|
||||
@@ -168,6 +184,26 @@ where
|
||||
) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>
|
||||
+ Send
|
||||
+ 'static,
|
||||
BIQ: FnOnce(
|
||||
Arc<TFullClient<Block, RuntimeApi, Executor>>,
|
||||
&Configuration,
|
||||
Option<TelemetryHandle>,
|
||||
&TaskManager,
|
||||
) -> Result<
|
||||
sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,
|
||||
sc_service::Error,
|
||||
>,
|
||||
BIC: FnOnce(
|
||||
Arc<TFullClient<Block, RuntimeApi, Executor>>,
|
||||
Option<&Registry>,
|
||||
Option<TelemetryHandle>,
|
||||
&TaskManager,
|
||||
&polkadot_service::NewFull<polkadot_service::Client>,
|
||||
Arc<sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>>,
|
||||
Arc<NetworkService<Block, Hash>>,
|
||||
SyncCryptoStorePtr,
|
||||
bool,
|
||||
) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,
|
||||
{
|
||||
if matches!(parachain_config.role, Role::Light) {
|
||||
return Err("Light client not supported!".into());
|
||||
@@ -175,10 +211,10 @@ where
|
||||
|
||||
let parachain_config = prepare_node_config(parachain_config);
|
||||
|
||||
let params = new_partial::<RuntimeApi, Executor>(¶chain_config)?;
|
||||
let params = new_partial::<RuntimeApi, Executor, BIQ>(¶chain_config, build_import_queue)?;
|
||||
let (mut telemetry, telemetry_worker_handle) = params.other;
|
||||
|
||||
let polkadot_full_node = cumulus_client_service::build_polkadot_full_node(
|
||||
let relay_chain_full_node = cumulus_client_service::build_polkadot_full_node(
|
||||
polkadot_config,
|
||||
collator_key.clone(),
|
||||
telemetry_worker_handle,
|
||||
@@ -191,12 +227,13 @@ where
|
||||
let client = params.client.clone();
|
||||
let backend = params.backend.clone();
|
||||
let block_announce_validator = build_block_announce_validator(
|
||||
polkadot_full_node.client.clone(),
|
||||
relay_chain_full_node.client.clone(),
|
||||
id,
|
||||
Box::new(polkadot_full_node.network.clone()),
|
||||
polkadot_full_node.backend.clone(),
|
||||
Box::new(relay_chain_full_node.network.clone()),
|
||||
relay_chain_full_node.backend.clone(),
|
||||
);
|
||||
|
||||
let force_authoring = parachain_config.force_authoring;
|
||||
let validator = parachain_config.role.is_authority();
|
||||
let prometheus_registry = parachain_config.prometheus_registry().cloned();
|
||||
let transaction_pool = params.transaction_pool.clone();
|
||||
@@ -238,25 +275,19 @@ where
|
||||
};
|
||||
|
||||
if validator {
|
||||
let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
|
||||
task_manager.spawn_handle(),
|
||||
let parachain_consensus = build_consensus(
|
||||
client.clone(),
|
||||
transaction_pool,
|
||||
prometheus_registry.as_ref(),
|
||||
telemetry.as_ref().map(|x| x.handle()),
|
||||
);
|
||||
let spawner = task_manager.spawn_handle();
|
||||
telemetry.as_ref().map(|t| t.handle()),
|
||||
&task_manager,
|
||||
&relay_chain_full_node,
|
||||
transaction_pool,
|
||||
network,
|
||||
params.keystore_container.sync_keystore(),
|
||||
force_authoring,
|
||||
)?;
|
||||
|
||||
let parachain_consensus = build_relay_chain_consensus(BuildRelayChainConsensusParams {
|
||||
para_id: id,
|
||||
proposer_factory,
|
||||
create_inherent_data_providers: |_, _| async {
|
||||
Ok(sp_timestamp::InherentDataProvider::from_system_time())
|
||||
},
|
||||
block_import: client.clone(),
|
||||
relay_chain_client: polkadot_full_node.client.clone(),
|
||||
relay_chain_backend: polkadot_full_node.backend.clone(),
|
||||
});
|
||||
let spawner = task_manager.spawn_handle();
|
||||
|
||||
let params = StartCollatorParams {
|
||||
para_id: id,
|
||||
@@ -265,7 +296,7 @@ where
|
||||
client: client.clone(),
|
||||
task_manager: &mut task_manager,
|
||||
collator_key,
|
||||
relay_chain_full_node: polkadot_full_node,
|
||||
relay_chain_full_node,
|
||||
spawner,
|
||||
backend,
|
||||
parachain_consensus,
|
||||
@@ -278,7 +309,7 @@ where
|
||||
announce_block,
|
||||
task_manager: &mut task_manager,
|
||||
para_id: id,
|
||||
polkadot_full_node,
|
||||
polkadot_full_node: relay_chain_full_node,
|
||||
};
|
||||
|
||||
start_full_node(params)?;
|
||||
@@ -289,6 +320,58 @@ where
|
||||
Ok((task_manager, client))
|
||||
}
|
||||
|
||||
/// Build the import queue for the "default" runtime.
|
||||
pub fn build_import_queue(
|
||||
client: Arc<TFullClient<Block, parachain_runtime::RuntimeApi, RuntimeExecutor>>,
|
||||
config: &Configuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
task_manager: &TaskManager,
|
||||
) -> Result<
|
||||
sp_consensus::DefaultImportQueue<
|
||||
Block,
|
||||
TFullClient<Block, shell_runtime::RuntimeApi, ShellRuntimeExecutor>,
|
||||
>,
|
||||
sc_service::Error,
|
||||
> {
|
||||
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
|
||||
|
||||
let block_import = cumulus_client_consensus_aura::AuraBlockImport::<
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
sp_consensus_aura::sr25519::AuthorityPair,
|
||||
>::new(client.clone(), client.clone());
|
||||
|
||||
cumulus_client_consensus_aura::import_queue::<
|
||||
sp_consensus_aura::sr25519::AuthorityPair,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
>(cumulus_client_consensus_aura::ImportQueueParams {
|
||||
block_import,
|
||||
client: client.clone(),
|
||||
create_inherent_data_providers: move |_, _| async move {
|
||||
let time = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
|
||||
let slot =
|
||||
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
|
||||
*time,
|
||||
slot_duration.slot_duration(),
|
||||
);
|
||||
|
||||
Ok((time, slot))
|
||||
},
|
||||
registry: config.prometheus_registry().clone(),
|
||||
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
|
||||
spawner: &task_manager.spawn_essential_handle(),
|
||||
telemetry,
|
||||
})
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Start a rococo-test parachain node.
|
||||
pub async fn start_node(
|
||||
parachain_config: Configuration,
|
||||
@@ -298,16 +381,114 @@ pub async fn start_node(
|
||||
) -> sc_service::error::Result<
|
||||
(TaskManager, Arc<TFullClient<Block, parachain_runtime::RuntimeApi, RuntimeExecutor>>)
|
||||
> {
|
||||
start_node_impl::<parachain_runtime::RuntimeApi, RuntimeExecutor, _>(
|
||||
start_node_impl::<parachain_runtime::RuntimeApi, RuntimeExecutor, _, _, _>(
|
||||
parachain_config,
|
||||
collator_key,
|
||||
polkadot_config,
|
||||
id,
|
||||
|_| Default::default(),
|
||||
build_import_queue,
|
||||
|client,
|
||||
prometheus_registry,
|
||||
telemetry,
|
||||
task_manager,
|
||||
relay_chain_node,
|
||||
transaction_pool,
|
||||
sync_oracle,
|
||||
keystore,
|
||||
force_authoring| {
|
||||
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
|
||||
|
||||
let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
transaction_pool,
|
||||
prometheus_registry.clone(),
|
||||
telemetry.clone(),
|
||||
);
|
||||
|
||||
let relay_chain_backend = relay_chain_node.backend.clone();
|
||||
let relay_chain_client = relay_chain_node.client.clone();
|
||||
Ok(build_aura_consensus::<
|
||||
sp_consensus_aura::sr25519::AuthorityPair,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
>(BuildAuraConsensusParams {
|
||||
proposer_factory,
|
||||
create_inherent_data_providers: move |_, (relay_parent, validation_data)| {
|
||||
let parachain_inherent =
|
||||
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(
|
||||
relay_parent,
|
||||
&relay_chain_client,
|
||||
&*relay_chain_backend,
|
||||
&validation_data,
|
||||
id,
|
||||
);
|
||||
async move {
|
||||
let time = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
|
||||
let slot =
|
||||
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
|
||||
*time,
|
||||
slot_duration.slot_duration(),
|
||||
);
|
||||
|
||||
let parachain_inherent = parachain_inherent.ok_or_else(|| {
|
||||
Box::<dyn std::error::Error + Send + Sync>::from(
|
||||
"Failed to create parachain inherent",
|
||||
)
|
||||
})?;
|
||||
Ok((time, slot, parachain_inherent))
|
||||
}
|
||||
},
|
||||
block_import: client.clone(),
|
||||
relay_chain_client: relay_chain_node.client.clone(),
|
||||
relay_chain_backend: relay_chain_node.backend.clone(),
|
||||
para_client: client.clone(),
|
||||
backoff_authoring_blocks: Option::<()>::None,
|
||||
sync_oracle,
|
||||
keystore,
|
||||
force_authoring,
|
||||
slot_duration,
|
||||
// We got around 500ms for proposing
|
||||
block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),
|
||||
telemetry,
|
||||
}))
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Build the import queue for the shell runtime.
|
||||
pub fn shell_build_import_queue(
|
||||
client: Arc<TFullClient<Block, shell_runtime::RuntimeApi, ShellRuntimeExecutor>>,
|
||||
config: &Configuration,
|
||||
_: Option<TelemetryHandle>,
|
||||
task_manager: &TaskManager,
|
||||
) -> Result<
|
||||
sp_consensus::DefaultImportQueue<
|
||||
Block,
|
||||
TFullClient<Block, shell_runtime::RuntimeApi, ShellRuntimeExecutor>,
|
||||
>,
|
||||
sc_service::Error,
|
||||
> {
|
||||
cumulus_client_consensus_relay_chain::import_queue(
|
||||
client.clone(),
|
||||
client,
|
||||
|_, _| async { Ok(()) },
|
||||
&task_manager.spawn_essential_handle(),
|
||||
config.prometheus_registry().clone(),
|
||||
)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Start a rococo-shell parachain node.
|
||||
pub async fn start_shell_node(
|
||||
parachain_config: Configuration,
|
||||
@@ -317,12 +498,65 @@ pub async fn start_shell_node(
|
||||
) -> sc_service::error::Result<
|
||||
(TaskManager, Arc<TFullClient<Block, shell_runtime::RuntimeApi, ShellRuntimeExecutor>>)
|
||||
> {
|
||||
start_node_impl::<shell_runtime::RuntimeApi, ShellRuntimeExecutor, _>(
|
||||
start_node_impl::<shell_runtime::RuntimeApi, ShellRuntimeExecutor, _, _, _>(
|
||||
parachain_config,
|
||||
collator_key,
|
||||
polkadot_config,
|
||||
id,
|
||||
|_| Default::default(),
|
||||
shell_build_import_queue,
|
||||
|client,
|
||||
prometheus_registry,
|
||||
telemetry,
|
||||
task_manager,
|
||||
relay_chain_node,
|
||||
transaction_pool,
|
||||
_,
|
||||
_,
|
||||
_| {
|
||||
let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
transaction_pool,
|
||||
prometheus_registry.clone(),
|
||||
telemetry.clone(),
|
||||
);
|
||||
|
||||
let relay_chain_backend = relay_chain_node.backend.clone();
|
||||
let relay_chain_client = relay_chain_node.client.clone();
|
||||
|
||||
Ok(
|
||||
cumulus_client_consensus_relay_chain::build_relay_chain_consensus(
|
||||
cumulus_client_consensus_relay_chain::BuildRelayChainConsensusParams {
|
||||
para_id: id,
|
||||
proposer_factory,
|
||||
block_import: client.clone(),
|
||||
relay_chain_client: relay_chain_node.client.clone(),
|
||||
relay_chain_backend: relay_chain_node.backend.clone(),
|
||||
create_inherent_data_providers:
|
||||
move |_, (relay_parent, validation_data)| {
|
||||
let parachain_inherent =
|
||||
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(
|
||||
relay_parent,
|
||||
&relay_chain_client,
|
||||
&*relay_chain_backend,
|
||||
&validation_data,
|
||||
id,
|
||||
);
|
||||
async move {
|
||||
let parachain_inherent =
|
||||
parachain_inherent.ok_or_else(|| {
|
||||
Box::<dyn std::error::Error + Send + Sync>::from(
|
||||
"Failed to create parachain inherent",
|
||||
)
|
||||
})?;
|
||||
Ok(parachain_inherent)
|
||||
}
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ cumulus-client-consensus-relay-chain = { path = "../../client/consensus/relay-ch
|
||||
cumulus-client-network = { path = "../../client/network" }
|
||||
cumulus-client-service = { path = "../../client/service" }
|
||||
cumulus-primitives-core = { path = "../../primitives/core" }
|
||||
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" }
|
||||
cumulus-test-runtime = { path = "../runtime" }
|
||||
cumulus-test-relay-validation-worker-provider = { path = "../relay-validation-worker-provider" }
|
||||
|
||||
@@ -60,6 +61,10 @@ jsonrpc-core = "15.1.0"
|
||||
futures = { version = "0.3.5" }
|
||||
tokio = { version = "0.2.21", features = ["macros"] }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-test-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
|
||||
# Substrate dependencies
|
||||
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
+22
-1
@@ -232,10 +232,31 @@ where
|
||||
prometheus_registry.as_ref(),
|
||||
None,
|
||||
);
|
||||
|
||||
let relay_chain_client = relay_chain_full_node.client.clone();
|
||||
let relay_chain_backend = relay_chain_full_node.backend.clone();
|
||||
|
||||
let parachain_consensus = cumulus_client_consensus_relay_chain::RelayChainConsensus::new(
|
||||
para_id,
|
||||
proposer_factory,
|
||||
|_, _| async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) },
|
||||
move |_, (relay_parent, validation_data)| {
|
||||
let parachain_inherent =
|
||||
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(
|
||||
relay_parent,
|
||||
&*relay_chain_client,
|
||||
&*relay_chain_backend,
|
||||
&validation_data,
|
||||
para_id,
|
||||
);
|
||||
async move {
|
||||
let time = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
|
||||
let parachain_inherent = parachain_inherent.ok_or_else(|| {
|
||||
Box::<dyn std::error::Error + Send + Sync>::from(String::from("error"))
|
||||
})?;
|
||||
Ok((time, parachain_inherent))
|
||||
}
|
||||
},
|
||||
client.clone(),
|
||||
relay_chain_full_node.client.clone(),
|
||||
relay_chain_full_node.backend.clone(),
|
||||
|
||||
Reference in New Issue
Block a user