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(), } }