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:
Bastian Köcher
2021-05-10 14:43:00 +02:00
committed by GitHub
parent 78ad174b15
commit d01bc247cb
22 changed files with 1694 additions and 332 deletions
Generated
+339 -206
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -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",
+38
View File
@@ -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"
+101
View File
@@ -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,
})
}
+536
View File
@@ -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,
))
}
}
-1
View File
@@ -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()
+12 -35
View File
@@ -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,
&parachain_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>>;
+39
View File
@@ -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",
]
+161
View File
@@ -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);
};
}
+6
View File
@@ -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,
)
}
}
+6 -1
View File
@@ -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" }
+6
View File
@@ -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",
]
+27 -12
View File
@@ -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>,
);
+2 -12
View File
@@ -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,
+17 -1
View File
@@ -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(),
}
}
+31 -19
View File
@@ -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)) => {
+275 -41
View File
@@ -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>(&parachain_config)?;
let params = new_partial::<RuntimeApi, Executor, BIQ>(&parachain_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
}
+5
View File
@@ -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
View File
@@ -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(),