// This file is part of Substrate. // Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Trie-based state machine backend. use crate::{warn, debug}; use hash_db::Hasher; use sp_trie::{Trie, delta_trie_root, empty_child_trie_root, child_delta_trie_root}; use sp_trie::trie_types::{TrieDB, TrieError, Layout}; use sp_core::storage::{ChildInfo, ChildType}; use codec::{Codec, Decode}; use crate::{ StorageKey, StorageValue, Backend, trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral}, }; use sp_std::{boxed::Box, vec::Vec}; /// Patricia trie-based backend. Transaction type is an overlay of changes to commit. pub struct TrieBackend, H: Hasher> { pub (crate) essence: TrieBackendEssence, } impl, H: Hasher> TrieBackend where H::Out: Codec { /// Create new trie-based backend. pub fn new(storage: S, root: H::Out) -> Self { TrieBackend { essence: TrieBackendEssence::new(storage, root), } } /// Get backend essence reference. pub fn essence(&self) -> &TrieBackendEssence { &self.essence } /// Get backend storage reference. pub fn backend_storage(&self) -> &S { self.essence.backend_storage() } /// Get backend storage reference. pub fn backend_storage_mut(&mut self) -> &mut S { self.essence.backend_storage_mut() } /// Get trie root. pub fn root(&self) -> &H::Out { self.essence.root() } /// Consumes self and returns underlying storage. pub fn into_storage(self) -> S { self.essence.into_storage() } } impl, H: Hasher> sp_std::fmt::Debug for TrieBackend { fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { write!(f, "TrieBackend") } } impl, H: Hasher> Backend for TrieBackend where H::Out: Ord + Codec, { type Error = crate::DefaultError; type Transaction = S::Overlay; type TrieBackendStorage = S; fn storage(&self, key: &[u8]) -> Result, Self::Error> { self.essence.storage(key) } fn child_storage( &self, child_info: &ChildInfo, key: &[u8], ) -> Result, Self::Error> { self.essence.child_storage(child_info, key) } fn next_storage_key(&self, key: &[u8]) -> Result, Self::Error> { self.essence.next_storage_key(key) } fn next_child_storage_key( &self, child_info: &ChildInfo, key: &[u8], ) -> Result, Self::Error> { self.essence.next_child_storage_key(child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { self.essence.for_keys_with_prefix(prefix, f) } fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { self.essence.for_key_values_with_prefix(prefix, f) } fn for_keys_in_child_storage( &self, child_info: &ChildInfo, f: F, ) { self.essence.for_keys_in_child_storage(child_info, f) } fn for_child_keys_with_prefix( &self, child_info: &ChildInfo, prefix: &[u8], f: F, ) { self.essence.for_child_keys_with_prefix(child_info, prefix, f) } fn pairs(&self) -> Vec<(StorageKey, StorageValue)> { let collect_all = || -> Result<_, Box>> { let trie = TrieDB::::new(self.essence(), self.essence.root())?; let mut v = Vec::new(); for x in trie.iter()? { let (key, value) = x?; v.push((key.to_vec(), value.to_vec())); } Ok(v) }; match collect_all() { Ok(v) => v, Err(e) => { debug!(target: "trie", "Error extracting trie values: {}", e); Vec::new() } } } fn keys(&self, prefix: &[u8]) -> Vec { let collect_all = || -> Result<_, Box>> { let trie = TrieDB::::new(self.essence(), self.essence.root())?; let mut v = Vec::new(); for x in trie.iter()? { let (key, _) = x?; if key.starts_with(prefix) { v.push(key.to_vec()); } } Ok(v) }; collect_all().map_err(|e| debug!(target: "trie", "Error extracting trie keys: {}", e)).unwrap_or_default() } fn storage_root<'a>( &self, delta: impl Iterator)>, ) -> (H::Out, Self::Transaction) where H::Out: Ord { let mut write_overlay = S::Overlay::default(); let mut root = *self.essence.root(); { let mut eph = Ephemeral::new( self.essence.backend_storage(), &mut write_overlay, ); match delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta) { Ok(ret) => root = ret, Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), } } (root, write_overlay) } fn child_storage_root<'a>( &self, child_info: &ChildInfo, delta: impl Iterator)>, ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord { let default_root = match child_info.child_type() { ChildType::ParentKeyId => empty_child_trie_root::>() }; let mut write_overlay = S::Overlay::default(); let prefixed_storage_key = child_info.prefixed_storage_key(); let mut root = match self.storage(prefixed_storage_key.as_slice()) { Ok(value) => value.and_then(|r| Decode::decode(&mut &r[..]).ok()).unwrap_or_else(|| default_root.clone()), Err(e) => { warn!(target: "trie", "Failed to read child storage root: {}", e); default_root.clone() }, }; { let mut eph = Ephemeral::new( self.essence.backend_storage(), &mut write_overlay, ); match child_delta_trie_root::, _, _, _, _, _, _>( child_info.keyspace(), &mut eph, root, delta, ) { Ok(ret) => root = ret, Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), } } let is_default = root == default_root; (root, is_default, write_overlay) } fn as_trie_backend(&mut self) -> Option<&TrieBackend> { Some(self) } fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { } fn usage_info(&self) -> crate::UsageInfo { crate::UsageInfo::empty() } fn wipe(&self) -> Result<(), Self::Error> { Ok(()) } } #[cfg(test)] pub mod tests { use std::{collections::HashSet, iter}; use sp_core::H256; use codec::Encode; use sp_trie::{TrieMut, PrefixedMemoryDB, trie_types::TrieDBMut, KeySpacedDBMut}; use sp_runtime::traits::BlakeTwo256; use super::*; const CHILD_KEY_1: &[u8] = b"sub1"; fn test_db() -> (PrefixedMemoryDB, H256) { let child_info = ChildInfo::new_default(CHILD_KEY_1); let mut root = H256::default(); let mut mdb = PrefixedMemoryDB::::default(); { let mut mdb = KeySpacedDBMut::new(&mut mdb, child_info.keyspace()); let mut trie = TrieDBMut::new(&mut mdb, &mut root); trie.insert(b"value3", &[142]).expect("insert failed"); trie.insert(b"value4", &[124]).expect("insert failed"); }; { let mut sub_root = Vec::new(); root.encode_to(&mut sub_root); let mut trie = TrieDBMut::new(&mut mdb, &mut root); trie.insert(child_info.prefixed_storage_key().as_slice(), &sub_root[..]) .expect("insert failed"); trie.insert(b"key", b"value").expect("insert failed"); trie.insert(b"value1", &[42]).expect("insert failed"); trie.insert(b"value2", &[24]).expect("insert failed"); trie.insert(b":code", b"return 42").expect("insert failed"); for i in 128u8..255u8 { trie.insert(&[i], &[i]).unwrap(); } } (mdb, root) } pub(crate) fn test_trie() -> TrieBackend, BlakeTwo256> { let (mdb, root) = test_db(); TrieBackend::new(mdb, root) } #[test] fn read_from_storage_returns_some() { assert_eq!(test_trie().storage(b"key").unwrap(), Some(b"value".to_vec())); } #[test] fn read_from_child_storage_returns_some() { let test_trie = test_trie(); assert_eq!( test_trie.child_storage(&ChildInfo::new_default(CHILD_KEY_1), b"value3").unwrap(), Some(vec![142u8]), ); } #[test] fn read_from_storage_returns_none() { assert_eq!(test_trie().storage(b"non-existing-key").unwrap(), None); } #[test] fn pairs_are_not_empty_on_non_empty_storage() { assert!(!test_trie().pairs().is_empty()); } #[test] fn pairs_are_empty_on_empty_storage() { assert!(TrieBackend::, BlakeTwo256>::new( PrefixedMemoryDB::default(), Default::default(), ).pairs().is_empty()); } #[test] fn storage_root_is_non_default() { assert!(test_trie().storage_root(iter::empty()).0 != H256::repeat_byte(0)); } #[test] fn storage_root_transaction_is_empty() { assert!(test_trie().storage_root(iter::empty()).1.drain().is_empty()); } #[test] fn storage_root_transaction_is_non_empty() { let (new_root, mut tx) = test_trie().storage_root( iter::once((&b"new-key"[..], Some(&b"new-value"[..]))), ); assert!(!tx.drain().is_empty()); assert!(new_root != test_trie().storage_root(iter::empty()).0); } #[test] fn prefix_walking_works() { let trie = test_trie(); let mut seen = HashSet::new(); trie.for_keys_with_prefix(b"value", |key| { let for_first_time = seen.insert(key.to_vec()); assert!(for_first_time, "Seen key '{:?}' more than once", key); }); let mut expected = HashSet::new(); expected.insert(b"value1".to_vec()); expected.insert(b"value2".to_vec()); assert_eq!(seen, expected); } }