From 7f7f5fa857502b6e3649081abb6b53c3512bfedb Mon Sep 17 00:00:00 2001
From: Serban Iorga <serban@parity.io>
Date: Fri, 14 Jun 2024 09:29:04 +0300
Subject: [PATCH] `polkadot-parachain-bin`: small cosmetics and improvements
 (#4666)

Related to: https://github.com/paritytech/polkadot-sdk/issues/5

A couple of cosmetics and improvements related to
`polkadot-parachain-bin`:

- Adding some convenience traits in order to avoid declaring long
duplicate bounds
- Specifically check if the runtime exposes `AuraApi` when executing
`start_lookahead_aura_consensus()`
- Some fixes for the `RelayChainCli`. Details in the commits description
---
 cumulus/polkadot-parachain/Cargo.toml         |   2 +-
 cumulus/polkadot-parachain/src/cli.rs         |  14 +-
 cumulus/polkadot-parachain/src/command.rs     |  14 +-
 cumulus/polkadot-parachain/src/common/aura.rs |  68 +++++++
 cumulus/polkadot-parachain/src/common/mod.rs  |  67 +++++++
 .../asset_hub_polkadot_aura.rs                |   6 -
 .../src/fake_runtime_api/aura.rs              |   6 -
 cumulus/polkadot-parachain/src/main.rs        |   1 +
 cumulus/polkadot-parachain/src/service.rs     | 177 +++++-------------
 substrate/client/service/src/config.rs        |   2 +-
 10 files changed, 192 insertions(+), 165 deletions(-)
 create mode 100644 cumulus/polkadot-parachain/src/common/aura.rs
 create mode 100644 cumulus/polkadot-parachain/src/common/mod.rs

diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml
index 639b8b3d4dc..890cf519916 100644
--- a/cumulus/polkadot-parachain/Cargo.toml
+++ b/cumulus/polkadot-parachain/Cargo.toml
@@ -18,6 +18,7 @@ path = "src/main.rs"
 async-trait = "0.1.79"
 clap = { version = "4.5.3", features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "3.6.12" }
+color-print = "0.3.4"
 futures = "0.3.28"
 hex-literal = "0.4.1"
 log = { workspace = true, default-features = true }
@@ -111,7 +112,6 @@ cumulus-client-service = { path = "../client/service" }
 cumulus-primitives-aura = { path = "../primitives/aura" }
 cumulus-primitives-core = { path = "../primitives/core" }
 cumulus-relay-chain-interface = { path = "../client/relay-chain-interface" }
-color-print = "0.3.4"
 
 [build-dependencies]
 substrate-build-script-utils = { path = "../../substrate/utils/build-script-utils" }
diff --git a/cumulus/polkadot-parachain/src/cli.rs b/cumulus/polkadot-parachain/src/cli.rs
index f7d2fd0f0be..fa4b4da1ba9 100644
--- a/cumulus/polkadot-parachain/src/cli.rs
+++ b/cumulus/polkadot-parachain/src/cli.rs
@@ -14,6 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
 
+use clap::{CommandFactory, FromArgMatches};
 use std::path::PathBuf;
 
 /// Sub-commands supported by the collator.
@@ -108,18 +109,19 @@ pub struct RelayChainCli {
 }
 
 impl RelayChainCli {
-	/// Parse the relay chain CLI parameters using the para chain `Configuration`.
+	/// Parse the relay chain CLI parameters using the parachain `Configuration`.
 	pub fn new<'a>(
 		para_config: &sc_service::Configuration,
 		relay_chain_args: impl Iterator<Item = &'a String>,
 	) -> Self {
+		let polkadot_cmd = polkadot_cli::RunCmd::command().no_binary_name(true);
+		let matches = polkadot_cmd.get_matches_from(relay_chain_args);
+		let base = FromArgMatches::from_arg_matches(&matches).unwrap_or_else(|e| e.exit());
+
 		let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec);
 		let chain_id = extension.map(|e| e.relay_chain.clone());
+
 		let base_path = para_config.base_path.path().join("polkadot");
-		Self {
-			base_path: Some(base_path),
-			chain_id,
-			base: clap::Parser::parse_from(relay_chain_args),
-		}
+		Self { base, chain_id, base_path: Some(base_path) }
 	}
 }
diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs
index 653ea3281f0..6b3f4b4cd0a 100644
--- a/cumulus/polkadot-parachain/src/command.rs
+++ b/cumulus/polkadot-parachain/src/command.rs
@@ -530,13 +530,9 @@ pub fn run() -> Result<()> {
 		}),
 		Some(Subcommand::PurgeChain(cmd)) => {
 			let runner = cli.create_runner(cmd)?;
+			let polkadot_cli = RelayChainCli::new(runner.config(), cli.relaychain_args.iter());
 
 			runner.sync_run(|config| {
-				let polkadot_cli = RelayChainCli::new(
-					&config,
-					[RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()),
-				);
-
 				let polkadot_config = SubstrateCli::create_configuration(
 					&polkadot_cli,
 					&polkadot_cli,
@@ -603,6 +599,7 @@ pub fn run() -> Result<()> {
 		Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
 		None => {
 			let runner = cli.create_runner(&cli.run.normalize())?;
+			let polkadot_cli = RelayChainCli::new(runner.config(), cli.relaychain_args.iter());
 			let collator_options = cli.run.collator_options();
 
 			runner.run_node_until_exit(|config| async move {
@@ -648,11 +645,6 @@ pub fn run() -> Result<()> {
 					.map(|e| e.para_id)
 					.ok_or("Could not find parachain extension in chain-spec.")?;
 
-				let polkadot_cli = RelayChainCli::new(
-					&config,
-					[RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()),
-				);
-
 				let id = ParaId::from(para_id);
 
 				let parachain_account =
@@ -667,7 +659,7 @@ pub fn run() -> Result<()> {
 				info!("Parachain Account: {}", parachain_account);
 				info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" });
 
-				match polkadot_config.network.network_backend {
+				match config.network.network_backend {
 					sc_network::config::NetworkBackendType::Libp2p =>
 						start_node::<sc_network::NetworkWorker<_, _>>(
 							config,
diff --git a/cumulus/polkadot-parachain/src/common/aura.rs b/cumulus/polkadot-parachain/src/common/aura.rs
new file mode 100644
index 00000000000..9f72d847926
--- /dev/null
+++ b/cumulus/polkadot-parachain/src/common/aura.rs
@@ -0,0 +1,68 @@
+// Copyright (C) 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/>.
+
+//! Aura-related primitives for cumulus parachain collators.
+
+use codec::Codec;
+use cumulus_primitives_aura::AuraUnincludedSegmentApi;
+use cumulus_primitives_core::BlockT;
+use sp_consensus_aura::AuraApi;
+use sp_runtime::app_crypto::{AppCrypto, AppPair, AppSignature, Pair};
+
+/// Convenience trait for defining the basic bounds of an `AuraId`.
+pub trait AuraIdT: AppCrypto<Pair = Self::BoundedPair> + Codec + Send {
+	/// Extra bounds for the `Pair`.
+	type BoundedPair: AppPair + AppCrypto<Signature = Self::BoundedSignature>;
+
+	/// Extra bounds for the `Signature`.
+	type BoundedSignature: AppSignature
+		+ TryFrom<Vec<u8>>
+		+ std::hash::Hash
+		+ sp_runtime::traits::Member
+		+ Codec;
+}
+
+impl<T> AuraIdT for T
+where
+	T: AppCrypto + Codec + Send + Sync,
+	<<T as AppCrypto>::Pair as AppCrypto>::Signature:
+		TryFrom<Vec<u8>> + std::hash::Hash + sp_runtime::traits::Member + Codec,
+{
+	type BoundedPair = <T as AppCrypto>::Pair;
+	type BoundedSignature = <<T as AppCrypto>::Pair as AppCrypto>::Signature;
+}
+
+/// Convenience trait for defining the basic bounds of a parachain runtime that supports
+/// the Aura consensus.
+pub trait AuraRuntimeApi<Block: BlockT, AuraId: AuraIdT>:
+	sp_api::ApiExt<Block>
+	+ AuraApi<Block, <AuraId::BoundedPair as Pair>::Public>
+	+ AuraUnincludedSegmentApi<Block>
+	+ Sized
+{
+	/// Check if the runtime has the Aura API.
+	fn has_aura_api(&self, at: Block::Hash) -> bool {
+		self.has_api::<dyn AuraApi<Block, <AuraId::BoundedPair as Pair>::Public>>(at)
+			.unwrap_or(false)
+	}
+}
+
+impl<T, Block: BlockT, AuraId: AuraIdT> AuraRuntimeApi<Block, AuraId> for T where
+	T: sp_api::ApiExt<Block>
+		+ AuraApi<Block, <AuraId::BoundedPair as Pair>::Public>
+		+ AuraUnincludedSegmentApi<Block>
+{
+}
diff --git a/cumulus/polkadot-parachain/src/common/mod.rs b/cumulus/polkadot-parachain/src/common/mod.rs
new file mode 100644
index 00000000000..5adbb4137cd
--- /dev/null
+++ b/cumulus/polkadot-parachain/src/common/mod.rs
@@ -0,0 +1,67 @@
+// Copyright (C) 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 parachain collator primitives.
+
+#![warn(missing_docs)]
+
+pub mod aura;
+
+use cumulus_primitives_core::CollectCollationInfo;
+use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata};
+use sp_block_builder::BlockBuilder;
+use sp_runtime::traits::Block as BlockT;
+use sp_session::SessionKeys;
+use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
+
+/// Convenience trait that defines the basic bounds for the `RuntimeApi` of a parachain node.
+pub trait NodeRuntimeApi<Block: BlockT>:
+	ApiExt<Block>
+	+ Metadata<Block>
+	+ SessionKeys<Block>
+	+ BlockBuilder<Block>
+	+ TaggedTransactionQueue<Block>
+	+ CollectCollationInfo<Block>
+	+ Sized
+{
+}
+
+impl<T, Block: BlockT> NodeRuntimeApi<Block> for T where
+	T: ApiExt<Block>
+		+ Metadata<Block>
+		+ SessionKeys<Block>
+		+ BlockBuilder<Block>
+		+ TaggedTransactionQueue<Block>
+		+ CollectCollationInfo<Block>
+{
+}
+
+/// Convenience trait that defines the basic bounds for the `ConstructRuntimeApi` of a parachain
+/// node.
+pub trait ConstructNodeRuntimeApi<Block: BlockT, C: CallApiAt<Block>>:
+	ConstructRuntimeApi<Block, C, RuntimeApi = Self::BoundedRuntimeApi> + Send + Sync + 'static
+{
+	/// Basic bounds for the `RuntimeApi` of a parachain node.
+	type BoundedRuntimeApi: NodeRuntimeApi<Block>;
+}
+
+impl<T, Block: BlockT, C: CallApiAt<Block>> ConstructNodeRuntimeApi<Block, C> for T
+where
+	T: ConstructRuntimeApi<Block, C> + Send + Sync + 'static,
+	T::RuntimeApi: NodeRuntimeApi<Block>,
+{
+	type BoundedRuntimeApi = T::RuntimeApi;
+}
diff --git a/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs b/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs
index 82c02943c5f..0b79d338c16 100644
--- a/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs
+++ b/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs
@@ -105,12 +105,6 @@ sp_api::impl_runtime_apis! {
 		}
 	}
 
-	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
-		fn offchain_worker(_: &<Block as BlockT>::Header) {
-			unimplemented!()
-		}
-	}
-
 	impl sp_session::SessionKeys<Block> for Runtime {
 		fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> {
 			unimplemented!()
diff --git a/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs b/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs
index 6b718e91216..823eb9ab584 100644
--- a/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs
+++ b/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs
@@ -105,12 +105,6 @@ sp_api::impl_runtime_apis! {
 		}
 	}
 
-	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
-		fn offchain_worker(_: &<Block as BlockT>::Header) {
-			unimplemented!()
-		}
-	}
-
 	impl sp_session::SessionKeys<Block> for Runtime {
 		fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> {
 			unimplemented!()
diff --git a/cumulus/polkadot-parachain/src/main.rs b/cumulus/polkadot-parachain/src/main.rs
index 0757bea84aa..2bf659228bc 100644
--- a/cumulus/polkadot-parachain/src/main.rs
+++ b/cumulus/polkadot-parachain/src/main.rs
@@ -22,6 +22,7 @@
 mod chain_spec;
 mod cli;
 mod command;
+mod common;
 mod fake_runtime_api;
 mod rpc;
 mod service;
diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs
index 19ad75e384c..9cd3a003722 100644
--- a/cumulus/polkadot-parachain/src/service.rs
+++ b/cumulus/polkadot-parachain/src/service.rs
@@ -14,13 +14,11 @@
 // You should have received a copy of the GNU General Public License
 // along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
 
-use codec::{Codec, Decode};
+use codec::Decode;
 use cumulus_client_cli::CollatorOptions;
 use cumulus_client_collator::service::CollatorService;
 use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams};
-use cumulus_client_consensus_common::{
-	ParachainBlockImport as TParachainBlockImport, ParachainCandidate, ParachainConsensus,
-};
+use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport;
 use cumulus_client_consensus_proposer::Proposer;
 #[allow(deprecated)]
 use cumulus_client_service::old_consensus;
@@ -28,22 +26,26 @@ use cumulus_client_service::{
 	build_network, build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks,
 	BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams,
 };
-use cumulus_primitives_core::{
-	relay_chain::{Hash as PHash, PersistedValidationData, ValidationCode},
-	ParaId,
-};
+use cumulus_primitives_core::{relay_chain::ValidationCode, ParaId};
 use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};
 use sc_rpc::DenyUnsafe;
-use sp_core::Pair;
 
 use jsonrpsee::RpcModule;
 
-use crate::{fake_runtime_api::aura::RuntimeApi as FakeRuntimeApi, rpc};
-pub use parachains_common::{AccountId, AuraId, Balance, Block, Hash, Header, Nonce};
+use crate::{
+	common::{
+		aura::{AuraIdT, AuraRuntimeApi},
+		ConstructNodeRuntimeApi,
+	},
+	fake_runtime_api::aura::RuntimeApi as FakeRuntimeApi,
+	rpc,
+};
+pub use parachains_common::{AccountId, AuraId, Balance, Block, Hash, Nonce};
 
 use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier;
-use futures::{lock::Mutex, prelude::*};
+use futures::prelude::*;
 use prometheus_endpoint::Registry;
+use sc_client_api::Backend as ClientApiBackend;
 use sc_consensus::{
 	import_queue::{BasicQueue, Verifier as VerifierT},
 	BlockImportParams, ImportQueue,
@@ -53,8 +55,8 @@ use sc_network::{config::FullNetworkConfiguration, service::traits::NetworkBacke
 use sc_network_sync::SyncingService;
 use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager};
 use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
-use sp_api::{ApiExt, ConstructRuntimeApi, ProvideRuntimeApi};
-use sp_consensus_aura::AuraApi;
+use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi};
+use sp_blockchain::HeaderBackend;
 use sp_core::traits::SpawnEssentialNamed;
 use sp_keystore::KeystorePtr;
 use sp_runtime::{
@@ -100,13 +102,7 @@ pub fn new_partial<RuntimeApi, BIQ>(
 	build_import_queue: BIQ,
 ) -> Result<Service<RuntimeApi>, sc_service::Error>
 where
-	RuntimeApi: ConstructRuntimeApi<Block, ParachainClient<RuntimeApi>> + Send + Sync + 'static,
-	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
-		+ sp_api::Metadata<Block>
-		+ sp_session::SessionKeys<Block>
-		+ sp_api::ApiExt<Block>
-		+ sp_offchain::OffchainWorkerApi<Block>
-		+ sp_block_builder::BlockBuilder<Block>,
+	RuntimeApi: ConstructNodeRuntimeApi<Block, ParachainClient<RuntimeApi>>,
 	BIQ: FnOnce(
 		Arc<ParachainClient<RuntimeApi>>,
 		ParachainBlockImport<RuntimeApi>,
@@ -200,16 +196,7 @@ async fn start_node_impl<RuntimeApi, RB, BIQ, SC, Net>(
 	hwbench: Option<sc_sysinfo::HwBench>,
 ) -> sc_service::error::Result<(TaskManager, Arc<ParachainClient<RuntimeApi>>)>
 where
-	RuntimeApi: ConstructRuntimeApi<Block, ParachainClient<RuntimeApi>> + Send + Sync + 'static,
-	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
-		+ sp_api::Metadata<Block>
-		+ sp_session::SessionKeys<Block>
-		+ sp_api::ApiExt<Block>
-		+ sp_offchain::OffchainWorkerApi<Block>
-		+ sp_block_builder::BlockBuilder<Block>
-		+ cumulus_primitives_core::CollectCollationInfo<Block>
-		+ pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
-		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
+	RuntimeApi: ConstructNodeRuntimeApi<Block, ParachainClient<RuntimeApi>>,
 	RB: Fn(
 			DenyUnsafe,
 			Arc<ParachainClient<RuntimeApi>>,
@@ -529,61 +516,6 @@ impl<R> BuildOnAccess<R> {
 	}
 }
 
-/// Special [`ParachainConsensus`] implementation that waits for the upgrade from
-/// shell to a parachain runtime that implements Aura.
-struct WaitForAuraConsensus<Client, AuraId> {
-	client: Arc<Client>,
-	aura_consensus: Arc<Mutex<BuildOnAccess<Box<dyn ParachainConsensus<Block>>>>>,
-	relay_chain_consensus: Arc<Mutex<Box<dyn ParachainConsensus<Block>>>>,
-	_phantom: PhantomData<AuraId>,
-}
-
-impl<Client, AuraId> Clone for WaitForAuraConsensus<Client, AuraId> {
-	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<Client, AuraId> ParachainConsensus<Block> for WaitForAuraConsensus<Client, AuraId>
-where
-	Client: sp_api::ProvideRuntimeApi<Block> + Send + Sync,
-	Client::Api: AuraApi<Block, AuraId>,
-	AuraId: Send + Codec + Sync,
-{
-	async fn produce_candidate(
-		&mut self,
-		parent: &Header,
-		relay_parent: PHash,
-		validation_data: &PersistedValidationData,
-	) -> Option<ParachainCandidate<Block>> {
-		if self
-			.client
-			.runtime_api()
-			.has_api::<dyn AuraApi<Block, AuraId>>(parent.hash())
-			.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, AuraId> {
 	client: Arc<Client>,
 	aura_verifier: BuildOnAccess<Box<dyn VerifierT<Block>>>,
@@ -592,22 +524,16 @@ struct Verifier<Client, AuraId> {
 }
 
 #[async_trait::async_trait]
-impl<Client, AuraId> VerifierT<Block> for Verifier<Client, AuraId>
+impl<Client, AuraId: AuraIdT> VerifierT<Block> for Verifier<Client, AuraId>
 where
 	Client: sp_api::ProvideRuntimeApi<Block> + Send + Sync,
-	Client::Api: AuraApi<Block, AuraId>,
-	AuraId: Send + Sync + Codec,
+	Client::Api: AuraRuntimeApi<Block, AuraId>,
 {
 	async fn verify(
 		&mut self,
 		block_import: BlockImportParams<Block>,
 	) -> Result<BlockImportParams<Block>, String> {
-		if self
-			.client
-			.runtime_api()
-			.has_api::<dyn AuraApi<Block, AuraId>>(*block_import.header.parent_hash())
-			.unwrap_or(false)
-		{
+		if self.client.runtime_api().has_aura_api(*block_import.header.parent_hash()) {
 			self.aura_verifier.get_mut().verify(block_import).await
 		} else {
 			self.relay_chain_verifier.verify(block_import).await
@@ -617,7 +543,7 @@ where
 
 /// Build the import queue for parachain runtimes that started with relay chain consensus and
 /// switched to aura.
-pub fn build_relay_to_aura_import_queue<RuntimeApi, AuraId: AppCrypto>(
+pub fn build_relay_to_aura_import_queue<RuntimeApi, AuraId: AuraIdT>(
 	client: Arc<ParachainClient<RuntimeApi>>,
 	block_import: ParachainBlockImport<RuntimeApi>,
 	config: &Configuration,
@@ -625,16 +551,8 @@ pub fn build_relay_to_aura_import_queue<RuntimeApi, AuraId: AppCrypto>(
 	task_manager: &TaskManager,
 ) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>
 where
-	RuntimeApi: ConstructRuntimeApi<Block, ParachainClient<RuntimeApi>> + Send + Sync + 'static,
-	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
-		+ sp_api::Metadata<Block>
-		+ sp_session::SessionKeys<Block>
-		+ sp_api::ApiExt<Block>
-		+ sp_offchain::OffchainWorkerApi<Block>
-		+ sp_block_builder::BlockBuilder<Block>
-		+ sp_consensus_aura::AuraApi<Block, <<AuraId as AppCrypto>::Pair as Pair>::Public>,
-	<<AuraId as AppCrypto>::Pair as Pair>::Signature:
-		TryFrom<Vec<u8>> + std::hash::Hash + sp_runtime::traits::Member + Codec,
+	RuntimeApi: ConstructNodeRuntimeApi<Block, ParachainClient<RuntimeApi>>,
+	RuntimeApi::RuntimeApi: AuraRuntimeApi<Block, AuraId>,
 {
 	let verifier_client = client.clone();
 
@@ -714,11 +632,7 @@ pub async fn start_generic_aura_lookahead_node<Net: NetworkBackend<Block, Hash>>
 ///
 /// Uses the lookahead collator to support async backing.
 #[sc_tracing::logging::prefix_logs_with("Parachain")]
-pub async fn start_asset_hub_lookahead_node<
-	RuntimeApi,
-	AuraId: AppCrypto + Send + Codec + Sync,
-	Net,
->(
+pub async fn start_asset_hub_lookahead_node<RuntimeApi, AuraId: AuraIdT, Net>(
 	parachain_config: Configuration,
 	polkadot_config: Configuration,
 	collator_options: CollatorOptions,
@@ -726,20 +640,10 @@ pub async fn start_asset_hub_lookahead_node<
 	hwbench: Option<sc_sysinfo::HwBench>,
 ) -> sc_service::error::Result<(TaskManager, Arc<ParachainClient<RuntimeApi>>)>
 where
-	RuntimeApi: ConstructRuntimeApi<Block, ParachainClient<RuntimeApi>> + Send + Sync + 'static,
-	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
-		+ sp_api::Metadata<Block>
-		+ sp_session::SessionKeys<Block>
-		+ sp_api::ApiExt<Block>
-		+ sp_offchain::OffchainWorkerApi<Block>
-		+ sp_block_builder::BlockBuilder<Block>
-		+ cumulus_primitives_core::CollectCollationInfo<Block>
-		+ sp_consensus_aura::AuraApi<Block, <<AuraId as AppCrypto>::Pair as Pair>::Public>
+	RuntimeApi: ConstructNodeRuntimeApi<Block, ParachainClient<RuntimeApi>>,
+	RuntimeApi::RuntimeApi: AuraRuntimeApi<Block, AuraId>
 		+ pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
-		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
-		+ cumulus_primitives_aura::AuraUnincludedSegmentApi<Block>,
-	<<AuraId as AppCrypto>::Pair as Pair>::Signature:
-		TryFrom<Vec<u8>> + std::hash::Hash + sp_runtime::traits::Member + Codec,
+		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
 	Net: NetworkBackend<Block, Hash>,
 {
 	start_node_impl::<RuntimeApi, _, _, _, Net>(
@@ -807,11 +711,7 @@ where
 
 					// Check if we have upgraded to an Aura compatible runtime and transition if
 					// necessary.
-					if client
-						.runtime_api()
-						.has_api::<dyn AuraApi<Block, AuraId>>(last_head_hash)
-						.unwrap_or(false)
-					{
+					if client.runtime_api().has_aura_api(last_head_hash) {
 						// Respond to this request before transitioning to Aura.
 						request.complete(None);
 						break
@@ -930,14 +830,14 @@ fn start_relay_chain_consensus(
 }
 
 /// Start consensus using the lookahead aura collator.
-fn start_lookahead_aura_consensus(
-	client: Arc<ParachainClient<FakeRuntimeApi>>,
-	block_import: ParachainBlockImport<FakeRuntimeApi>,
+fn start_lookahead_aura_consensus<RuntimeApi>(
+	client: Arc<ParachainClient<RuntimeApi>>,
+	block_import: ParachainBlockImport<RuntimeApi>,
 	prometheus_registry: Option<&Registry>,
 	telemetry: Option<TelemetryHandle>,
 	task_manager: &TaskManager,
 	relay_chain_interface: Arc<dyn RelayChainInterface>,
-	transaction_pool: Arc<sc_transaction_pool::FullPool<Block, ParachainClient<FakeRuntimeApi>>>,
+	transaction_pool: Arc<sc_transaction_pool::FullPool<Block, ParachainClient<RuntimeApi>>>,
 	sync_oracle: Arc<SyncingService<Block>>,
 	keystore: KeystorePtr,
 	relay_chain_slot_duration: Duration,
@@ -946,7 +846,16 @@ fn start_lookahead_aura_consensus(
 	overseer_handle: OverseerHandle,
 	announce_block: Arc<dyn Fn(Hash, Option<Vec<u8>>) + Send + Sync>,
 	backend: Arc<ParachainBackend>,
-) -> Result<(), sc_service::Error> {
+) -> Result<(), sc_service::Error>
+where
+	RuntimeApi: ConstructNodeRuntimeApi<Block, ParachainClient<RuntimeApi>>,
+	RuntimeApi::RuntimeApi: AuraRuntimeApi<Block, AuraId>,
+{
+	let info = backend.blockchain().info();
+	if !client.runtime_api().has_aura_api(info.finalized_hash) {
+		return Err(sc_service::error::Error::Other("Missing aura runtime APIs".to_string()));
+	}
+
 	let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
 		task_manager.spawn_handle(),
 		client.clone(),
diff --git a/substrate/client/service/src/config.rs b/substrate/client/service/src/config.rs
index 187e18aa3ca..e4788f1f337 100644
--- a/substrate/client/service/src/config.rs
+++ b/substrate/client/service/src/config.rs
@@ -280,7 +280,7 @@ impl Default for RpcMethods {
 static mut BASE_PATH_TEMP: Option<TempDir> = None;
 
 /// The base path that is used for everything that needs to be written on disk to run a node.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 pub struct BasePath {
 	path: PathBuf,
 }
-- 
GitLab