tp_state_machine/
trie_backend.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Trie-based state machine backend.
19
20use crate::{warn, debug};
21use tetsy_hash_db::Hasher;
22use tp_trie::{Trie, delta_trie_root, empty_child_trie_root, child_delta_trie_root};
23use tp_trie::trie_types::{TrieDB, TrieError, Layout};
24use tet_core::storage::{ChildInfo, ChildType};
25use codec::{Codec, Decode};
26use crate::{
27	StorageKey, StorageValue, Backend,
28	trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral},
29};
30use tetcore_std::{boxed::Box, vec::Vec};
31
32/// Patricia trie-based backend. Transaction type is an overlay of changes to commit.
33pub struct TrieBackend<S: TrieBackendStorage<H>, H: Hasher> {
34	pub (crate) essence: TrieBackendEssence<S, H>,
35}
36
37impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackend<S, H> where H::Out: Codec {
38	/// Create new trie-based backend.
39	pub fn new(storage: S, root: H::Out) -> Self {
40		TrieBackend {
41			essence: TrieBackendEssence::new(storage, root),
42		}
43	}
44
45	/// Get backend essence reference.
46	pub fn essence(&self) -> &TrieBackendEssence<S, H> {
47		&self.essence
48	}
49
50	/// Get backend storage reference.
51	pub fn backend_storage(&self) -> &S {
52		self.essence.backend_storage()
53	}
54
55	/// Get backend storage reference.
56	pub fn backend_storage_mut(&mut self) -> &mut S {
57		self.essence.backend_storage_mut()
58	}
59
60	/// Get trie root.
61	pub fn root(&self) -> &H::Out {
62		self.essence.root()
63	}
64
65	/// Consumes self and returns underlying storage.
66	pub fn into_storage(self) -> S {
67		self.essence.into_storage()
68	}
69}
70
71impl<S: TrieBackendStorage<H>, H: Hasher> tetcore_std::fmt::Debug for TrieBackend<S, H> {
72	fn fmt(&self, f: &mut tetcore_std::fmt::Formatter<'_>) -> tetcore_std::fmt::Result {
73		write!(f, "TrieBackend")
74	}
75}
76
77impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
78	H::Out: Ord + Codec,
79{
80	type Error = crate::DefaultError;
81	type Transaction = S::Overlay;
82	type TrieBackendStorage = S;
83
84	fn storage(&self, key: &[u8]) -> Result<Option<StorageValue>, Self::Error> {
85		self.essence.storage(key)
86	}
87
88	fn child_storage(
89		&self,
90		child_info: &ChildInfo,
91		key: &[u8],
92	) -> Result<Option<StorageValue>, Self::Error> {
93		self.essence.child_storage(child_info, key)
94	}
95
96	fn next_storage_key(&self, key: &[u8]) -> Result<Option<StorageKey>, Self::Error> {
97		self.essence.next_storage_key(key)
98	}
99
100	fn next_child_storage_key(
101		&self,
102		child_info: &ChildInfo,
103		key: &[u8],
104	) -> Result<Option<StorageKey>, Self::Error> {
105		self.essence.next_child_storage_key(child_info, key)
106	}
107
108	fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], f: F) {
109		self.essence.for_keys_with_prefix(prefix, f)
110	}
111
112	fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F) {
113		self.essence.for_key_values_with_prefix(prefix, f)
114	}
115
116	fn apply_to_child_keys_while<F: FnMut(&[u8]) -> bool>(
117		&self,
118		child_info: &ChildInfo,
119		f: F,
120	) {
121		self.essence.apply_to_child_keys_while(child_info, f)
122	}
123
124	fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
125		&self,
126		child_info: &ChildInfo,
127		prefix: &[u8],
128		f: F,
129	) {
130		self.essence.for_child_keys_with_prefix(child_info, prefix, f)
131	}
132
133	fn pairs(&self) -> Vec<(StorageKey, StorageValue)> {
134		let collect_all = || -> Result<_, Box<TrieError<H::Out>>> {
135			let trie = TrieDB::<H>::new(self.essence(), self.essence.root())?;
136			let mut v = Vec::new();
137			for x in trie.iter()? {
138				let (key, value) = x?;
139				v.push((key.to_vec(), value.to_vec()));
140			}
141
142			Ok(v)
143		};
144
145		match collect_all() {
146			Ok(v) => v,
147			Err(e) => {
148				debug!(target: "trie", "Error extracting trie values: {}", e);
149				Vec::new()
150			}
151		}
152	}
153
154	fn keys(&self, prefix: &[u8]) -> Vec<StorageKey> {
155		let collect_all = || -> Result<_, Box<TrieError<H::Out>>> {
156			let trie = TrieDB::<H>::new(self.essence(), self.essence.root())?;
157			let mut v = Vec::new();
158			for x in trie.iter()? {
159				let (key, _) = x?;
160				if key.starts_with(prefix) {
161					v.push(key.to_vec());
162				}
163			}
164
165			Ok(v)
166		};
167
168		collect_all().map_err(|e| debug!(target: "trie", "Error extracting trie keys: {}", e)).unwrap_or_default()
169	}
170
171	fn storage_root<'a>(
172		&self,
173		delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
174	) -> (H::Out, Self::Transaction) where H::Out: Ord {
175		let mut write_overlay = S::Overlay::default();
176		let mut root = *self.essence.root();
177
178		{
179			let mut eph = Ephemeral::new(
180				self.essence.backend_storage(),
181				&mut write_overlay,
182			);
183
184			match delta_trie_root::<Layout<H>, _, _, _, _, _>(&mut eph, root, delta) {
185				Ok(ret) => root = ret,
186				Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e),
187			}
188		}
189
190		(root, write_overlay)
191	}
192
193	fn child_storage_root<'a>(
194		&self,
195		child_info: &ChildInfo,
196		delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
197	) -> (H::Out, bool, Self::Transaction) where H::Out: Ord {
198		let default_root = match child_info.child_type() {
199			ChildType::ParentKeyId => empty_child_trie_root::<Layout<H>>()
200		};
201
202		let mut write_overlay = S::Overlay::default();
203		let prefixed_storage_key = child_info.prefixed_storage_key();
204		let mut root = match self.storage(prefixed_storage_key.as_slice()) {
205			Ok(value) =>
206				value.and_then(|r| Decode::decode(&mut &r[..]).ok()).unwrap_or_else(|| default_root.clone()),
207			Err(e) => {
208				warn!(target: "trie", "Failed to read child storage root: {}", e);
209				default_root.clone()
210			},
211		};
212
213		{
214			let mut eph = Ephemeral::new(
215				self.essence.backend_storage(),
216				&mut write_overlay,
217			);
218
219			match child_delta_trie_root::<Layout<H>, _, _, _, _, _, _>(
220				child_info.keyspace(),
221				&mut eph,
222				root,
223				delta,
224			) {
225				Ok(ret) => root = ret,
226				Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e),
227			}
228		}
229
230		let is_default = root == default_root;
231
232		(root, is_default, write_overlay)
233	}
234
235	fn as_trie_backend(&mut self) -> Option<&TrieBackend<Self::TrieBackendStorage, H>> {
236		Some(self)
237	}
238
239	fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { }
240
241	fn usage_info(&self) -> crate::UsageInfo {
242		crate::UsageInfo::empty()
243	}
244
245	fn wipe(&self) -> Result<(), Self::Error> {
246		Ok(())
247	}
248}
249
250#[cfg(test)]
251pub mod tests {
252	use std::{collections::HashSet, iter};
253	use tet_core::H256;
254	use codec::Encode;
255	use tp_trie::{TrieMut, PrefixedMemoryDB, trie_types::TrieDBMut, KeySpacedDBMut};
256	use tp_runtime::traits::BlakeTwo256;
257	use super::*;
258
259	const CHILD_KEY_1: &[u8] = b"sub1";
260
261	fn test_db() -> (PrefixedMemoryDB<BlakeTwo256>, H256) {
262		let child_info = ChildInfo::new_default(CHILD_KEY_1);
263		let mut root = H256::default();
264		let mut mdb = PrefixedMemoryDB::<BlakeTwo256>::default();
265		{
266			let mut mdb = KeySpacedDBMut::new(&mut mdb, child_info.keyspace());
267			let mut trie = TrieDBMut::new(&mut mdb, &mut root);
268			trie.insert(b"value3", &[142]).expect("insert failed");
269			trie.insert(b"value4", &[124]).expect("insert failed");
270		};
271
272		{
273			let mut sub_root = Vec::new();
274			root.encode_to(&mut sub_root);
275			let mut trie = TrieDBMut::new(&mut mdb, &mut root);
276			trie.insert(child_info.prefixed_storage_key().as_slice(), &sub_root[..])
277				.expect("insert failed");
278			trie.insert(b"key", b"value").expect("insert failed");
279			trie.insert(b"value1", &[42]).expect("insert failed");
280			trie.insert(b"value2", &[24]).expect("insert failed");
281			trie.insert(b":code", b"return 42").expect("insert failed");
282			for i in 128u8..255u8 {
283				trie.insert(&[i], &[i]).unwrap();
284			}
285		}
286		(mdb, root)
287	}
288
289	pub(crate) fn test_trie() -> TrieBackend<PrefixedMemoryDB<BlakeTwo256>, BlakeTwo256> {
290		let (mdb, root) = test_db();
291		TrieBackend::new(mdb, root)
292	}
293
294	#[test]
295	fn read_from_storage_returns_some() {
296		assert_eq!(test_trie().storage(b"key").unwrap(), Some(b"value".to_vec()));
297	}
298
299	#[test]
300	fn read_from_child_storage_returns_some() {
301		let test_trie = test_trie();
302		assert_eq!(
303			test_trie.child_storage(&ChildInfo::new_default(CHILD_KEY_1), b"value3").unwrap(),
304			Some(vec![142u8]),
305		);
306	}
307
308	#[test]
309	fn read_from_storage_returns_none() {
310		assert_eq!(test_trie().storage(b"non-existing-key").unwrap(), None);
311	}
312
313	#[test]
314	fn pairs_are_not_empty_on_non_empty_storage() {
315		assert!(!test_trie().pairs().is_empty());
316	}
317
318	#[test]
319	fn pairs_are_empty_on_empty_storage() {
320		assert!(TrieBackend::<PrefixedMemoryDB<BlakeTwo256>, BlakeTwo256>::new(
321			PrefixedMemoryDB::default(),
322			Default::default(),
323		).pairs().is_empty());
324	}
325
326	#[test]
327	fn storage_root_is_non_default() {
328		assert!(test_trie().storage_root(iter::empty()).0 != H256::repeat_byte(0));
329	}
330
331	#[test]
332	fn storage_root_transaction_is_empty() {
333		assert!(test_trie().storage_root(iter::empty()).1.drain().is_empty());
334	}
335
336	#[test]
337	fn storage_root_transaction_is_non_empty() {
338		let (new_root, mut tx) = test_trie().storage_root(
339			iter::once((&b"new-key"[..], Some(&b"new-value"[..]))),
340		);
341		assert!(!tx.drain().is_empty());
342		assert!(new_root != test_trie().storage_root(iter::empty()).0);
343	}
344
345	#[test]
346	fn prefix_walking_works() {
347		let trie = test_trie();
348
349		let mut seen = HashSet::new();
350		trie.for_keys_with_prefix(b"value", |key| {
351			let for_first_time = seen.insert(key.to_vec());
352			assert!(for_first_time, "Seen key '{:?}' more than once", key);
353		});
354
355		let mut expected = HashSet::new();
356		expected.insert(b"value1".to_vec());
357		expected.insert(b"value2".to_vec());
358		assert_eq!(seen, expected);
359	}
360}