// 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 . //! State machine backends. These manage the code and storage of contracts. use std::{error, fmt, cmp::Ord, collections::HashMap, marker::PhantomData}; use log::warn; use hash_db::Hasher; use crate::trie_backend::TrieBackend; use crate::trie_backend_essence::TrieBackendStorage; use trie::{ TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration, trie_types::{TrieDBMut, Layout}, }; /// 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: std::fmt::Debug { /// 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 or None if there is nothing associated. fn storage(&self, key: &[u8]) -> Result>, Self::Error>; /// Get keyed storage value hash or None if there is nothing associated. fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { self.storage(key).map(|v| v.map(|v| H::hash(&v))) } /// Get keyed child storage or None if there is nothing associated. fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error>; /// Get child keyed storage value hash or None if there is nothing associated. fn child_storage_hash(&self, storage_key: &[u8], key: &[u8]) -> Result, Self::Error> { self.child_storage(storage_key, key).map(|v| v.map(|v| H::hash(&v))) } /// 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 which start with the given prefix and /// call `f` for each of those keys. fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { self.for_key_values_with_prefix(prefix, |k, _v| f(k)) } /// Retrieve all entries keys and values of which start with the given prefix and /// call `f` for each of those keys. fn for_key_values_with_prefix(&self, prefix: &[u8], f: F); /// Retrieve all child entries keys which start with the given prefix and /// call `f` for each of those keys. fn for_child_keys_with_prefix(&self, storage_key: &[u8], 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. /// Does not include child storage updates. 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)>; /// Get all keys with given prefix fn keys(&self, prefix: &[u8]) -> Vec> { let mut all = Vec::new(); self.for_keys_with_prefix(prefix, |k| all.push(k.to_vec())); all } /// Get all keys of child storage with given prefix fn child_keys(&self, child_storage_key: &[u8], prefix: &[u8]) -> Vec> { let mut all = Vec::new(); self.for_child_keys_with_prefix(child_storage_key, prefix, |k| all.push(k.to_vec())); all } /// Try convert into trie backend. fn as_trie_backend(&mut self) -> Option<&TrieBackend> { None } /// 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. /// Does include child storage updates. fn full_storage_root( &self, delta: I1, child_deltas: I2) -> (H::Out, Self::Transaction) where I1: IntoIterator, Option>)>, I2i: IntoIterator, Option>)>, I2: IntoIterator, I2i)>, ::Out: Ord, { let mut txs: Self::Transaction = Default::default(); let mut child_roots: Vec<_> = Default::default(); // child first for (storage_key, child_delta) in child_deltas { let (child_root, empty, child_txs) = self.child_storage_root(&storage_key[..], child_delta); txs.consolidate(child_txs); if empty { child_roots.push((storage_key, None)); } else { child_roots.push((storage_key, Some(child_root))); } } let (root, parent_txs) = self.storage_root( delta.into_iter().chain(child_roots.into_iter()) ); txs.consolidate(parent_txs); (root, txs) } } impl<'a, T: Backend, H: Hasher> Backend for &'a T { type Error = T::Error; type Transaction = T::Transaction; type TrieBackendStorage = T::TrieBackendStorage; fn storage(&self, key: &[u8]) -> Result>, Self::Error> { (*self).storage(key) } fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { (*self).child_storage(storage_key, key) } fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { (*self).for_keys_in_child_storage(storage_key, f) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { (*self).for_keys_with_prefix(prefix, f) } fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { (*self).for_child_keys_with_prefix(storage_key, prefix, f) } fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord, { (*self).storage_root(delta) } fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord, { (*self).child_storage_root(storage_key, delta) } fn pairs(&self) -> Vec<(Vec, Vec)> { (*self).pairs() } fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { (*self).for_key_values_with_prefix(prefix, f); } } /// 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 trie::GenericMemoryDB { fn consolidate(&mut self, other: Self) { trie::GenericMemoryDB::consolidate(self, other) } } /// Error impossible. // FIXME: use `!` type when stabilized. https://github.com/rust-lang/rust/issues/35121 #[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. pub struct InMemory { inner: HashMap>, HashMap, Vec>>, trie: Option, H>>, _hasher: PhantomData, } impl std::fmt::Debug for InMemory { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "InMemory ({} values)", self.inner.len()) } } impl Default for InMemory { fn default() -> Self { InMemory { inner: Default::default(), trie: None, _hasher: PhantomData, } } } impl Clone for InMemory { fn clone(&self) -> Self { InMemory { inner: self.inner.clone(), trie: None, _hasher: PhantomData, } } } impl PartialEq for InMemory { fn eq(&self, other: &Self) -> bool { self.inner.eq(&other.inner) } } impl InMemory { /// 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, trie: None, _hasher: PhantomData, } } } impl From<( HashMap, Vec>, HashMap, HashMap, Vec>>, )> for InMemory { fn from(inners: ( HashMap, Vec>, HashMap, HashMap, Vec>>, )) -> Self { let mut inner: HashMap>, HashMap, Vec>> = inners.1.into_iter().map(|(k, v)| (Some(k), v)).collect(); inner.insert(None, inners.0); InMemory { inner: inner, trie: None, _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, trie: None, _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 InMemory { /// child storage key iterator pub fn child_storage_keys(&self) -> impl Iterator { self.inner.iter().filter_map(|item| item.0.as_ref().map(|v|&v[..])) } } impl Backend for InMemory { 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_key_values_with_prefix(&self, prefix: &[u8], mut f: F) { self.inner.get(&None).map(|map| map.iter().filter(|(key, _val)| key.starts_with(prefix)) .for_each(|(k, v)| f(k, v))); } 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 for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { self.inner.get(&Some(storage_key.to_vec())) .map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); } 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 = Layout::::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 keys(&self, prefix: &[u8]) -> Vec> { self.inner.get(&None) .into_iter() .flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()) .collect() } fn child_keys(&self, storage_key: &[u8], prefix: &[u8]) -> Vec> { self.inner.get(&Some(storage_key.to_vec())) .into_iter() .flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()) .collect() } fn as_trie_backend(&mut self)-> Option<&TrieBackend> { let mut mdb = MemoryDB::default(); let mut root = None; let mut new_child_roots = Vec::new(); let mut root_map = None; for (storage_key, map) in &self.inner { if let Some(storage_key) = storage_key.as_ref() { let ch = insert_into_memory_db::(&mut mdb, map.clone().into_iter())?; new_child_roots.push((storage_key.clone(), ch.as_ref().into())); } else { root_map = Some(map); } } // root handling if let Some(map) = root_map.take() { root = Some(insert_into_memory_db::( &mut mdb, map.clone().into_iter().chain(new_child_roots.into_iter()) )?); } let root = match root { Some(root) => root, None => insert_into_memory_db::(&mut mdb, ::std::iter::empty())?, }; self.trie = Some(TrieBackend::new(mdb, root)); self.trie.as_ref() } } /// Insert input pairs into memory db. pub(crate) fn insert_into_memory_db(mdb: &mut MemoryDB, input: I) -> Option where H: Hasher, 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) }