Files
pezkuwi-subxt/substrate/primitives/state-machine/src/changes_trie/storage.rs
T
Benjamin Kampmann 60e5011c72 Reorganising the repository - external renames and moves (#4074)
* Adding first rough ouline of the repository structure

* Remove old CI stuff

* add title

* formatting fixes

* move node-exits job's script to scripts dir

* Move docs into subdir

* move to bin

* move maintainence scripts, configs and helpers into its own dir

* add .local to ignore

* move core->client

* start up 'test' area

* move test client

* move test runtime

* make test move compile

* Add dependencies rule enforcement.

* Fix indexing.

* Update docs to reflect latest changes

* Moving /srml->/paint

* update docs

* move client/sr-* -> primitives/

* clean old readme

* remove old broken code in rhd

* update lock

* Step 1.

* starting to untangle client

* Fix after merge.

* start splitting out client interfaces

* move children and blockchain interfaces

* Move trie and state-machine to primitives.

* Fix WASM builds.

* fixing broken imports

* more interface moves

* move backend and light to interfaces

* move CallExecutor

* move cli off client

* moving around more interfaces

* re-add consensus crates into the mix

* fix subkey path

* relieve client from executor

* starting to pull out client from grandpa

* move is_decendent_of out of client

* grandpa still depends on client directly

* lemme tests pass

* rename srml->paint

* Make it compile.

* rename interfaces->client-api

* Move keyring to primitives.

* fixup libp2p dep

* fix broken use

* allow dependency enforcement to fail

* move fork-tree

* Moving wasm-builder

* make env

* move build-script-utils

* fixup broken crate depdencies and names

* fix imports for authority discovery

* fix typo

* update cargo.lock

* fixing imports

* Fix paths and add missing crates

* re-add missing crates
2019-11-14 21:51:17 +01:00

209 lines
6.0 KiB
Rust

// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Changes trie storage utilities.
use std::collections::{BTreeMap, HashSet, HashMap};
use hash_db::{Hasher, Prefix, EMPTY_PREFIX};
use trie::DBValue;
use trie::MemoryDB;
use parking_lot::RwLock;
use crate::changes_trie::{BuildCache, RootsStorage, Storage, AnchorBlockId, BlockNumber};
use crate::trie_backend_essence::TrieBackendStorage;
#[cfg(test)]
use crate::backend::insert_into_memory_db;
#[cfg(test)]
use crate::changes_trie::input::{InputPair, ChildIndex};
/// In-memory implementation of changes trie storage.
pub struct InMemoryStorage<H: Hasher, Number: BlockNumber> {
data: RwLock<InMemoryStorageData<H, Number>>,
cache: BuildCache<H::Out, Number>,
}
/// Adapter for using changes trie storage as a TrieBackendEssence' storage.
pub struct TrieBackendAdapter<'a, H: Hasher, Number: BlockNumber> {
storage: &'a dyn Storage<H, Number>,
_hasher: ::std::marker::PhantomData<(H, Number)>,
}
struct InMemoryStorageData<H: Hasher, Number: BlockNumber> {
roots: BTreeMap<Number, H::Out>,
mdb: MemoryDB<H>,
}
impl<H: Hasher, Number: BlockNumber> InMemoryStorage<H, Number> {
/// Creates storage from given in-memory database.
pub fn with_db(mdb: MemoryDB<H>) -> Self {
Self {
data: RwLock::new(InMemoryStorageData {
roots: BTreeMap::new(),
mdb,
}),
cache: BuildCache::new(),
}
}
/// Creates storage with empty database.
pub fn new() -> Self {
Self::with_db(Default::default())
}
/// Creates storage with given proof.
pub fn with_proof(proof: Vec<Vec<u8>>) -> Self {
use hash_db::HashDB;
let mut proof_db = MemoryDB::<H>::default();
for item in proof {
proof_db.insert(EMPTY_PREFIX, &item);
}
Self::with_db(proof_db)
}
/// Get mutable cache reference.
pub fn cache_mut(&mut self) -> &mut BuildCache<H::Out, Number> {
&mut self.cache
}
/// Create the storage with given blocks.
pub fn with_blocks(blocks: Vec<(Number, H::Out)>) -> Self {
Self {
data: RwLock::new(InMemoryStorageData {
roots: blocks.into_iter().collect(),
mdb: MemoryDB::default(),
}),
cache: BuildCache::new(),
}
}
#[cfg(test)]
pub fn with_inputs(
mut top_inputs: Vec<(Number, Vec<InputPair<Number>>)>,
children_inputs: Vec<(Vec<u8>, Vec<(Number, Vec<InputPair<Number>>)>)>,
) -> Self {
let mut mdb = MemoryDB::default();
let mut roots = BTreeMap::new();
for (storage_key, child_input) in children_inputs {
for (block, pairs) in child_input {
let root = insert_into_memory_db::<H, _>(&mut mdb, pairs.into_iter().map(Into::into));
if let Some(root) = root {
let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) {
ix
} else {
top_inputs.push((block.clone(), Default::default()));
top_inputs.len() - 1
};
top_inputs[ix].1.push(InputPair::ChildIndex(
ChildIndex { block: block.clone(), storage_key: storage_key.clone() },
root.as_ref().to_vec(),
));
}
}
}
for (block, pairs) in top_inputs {
let root = insert_into_memory_db::<H, _>(&mut mdb, pairs.into_iter().map(Into::into));
if let Some(root) = root {
roots.insert(block, root);
}
}
InMemoryStorage {
data: RwLock::new(InMemoryStorageData {
roots,
mdb,
}),
cache: BuildCache::new(),
}
}
#[cfg(test)]
pub fn clear_storage(&self) {
self.data.write().mdb = MemoryDB::default(); // use new to be more correct
}
#[cfg(test)]
pub fn remove_from_storage(&self, keys: &HashSet<H::Out>) {
let mut data = self.data.write();
for key in keys {
data.mdb.remove_and_purge(key, hash_db::EMPTY_PREFIX);
}
}
#[cfg(test)]
pub fn into_mdb(self) -> MemoryDB<H> {
self.data.into_inner().mdb
}
/// Insert changes trie for given block.
pub fn insert(&self, block: Number, changes_trie_root: H::Out, trie: MemoryDB<H>) {
let mut data = self.data.write();
data.roots.insert(block, changes_trie_root);
data.mdb.consolidate(trie);
}
}
impl<H: Hasher, Number: BlockNumber> RootsStorage<H, Number> for InMemoryStorage<H, Number> {
fn build_anchor(&self, parent_hash: H::Out) -> Result<AnchorBlockId<H::Out, Number>, String> {
self.data.read().roots.iter()
.find(|(_, v)| **v == parent_hash)
.map(|(k, _)| AnchorBlockId { hash: parent_hash, number: k.clone() })
.ok_or_else(|| format!("Can't find associated number for block {:?}", parent_hash))
}
fn root(&self, _anchor_block: &AnchorBlockId<H::Out, Number>, block: Number) -> Result<Option<H::Out>, String> {
Ok(self.data.read().roots.get(&block).cloned())
}
}
impl<H: Hasher, Number: BlockNumber> Storage<H, Number> for InMemoryStorage<H, Number> {
fn as_roots_storage(&self) -> &dyn RootsStorage<H, Number> {
self
}
fn with_cached_changed_keys(
&self,
root: &H::Out,
functor: &mut dyn FnMut(&HashMap<Option<Vec<u8>>, HashSet<Vec<u8>>>),
) -> bool {
self.cache.with_changed_keys(root, functor)
}
fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>, String> {
MemoryDB::<H>::get(&self.data.read().mdb, key, prefix)
}
}
impl<'a, H: Hasher, Number: BlockNumber> TrieBackendAdapter<'a, H, Number> {
pub fn new(storage: &'a dyn Storage<H, Number>) -> Self {
Self { storage, _hasher: Default::default() }
}
}
impl<'a, H, Number> TrieBackendStorage<H> for TrieBackendAdapter<'a, H, Number>
where
Number: BlockNumber,
H: Hasher,
{
type Overlay = MemoryDB<H>;
fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>, String> {
self.storage.get(key, prefix)
}
}