diff --git a/Cargo.lock b/Cargo.lock
index c52feafe7a706fca10b3b839470b6a8d26578484..27ba43780eda6b8c7bd2994581a1f75c71095c52 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4166,6 +4166,7 @@ dependencies = [
  "polkadot-node-subsystem-util",
  "polkadot-overseer",
  "polkadot-primitives",
+ "polkadot-service",
  "sc-authority-discovery",
  "sc-client-api",
  "sc-network",
diff --git a/cumulus/client/relay-chain-minimal-node/Cargo.toml b/cumulus/client/relay-chain-minimal-node/Cargo.toml
index 0b1e001e007a493f521f10c2659653699da04d0c..98240c92adab38ea103f14699e1e49f7449b3d24 100644
--- a/cumulus/client/relay-chain-minimal-node/Cargo.toml
+++ b/cumulus/client/relay-chain-minimal-node/Cargo.toml
@@ -24,6 +24,7 @@ polkadot-node-collation-generation = { path = "../../../polkadot/node/collation-
 polkadot-node-core-runtime-api = { path = "../../../polkadot/node/core/runtime-api" }
 polkadot-node-core-chain-api = { path = "../../../polkadot/node/core/chain-api" }
 polkadot-node-core-prospective-parachains = { path = "../../../polkadot/node/core/prospective-parachains" }
+polkadot-service = { path = "../../../polkadot/node/service" }
 
 # substrate deps
 sc-authority-discovery = { path = "../../../substrate/client/authority-discovery" }
diff --git a/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs b/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs
index 5f5bf338ef9907756adb1eab3f0541e870677fe5..f01ef8b05ecba77cf6458fdfe80e966b3a67e6a3 100644
--- a/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs
+++ b/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs
@@ -15,159 +15,29 @@
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
 use futures::{select, StreamExt};
-use parking_lot::Mutex;
-use std::{collections::HashMap, sync::Arc};
+use std::sync::Arc;
 
-use polkadot_availability_recovery::AvailabilityRecoverySubsystem;
-use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide};
-use polkadot_network_bridge::{
-	Metrics as NetworkBridgeMetrics, NetworkBridgeRx as NetworkBridgeRxSubsystem,
-	NetworkBridgeTx as NetworkBridgeTxSubsystem,
-};
-use polkadot_node_collation_generation::CollationGenerationSubsystem;
-use polkadot_node_core_chain_api::ChainApiSubsystem;
-use polkadot_node_core_prospective_parachains::ProspectiveParachainsSubsystem;
-use polkadot_node_core_runtime_api::RuntimeApiSubsystem;
-use polkadot_node_network_protocol::{
-	peer_set::{PeerSet, PeerSetProtocolNames},
-	request_response::{
-		v1::{self, AvailableDataFetchingRequest},
-		v2, IncomingRequestReceiver, ReqProtocolNames,
-	},
-};
-use polkadot_node_subsystem_util::metrics::{prometheus::Registry, Metrics};
 use polkadot_overseer::{
-	BlockInfo, DummySubsystem, Handle, Overseer, OverseerConnector, OverseerHandle, SpawnGlue,
-	UnpinHandle,
+	BlockInfo, Handle, Overseer, OverseerConnector, OverseerHandle, SpawnGlue, UnpinHandle,
 };
-use polkadot_primitives::CollatorPair;
+use polkadot_service::overseer::{collator_overseer_builder, OverseerGenArgs};
 
-use sc_authority_discovery::Service as AuthorityDiscoveryService;
-use sc_network::{NetworkStateInfo, NotificationService};
 use sc_service::TaskManager;
 use sc_utils::mpsc::tracing_unbounded;
 
-use cumulus_primitives_core::relay_chain::{Block, Hash as PHash};
 use cumulus_relay_chain_interface::RelayChainError;
 
 use crate::BlockChainRpcClient;
 
-/// Arguments passed for overseer construction.
-pub(crate) struct CollatorOverseerGenArgs<'a> {
-	/// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others.
-	pub runtime_client: Arc<BlockChainRpcClient>,
-	/// Underlying network service implementation.
-	pub network_service: Arc<sc_network::NetworkService<Block, PHash>>,
-	/// Syncing oracle.
-	pub sync_oracle: Box<dyn sp_consensus::SyncOracle + Send>,
-	/// Underlying authority discovery service.
-	pub authority_discovery_service: AuthorityDiscoveryService,
-	/// Receiver for collation request protocol v1.
-	pub collation_req_receiver_v1: IncomingRequestReceiver<v1::CollationFetchingRequest>,
-	/// Receiver for collation request protocol v2.
-	pub collation_req_receiver_v2: IncomingRequestReceiver<v2::CollationFetchingRequest>,
-	/// Receiver for availability request protocol
-	pub available_data_req_receiver: IncomingRequestReceiver<AvailableDataFetchingRequest>,
-	/// Prometheus registry, commonly used for production systems, less so for test.
-	pub registry: Option<&'a Registry>,
-	/// Task spawner to be used throughout the overseer and the APIs it provides.
-	pub spawner: sc_service::SpawnTaskHandle,
-	/// Determines the behavior of the collator.
-	pub collator_pair: CollatorPair,
-	/// Request response protocols
-	pub req_protocol_names: ReqProtocolNames,
-	/// Peerset protocols name mapping
-	pub peer_set_protocol_names: PeerSetProtocolNames,
-	/// Notification services for validation/collation protocols.
-	pub notification_services: HashMap<PeerSet, Box<dyn NotificationService>>,
-}
-
 fn build_overseer(
 	connector: OverseerConnector,
-	CollatorOverseerGenArgs {
-		runtime_client,
-		network_service,
-		sync_oracle,
-		authority_discovery_service,
-		collation_req_receiver_v1,
-		collation_req_receiver_v2,
-		available_data_req_receiver,
-		registry,
-		spawner,
-		collator_pair,
-		req_protocol_names,
-		peer_set_protocol_names,
-		notification_services,
-	}: CollatorOverseerGenArgs<'_>,
+	args: OverseerGenArgs<sc_service::SpawnTaskHandle, BlockChainRpcClient>,
 ) -> Result<
 	(Overseer<SpawnGlue<sc_service::SpawnTaskHandle>, Arc<BlockChainRpcClient>>, OverseerHandle),
 	RelayChainError,
 > {
-	let spawner = SpawnGlue(spawner);
-	let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?;
-	let notification_sinks = Arc::new(Mutex::new(HashMap::new()));
-
-	let builder = Overseer::builder()
-		.availability_distribution(DummySubsystem)
-		.availability_recovery(AvailabilityRecoverySubsystem::for_collator(
-			available_data_req_receiver,
-			Metrics::register(registry)?,
-		))
-		.availability_store(DummySubsystem)
-		.bitfield_distribution(DummySubsystem)
-		.bitfield_signing(DummySubsystem)
-		.candidate_backing(DummySubsystem)
-		.candidate_validation(DummySubsystem)
-		.pvf_checker(DummySubsystem)
-		.chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?))
-		.collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?))
-		.collator_protocol({
-			let side = ProtocolSide::Collator {
-				peer_id: network_service.local_peer_id(),
-				collator_pair,
-				request_receiver_v1: collation_req_receiver_v1,
-				request_receiver_v2: collation_req_receiver_v2,
-				metrics: Metrics::register(registry)?,
-			};
-			CollatorProtocolSubsystem::new(side)
-		})
-		.network_bridge_rx(NetworkBridgeRxSubsystem::new(
-			network_service.clone(),
-			authority_discovery_service.clone(),
-			sync_oracle,
-			network_bridge_metrics.clone(),
-			peer_set_protocol_names.clone(),
-			notification_services,
-			notification_sinks.clone(),
-		))
-		.network_bridge_tx(NetworkBridgeTxSubsystem::new(
-			network_service,
-			authority_discovery_service,
-			network_bridge_metrics,
-			req_protocol_names,
-			peer_set_protocol_names,
-			notification_sinks,
-		))
-		.provisioner(DummySubsystem)
-		.runtime_api(RuntimeApiSubsystem::new(
-			runtime_client.clone(),
-			Metrics::register(registry)?,
-			spawner.clone(),
-		))
-		.statement_distribution(DummySubsystem)
-		.prospective_parachains(ProspectiveParachainsSubsystem::new(Metrics::register(registry)?))
-		.approval_distribution(DummySubsystem)
-		.approval_voting(DummySubsystem)
-		.gossip_support(DummySubsystem)
-		.dispute_coordinator(DummySubsystem)
-		.dispute_distribution(DummySubsystem)
-		.chain_selection(DummySubsystem)
-		.activation_external_listeners(Default::default())
-		.span_per_active_leaf(Default::default())
-		.active_leaves(Default::default())
-		.supports_parachains(runtime_client)
-		.metrics(Metrics::register(registry)?)
-		.spawner(spawner);
+	let builder =
+		collator_overseer_builder(args).map_err(|e| RelayChainError::Application(e.into()))?;
 
 	builder
 		.build_with_connector(connector)
@@ -175,7 +45,7 @@ fn build_overseer(
 }
 
 pub(crate) fn spawn_overseer(
-	overseer_args: CollatorOverseerGenArgs,
+	overseer_args: OverseerGenArgs<sc_service::SpawnTaskHandle, BlockChainRpcClient>,
 	task_manager: &TaskManager,
 	relay_chain_rpc_client: Arc<BlockChainRpcClient>,
 ) -> Result<polkadot_overseer::Handle, RelayChainError> {
diff --git a/cumulus/client/relay-chain-minimal-node/src/lib.rs b/cumulus/client/relay-chain-minimal-node/src/lib.rs
index d121d2d3356765d9327fdaa0a8c0563c3917266f..4bccca59fe3ea2eec816513778885f43c9504d51 100644
--- a/cumulus/client/relay-chain-minimal-node/src/lib.rs
+++ b/cumulus/client/relay-chain-minimal-node/src/lib.rs
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-use collator_overseer::{CollatorOverseerGenArgs, NewMinimalNode};
+use collator_overseer::NewMinimalNode;
 
 use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};
 use cumulus_relay_chain_rpc_interface::{RelayChainRpcClient, RelayChainRpcInterface, Url};
@@ -29,6 +29,7 @@ use polkadot_node_network_protocol::{
 
 use polkadot_node_subsystem_util::metrics::prometheus::Registry;
 use polkadot_primitives::CollatorPair;
+use polkadot_service::{overseer::OverseerGenArgs, IsParachainNode};
 
 use sc_authority_discovery::Service as AuthorityDiscoveryService;
 use sc_network::{config::FullNetworkConfiguration, Event, NetworkEventStream, NetworkService};
@@ -172,10 +173,10 @@ async fn new_minimal_relay_chain(
 	}
 
 	let genesis_hash = relay_chain_rpc_client.block_get_hash(Some(0)).await?.unwrap_or_default();
-	let peer_set_protocol_names =
+	let peerset_protocol_names =
 		PeerSetProtocolNames::new(genesis_hash, config.chain_spec.fork_id());
 	let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No };
-	let notification_services = peer_sets_info(is_authority, &peer_set_protocol_names)
+	let notification_services = peer_sets_info(is_authority, &peerset_protocol_names)
 		.into_iter()
 		.map(|(config, (peerset, service))| {
 			net_config.add_notification_protocol(config);
@@ -184,14 +185,14 @@ async fn new_minimal_relay_chain(
 		.collect::<std::collections::HashMap<PeerSet, Box<dyn sc_network::NotificationService>>>();
 
 	let request_protocol_names = ReqProtocolNames::new(genesis_hash, config.chain_spec.fork_id());
-	let (collation_req_receiver_v1, collation_req_receiver_v2, available_data_req_receiver) =
+	let (collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver) =
 		build_request_response_protocol_receivers(&request_protocol_names, &mut net_config);
 
 	let best_header = relay_chain_rpc_client
 		.chain_get_header(None)
 		.await?
 		.ok_or_else(|| RelayChainError::RpcCallError("Unable to fetch best header".to_string()))?;
-	let (network, network_starter, sync_oracle) = build_collator_network(
+	let (network, network_starter, sync_service) = build_collator_network(
 		&config,
 		net_config,
 		task_manager.spawn_handle(),
@@ -208,19 +209,20 @@ async fn new_minimal_relay_chain(
 		prometheus_registry.cloned(),
 	);
 
-	let overseer_args = CollatorOverseerGenArgs {
+	let overseer_args = OverseerGenArgs {
 		runtime_client: relay_chain_rpc_client.clone(),
 		network_service: network,
-		sync_oracle,
+		sync_service,
 		authority_discovery_service,
-		collation_req_receiver_v1,
-		collation_req_receiver_v2,
+		collation_req_v1_receiver,
+		collation_req_v2_receiver,
 		available_data_req_receiver,
 		registry: prometheus_registry,
 		spawner: task_manager.spawn_handle(),
-		collator_pair,
+		is_parachain_node: IsParachainNode::Collator(collator_pair),
+		overseer_message_channel_capacity_override: None,
 		req_protocol_names: request_protocol_names,
-		peer_set_protocol_names,
+		peerset_protocol_names,
 		notification_services,
 	};
 
@@ -240,10 +242,10 @@ fn build_request_response_protocol_receivers(
 	IncomingRequestReceiver<v2::CollationFetchingRequest>,
 	IncomingRequestReceiver<v1::AvailableDataFetchingRequest>,
 ) {
-	let (collation_req_receiver_v1, cfg) =
+	let (collation_req_v1_receiver, cfg) =
 		IncomingRequest::get_config_receiver(request_protocol_names);
 	config.add_request_response_protocol(cfg);
-	let (collation_req_receiver_v2, cfg) =
+	let (collation_req_v2_receiver, cfg) =
 		IncomingRequest::get_config_receiver(request_protocol_names);
 	config.add_request_response_protocol(cfg);
 	let (available_data_req_receiver, cfg) =
@@ -251,5 +253,5 @@ fn build_request_response_protocol_receivers(
 	config.add_request_response_protocol(cfg);
 	let cfg = Protocol::ChunkFetchingV1.get_outbound_only_config(request_protocol_names);
 	config.add_request_response_protocol(cfg);
-	(collation_req_receiver_v1, collation_req_receiver_v2, available_data_req_receiver)
+	(collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver)
 }
diff --git a/cumulus/client/relay-chain-minimal-node/src/network.rs b/cumulus/client/relay-chain-minimal-node/src/network.rs
index 95785063c1aeb6649d7154fa39e4e111e226def3..7286fab7907cb6d475b81a4dfd97c5d001180873 100644
--- a/cumulus/client/relay-chain-minimal-node/src/network.rs
+++ b/cumulus/client/relay-chain-minimal-node/src/network.rs
@@ -40,7 +40,11 @@ pub(crate) fn build_collator_network(
 	genesis_hash: Hash,
 	best_header: Header,
 ) -> Result<
-	(Arc<NetworkService<Block, Hash>>, NetworkStarter, Box<dyn sp_consensus::SyncOracle + Send>),
+	(
+		Arc<NetworkService<Block, Hash>>,
+		NetworkStarter,
+		Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
+	),
 	Error,
 > {
 	let protocol_id = config.protocol_id();
@@ -112,7 +116,7 @@ pub(crate) fn build_collator_network(
 
 	let network_starter = NetworkStarter::new(network_start_tx);
 
-	Ok((network_service, network_starter, Box::new(SyncOracle {})))
+	Ok((network_service, network_starter, Arc::new(SyncOracle {})))
 }
 
 fn adjust_network_config_light_in_peers(config: &mut NetworkConfiguration) {
diff --git a/polkadot/node/malus/src/variants/back_garbage_candidate.rs b/polkadot/node/malus/src/variants/back_garbage_candidate.rs
index 82475d291422582f5197613d4f347baaf203b929..b939a2151e2359828da74d317c9e2bc0af2c6e0c 100644
--- a/polkadot/node/malus/src/variants/back_garbage_candidate.rs
+++ b/polkadot/node/malus/src/variants/back_garbage_candidate.rs
@@ -20,14 +20,13 @@
 
 use polkadot_cli::{
 	service::{
-		AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs,
-		HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle,
-		ParachainHost, ProvideRuntimeApi,
+		AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen,
+		OverseerGenArgs, OverseerHandle,
 	},
 	validator_overseer_builder, Cli,
 };
 use polkadot_node_subsystem::SpawnGlue;
-use polkadot_node_subsystem_types::DefaultSubsystemClient;
+use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
 use sp_core::traits::SpawnNamed;
 
 use crate::{
@@ -63,13 +62,9 @@ impl OverseerGen for BackGarbageCandidates {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		let spawner = args.spawner.clone();
diff --git a/polkadot/node/malus/src/variants/common.rs b/polkadot/node/malus/src/variants/common.rs
index 011fcc80e37331909434ccd2fa1bfa1e96f48f35..eb6988f81811687442a36ae3f8ec225de48dd9df 100644
--- a/polkadot/node/malus/src/variants/common.rs
+++ b/polkadot/node/malus/src/variants/common.rs
@@ -23,10 +23,6 @@ use crate::{
 
 use polkadot_node_core_candidate_validation::find_validation_data;
 use polkadot_node_primitives::{InvalidCandidate, ValidationResult};
-use polkadot_node_subsystem::{
-	messages::{CandidateValidationMessage, ValidationFailed},
-	overseer,
-};
 
 use polkadot_primitives::{
 	CandidateCommitments, CandidateDescriptor, CandidateReceipt, PersistedValidationData,
diff --git a/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs b/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs
index b3555ba2f5beb3e45285bc443dee9a4d029b070b..7a95bdaead26e204bd4cd8b386ae02b5e12297f9 100644
--- a/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs
+++ b/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs
@@ -34,14 +34,13 @@
 use futures::channel::oneshot;
 use polkadot_cli::{
 	service::{
-		AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs,
-		HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle,
-		ParachainHost, ProvideRuntimeApi,
+		AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen,
+		OverseerGenArgs, OverseerHandle,
 	},
 	validator_overseer_builder, Cli,
 };
-use polkadot_node_subsystem::{messages::ApprovalVotingMessage, SpawnGlue};
-use polkadot_node_subsystem_types::{DefaultSubsystemClient, OverseerSignal};
+use polkadot_node_subsystem::SpawnGlue;
+use polkadot_node_subsystem_types::{ChainApiBackend, OverseerSignal, RuntimeApiSubsystemClient};
 use polkadot_node_subsystem_util::request_candidate_events;
 use polkadot_primitives::CandidateEvent;
 use sp_core::traits::SpawnNamed;
@@ -237,13 +236,9 @@ impl OverseerGen for DisputeFinalizedCandidates {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		gum::info!(
diff --git a/polkadot/node/malus/src/variants/dispute_valid_candidates.rs b/polkadot/node/malus/src/variants/dispute_valid_candidates.rs
index b9812cbb5012a4ff97e3f1ed146538147efda03b..a50fdce16e4ec41d6b9bea4f0190616f756d9193 100644
--- a/polkadot/node/malus/src/variants/dispute_valid_candidates.rs
+++ b/polkadot/node/malus/src/variants/dispute_valid_candidates.rs
@@ -24,14 +24,13 @@
 
 use polkadot_cli::{
 	service::{
-		AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs,
-		HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle,
-		ParachainHost, ProvideRuntimeApi,
+		AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen,
+		OverseerGenArgs, OverseerHandle,
 	},
 	validator_overseer_builder, Cli,
 };
 use polkadot_node_subsystem::SpawnGlue;
-use polkadot_node_subsystem_types::DefaultSubsystemClient;
+use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
 use sp_core::traits::SpawnNamed;
 
 // Filter wrapping related types.
@@ -80,13 +79,9 @@ impl OverseerGen for DisputeValidCandidates {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		let spawner = args.spawner.clone();
diff --git a/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs b/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs
index 22b44ddd1dc359620b199118bebf0bb83b69dada..739ed40db362a2ae330f14b7a24cc77c1ab76159 100644
--- a/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs
+++ b/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs
@@ -25,14 +25,13 @@
 use futures::channel::oneshot;
 use polkadot_cli::{
 	service::{
-		AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs,
-		HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle,
-		ParachainHost, ProvideRuntimeApi,
+		AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen,
+		OverseerGenArgs, OverseerHandle,
 	},
 	validator_overseer_builder, Cli,
 };
 use polkadot_node_primitives::{AvailableData, BlockData, PoV};
-use polkadot_node_subsystem_types::DefaultSubsystemClient;
+use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
 use polkadot_primitives::{CandidateDescriptor, CandidateReceipt};
 
 use polkadot_node_subsystem_util::request_validators;
@@ -52,7 +51,7 @@ use crate::{
 
 // Import extra types relevant to the particular
 // subsystem.
-use polkadot_node_subsystem::{messages::CandidateBackingMessage, SpawnGlue};
+use polkadot_node_subsystem::SpawnGlue;
 
 use std::sync::Arc;
 
@@ -296,13 +295,9 @@ impl OverseerGen for SuggestGarbageCandidates {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		gum::info!(
diff --git a/polkadot/node/malus/src/variants/support_disabled.rs b/polkadot/node/malus/src/variants/support_disabled.rs
index e25df56fd643cdde44b861973751b1cd23e25480..169c442db25b7426f44cdfbe2c4181233802a914 100644
--- a/polkadot/node/malus/src/variants/support_disabled.rs
+++ b/polkadot/node/malus/src/variants/support_disabled.rs
@@ -19,14 +19,13 @@
 
 use polkadot_cli::{
 	service::{
-		AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs,
-		HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle,
-		ParachainHost, ProvideRuntimeApi,
+		AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen,
+		OverseerGenArgs, OverseerHandle,
 	},
 	validator_overseer_builder, Cli,
 };
 use polkadot_node_subsystem::SpawnGlue;
-use polkadot_node_subsystem_types::DefaultSubsystemClient;
+use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
 use sp_core::traits::SpawnNamed;
 
 use crate::interceptor::*;
@@ -50,13 +49,9 @@ impl OverseerGen for SupportDisabled {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		validator_overseer_builder(
diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs
index 6dcdec07ca84bd0fe9456e2bc29cbdf6cee6a9f8..83a0afc077e7edfb4a60fb8ed4109157f020695b 100644
--- a/polkadot/node/service/src/lib.rs
+++ b/polkadot/node/service/src/lib.rs
@@ -92,6 +92,7 @@ pub use chain_spec::{GenericChainSpec, RococoChainSpec, WestendChainSpec};
 pub use consensus_common::{Proposal, SelectChain};
 use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE;
 use mmr_gadget::MmrGadget;
+use polkadot_node_subsystem_types::DefaultSubsystemClient;
 pub use polkadot_primitives::{Block, BlockId, BlockNumber, CollatorPair, Hash, Id as ParaId};
 pub use sc_client_api::{Backend, CallExecutor};
 pub use sc_consensus::{BlockImport, LongestChain};
@@ -1081,12 +1082,17 @@ pub fn new_full<OverseerGenerator: OverseerGen>(
 			None
 		};
 
+	let runtime_client = Arc::new(DefaultSubsystemClient::new(
+		overseer_client.clone(),
+		OffchainTransactionPoolFactory::new(transaction_pool.clone()),
+	));
+
 	let overseer_handle = if let Some(authority_discovery_service) = authority_discovery_service {
 		let (overseer, overseer_handle) = overseer_gen
-			.generate::<service::SpawnTaskHandle, FullClient>(
+			.generate::<service::SpawnTaskHandle, DefaultSubsystemClient<FullClient>>(
 				overseer_connector,
 				OverseerGenArgs {
-					runtime_client: overseer_client.clone(),
+					runtime_client,
 					network_service: network.clone(),
 					sync_service: sync_service.clone(),
 					authority_discovery_service,
@@ -1099,9 +1105,6 @@ pub fn new_full<OverseerGenerator: OverseerGen>(
 					overseer_message_channel_capacity_override,
 					req_protocol_names,
 					peerset_protocol_names,
-					offchain_transaction_pool_factory: OffchainTransactionPoolFactory::new(
-						transaction_pool.clone(),
-					),
 					notification_services,
 				},
 				ext_overseer_args,
diff --git a/polkadot/node/service/src/overseer.rs b/polkadot/node/service/src/overseer.rs
index b2b0786bfc24e5f702ddd82aec0676f0f9f795a8..a8167370464937ac91ae44056ea0b17b7184927a 100644
--- a/polkadot/node/service/src/overseer.rs
+++ b/polkadot/node/service/src/overseer.rs
@@ -14,10 +14,9 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-use super::{AuthorityDiscoveryApi, Block, Error, Hash, IsParachainNode, Registry};
-use polkadot_node_subsystem_types::DefaultSubsystemClient;
+use super::{Block, Error, Hash, IsParachainNode, Registry};
+use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
 use polkadot_overseer::{DummySubsystem, InitializedOverseerBuilder, SubsystemError};
-use sc_transaction_pool_api::OffchainTransactionPoolFactory;
 use sp_core::traits::SpawnNamed;
 
 use polkadot_availability_distribution::IncomingRequestReceivers;
@@ -40,14 +39,10 @@ use polkadot_overseer::{
 };
 
 use parking_lot::Mutex;
-use polkadot_primitives::runtime_api::ParachainHost;
 use sc_authority_discovery::Service as AuthorityDiscoveryService;
 use sc_client_api::AuxStore;
 use sc_keystore::LocalKeystore;
 use sc_network::{NetworkStateInfo, NotificationService};
-use sp_api::ProvideRuntimeApi;
-use sp_blockchain::HeaderBackend;
-use sp_consensus_babe::BabeApi;
 use std::{collections::HashMap, sync::Arc};
 
 pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem;
@@ -80,8 +75,6 @@ pub use polkadot_statement_distribution::StatementDistributionSubsystem;
 /// Arguments passed for overseer construction.
 pub struct OverseerGenArgs<'a, Spawner, RuntimeClient>
 where
-	RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-	RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
 	Spawner: 'static + SpawnNamed + Clone + Unpin,
 {
 	/// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others.
@@ -89,7 +82,7 @@ where
 	/// Underlying network service implementation.
 	pub network_service: Arc<sc_network::NetworkService<Block, Hash>>,
 	/// Underlying syncing service implementation.
-	pub sync_service: Arc<sc_network_sync::SyncingService<Block>>,
+	pub sync_service: Arc<dyn consensus_common::SyncOracle + Send + Sync>,
 	/// Underlying authority discovery service.
 	pub authority_discovery_service: AuthorityDiscoveryService,
 	/// Collations request receiver for network protocol v1.
@@ -111,8 +104,6 @@ where
 	pub req_protocol_names: ReqProtocolNames,
 	/// `PeerSet` protocol names to protocols mapping.
 	pub peerset_protocol_names: PeerSetProtocolNames,
-	/// The offchain transaction pool factory.
-	pub offchain_transaction_pool_factory: OffchainTransactionPoolFactory<Block>,
 	/// Notification services for validation/collation protocols.
 	pub notification_services: HashMap<PeerSet, Box<dyn NotificationService>>,
 }
@@ -160,7 +151,6 @@ pub fn validator_overseer_builder<Spawner, RuntimeClient>(
 		overseer_message_channel_capacity_override,
 		req_protocol_names,
 		peerset_protocol_names,
-		offchain_transaction_pool_factory,
 		notification_services,
 	}: OverseerGenArgs<Spawner, RuntimeClient>,
 	ExtendedOverseerGenArgs {
@@ -180,7 +170,7 @@ pub fn validator_overseer_builder<Spawner, RuntimeClient>(
 ) -> Result<
 	InitializedOverseerBuilder<
 		SpawnGlue<Spawner>,
-		Arc<DefaultSubsystemClient<RuntimeClient>>,
+		Arc<RuntimeClient>,
 		CandidateValidationSubsystem,
 		PvfCheckerSubsystem,
 		CandidateBackingSubsystem,
@@ -190,7 +180,7 @@ pub fn validator_overseer_builder<Spawner, RuntimeClient>(
 		BitfieldSigningSubsystem,
 		BitfieldDistributionSubsystem,
 		ProvisionerSubsystem,
-		RuntimeApiSubsystem<DefaultSubsystemClient<RuntimeClient>>,
+		RuntimeApiSubsystem<RuntimeClient>,
 		AvailabilityStoreSubsystem,
 		NetworkBridgeRxSubsystem<
 			Arc<sc_network::NetworkService<Block, Hash>>,
@@ -214,8 +204,7 @@ pub fn validator_overseer_builder<Spawner, RuntimeClient>(
 	Error,
 >
 where
-	RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-	RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+	RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 	Spawner: 'static + SpawnNamed + Clone + Unpin,
 {
 	use polkadot_node_subsystem_util::metrics::Metrics;
@@ -227,11 +216,6 @@ where
 
 	let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?;
 
-	let runtime_api_client = Arc::new(DefaultSubsystemClient::new(
-		runtime_client.clone(),
-		offchain_transaction_pool_factory,
-	));
-
 	let builder = Overseer::builder()
 		.network_bridge_tx(NetworkBridgeTxSubsystem::new(
 			network_service.clone(),
@@ -298,7 +282,7 @@ where
 		})
 		.provisioner(ProvisionerSubsystem::new(Metrics::register(registry)?))
 		.runtime_api(RuntimeApiSubsystem::new(
-			runtime_api_client.clone(),
+			runtime_client.clone(),
 			Metrics::register(registry)?,
 			spawner.clone(),
 		))
@@ -339,7 +323,7 @@ where
 		.activation_external_listeners(Default::default())
 		.span_per_active_leaf(Default::default())
 		.active_leaves(Default::default())
-		.supports_parachains(runtime_api_client)
+		.supports_parachains(runtime_client)
 		.metrics(metrics)
 		.spawner(spawner);
 
@@ -367,13 +351,12 @@ pub fn collator_overseer_builder<Spawner, RuntimeClient>(
 		overseer_message_channel_capacity_override,
 		req_protocol_names,
 		peerset_protocol_names,
-		offchain_transaction_pool_factory,
 		notification_services,
 	}: OverseerGenArgs<Spawner, RuntimeClient>,
 ) -> Result<
 	InitializedOverseerBuilder<
 		SpawnGlue<Spawner>,
-		Arc<DefaultSubsystemClient<RuntimeClient>>,
+		Arc<RuntimeClient>,
 		DummySubsystem,
 		DummySubsystem,
 		DummySubsystem,
@@ -383,7 +366,7 @@ pub fn collator_overseer_builder<Spawner, RuntimeClient>(
 		DummySubsystem,
 		DummySubsystem,
 		DummySubsystem,
-		RuntimeApiSubsystem<DefaultSubsystemClient<RuntimeClient>>,
+		RuntimeApiSubsystem<RuntimeClient>,
 		DummySubsystem,
 		NetworkBridgeRxSubsystem<
 			Arc<sc_network::NetworkService<Block, Hash>>,
@@ -407,24 +390,17 @@ pub fn collator_overseer_builder<Spawner, RuntimeClient>(
 	Error,
 >
 where
-	RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-	RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
 	Spawner: 'static + SpawnNamed + Clone + Unpin,
+	RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 {
 	use polkadot_node_subsystem_util::metrics::Metrics;
 
-	let metrics = <OverseerMetrics as MetricsTrait>::register(registry)?;
 	let notification_sinks = Arc::new(Mutex::new(HashMap::new()));
 
 	let spawner = SpawnGlue(spawner);
 
 	let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?;
 
-	let runtime_api_client = Arc::new(DefaultSubsystemClient::new(
-		runtime_client.clone(),
-		offchain_transaction_pool_factory,
-	));
-
 	let builder = Overseer::builder()
 		.network_bridge_tx(NetworkBridgeTxSubsystem::new(
 			network_service.clone(),
@@ -475,7 +451,7 @@ where
 		})
 		.provisioner(DummySubsystem)
 		.runtime_api(RuntimeApiSubsystem::new(
-			runtime_api_client.clone(),
+			runtime_client.clone(),
 			Metrics::register(registry)?,
 			spawner.clone(),
 		))
@@ -490,8 +466,8 @@ where
 		.activation_external_listeners(Default::default())
 		.span_per_active_leaf(Default::default())
 		.active_leaves(Default::default())
-		.supports_parachains(runtime_api_client)
-		.metrics(metrics)
+		.supports_parachains(runtime_client)
+		.metrics(Metrics::register(registry)?)
 		.spawner(spawner);
 
 	let builder = if let Some(capacity) = overseer_message_channel_capacity_override {
@@ -510,13 +486,9 @@ pub trait OverseerGen {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin;
 
 	// It would be nice to make `create_subsystems` part of this trait,
@@ -533,13 +505,9 @@ impl OverseerGen for ValidatorOverseerGen {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<Spawner, RuntimeClient>,
 		ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		let ext_args = ext_args.ok_or(Error::Overseer(SubsystemError::Context(
@@ -561,13 +529,9 @@ impl OverseerGen for CollatorOverseerGen {
 		connector: OverseerConnector,
 		args: OverseerGenArgs<Spawner, RuntimeClient>,
 		_ext_args: Option<ExtendedOverseerGenArgs>,
-	) -> Result<
-		(Overseer<SpawnGlue<Spawner>, Arc<DefaultSubsystemClient<RuntimeClient>>>, OverseerHandle),
-		Error,
-	>
+	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
 	where
-		RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
-		RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
 		Spawner: 'static + SpawnNamed + Clone + Unpin,
 	{
 		collator_overseer_builder(args)?
diff --git a/polkadot/node/subsystem-types/src/runtime_client.rs b/polkadot/node/subsystem-types/src/runtime_client.rs
index 7f6183076101b4474e8059435b42a69b108fbb05..4039fc9127da95e19e0aca427740793c39131ab9 100644
--- a/polkadot/node/subsystem-types/src/runtime_client.rs
+++ b/polkadot/node/subsystem-types/src/runtime_client.rs
@@ -26,13 +26,13 @@ use polkadot_primitives::{
 	PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo,
 	ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature,
 };
-use sc_client_api::HeaderBackend;
+use sc_client_api::{AuxStore, HeaderBackend};
 use sc_transaction_pool_api::OffchainTransactionPoolFactory;
 use sp_api::{ApiError, ApiExt, ProvideRuntimeApi};
 use sp_authority_discovery::AuthorityDiscoveryApi;
-use sp_blockchain::Info;
+use sp_blockchain::{BlockStatus, Info};
 use sp_consensus_babe::{BabeApi, Epoch};
-use sp_runtime::traits::{Header as HeaderT, NumberFor};
+use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
 use std::{collections::BTreeMap, sync::Arc};
 
 /// Offers header utilities.
@@ -595,3 +595,61 @@ where
 		self.client.runtime_api().approval_voting_params(at)
 	}
 }
+
+impl<Client, Block> HeaderBackend<Block> for DefaultSubsystemClient<Client>
+where
+	Client: HeaderBackend<Block>,
+	Block: sp_runtime::traits::Block,
+{
+	fn header(
+		&self,
+		hash: Block::Hash,
+	) -> sc_client_api::blockchain::Result<Option<Block::Header>> {
+		self.client.header(hash)
+	}
+
+	fn info(&self) -> Info<Block> {
+		self.client.info()
+	}
+
+	fn status(&self, hash: Block::Hash) -> sc_client_api::blockchain::Result<BlockStatus> {
+		self.client.status(hash)
+	}
+
+	fn number(
+		&self,
+		hash: Block::Hash,
+	) -> sc_client_api::blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
+		self.client.number(hash)
+	}
+
+	fn hash(
+		&self,
+		number: NumberFor<Block>,
+	) -> sc_client_api::blockchain::Result<Option<Block::Hash>> {
+		self.client.hash(number)
+	}
+}
+
+impl<Client> AuxStore for DefaultSubsystemClient<Client>
+where
+	Client: AuxStore,
+{
+	fn insert_aux<
+		'a,
+		'b: 'a,
+		'c: 'a,
+		I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
+		D: IntoIterator<Item = &'a &'b [u8]>,
+	>(
+		&self,
+		insert: I,
+		delete: D,
+	) -> sp_blockchain::Result<()> {
+		self.client.insert_aux(insert, delete)
+	}
+
+	fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
+		self.client.get_aux(key)
+	}
+}
diff --git a/substrate/utils/wasm-builder/src/prerequisites.rs b/substrate/utils/wasm-builder/src/prerequisites.rs
index a601e3210dd0c2b89beffa1d5d6b788cb35fd6a3..22caf8950637960310c62eb98c5358de55c1662d 100644
--- a/substrate/utils/wasm-builder/src/prerequisites.rs
+++ b/substrate/utils/wasm-builder/src/prerequisites.rs
@@ -149,6 +149,14 @@ impl<'a> DummyCrate<'a> {
 		sysroot_cmd.output().ok().and_then(|o| String::from_utf8(o.stdout).ok())
 	}
 
+	fn get_toolchain(&self) -> Option<String> {
+		let sysroot = self.get_sysroot()?;
+		Path::new(sysroot.trim())
+			.file_name()
+			.and_then(|s| s.to_str())
+			.map(|s| s.to_string())
+	}
+
 	fn try_build(&self) -> Result<(), Option<String>> {
 		let Ok(result) = self.prepare_command("build").output() else { return Err(None) };
 		if !result.status.success() {
@@ -164,14 +172,15 @@ fn check_wasm_toolchain_installed(
 	let dummy_crate = DummyCrate::new(&cargo_command, RuntimeTarget::Wasm);
 
 	if let Err(error) = dummy_crate.try_build() {
+		let toolchain = dummy_crate.get_toolchain().unwrap_or("<unknown>".to_string());
 		let basic_error_message = colorize_error_message(
-			"Rust WASM toolchain is not properly installed; please install it!",
+			&format!("Rust WASM target for toolchain {toolchain} is not properly installed; please install it!")
 		);
 		return match error {
 			None => Err(basic_error_message),
 			Some(error) if error.contains("the `wasm32-unknown-unknown` target may not be installed") => {
-				Err(colorize_error_message("Cannot compile the WASM runtime: the `wasm32-unknown-unknown` target is not installed!\n\
-				                         You can install it with `rustup target add wasm32-unknown-unknown` if you're using `rustup`."))
+				Err(colorize_error_message(&format!("Cannot compile the WASM runtime: the `wasm32-unknown-unknown` target is not installed!\n\
+				                         You can install it with `rustup target add wasm32-unknown-unknown --toolchain {toolchain}` if you're using `rustup`.")))
 			},
 			// Apparently this can happen when we're running on a non Tier 1 platform.
 			Some(ref error) if error.contains("linker `rust-lld` not found") =>
@@ -193,9 +202,10 @@ fn check_wasm_toolchain_installed(
 			let src_path =
 				Path::new(sysroot.trim()).join("lib").join("rustlib").join("src").join("rust");
 			if !src_path.exists() {
+				let toolchain = dummy_crate.get_toolchain().unwrap_or("<toolchain>".to_string());
 				return Err(colorize_error_message(
-					"Cannot compile the WASM runtime: no standard library sources found!\n\
-					 You can install them with `rustup component add rust-src` if you're using `rustup`.",
+					&format!("Cannot compile the WASM runtime: no standard library sources found at {}!\n\
+					 You can install them with `rustup component add rust-src --toolchain {toolchain}` if you're using `rustup`.", src_path.display()),
 				))
 			}
 		}