diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs
index a7246f398df5d21ae3e891c8abd79b3ca97935a0..5edfcb046f625971cd51fd87fa9472640e367c39 100644
--- a/substrate/client/db/src/lib.rs
+++ b/substrate/client/db/src/lib.rs
@@ -1590,10 +1590,16 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
 			_ => {}
 		}
 
-		match self.blockchain.header(block) {
-			Ok(Some(ref hdr)) => {
-				let hash = hdr.hash();
-				if !self.have_state_at(&hash, *hdr.number()) {
+		let hash = match block {
+			BlockId::Hash(h) => h,
+			BlockId::Number(n) => self.blockchain.hash(n)?.ok_or_else(||
+				sp_blockchain::Error::UnknownBlock(format!("Unknown block number {}", n))
+			)?,
+		};
+
+		match self.blockchain.header_metadata(hash) {
+			Ok(ref hdr) => {
+				if !self.have_state_at(&hash, hdr.number) {
 					return Err(
 						sp_blockchain::Error::UnknownBlock(
 							format!("State already discarded for {:?}", block)
@@ -1601,8 +1607,8 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
 					)
 				}
 				if let Ok(()) = self.storage.state_db.pin(&hash) {
-					let root = hdr.state_root();
-					let db_state = DbState::<Block>::new(self.storage.clone(), *root);
+					let root = hdr.state_root;
+					let db_state = DbState::<Block>::new(self.storage.clone(), root);
 					let state = RefTrackingState::new(
 						db_state,
 						self.storage.clone(),
@@ -1627,22 +1633,17 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
 					)
 				}
 			},
-			Ok(None) => Err(
-				sp_blockchain::Error::UnknownBlock(
-					format!("Unknown state for block {:?}", block)
-				)
-			),
 			Err(e) => Err(e),
 		}
 	}
 
 	fn have_state_at(&self, hash: &Block::Hash, number: NumberFor<Block>) -> bool {
 		if self.is_archive {
-			match self.blockchain.header(BlockId::Hash(hash.clone())) {
-				Ok(Some(header)) => {
+			match self.blockchain.header_metadata(hash.clone()) {
+				Ok(header) => {
 					sp_state_machine::Storage::get(
 						self.storage.as_ref(),
-						&header.state_root(),
+						&header.state_root,
 						(&[], None),
 					).unwrap_or(None).is_some()
 				},
diff --git a/substrate/client/service/src/client/client.rs b/substrate/client/service/src/client/client.rs
index a5a02c85cfd36ca86aec024e037a0bc2d13da87d..bc992291bdbf2bdba57cacb746d26860854c0324 100644
--- a/substrate/client/service/src/client/client.rs
+++ b/substrate/client/service/src/client/client.rs
@@ -26,7 +26,7 @@ use parking_lot::{Mutex, RwLock};
 use codec::{Encode, Decode};
 use hash_db::Prefix;
 use sp_core::{
-	ChangesTrieConfiguration, convert_hash, traits::CodeExecutor, NativeOrEncoded,
+	ChangesTrieConfiguration, convert_hash, NativeOrEncoded,
 	storage::{StorageKey, PrefixedStorageKey, StorageData, well_known_keys, ChildInfo},
 };
 use sc_telemetry::{telemetry, SUBSTRATE_INFO};
@@ -43,7 +43,7 @@ use sp_state_machine::{
 	prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage,
 	ChangesTrieConfigurationRange, key_changes, key_changes_proof,
 };
-use sc_executor::{RuntimeVersion, RuntimeInfo};
+use sc_executor::RuntimeVersion;
 use sp_consensus::{
 	Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams,
 	ImportResult, BlockOrigin, ForkChoiceStrategy, RecordProof,
@@ -61,26 +61,41 @@ use sp_api::{
 	CallApiAtParams,
 };
 use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider};
-use sc_client_api::{backend::{
-	self, BlockImportOperation, PrunableStateChangesTrieStorage,
-	ClientImportOperation, Finalizer, ImportSummary, NewBlockState,
-	changes_tries_state_at_block, StorageProvider,
-	LockImportRun, apply_aux,
-}, client::{
-	ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification,
-	ClientInfo, BlockchainEvents, BlockBackend, ProvideUncles, BadBlocks, ForkBlocks,
-	BlockOf,
-}, execution_extensions::ExecutionExtensions, notifications::{StorageNotifications, StorageEventStream}, KeyIterator, CallExecutor, ExecutorProvider, ProofProvider, CloneableSpawn, cht, in_mem, UsageProvider};
+use sc_client_api::{
+	backend::{
+		self, BlockImportOperation, PrunableStateChangesTrieStorage,
+		ClientImportOperation, Finalizer, ImportSummary, NewBlockState,
+		changes_tries_state_at_block, StorageProvider,
+		LockImportRun, apply_aux,
+	},
+	client::{
+		ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification,
+		ClientInfo, BlockchainEvents, BlockBackend, ProvideUncles, BadBlocks, ForkBlocks,
+		BlockOf,
+	},
+	execution_extensions::ExecutionExtensions,
+	notifications::{StorageNotifications, StorageEventStream},
+	KeyIterator, CallExecutor, ExecutorProvider, ProofProvider,
+	cht, UsageProvider
+};
 use sp_utils::mpsc::tracing_unbounded;
 use sp_blockchain::Error;
 use prometheus_endpoint::Registry;
 use super::{
-	genesis, call_executor::LocalCallExecutor,
+	genesis,
 	light::{call_executor::prove_execution, fetcher::ChangesProof},
 	block_rules::{BlockRules, LookupResult as BlockLookupResult},
 };
 use futures::channel::mpsc;
 
+#[cfg(feature="test-helpers")]
+use {
+	sp_core::traits::CodeExecutor,
+	sc_client_api::{CloneableSpawn, in_mem},
+	sc_executor::RuntimeInfo,
+	super::call_executor::LocalCallExecutor,
+};
+
 type NotificationSinks<T> = Mutex<Vec<mpsc::UnboundedSender<T>>>;
 
 /// Substrate Client
@@ -126,6 +141,7 @@ impl<H> PrePostHeader<H> {
 }
 
 /// Create an instance of in-memory client.
+#[cfg(feature="test-helpers")]
 pub fn new_in_mem<E, Block, S, RA>(
 	executor: E,
 	genesis_storage: &S,
@@ -165,6 +181,7 @@ pub struct ClientConfig {
 
 /// Create a client with the explicitly provided backend.
 /// This is useful for testing backend implementations.
+#[cfg(feature="test-helpers")]
 pub fn new_with_backend<B, E, Block, S, RA>(
 	backend: Arc<B>,
 	executor: E,
diff --git a/substrate/client/service/src/client/mod.rs b/substrate/client/service/src/client/mod.rs
index 079b9d243f982aec3ac1b105af2600df64d8624c..fe3ad992b6690dcf0e9aae19bb3e855d4078581a 100644
--- a/substrate/client/service/src/client/mod.rs
+++ b/substrate/client/service/src/client/mod.rs
@@ -50,5 +50,8 @@ mod block_rules;
 
 pub use self::{
 	call_executor::LocalCallExecutor,
-	client::{new_with_backend, new_in_mem, Client, ClientConfig},
+	client::{Client, ClientConfig},
 };
+
+#[cfg(feature="test-helpers")]
+pub use self::client::{new_with_backend, new_in_mem};
diff --git a/substrate/primitives/blockchain/src/header_metadata.rs b/substrate/primitives/blockchain/src/header_metadata.rs
index 85a94624c9243ca24e9f7b7b7fa0eef7b46c3b89..bdc2b09eea4b45ec02e6329602a888fd7b98ca8d 100644
--- a/substrate/primitives/blockchain/src/header_metadata.rs
+++ b/substrate/primitives/blockchain/src/header_metadata.rs
@@ -265,6 +265,8 @@ pub struct CachedHeaderMetadata<Block: BlockT> {
 	pub number: NumberFor<Block>,
 	/// Hash of parent header.
 	pub parent: Block::Hash,
+	/// Block state root.
+	pub state_root: Block::Hash,
 	/// Hash of an ancestor header. Used to jump through the tree.
 	ancestor: Block::Hash,
 }
@@ -275,6 +277,7 @@ impl<Block: BlockT> From<&Block::Header> for CachedHeaderMetadata<Block> {
 			hash: header.hash().clone(),
 			number: header.number().clone(),
 			parent: header.parent_hash().clone(),
+			state_root: header.state_root().clone(),
 			ancestor: header.parent_hash().clone(),
 		}
 	}