,
+ /// Transaction pool instance.
+ pub pool: Arc,
+ /// Whether to deny unsafe calls
+ pub deny_unsafe: DenyUnsafe,
+}
+
+/// Instantiate all RPC extensions.
+pub fn create_full(
+ deps: FullDeps,
+ backend: Arc,
+) -> Result>
+where
+ C: ProvideRuntimeApi
+ + HeaderBackend
+ + AuxStore
+ + HeaderMetadata
+ + Send
+ + Sync
+ + 'static,
+ C::Api: frame_rpc_system::AccountNonceApi,
+ C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
+ C::Api: BlockBuilder,
+ C::Api: pallet_dex_rpc::DexRuntimeApi<
+ trappist_runtime::opaque::Block,
+ trappist_runtime::AssetId,
+ trappist_runtime::Balance,
+ trappist_runtime::AssetBalance,
+ >,
+ P: TransactionPool + Sync + Send + 'static,
+ B: sc_client_api::Backend + Send + Sync + 'static,
+ B::State: sc_client_api::backend::StateBackend>,
+{
+ use frame_rpc_system::{System, SystemApiServer};
+ use pallet_dex_rpc::{Dex, DexApiServer};
+ use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
+ use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
+
+ let mut module = RpcExtension::new(());
+ let FullDeps { client, pool, deny_unsafe } = deps;
+
+ module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?;
+ module.merge(TransactionPayment::new(client.clone()).into_rpc())?;
+ module.merge(StateMigration::new(client.clone(), backend, deny_unsafe).into_rpc())?;
+ module.merge(Dex::new(client).into_rpc())?;
+
+ Ok(module)
+}
diff --git a/node/src/service.rs b/node/src/service.rs
new file mode 100644
index 00000000..adf737c2
--- /dev/null
+++ b/node/src/service.rs
@@ -0,0 +1,752 @@
+// Copyright 2019-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 .
+
+use codec::Codec;
+use cumulus_client_cli::CollatorOptions;
+use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion};
+use cumulus_client_consensus_common::{
+ ParachainBlockImport as TParachainBlockImport, ParachainCandidate, ParachainConsensus,
+};
+use cumulus_client_network::BlockAnnounceValidator;
+use cumulus_client_service::{
+ build_relay_chain_interface, prepare_node_config, start_collator, start_full_node,
+ StartCollatorParams, StartFullNodeParams,
+};
+use cumulus_primitives_core::{
+ relay_chain::v2::{Hash as PHash, PersistedValidationData},
+ ParaId,
+};
+use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface};
+use sp_core::Pair;
+
+use jsonrpsee::RpcModule;
+
+use crate::rpc;
+pub use parachains_common::{
+ AccountId, AssetId, Balance, Block, BlockNumber, Hash, Header, Index as Nonce,
+};
+
+use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier;
+use futures::lock::Mutex;
+use sc_consensus::{
+ import_queue::{BasicQueue, Verifier as VerifierT},
+ BlockImportParams, ImportQueue,
+};
+use sc_executor::WasmExecutor;
+use sc_network::NetworkService;
+use sc_network_common::service::NetworkBlock;
+use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager};
+use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
+use sp_api::{ApiExt, ConstructRuntimeApi};
+use sp_consensus::CacheKeyId;
+use sp_consensus_aura::AuraApi;
+use sp_keystore::SyncCryptoStorePtr;
+use sp_runtime::{
+ app_crypto::AppKey,
+ generic::BlockId,
+ traits::{BlakeTwo256, Header as HeaderT},
+};
+use std::{marker::PhantomData, sync::Arc, time::Duration};
+use substrate_prometheus_endpoint::Registry;
+
+#[cfg(not(feature = "runtime-benchmarks"))]
+type HostFunctions = sp_io::SubstrateHostFunctions;
+
+#[cfg(feature = "runtime-benchmarks")]
+type HostFunctions =
+ (sp_io::SubstrateHostFunctions, frame_benchmarking::benchmarking::HostFunctions);
+
+type ParachainClient = TFullClient>;
+
+type ParachainBackend = TFullBackend;
+
+type ParachainBlockImport =
+ TParachainBlockImport>, ParachainBackend>;
+
+/// Native Stout executor instance.
+pub struct StoutRuntimeExecutor;
+
+impl sc_executor::NativeExecutionDispatch for StoutRuntimeExecutor {
+ type ExtendHostFunctions = ();
+
+ fn dispatch(method: &str, data: &[u8]) -> Option> {
+ stout_runtime::api::dispatch(method, data)
+ }
+
+ fn native_version() -> sc_executor::NativeVersion {
+ stout_runtime::native_version()
+ }
+}
+
+// Native Trappist executor instance.
+pub struct TrappistRuntimeExecutor;
+
+impl sc_executor::NativeExecutionDispatch for TrappistRuntimeExecutor {
+ type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
+
+ fn dispatch(method: &str, data: &[u8]) -> Option> {
+ trappist_runtime::api::dispatch(method, data)
+ }
+
+ fn native_version() -> sc_executor::NativeVersion {
+ trappist_runtime::native_version()
+ }
+}
+
+/// Starts a `ServiceBuilder` for a full service.
+///
+/// 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(
+ config: &Configuration,
+ build_import_queue: BIQ,
+) -> Result<
+ PartialComponents<
+ ParachainClient,
+ ParachainBackend,
+ (),
+ sc_consensus::DefaultImportQueue>,
+ sc_transaction_pool::FullPool>,
+ (ParachainBlockImport, Option, Option),
+ >,
+ sc_service::Error,
+>
+where
+ RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static,
+ RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue
+ + sp_api::Metadata
+ + sp_session::SessionKeys
+ + sp_api::ApiExt<
+ Block,
+ StateBackend = sc_client_api::StateBackendFor,
+ > + sp_offchain::OffchainWorkerApi
+ + pallet_dex_rpc::DexRuntimeApi
+ + sp_block_builder::BlockBuilder,
+ sc_client_api::StateBackendFor: sp_api::StateBackend,
+ BIQ: FnOnce(
+ Arc>,
+ ParachainBlockImport,
+ &Configuration,
+ Option,
+ &TaskManager,
+ ) -> Result<
+ sc_consensus::DefaultImportQueue>,
+ sc_service::Error,
+ >,
+{
+ let telemetry = config
+ .telemetry_endpoints
+ .clone()
+ .filter(|x| !x.is_empty())
+ .map(|endpoints| -> Result<_, sc_telemetry::Error> {
+ let worker = TelemetryWorker::new(16)?;
+ let telemetry = worker.handle().new_telemetry(endpoints);
+ Ok((worker, telemetry))
+ })
+ .transpose()?;
+
+ let executor = sc_executor::WasmExecutor::::new(
+ config.wasm_method,
+ config.default_heap_pages,
+ config.max_runtime_instances,
+ None,
+ config.runtime_cache_size,
+ );
+
+ let (client, backend, keystore_container, task_manager) =
+ sc_service::new_full_parts::(
+ config,
+ telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
+ executor,
+ )?;
+ let client = Arc::new(client);
+
+ let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
+
+ let telemetry = telemetry.map(|(worker, telemetry)| {
+ task_manager.spawn_handle().spawn("telemetry", None, worker.run());
+ telemetry
+ });
+
+ let transaction_pool = sc_transaction_pool::BasicPool::new_full(
+ config.transaction_pool.clone(),
+ config.role.is_authority().into(),
+ config.prometheus_registry(),
+ task_manager.spawn_essential_handle(),
+ client.clone(),
+ );
+
+ let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
+
+ let import_queue = build_import_queue(
+ client.clone(),
+ block_import.clone(),
+ config,
+ telemetry.as_ref().map(|telemetry| telemetry.handle()),
+ &task_manager,
+ )?;
+
+ let params = PartialComponents {
+ backend,
+ client,
+ import_queue,
+ keystore_container,
+ task_manager,
+ transaction_pool,
+ select_chain: (),
+ other: (block_import, telemetry, telemetry_worker_handle),
+ };
+
+ Ok(params)
+}
+
+/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.
+///
+/// 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(
+ parachain_config: Configuration,
+ polkadot_config: Configuration,
+ collator_options: CollatorOptions,
+ para_id: ParaId,
+ _rpc_ext_builder: RB,
+ build_import_queue: BIQ,
+ build_consensus: BIC,
+ hwbench: Option,
+) -> sc_service::error::Result<(TaskManager, Arc>)>
+where
+ RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static,
+ RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue
+ + sp_api::Metadata
+ + sp_session::SessionKeys
+ + sp_api::ApiExt<
+ Block,
+ StateBackend = sc_client_api::StateBackendFor,
+ > + sp_offchain::OffchainWorkerApi
+ + sp_block_builder::BlockBuilder
+ + cumulus_primitives_core::CollectCollationInfo
+ + frame_rpc_system::AccountNonceApi
+ + pallet_dex_rpc::DexRuntimeApi
+ + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
+ sc_client_api::StateBackendFor: sp_api::StateBackend,
+ RB: Fn(Arc>) -> Result, sc_service::Error>,
+ BIQ: FnOnce(
+ Arc>,
+ ParachainBlockImport,
+ &Configuration,
+ Option,
+ &TaskManager,
+ ) -> Result<
+ sc_consensus::DefaultImportQueue>,
+ sc_service::Error,
+ >,
+ BIC: FnOnce(
+ Arc>,
+ ParachainBlockImport,
+ Option<&Registry>,
+ Option,
+ &TaskManager,
+ Arc,
+ Arc>>,
+ Arc>,
+ SyncCryptoStorePtr,
+ bool,
+ ) -> Result>, sc_service::Error>,
+{
+ let parachain_config = prepare_node_config(parachain_config);
+
+ let params = new_partial::(¶chain_config, build_import_queue)?;
+ let (block_import, mut telemetry, telemetry_worker_handle) = params.other;
+
+ let client = params.client.clone();
+ let backend = params.backend.clone();
+
+ let mut task_manager = params.task_manager;
+ let (relay_chain_interface, collator_key) = build_relay_chain_interface(
+ polkadot_config,
+ ¶chain_config,
+ telemetry_worker_handle,
+ &mut task_manager,
+ collator_options.clone(),
+ hwbench.clone(),
+ )
+ .await
+ .map_err(|e| match e {
+ RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x,
+ s => s.to_string().into(),
+ })?;
+
+ let block_announce_validator =
+ BlockAnnounceValidator::new(relay_chain_interface.clone(), para_id);
+
+ 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();
+ let import_queue_service = params.import_queue.service();
+
+ let (network, system_rpc_tx, tx_handler_controller, start_network) =
+ sc_service::build_network(sc_service::BuildNetworkParams {
+ config: ¶chain_config,
+ client: client.clone(),
+ transaction_pool: transaction_pool.clone(),
+ spawn_handle: task_manager.spawn_handle(),
+ import_queue: params.import_queue,
+ block_announce_validator_builder: Some(Box::new(|_| {
+ Box::new(block_announce_validator)
+ })),
+ warp_sync: None,
+ })?;
+
+ let rpc_builder = {
+ let client = client.clone();
+ let transaction_pool = transaction_pool.clone();
+
+ let backend_for_rpc = backend.clone();
+ Box::new(move |deny_unsafe, _| {
+ let deps = rpc::FullDeps {
+ client: client.clone(),
+ pool: transaction_pool.clone(),
+ deny_unsafe,
+ };
+
+ rpc::create_full(deps, backend_for_rpc.clone()).map_err(Into::into)
+ })
+ };
+
+ sc_service::spawn_tasks(sc_service::SpawnTasksParams {
+ rpc_builder,
+ client: client.clone(),
+ transaction_pool: transaction_pool.clone(),
+ task_manager: &mut task_manager,
+ config: parachain_config,
+ keystore: params.keystore_container.sync_keystore(),
+ backend: backend.clone(),
+ network: network.clone(),
+ system_rpc_tx,
+ tx_handler_controller,
+ telemetry: telemetry.as_mut(),
+ })?;
+
+ if let Some(hwbench) = hwbench {
+ sc_sysinfo::print_hwbench(&hwbench);
+
+ if let Some(ref mut telemetry) = telemetry {
+ let telemetry_handle = telemetry.handle();
+ task_manager.spawn_handle().spawn(
+ "telemetry_hwbench",
+ None,
+ sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),
+ );
+ }
+ }
+
+ let announce_block = {
+ let network = network.clone();
+ Arc::new(move |hash, data| network.announce_block(hash, data))
+ };
+
+ let relay_chain_slot_duration = Duration::from_secs(6);
+
+ if validator {
+ let parachain_consensus = build_consensus(
+ client.clone(),
+ block_import,
+ prometheus_registry.as_ref(),
+ telemetry.as_ref().map(|t| t.handle()),
+ &task_manager,
+ relay_chain_interface.clone(),
+ transaction_pool,
+ network,
+ params.keystore_container.sync_keystore(),
+ force_authoring,
+ )?;
+
+ let spawner = task_manager.spawn_handle();
+
+ let params = StartCollatorParams {
+ para_id,
+ block_status: client.clone(),
+ announce_block,
+ client: client.clone(),
+ task_manager: &mut task_manager,
+ relay_chain_interface: relay_chain_interface.clone(),
+ spawner,
+ parachain_consensus,
+ import_queue: import_queue_service,
+ collator_key: collator_key.expect("Command line arguments do not allow this. qed"),
+ relay_chain_slot_duration,
+ };
+
+ start_collator(params).await?;
+ } else {
+ let params = StartFullNodeParams {
+ client: client.clone(),
+ announce_block,
+ task_manager: &mut task_manager,
+ para_id,
+ relay_chain_interface,
+ relay_chain_slot_duration,
+ import_queue: import_queue_service,
+ };
+
+ start_full_node(params)?;
+ }
+
+ start_network.start_network();
+
+ Ok((task_manager, client))
+}
+
+enum BuildOnAccess {
+ Uninitialized(Option R + Send + Sync>>),
+ Initialized(R),
+}
+
+impl BuildOnAccess {
+ fn get_mut(&mut self) -> &mut R {
+ loop {
+ match self {
+ Self::Uninitialized(f) => {
+ *self = Self::Initialized((f.take().unwrap())());
+ },
+ Self::Initialized(ref mut r) => return r,
+ }
+ }
+ }
+}
+
+/// Special [`ParachainConsensus`] implementation that waits for the upgrade from
+/// shell to a parachain runtime that implements Aura.
+struct WaitForAuraConsensus {
+ client: Arc,
+ aura_consensus: Arc>>>>,
+ relay_chain_consensus: Arc>>>,
+ _phantom: PhantomData,
+}
+
+impl Clone for WaitForAuraConsensus {
+ fn clone(&self) -> Self {
+ Self {
+ client: self.client.clone(),
+ aura_consensus: self.aura_consensus.clone(),
+ relay_chain_consensus: self.relay_chain_consensus.clone(),
+ _phantom: PhantomData,
+ }
+ }
+}
+
+#[async_trait::async_trait]
+impl ParachainConsensus for WaitForAuraConsensus
+where
+ Client: sp_api::ProvideRuntimeApi + Send + Sync,
+ Client::Api: AuraApi,
+ AuraId: Send + Codec + Sync,
+{
+ async fn produce_candidate(
+ &mut self,
+ parent: &Header,
+ relay_parent: PHash,
+ validation_data: &PersistedValidationData,
+ ) -> Option> {
+ let block_id = BlockId::hash(parent.hash());
+ if self
+ .client
+ .runtime_api()
+ .has_api::>(&block_id)
+ .unwrap_or(false)
+ {
+ self.aura_consensus
+ .lock()
+ .await
+ .get_mut()
+ .produce_candidate(parent, relay_parent, validation_data)
+ .await
+ } else {
+ self.relay_chain_consensus
+ .lock()
+ .await
+ .produce_candidate(parent, relay_parent, validation_data)
+ .await
+ }
+ }
+}
+
+struct Verifier {
+ client: Arc,
+ aura_verifier: BuildOnAccess>>,
+ relay_chain_verifier: Box>,
+ _phantom: PhantomData,
+}
+
+#[async_trait::async_trait]
+impl VerifierT for Verifier
+where
+ Client: sp_api::ProvideRuntimeApi + Send + Sync,
+ Client::Api: AuraApi,
+ AuraId: Send + Sync + Codec,
+{
+ async fn verify(
+ &mut self,
+ block_import: BlockImportParams,
+ ) -> Result<(BlockImportParams, Option)>>), String> {
+ let block_id = BlockId::hash(*block_import.header.parent_hash());
+
+ if self
+ .client
+ .runtime_api()
+ .has_api::>(&block_id)
+ .unwrap_or(false)
+ {
+ self.aura_verifier.get_mut().verify(block_import).await
+ } else {
+ self.relay_chain_verifier.verify(block_import).await
+ }
+ }
+}
+
+/// Start an aura powered parachain node.
+/// (collective-polkadot and statemine/t use this)
+pub async fn start_aura_node(
+ parachain_config: Configuration,
+ polkadot_config: Configuration,
+ collator_options: CollatorOptions,
+ para_id: ParaId,
+ hwbench: Option,
+) -> sc_service::error::Result<(TaskManager, Arc>)>
+where
+ RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static,
+ RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue
+ + sp_api::Metadata
+ + sp_session::SessionKeys
+ + sp_api::ApiExt<
+ Block,
+ StateBackend = sc_client_api::StateBackendFor,
+ > + sp_offchain::OffchainWorkerApi
+ + sp_block_builder::BlockBuilder
+ + cumulus_primitives_core::CollectCollationInfo
+ + sp_consensus_aura::AuraApi::Pair as Pair>::Public>
+ + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi
+ + pallet_dex_rpc::DexRuntimeApi
+ + frame_rpc_system::AccountNonceApi,
+ sc_client_api::StateBackendFor: sp_api::StateBackend,
+ <::Pair as Pair>::Signature:
+ TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec,
+{
+ start_node_impl::(
+ parachain_config,
+ polkadot_config,
+ collator_options,
+ para_id,
+ |_| Ok(RpcModule::new(())),
+ aura_build_import_queue::<_, AuraId>,
+ |client,
+ block_import,
+ prometheus_registry,
+ telemetry,
+ task_manager,
+ relay_chain_interface,
+ transaction_pool,
+ sync_oracle,
+ keystore,
+ force_authoring| {
+ let spawn_handle = task_manager.spawn_handle();
+ let client2 = client.clone();
+ let block_import2 = block_import.clone();
+ let transaction_pool2 = transaction_pool.clone();
+ let telemetry2 = telemetry.clone();
+ let prometheus_registry2 = prometheus_registry.map(|r| (*r).clone());
+ let relay_chain_for_aura = relay_chain_interface.clone();
+
+ let aura_consensus = BuildOnAccess::Uninitialized(Some(Box::new(move || {
+ let slot_duration =
+ cumulus_client_consensus_aura::slot_duration(&*client2).unwrap();
+
+ let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
+ spawn_handle,
+ client2.clone(),
+ transaction_pool2,
+ prometheus_registry2.as_ref(),
+ telemetry2.clone(),
+ );
+
+ AuraConsensus::build::<::Pair, _, _, _, _, _, _>(
+ BuildAuraConsensusParams {
+ proposer_factory,
+ create_inherent_data_providers:
+ move |_, (relay_parent, validation_data)| {
+ let relay_chain_for_aura = relay_chain_for_aura.clone();
+ async move {
+ let parachain_inherent =
+ cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(
+ relay_parent,
+ &relay_chain_for_aura,
+ &validation_data,
+ para_id,
+ ).await;
+
+ let timestamp =
+ sp_timestamp::InherentDataProvider::from_system_time();
+
+ let slot =
+ sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
+ *timestamp,
+ slot_duration,
+ );
+
+ let parachain_inherent =
+ parachain_inherent.ok_or_else(|| {
+ Box::::from(
+ "Failed to create parachain inherent",
+ )
+ })?;
+
+ Ok((slot, timestamp, parachain_inherent))
+ }
+ },
+ block_import: block_import2,
+ para_client: client2,
+ 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),
+ // And a maximum of 750ms if slots are skipped
+ max_block_proposal_slot_portion: Some(SlotProportion::new(1f32 / 16f32)),
+ telemetry: telemetry2,
+ },
+ )
+ })));
+
+ let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
+ task_manager.spawn_handle(),
+ client.clone(),
+ transaction_pool,
+ prometheus_registry,
+ telemetry,
+ );
+
+ let relay_chain_consensus =
+ cumulus_client_consensus_relay_chain::build_relay_chain_consensus(
+ cumulus_client_consensus_relay_chain::BuildRelayChainConsensusParams {
+ para_id,
+ proposer_factory,
+ block_import,
+ relay_chain_interface: relay_chain_interface.clone(),
+ create_inherent_data_providers:
+ move |_, (relay_parent, validation_data)| {
+ let relay_chain_interface = relay_chain_interface.clone();
+ async move {
+ let parachain_inherent =
+ cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(
+ relay_parent,
+ &relay_chain_interface,
+ &validation_data,
+ para_id,
+ ).await;
+ let parachain_inherent =
+ parachain_inherent.ok_or_else(|| {
+ Box::::from(
+ "Failed to create parachain inherent",
+ )
+ })?;
+ Ok(parachain_inherent)
+ }
+ },
+ },
+ );
+
+ let parachain_consensus = Box::new(WaitForAuraConsensus {
+ client,
+ aura_consensus: Arc::new(Mutex::new(aura_consensus)),
+ relay_chain_consensus: Arc::new(Mutex::new(relay_chain_consensus)),
+ _phantom: PhantomData,
+ });
+
+ Ok(parachain_consensus)
+ },
+ hwbench,
+ )
+ .await
+}
+
+/// Build the import queue for Aura-based parachains.
+pub fn aura_build_import_queue(
+ client: Arc>,
+ block_import: ParachainBlockImport,
+ config: &Configuration,
+ telemetry_handle: Option,
+ task_manager: &TaskManager,
+) -> Result>, sc_service::Error>
+where
+ RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static,
+ RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue
+ + sp_api::Metadata
+ + sp_session::SessionKeys
+ + sp_api::ApiExt<
+ Block,
+ StateBackend = sc_client_api::StateBackendFor,
+ > + sp_offchain::OffchainWorkerApi