// Copyright 2017-2018 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 . //! State machine backends. These manage the code and storage of contracts. use std::{error, fmt}; use std::cmp::Ord; use std::collections::HashMap; use std::marker::PhantomData; use hash_db::Hasher; use trie_backend::TrieBackend; use trie_backend_essence::TrieBackendStorage; use substrate_trie::{TrieDBMut, TrieMut, MemoryDB, trie_root, child_trie_root, default_child_trie_root}; use heapsize::HeapSizeOf; /// A state backend is used to read state data and can have changes committed /// to it. /// /// The clone operation (if implemented) should be cheap. pub trait Backend { /// An error type when fetching data is not possible. type Error: super::Error; /// Storage changes to be applied if committing type Transaction: Consolidate + Default; /// Type of trie backend storage. type TrieBackendStorage: TrieBackendStorage; /// Get keyed storage associated with specific address, or None if there is nothing associated. fn storage(&self, key: &[u8]) -> Result>, Self::Error>; /// Get keyed child storage associated with specific address, or None if there is nothing associated. fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error>; /// true if a key exists in storage. fn exists_storage(&self, key: &[u8]) -> Result { Ok(self.storage(key)?.is_some()) } /// true if a key exists in child storage. fn exists_child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result { Ok(self.child_storage(storage_key, key)?.is_some()) } /// Retrieve all entries keys of child storage and call `f` for each of those keys. fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F); /// Retrieve all entries keys of which start with the given prefix and /// call `f` for each of those keys. fn for_keys_with_prefix(&self, prefix: &[u8], f: F); /// Calculate the storage root, with given delta over what is already stored in /// the backend, and produce a "transaction" that can be used to commit. fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord; /// Calculate the child storage root, with given delta over what is already stored in /// the backend, and produce a "transaction" that can be used to commit. The second argument /// is true if child storage root equals default storage root. fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord; /// Get all key/value pairs into a Vec. fn pairs(&self) -> Vec<(Vec, Vec)>; /// Try convert into trie backend. fn try_into_trie_backend(self) -> Option>; } /// Trait that allows consolidate two transactions together. pub trait Consolidate { /// Consolidate two transactions into one. fn consolidate(&mut self, other: Self); } impl Consolidate for () { fn consolidate(&mut self, _: Self) { () } } impl Consolidate for Vec<(Option>, Vec, Option>)> { fn consolidate(&mut self, mut other: Self) { self.append(&mut other); } } impl Consolidate for MemoryDB { fn consolidate(&mut self, other: Self) { MemoryDB::consolidate(self, other) } } /// Error impossible. // TODO: use `!` type when stabilized. #[derive(Debug)] pub enum Void {} impl fmt::Display for Void { fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { match *self {} } } impl error::Error for Void { fn description(&self) -> &str { "unreachable error" } } /// In-memory backend. Fully recomputes tries on each commit but useful for /// tests. #[derive(Eq)] pub struct InMemory { inner: HashMap>, HashMap, Vec>>, _hasher: PhantomData, } impl Default for InMemory { fn default() -> Self { InMemory { inner: Default::default(), _hasher: PhantomData, } } } impl Clone for InMemory { fn clone(&self) -> Self { InMemory { inner: self.inner.clone(), _hasher: PhantomData, } } } impl PartialEq for InMemory { fn eq(&self, other: &Self) -> bool { self.inner.eq(&other.inner) } } impl InMemory where H::Out: HeapSizeOf { /// Copy the state, with applied updates pub fn update(&self, changes: >::Transaction) -> Self { let mut inner: HashMap<_, _> = self.inner.clone(); for (storage_key, key, val) in changes { match val { Some(v) => { inner.entry(storage_key).or_default().insert(key, v); }, None => { inner.entry(storage_key).or_default().remove(&key); }, } } inner.into() } } impl From>, HashMap, Vec>>> for InMemory { fn from(inner: HashMap>, HashMap, Vec>>) -> Self { InMemory { inner: inner, _hasher: PhantomData, } } } impl From, Vec>> for InMemory { fn from(inner: HashMap, Vec>) -> Self { let mut expanded = HashMap::new(); expanded.insert(None, inner); InMemory { inner: expanded, _hasher: PhantomData, } } } impl From>, Vec, Option>)>> for InMemory { fn from(inner: Vec<(Option>, Vec, Option>)>) -> Self { let mut expanded: HashMap>, HashMap, Vec>> = HashMap::new(); for (child_key, key, value) in inner { if let Some(value) = value { expanded.entry(child_key).or_default().insert(key, value); } } expanded.into() } } impl super::Error for Void {} impl Backend for InMemory where H::Out: HeapSizeOf { type Error = Void; type Transaction = Vec<(Option>, Vec, Option>)>; type TrieBackendStorage = MemoryDB; fn storage(&self, key: &[u8]) -> Result>, Self::Error> { Ok(self.inner.get(&None).and_then(|map| map.get(key).map(Clone::clone))) } fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { Ok(self.inner.get(&Some(storage_key.to_vec())).and_then(|map| map.get(key).map(Clone::clone))) } fn exists_storage(&self, key: &[u8]) -> Result { Ok(self.inner.get(&None).map(|map| map.get(key).is_some()).unwrap_or(false)) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { self.inner.get(&None).map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); } fn for_keys_in_child_storage(&self, storage_key: &[u8], mut f: F) { self.inner.get(&Some(storage_key.to_vec())).map(|map| map.keys().for_each(|k| f(&k))); } fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) where I: IntoIterator, Option>)>, ::Out: Ord, { let existing_pairs = self.inner.get(&None).into_iter().flat_map(|map| map.iter().map(|(k, v)| (k.clone(), Some(v.clone())))); let transaction: Vec<_> = delta.into_iter().collect(); let root = trie_root::(existing_pairs.chain(transaction.iter().cloned()) .collect::>() .into_iter() .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) ); let full_transaction = transaction.into_iter().map(|(k, v)| (None, k, v)).collect(); (root, full_transaction) } fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord { let storage_key = storage_key.to_vec(); let existing_pairs = self.inner.get(&Some(storage_key.clone())).into_iter().flat_map(|map| map.iter().map(|(k, v)| (k.clone(), Some(v.clone())))); let transaction: Vec<_> = delta.into_iter().collect(); let root = child_trie_root::( &storage_key, existing_pairs.chain(transaction.iter().cloned()) .collect::>() .into_iter() .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) ); let full_transaction = transaction.into_iter().map(|(k, v)| (Some(storage_key.clone()), k, v)).collect(); let is_default = root == default_child_trie_root::(&storage_key); (root, is_default, full_transaction) } fn pairs(&self) -> Vec<(Vec, Vec)> { self.inner.get(&None).into_iter().flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.clone()))).collect() } fn try_into_trie_backend(self) -> Option> { let mut mdb = MemoryDB::default(); // TODO: should be more correct and use ::new() let mut root = None; for (storage_key, map) in self.inner { if storage_key != None { let _ = insert_into_memory_db::(&mut mdb, map.into_iter())?; } else { root = Some(insert_into_memory_db::(&mut mdb, map.into_iter())?); } } let root = match root { Some(root) => root, None => insert_into_memory_db::(&mut mdb, ::std::iter::empty())?, }; Some(TrieBackend::new(mdb, root)) } } /// Insert input pairs into memory db. pub(crate) fn insert_into_memory_db(mdb: &mut MemoryDB, input: I) -> Option where H: Hasher, H::Out: HeapSizeOf, I: IntoIterator, Vec)>, { let mut root = ::Out::default(); { let mut trie = TrieDBMut::::new(mdb, &mut root); for (key, value) in input { if let Err(e) = trie.insert(&key, &value) { warn!(target: "trie", "Failed to write to trie: {}", e); return None; } } } Some(root) }