// Copyright 2019 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 . use std::{marker::PhantomData, sync::Arc}; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder as BlockBuilderApi; use sp_blockchain::Result as ClientResult; use sp_consensus::{ error::Error as ConsensusError, import_queue::{BasicQueue, CacheKeyId, Verifier as VerifierT}, BlockImport, BlockImportParams, BlockOrigin, ForkChoiceStrategy, }; use sp_inherents::InherentDataProviders; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Header as HeaderT}, Justification, }; /// A verifier that just checks the inherents. struct Verifier { client: Arc, inherent_data_providers: InherentDataProviders, _marker: PhantomData, } impl VerifierT for Verifier where Block: BlockT, Client: ProvideRuntimeApi + Send + Sync, >::Api: BlockBuilderApi, { fn verify( &mut self, origin: BlockOrigin, header: Block::Header, justification: Option, mut body: Option>, ) -> Result< ( BlockImportParams, Option)>>, ), String, > { if let Some(inner_body) = body.take() { let inherent_data = self .inherent_data_providers .create_inherent_data() .map_err(|e| e.into_string())?; let block = Block::new(header.clone(), inner_body); let inherent_res = self .client .runtime_api() .check_inherents( &BlockId::Hash(*header.parent_hash()), block.clone(), inherent_data, ) .map_err(|e| format!("{:?}", e))?; if !inherent_res.ok() { inherent_res.into_errors().try_for_each(|(i, e)| { Err(self.inherent_data_providers.error_to_string(&i, &e)) })?; } let (_, inner_body) = block.deconstruct(); body = Some(inner_body); } let post_hash = Some(header.hash()); let mut block_import_params = BlockImportParams::new(origin, header); block_import_params.body = body; block_import_params.justification = justification; block_import_params.fork_choice = Some(ForkChoiceStrategy::LongestChain); block_import_params.post_hash = post_hash; Ok((block_import_params, None)) } } /// Start an import queue for a Cumulus collator that does not uses any special authoring logic. pub fn import_queue( client: Arc, block_import: I, inherent_data_providers: InherentDataProviders, spawner: &impl sp_core::traits::SpawnNamed, registry: Option<&substrate_prometheus_endpoint::Registry>, ) -> ClientResult> where I: BlockImport + Send + Sync + 'static, I::Transaction: Send, Client: ProvideRuntimeApi + Send + Sync + 'static, >::Api: BlockBuilderApi, { let verifier = Verifier { client, inherent_data_providers, _marker: PhantomData, }; Ok(BasicQueue::new( verifier, Box::new(block_import), None, None, spawner, registry, )) }