From 074e9e7de661cd90b80e2fe989232d497ff2a72d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 22 Oct 2019 15:26:11 +0200 Subject: [PATCH] Implement block import --- cumulus/collator/src/lib.rs | 88 ++++++++++++++++++++++----- cumulus/runtime/src/lib.rs | 10 +++ cumulus/test/parachain/src/service.rs | 20 ++++-- 3 files changed, 98 insertions(+), 20 deletions(-) diff --git a/cumulus/collator/src/lib.rs b/cumulus/collator/src/lib.rs index 202bab4540..60a4f112a1 100644 --- a/cumulus/collator/src/lib.rs +++ b/cumulus/collator/src/lib.rs @@ -19,7 +19,10 @@ use cumulus_runtime::ParachainBlockData; use sr_primitives::traits::{Block as BlockT, Header as HeaderT}; -use consensus_common::{Environment, Proposer}; +use consensus_common::{ + BlockImport, Environment, Proposer, ForkChoiceStrategy, BlockImportParams, BlockOrigin, + Error as ConsensusError, +}; use inherents::InherentDataProviders; use substrate_primitives::Blake2Hasher; @@ -53,44 +56,49 @@ struct HeadData { } /// The implementation of the Cumulus `Collator`. -pub struct Collator { +pub struct Collator { proposer_factory: Arc>, _phantom: PhantomData, inherent_data_providers: InherentDataProviders, collator_network: Arc, + block_import: Arc>, } -impl> Collator { +impl Collator { /// Create a new instance. fn new( proposer_factory: PF, inherent_data_providers: InherentDataProviders, collator_network: Arc, + block_import: BI, ) -> Self { Self { proposer_factory: Arc::new(Mutex::new(proposer_factory)), inherent_data_providers, _phantom: PhantomData, collator_network, + block_import: Arc::new(Mutex::new(block_import)), } } } -impl Clone for Collator { +impl Clone for Collator { fn clone(&self) -> Self { Self { proposer_factory: self.proposer_factory.clone(), inherent_data_providers: self.inherent_data_providers.clone(), _phantom: PhantomData, collator_network: self.collator_network.clone(), + block_import: self.block_import.clone(), } } } -impl ParachainContext for Collator +impl ParachainContext for Collator where Block: BlockT, PF: Environment + 'static + Send, + BI: BlockImport + Send + Sync + 'static, { type ProduceCandidate = Box< dyn Future @@ -107,9 +115,13 @@ impl ParachainContext for Collator let factory = self.proposer_factory.clone(); let inherent_providers = self.inherent_data_providers.clone(); + let block_import = self.block_import.clone(); let res = HeadData::::decode(&mut &status.head_data.0[..]) - .map_err(|_| InvalidHead) + .map_err(|e| { + error!(target: "cumulus-collator", "Could not decode the head data: {:?}", e); + InvalidHead + }) .into_future() .and_then(move |last_head| { let parent_state_root = *last_head.header.state_root(); @@ -117,14 +129,21 @@ impl ParachainContext for Collator factory.lock() .init(&last_head.header) .map_err(|e| { - //TODO: Do we want to return the real error? - error!("Could not create proposer: {:?}", e); + error!( + target: "cumulus-collator", + "Could not create proposer: {:?}", + e, + ); InvalidHead }) .and_then(|mut proposer| { let inherent_data = inherent_providers.create_inherent_data() .map_err(|e| { - error!("Failed to create inherent data: {:?}", e); + error!( + target: "cumulus-collator", + "Failed to create inherent data: {:?}", + e, + ); InvalidHead })?; @@ -136,7 +155,11 @@ impl ParachainContext for Collator true, ) .map_err(|e| { - error!("Proposing failed: {:?}", e); + error!( + target: "cumulus-collator", + "Proposing failed: {:?}", + e, + ); InvalidHead }) .and_then(move |(block, proof)| { @@ -155,7 +178,10 @@ impl ParachainContext for Collator ) } None => { - error!("Proposer did not return the requested proof."); + error!( + target: "cumulus-collator", + "Proposer did not return the requested proof.", + ); Err(InvalidHead) } }; @@ -168,6 +194,36 @@ impl ParachainContext for Collator }) }) .flatten() + .and_then(move |b| { + let block_import_params = BlockImportParams { + origin: BlockOrigin::Own, + header: b.header().clone(), + justification: None, + post_digests: vec![], + body: Some(b.extrinsics().to_vec()), + finalized: false, + auxiliary: vec![], // block-weight is written in block import. + // TODO: block-import handles fork choice and this shouldn't even have the + // option to specify one. + // https://github.com/paritytech/substrate/issues/3623 + fork_choice: ForkChoiceStrategy::LongestChain, + }; + + if let Err(err) = block_import.lock().import_block( + block_import_params, + Default::default(), + ) { + error!( + target: "cumulus-collator", + "Error importing build block (at {:?}): {:?}", + b.header().parent_hash(), + err, + ); + Err(InvalidHead) + } else { + Ok(b) + } + }) .map(|b| { let block_data = BlockData(b.encode()); let head_data = HeadData:: { header: b.into_header() }; @@ -201,7 +257,7 @@ impl CollatorBuilder { } impl> BuildParachainContext for CollatorBuilder { - type ParachainContext = Collator; + type ParachainContext = Collator; fn build( self, @@ -213,11 +269,11 @@ impl> BuildParachainContext for Collato B: substrate_client::backend::Backend + 'static, E: substrate_client::CallExecutor + Clone + Send + Sync + 'static { - let (proposer_factory, inherent_data_providers) = self.setup_parachain + let (proposer_factory, block_import, inherent_data_providers) = self.setup_parachain .setup_parachain(client, task_executor) .map_err(|e| error!("Error setting up the parachain: {}", e))?; - Ok(Collator::new(proposer_factory, inherent_data_providers, network)) + Ok(Collator::new(proposer_factory, inherent_data_providers, network, block_import)) } } @@ -225,13 +281,15 @@ impl> BuildParachainContext for Collato pub trait SetupParachain: Send { /// The proposer factory of the parachain to build blocks. type ProposerFactory: Environment + Send + 'static; + /// The block import for importing the blocks build by the collator. + type BlockImport: BlockImport + Send + Sync + 'static; /// Setup the parachain. fn setup_parachain( self, polkadot_client: P, task_executor: TaskExecutor, - ) -> Result<(Self::ProposerFactory, InherentDataProviders), String>; + ) -> Result<(Self::ProposerFactory, Self::BlockImport, InherentDataProviders), String>; } /// Run a collator with the given proposer factory. diff --git a/cumulus/runtime/src/lib.rs b/cumulus/runtime/src/lib.rs index 4a038f4b4a..f6f223fa73 100644 --- a/cumulus/runtime/src/lib.rs +++ b/cumulus/runtime/src/lib.rs @@ -64,4 +64,14 @@ impl ParachainBlockData { pub fn into_header(self) -> B::Header { self.header } + + /// Returns the header. + pub fn header(&self) -> &B::Header { + &self.header + } + + /// Returns the extrinsics. + pub fn extrinsics(&self) -> &[B::Extrinsic] { + &self.extrinsics + } } diff --git a/cumulus/test/parachain/src/service.rs b/cumulus/test/parachain/src/service.rs index b6f0aadd65..1e431bf1dd 100644 --- a/cumulus/test/parachain/src/service.rs +++ b/cumulus/test/parachain/src/service.rs @@ -91,32 +91,42 @@ pub fn run_collator { +struct SetupParachain { service: S, proposer_factory: PF, exit: E, inherent_data_providers: InherentDataProviders, + block_import: BI, } -impl cumulus_collator::SetupParachain for SetupParachain +impl cumulus_collator::SetupParachain for SetupParachain where S: AbstractService, E: Send + crate::cli::IntoExit, PF: consensus_common::Environment + Send + 'static, + BI: consensus_common::BlockImport + Send + Sync + 'static, { type ProposerFactory = PF; + type BlockImport = BI; fn setup_parachain( self, polkadot_client: P, task_executor: polkadot_collator::TaskExecutor, - ) -> Result<(Self::ProposerFactory, InherentDataProviders), String> { + ) -> Result<(Self::ProposerFactory, Self::BlockImport, InherentDataProviders), String> { let client = self.service.client(); let follow = match cumulus_consensus::follow_polkadot(crate::PARA_ID, client, polkadot_client) { @@ -139,6 +149,6 @@ impl cumulus_collator::SetupParachain for SetupParachain