Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Changes tries build cache #2933

Merged
merged 7 commits into from
Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions core/client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ mod utils;
use std::sync::Arc;
use std::path::PathBuf;
use std::io;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

use client::backend::NewBlockState;
use client::blockchain::HeaderBackend;
Expand All @@ -58,7 +58,7 @@ use sr_primitives::traits::{
};
use state_machine::backend::Backend as StateBackend;
use executor::RuntimeInfo;
use state_machine::{CodeExecutor, DBValue};
use state_machine::{CodeExecutor, DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, ChangesTrieBuildCache};
use crate::utils::{Meta, db_err, meta_keys, read_db, block_id_to_lookup_key, read_meta};
use client::leaves::{LeafSet, FinalizationDisplaced};
use client::children;
Expand Down Expand Up @@ -405,6 +405,7 @@ pub struct BlockImportOperation<Block: BlockT, H: Hasher> {
storage_updates: StorageCollection,
child_storage_updates: ChildStorageCollection,
changes_trie_updates: MemoryDB<H>,
changes_trie_cache_update: Option<ChangesTrieCacheAction<H::Out, NumberFor<Block>>>,
pending_block: Option<PendingBlock<Block>>,
aux_ops: Vec<(Vec<u8>, Option<Vec<u8>>)>,
finalized_blocks: Vec<(BlockId<Block>, Option<Justification>)>,
Expand Down Expand Up @@ -487,8 +488,12 @@ where Block: BlockT<Hash=H256>,
Ok(root)
}

fn update_changes_trie(&mut self, update: MemoryDB<Blake2Hasher>) -> Result<(), client::error::Error> {
self.changes_trie_updates = update;
fn update_changes_trie(
&mut self,
update: ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>,
) -> Result<(), client::error::Error> {
self.changes_trie_updates = update.0;
self.changes_trie_cache_update = Some(update.1);
Ok(())
}

Expand Down Expand Up @@ -565,6 +570,7 @@ pub struct DbChangesTrieStorage<Block: BlockT> {
db: Arc<dyn KeyValueDB>,
meta: Arc<RwLock<Meta<NumberFor<Block>, Block::Hash>>>,
min_blocks_to_keep: Option<u32>,
cache: RwLock<ChangesTrieBuildCache<Block::Hash, NumberFor<Block>>>,
_phantom: ::std::marker::PhantomData<Block>,
}

Expand All @@ -576,6 +582,11 @@ impl<Block: BlockT<Hash=H256>> DbChangesTrieStorage<Block> {
}
}

/// Commit changes into changes trie build cache.
pub fn commit_cache(&self, cache_update: ChangesTrieCacheAction<Block::Hash, NumberFor<Block>>) {
self.cache.write().perform(cache_update);
}

/// Prune obsolete changes tries.
pub fn prune(
&self,
Expand Down Expand Up @@ -699,6 +710,14 @@ where
self
}

fn with_cached_changed_keys(
&self,
root: &H256,
functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
) -> bool {
self.cache.read().with_changed_keys(root, functor)
}

fn get(&self, key: &H256, _prefix: Prefix) -> Result<Option<DBValue>, String> {
self.db.get(columns::CHANGES_TRIE, &key[..])
.map_err(|err| format!("{}", err))
Expand Down Expand Up @@ -783,6 +802,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
db,
meta,
min_blocks_to_keep: if is_archive_pruning { None } else { Some(MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR) },
cache: RwLock::new(ChangesTrieBuildCache::new()),
_phantom: Default::default(),
};

Expand Down Expand Up @@ -1098,7 +1118,6 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
self.changes_tries_storage.commit(&mut transaction, changes_trie_updates);
let cache = operation.old_state.release(); // release state reference so that it can be finalized


if finalized {
// TODO: ensure best chain contains this block.
self.ensure_sequential_finalization(header, Some(last_finalized_hash))?;
Expand Down Expand Up @@ -1155,6 +1174,10 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {

let write_result = self.storage.db.write(transaction).map_err(db_err);

if let Some(changes_trie_cache_update) = operation.changes_trie_cache_update {
self.changes_tries_storage.commit_cache(changes_trie_cache_update);
}

if let Some((number, hash, enacted, retracted, displaced_leaf, is_best, mut cache)) = imported {
if let Err(e) = write_result {
let mut leaves = self.blockchain.leaves.write();
Expand Down Expand Up @@ -1288,6 +1311,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
storage_updates: Default::default(),
child_storage_updates: Default::default(),
changes_trie_updates: MemoryDB::default(),
changes_trie_cache_update: None,
aux_ops: Vec::new(),
finalized_blocks: Vec::new(),
set_head: None,
Expand Down Expand Up @@ -1515,7 +1539,7 @@ mod tests {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block_id).unwrap();
op.set_block_data(header, None, None, NewBlockState::Best).unwrap();
op.update_changes_trie(changes_trie_update).unwrap();
op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)).unwrap();
backend.commit_operation(op).unwrap();

header_hash
Expand Down
5 changes: 2 additions & 3 deletions core/client/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ use primitives::ChangesTrieConfiguration;
use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay};
use sr_primitives::traits::{Block as BlockT, NumberFor};
use state_machine::backend::Backend as StateBackend;
use state_machine::ChangesTrieStorage as StateChangesTrieStorage;
use state_machine::{ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction};
use consensus::{well_known_cache_keys, BlockOrigin};
use hash_db::Hasher;
use trie::MemoryDB;
use parking_lot::Mutex;

/// In memory array of storage values.
Expand Down Expand Up @@ -116,7 +115,7 @@ pub trait BlockImportOperation<Block, H> where
child_update: ChildStorageCollection,
) -> error::Result<()>;
/// Inject changes trie data into the database.
fn update_changes_trie(&mut self, update: MemoryDB<H>) -> error::Result<()>;
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> error::Result<()>;
/// Insert auxiliary keys. Values are `None` if should be deleted.
fn insert_aux<I>(&mut self, ops: I) -> error::Result<()>
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>;
Expand Down
15 changes: 11 additions & 4 deletions core/client/src/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
use std::{sync::Arc, cmp::Ord, panic::UnwindSafe, result, cell::RefCell, rc::Rc};
use codec::{Encode, Decode};
use sr_primitives::{
generic::BlockId, traits::Block as BlockT,
generic::BlockId, traits::Block as BlockT, traits::NumberFor,
};
use state_machine::{
self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager,
ExecutionStrategy, NeverOffchainExt, backend::Backend as _,
ChangesTrieTransaction,
};
use executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
use hash_db::Hasher;
use trie::MemoryDB;
use primitives::{offchain, H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue};

use crate::runtime_api::{ProofRecorder, InitializeBlock};
Expand Down Expand Up @@ -111,7 +111,14 @@ where
manager: ExecutionManager<F>,
native_call: Option<NC>,
side_effects_handler: Option<&mut O>,
) -> Result<(NativeOrEncoded<R>, (S::Transaction, H::Out), Option<MemoryDB<H>>), error::Error>;
) -> Result<
(
NativeOrEncoded<R>,
(S::Transaction, H::Out),
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<B>>>
),
error::Error,
>;

/// Execute a call to a contract on top of given state, gathering execution proof.
///
Expand Down Expand Up @@ -345,7 +352,7 @@ where
) -> error::Result<(
NativeOrEncoded<R>,
(S::Transaction, <Blake2Hasher as Hasher>::Out),
Option<MemoryDB<Blake2Hasher>>,
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
)> {
state_machine::new(
state,
Expand Down
15 changes: 12 additions & 3 deletions core/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ use sr_primitives::{
use state_machine::{
DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId,
ExecutionStrategy, ExecutionManager, prove_read, prove_child_read,
ChangesTrieRootsStorage, ChangesTrieStorage, ChangesTrieConfigurationRange,
ChangesTrieRootsStorage, ChangesTrieStorage,
ChangesTrieTransaction, ChangesTrieConfigurationRange,
key_changes, key_changes_proof, OverlayedChanges, NeverOffchainExt,
};
use executor::{RuntimeVersion, RuntimeInfo};
Expand Down Expand Up @@ -86,7 +87,7 @@ type StorageUpdate<B, Block> = <
<B as backend::Backend<Block, Blake2Hasher>>::BlockImportOperation
as BlockImportOperation<Block, Blake2Hasher>
>::State as state_machine::Backend<Blake2Hasher>>::Transaction;
type ChangesUpdate = trie::MemoryDB<Blake2Hasher>;
type ChangesUpdate<Block> = ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>;

/// Execution strategies settings.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -635,6 +636,14 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
self
}

fn with_cached_changed_keys(
&self,
root: &H256,
functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
) -> bool {
self.storage.with_cached_changed_keys(root, functor)
}

fn get(&self, key: &H256, prefix: Prefix) -> Result<Option<DBValue>, String> {
self.storage.get(key, prefix)
}
Expand Down Expand Up @@ -1010,7 +1019,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
body: Option<Vec<Block::Extrinsic>>,
) -> error::Result<(
Option<StorageUpdate<B, Block>>,
Option<Option<ChangesUpdate>>,
Option<Option<ChangesUpdate<Block>>>,
Option<(
Vec<(Vec<u8>, Option<Vec<u8>>)>,
Vec<(Vec<u8>, Vec<(Vec<u8>, Option<Vec<u8>>)>)>
Expand Down
16 changes: 12 additions & 4 deletions core/client/src/in_mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

//! In memory client backend

use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use parking_lot::{RwLock, Mutex};
use primitives::{ChangesTrieConfiguration, storage::well_known_keys};
use sr_primitives::generic::{BlockId, DigestItem};
use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor};
use sr_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay};
use state_machine::backend::{Backend as StateBackend, InMemory};
use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId};
use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction};
use hash_db::{Hasher, Prefix};
use trie::MemoryDB;
use consensus::well_known_cache_keys::Id as CacheKeyId;
Expand Down Expand Up @@ -484,8 +484,8 @@ where
Ok(())
}

fn update_changes_trie(&mut self, update: MemoryDB<H>) -> error::Result<()> {
self.changes_trie_update = Some(update);
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> error::Result<()> {
self.changes_trie_update = Some(update.0);
svyatonik marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}

Expand Down Expand Up @@ -766,6 +766,14 @@ impl<Block, H> state_machine::ChangesTrieStorage<H, NumberFor<Block>> for Change
self
}

fn with_cached_changed_keys(
&self,
_root: &H::Out,
_functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
) -> bool {
false
}

fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<state_machine::DBValue>, String> {
self.0.get(key, prefix)
}
Expand Down
4 changes: 2 additions & 2 deletions core/client/src/light/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::sync::{Arc, Weak};
use parking_lot::{RwLock, Mutex};

use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay};
use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState};
use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState, ChangesTrieTransaction};
use sr_primitives::traits::{Block as BlockT, NumberFor, Zero, Header};
use crate::in_mem::{self, check_genesis_storage};
use crate::backend::{
Expand Down Expand Up @@ -284,7 +284,7 @@ where
Ok(())
}

fn update_changes_trie(&mut self, _update: MemoryDB<H>) -> ClientResult<()> {
fn update_changes_trie(&mut self, _update: ChangesTrieTransaction<H, NumberFor<Block>>) -> ClientResult<()> {
// we're not storing anything locally => ignore changes
Ok(())
}
Expand Down
9 changes: 4 additions & 5 deletions core/client/src/light/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ use std::{
use codec::{Encode, Decode};
use primitives::{offchain, H256, Blake2Hasher, convert_hash, NativeOrEncoded};
use sr_primitives::generic::BlockId;
use sr_primitives::traits::{One, Block as BlockT, Header as HeaderT};
use sr_primitives::traits::{One, Block as BlockT, Header as HeaderT, NumberFor};
use state_machine::{
self, Backend as StateBackend, CodeExecutor, OverlayedChanges,
ExecutionStrategy, create_proof_check_backend,
ExecutionStrategy, ChangesTrieTransaction, create_proof_check_backend,
execution_proof_check_on_trie_backend, ExecutionManager, NeverOffchainExt
};
use hash_db::Hasher;
Expand All @@ -40,7 +40,6 @@ use crate::call_executor::CallExecutor;
use crate::error::{Error as ClientError, Result as ClientResult};
use crate::light::fetcher::{Fetcher, RemoteCallRequest};
use executor::{RuntimeVersion, NativeVersion};
use trie::MemoryDB;

/// Call executor that executes methods on remote node, querying execution proof
/// and checking proof by re-executing locally.
Expand Down Expand Up @@ -185,7 +184,7 @@ where
) -> ClientResult<(
NativeOrEncoded<R>,
(S::Transaction, <Blake2Hasher as Hasher>::Out),
Option<MemoryDB<Blake2Hasher>>,
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
)> {
Err(ClientError::NotAvailableOnLightClient.into())
}
Expand Down Expand Up @@ -365,7 +364,7 @@ impl<Block, B, Remote, Local> CallExecutor<Block, Blake2Hasher> for
) -> ClientResult<(
NativeOrEncoded<R>,
(S::Transaction, <Blake2Hasher as Hasher>::Out),
Option<MemoryDB<Blake2Hasher>>,
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
)> {
// there's no actual way/need to specify native/wasm execution strategy on light node
// => we can safely ignore passed values
Expand Down
2 changes: 1 addition & 1 deletion core/client/src/light/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ struct RootsStorage<'a, Number: SimpleArithmetic, Hash: 'a> {
impl<'a, H, Number, Hash> ChangesTrieRootsStorage<H, Number> for RootsStorage<'a, Number, Hash>
where
H: Hasher,
Number: ::std::fmt::Display + Clone + SimpleArithmetic + Encode + Decode + Send + Sync + 'static,
Number: ::std::fmt::Display + ::std::hash::Hash + Clone + SimpleArithmetic + Encode + Decode + Send + Sync + 'static,
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
{
fn build_anchor(
Expand Down
Loading