From 4151dc6bfe789e38cc49f0fefebb7e6a9d9541ea Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 4 May 2020 15:47:23 +0200 Subject: [PATCH] Use header cache when creating state. (#5868) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use header cache for state_at * Fixed warnings * Update client/db/src/lib.rs Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher --- substrate/client/db/src/lib.rs | 29 +++++++------ substrate/client/service/src/client/client.rs | 43 +++++++++++++------ substrate/client/service/src/client/mod.rs | 5 ++- .../blockchain/src/header_metadata.rs | 3 ++ 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index a7246f398d..5edfcb046f 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -1590,10 +1590,16 @@ impl sc_client_api::backend::Backend for Backend { _ => {} } - 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 sc_client_api::backend::Backend for Backend { ) } if let Ok(()) = self.storage.state_db.pin(&hash) { - let root = hdr.state_root(); - let db_state = DbState::::new(self.storage.clone(), *root); + let root = hdr.state_root; + let db_state = DbState::::new(self.storage.clone(), root); let state = RefTrackingState::new( db_state, self.storage.clone(), @@ -1627,22 +1633,17 @@ impl sc_client_api::backend::Backend for Backend { ) } }, - 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) -> 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 a5a02c85cf..bc992291bd 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 = Mutex>>; /// Substrate Client @@ -126,6 +141,7 @@ impl PrePostHeader { } /// Create an instance of in-memory client. +#[cfg(feature="test-helpers")] pub fn new_in_mem( 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( backend: Arc, executor: E, diff --git a/substrate/client/service/src/client/mod.rs b/substrate/client/service/src/client/mod.rs index 079b9d243f..fe3ad992b6 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 85a94624c9..bdc2b09eea 100644 --- a/substrate/primitives/blockchain/src/header_metadata.rs +++ b/substrate/primitives/blockchain/src/header_metadata.rs @@ -265,6 +265,8 @@ pub struct CachedHeaderMetadata { pub number: NumberFor, /// 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 From<&Block::Header> for CachedHeaderMetadata { hash: header.hash().clone(), number: header.number().clone(), parent: header.parent_hash().clone(), + state_root: header.state_root().clone(), ancestor: header.parent_hash().clone(), } }