// 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 in memory backend. use crate::{ StorageKey, StorageValue, StorageCollection, trie_backend::TrieBackend, backend::{Backend, insert_into_memory_db}, }; use std::{error, fmt, collections::{BTreeMap, HashMap}, marker::PhantomData, ops}; use hash_db::Hasher; use sp_trie::{ MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration, trie_types::Layout, }; use codec::Codec; use sp_core::storage::{ChildInfo, OwnedChildInfo, Storage}; /// 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 each time `as_trie_backend` is called but useful for /// tests and proof checking. pub struct InMemory { inner: HashMap, BTreeMap>, // This field is only needed for returning reference in `as_trie_backend`. 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< T: IntoIterator, StorageCollection)> >( &self, changes: T, ) -> Self { let mut inner = self.inner.clone(); for (child_info, key_values) in changes.into_iter() { let entry = inner.entry(child_info).or_default(); for (key, val) in key_values { match val { Some(v) => { entry.insert(key, v); }, None => { entry.remove(&key); }, } } } inner.into() } } impl From, BTreeMap>> for InMemory { fn from(inner: HashMap, BTreeMap>) -> Self { InMemory { inner, trie: None, _hasher: PhantomData, } } } impl From for InMemory { fn from(inners: Storage) -> Self { let mut inner: HashMap, BTreeMap> = inners.children.into_iter().map(|(k, c)| (Some((k, c.child_info)), c.data)).collect(); inner.insert(None, inners.top); InMemory { inner, trie: None, _hasher: PhantomData, } } } impl From> for InMemory { fn from(inner: BTreeMap) -> Self { let mut expanded = HashMap::new(); expanded.insert(None, inner); InMemory { inner: expanded, trie: None, _hasher: PhantomData, } } } impl From, StorageCollection)>> for InMemory { fn from( inner: Vec<(Option<(StorageKey, OwnedChildInfo)>, StorageCollection)>, ) -> Self { let mut expanded: HashMap, BTreeMap> = HashMap::new(); for (child_info, key_values) in inner { let entry = expanded.entry(child_info).or_default(); for (key, value) in key_values { if let Some(value) = value { entry.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.0[..], v.1.as_ref())) ) } } impl Backend for InMemory where H::Out: Codec { type Error = Void; type Transaction = Vec<( Option<(StorageKey, OwnedChildInfo)>, StorageCollection, )>; 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], child_info: ChildInfo, key: &[u8], ) -> Result, Self::Error> { Ok(self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) .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], child_info: ChildInfo, mut f: F, ) { self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) .map(|map| map.keys().for_each(|k| f(&k))); } fn for_child_keys_with_prefix( &self, storage_key: &[u8], child_info: ChildInfo, prefix: &[u8], f: F, ) { self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) .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().collect(); (root, vec![(None, full_transaction)]) } fn child_storage_root( &self, storage_key: &[u8], child_info: ChildInfo, delta: I, ) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord { let storage_key = storage_key.to_vec(); let child_info = Some((storage_key.clone(), child_info.to_owned())); let existing_pairs = self.inner.get(&child_info) .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().collect(); let is_default = root == default_child_trie_root::>(&storage_key); (root, is_default, vec![(child_info, full_transaction)]) } fn next_storage_key(&self, key: &[u8]) -> Result, Self::Error> { let range = (ops::Bound::Excluded(key), ops::Bound::Unbounded); let next_key = self.inner.get(&None) .and_then(|map| map.range::<[u8], _>(range).next().map(|(k, _)| k).cloned()); Ok(next_key) } fn next_child_storage_key( &self, storage_key: &[u8], child_info: ChildInfo, key: &[u8], ) -> Result, Self::Error> { let range = (ops::Bound::Excluded(key), ops::Bound::Unbounded); let next_key = self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) .and_then(|map| map.range::<[u8], _>(range).next().map(|(k, _)| k).cloned()); Ok(next_key) } fn pairs(&self) -> Vec<(StorageKey, StorageValue)> { 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], child_info: ChildInfo, prefix: &[u8], ) -> Vec { self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) .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 new_child_roots = Vec::new(); let mut root_map = None; for (child_info, map) in &self.inner { if let Some((storage_key, _child_info)) = child_info.as_ref() { // no need to use child_info at this point because we use a MemoryDB for // proof (with PrefixedMemoryDB it would be needed). 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); } } let root = match root_map { Some(map) => insert_into_memory_db::( &mut mdb, map.clone().into_iter().chain(new_child_roots.into_iter()), )?, None => insert_into_memory_db::( &mut mdb, new_child_roots.into_iter(), )?, }; self.trie = Some(TrieBackend::new(mdb, root)); self.trie.as_ref() } } #[cfg(test)] mod tests { use super::*; /// Assert in memory backend with only child trie keys works as trie backend. #[test] fn in_memory_with_child_trie_only() { let storage = InMemory::::default(); let child_info = OwnedChildInfo::new_default(b"unique_id_1".to_vec()); let mut storage = storage.update( vec![( Some((b"1".to_vec(), child_info.clone())), vec![(b"2".to_vec(), Some(b"3".to_vec()))] )] ); let trie_backend = storage.as_trie_backend().unwrap(); assert_eq!(trie_backend.child_storage(b"1", child_info.as_ref(), b"2").unwrap(), Some(b"3".to_vec())); assert!(trie_backend.storage(b"1").unwrap().is_some()); } }