Use header cache when creating state. (#5868)

* Use header cache for state_at

* Fixed warnings

* Update client/db/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Arkadiy Paronyan
2020-05-04 15:47:23 +02:00
committed by GitHub
parent e5163380e7
commit 4151dc6bfe
4 changed files with 52 additions and 28 deletions
+15 -14
View File
@@ -1590,10 +1590,16 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
_ => {} _ => {}
} }
match self.blockchain.header(block) { let hash = match block {
Ok(Some(ref hdr)) => { BlockId::Hash(h) => h,
let hash = hdr.hash(); BlockId::Number(n) => self.blockchain.hash(n)?.ok_or_else(||
if !self.have_state_at(&hash, *hdr.number()) { 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( return Err(
sp_blockchain::Error::UnknownBlock( sp_blockchain::Error::UnknownBlock(
format!("State already discarded for {:?}", block) 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) { if let Ok(()) = self.storage.state_db.pin(&hash) {
let root = hdr.state_root(); let root = hdr.state_root;
let db_state = DbState::<Block>::new(self.storage.clone(), *root); let db_state = DbState::<Block>::new(self.storage.clone(), root);
let state = RefTrackingState::new( let state = RefTrackingState::new(
db_state, db_state,
self.storage.clone(), 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), Err(e) => Err(e),
} }
} }
fn have_state_at(&self, hash: &Block::Hash, number: NumberFor<Block>) -> bool { fn have_state_at(&self, hash: &Block::Hash, number: NumberFor<Block>) -> bool {
if self.is_archive { if self.is_archive {
match self.blockchain.header(BlockId::Hash(hash.clone())) { match self.blockchain.header_metadata(hash.clone()) {
Ok(Some(header)) => { Ok(header) => {
sp_state_machine::Storage::get( sp_state_machine::Storage::get(
self.storage.as_ref(), self.storage.as_ref(),
&header.state_root(), &header.state_root,
(&[], None), (&[], None),
).unwrap_or(None).is_some() ).unwrap_or(None).is_some()
}, },
+30 -13
View File
@@ -26,7 +26,7 @@ use parking_lot::{Mutex, RwLock};
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use hash_db::Prefix; use hash_db::Prefix;
use sp_core::{ use sp_core::{
ChangesTrieConfiguration, convert_hash, traits::CodeExecutor, NativeOrEncoded, ChangesTrieConfiguration, convert_hash, NativeOrEncoded,
storage::{StorageKey, PrefixedStorageKey, StorageData, well_known_keys, ChildInfo}, storage::{StorageKey, PrefixedStorageKey, StorageData, well_known_keys, ChildInfo},
}; };
use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sc_telemetry::{telemetry, SUBSTRATE_INFO};
@@ -43,7 +43,7 @@ use sp_state_machine::{
prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage,
ChangesTrieConfigurationRange, key_changes, key_changes_proof, ChangesTrieConfigurationRange, key_changes, key_changes_proof,
}; };
use sc_executor::{RuntimeVersion, RuntimeInfo}; use sc_executor::RuntimeVersion;
use sp_consensus::{ use sp_consensus::{
Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams,
ImportResult, BlockOrigin, ForkChoiceStrategy, RecordProof, ImportResult, BlockOrigin, ForkChoiceStrategy, RecordProof,
@@ -61,26 +61,41 @@ use sp_api::{
CallApiAtParams, CallApiAtParams,
}; };
use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider};
use sc_client_api::{backend::{ use sc_client_api::{
self, BlockImportOperation, PrunableStateChangesTrieStorage, backend::{
ClientImportOperation, Finalizer, ImportSummary, NewBlockState, self, BlockImportOperation, PrunableStateChangesTrieStorage,
changes_tries_state_at_block, StorageProvider, ClientImportOperation, Finalizer, ImportSummary, NewBlockState,
LockImportRun, apply_aux, changes_tries_state_at_block, StorageProvider,
}, client::{ LockImportRun, apply_aux,
ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification, },
ClientInfo, BlockchainEvents, BlockBackend, ProvideUncles, BadBlocks, ForkBlocks, client::{
BlockOf, ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification,
}, execution_extensions::ExecutionExtensions, notifications::{StorageNotifications, StorageEventStream}, KeyIterator, CallExecutor, ExecutorProvider, ProofProvider, CloneableSpawn, cht, in_mem, UsageProvider}; 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_utils::mpsc::tracing_unbounded;
use sp_blockchain::Error; use sp_blockchain::Error;
use prometheus_endpoint::Registry; use prometheus_endpoint::Registry;
use super::{ use super::{
genesis, call_executor::LocalCallExecutor, genesis,
light::{call_executor::prove_execution, fetcher::ChangesProof}, light::{call_executor::prove_execution, fetcher::ChangesProof},
block_rules::{BlockRules, LookupResult as BlockLookupResult}, block_rules::{BlockRules, LookupResult as BlockLookupResult},
}; };
use futures::channel::mpsc; 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>>>; type NotificationSinks<T> = Mutex<Vec<mpsc::UnboundedSender<T>>>;
/// Substrate Client /// Substrate Client
@@ -126,6 +141,7 @@ impl<H> PrePostHeader<H> {
} }
/// Create an instance of in-memory client. /// Create an instance of in-memory client.
#[cfg(feature="test-helpers")]
pub fn new_in_mem<E, Block, S, RA>( pub fn new_in_mem<E, Block, S, RA>(
executor: E, executor: E,
genesis_storage: &S, genesis_storage: &S,
@@ -165,6 +181,7 @@ pub struct ClientConfig {
/// Create a client with the explicitly provided backend. /// Create a client with the explicitly provided backend.
/// This is useful for testing backend implementations. /// This is useful for testing backend implementations.
#[cfg(feature="test-helpers")]
pub fn new_with_backend<B, E, Block, S, RA>( pub fn new_with_backend<B, E, Block, S, RA>(
backend: Arc<B>, backend: Arc<B>,
executor: E, executor: E,
+4 -1
View File
@@ -50,5 +50,8 @@ mod block_rules;
pub use self::{ pub use self::{
call_executor::LocalCallExecutor, 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};
@@ -265,6 +265,8 @@ pub struct CachedHeaderMetadata<Block: BlockT> {
pub number: NumberFor<Block>, pub number: NumberFor<Block>,
/// Hash of parent header. /// Hash of parent header.
pub parent: Block::Hash, pub parent: Block::Hash,
/// Block state root.
pub state_root: Block::Hash,
/// Hash of an ancestor header. Used to jump through the tree. /// Hash of an ancestor header. Used to jump through the tree.
ancestor: Block::Hash, ancestor: Block::Hash,
} }
@@ -275,6 +277,7 @@ impl<Block: BlockT> From<&Block::Header> for CachedHeaderMetadata<Block> {
hash: header.hash().clone(), hash: header.hash().clone(),
number: header.number().clone(), number: header.number().clone(),
parent: header.parent_hash().clone(), parent: header.parent_hash().clone(),
state_root: header.state_root().clone(),
ancestor: header.parent_hash().clone(), ancestor: header.parent_hash().clone(),
} }
} }