1use crate::{
21 StorageKey, StorageValue, StorageCollection, trie_backend::TrieBackend, backend::Backend,
22};
23use std::collections::{BTreeMap, HashMap};
24use tetsy_hash_db::Hasher;
25use tp_trie::{MemoryDB, empty_trie_root, Layout};
26use codec::Codec;
27use tet_core::storage::{ChildInfo, Storage};
28
29pub fn new_in_mem<H: Hasher>() -> TrieBackend<MemoryDB<H>, H>
31where
32 H::Out: Codec + Ord,
33{
34 let db = MemoryDB::default();
35 TrieBackend::new(db, empty_trie_root::<Layout<H>>())
36}
37
38impl<H: Hasher> TrieBackend<MemoryDB<H>, H>
39where
40 H::Out: Codec + Ord,
41{
42 pub fn update<
44 T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>
45 >(
46 &self,
47 changes: T,
48 ) -> Self {
49 let mut clone = self.clone();
50 clone.insert(changes);
51 clone
52 }
53
54 pub fn insert<
56 T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>
57 >(
58 &mut self,
59 changes: T,
60 ) {
61 let (top, child) = changes.into_iter().partition::<Vec<_>, _>(|v| v.0.is_none());
62 let (root, transaction) = self.full_storage_root(
63 top.iter().map(|(_, v)| v).flatten().map(|(k, v)| (&k[..], v.as_deref())),
64 child.iter()
65 .filter_map(|v|
66 v.0.as_ref().map(|c| (c, v.1.iter().map(|(k, v)| (&k[..], v.as_deref()))))
67 ),
68 );
69
70 self.apply_transaction(root, transaction);
71 }
72
73 pub fn update_backend(&self, root: H::Out, changes: MemoryDB<H>) -> Self {
75 let mut clone = self.backend_storage().clone();
76 clone.consolidate(changes);
77 Self::new(clone, root)
78 }
79
80 pub fn apply_transaction(&mut self, root: H::Out, transaction: MemoryDB<H>) {
82 self.backend_storage_mut().consolidate(transaction);
83 self.essence.set_root(root);
84 }
85
86 pub fn eq(&self, other: &Self) -> bool {
88 self.root() == other.root()
89 }
90}
91
92impl<H: Hasher> Clone for TrieBackend<MemoryDB<H>, H>
93where
94 H::Out: Codec + Ord,
95{
96 fn clone(&self) -> Self {
97 TrieBackend::new(self.backend_storage().clone(), self.root().clone())
98 }
99}
100
101impl<H: Hasher> Default for TrieBackend<MemoryDB<H>, H>
102where
103 H::Out: Codec + Ord,
104{
105 fn default() -> Self {
106 new_in_mem()
107 }
108}
109
110impl<H: Hasher> From<HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>>
111 for TrieBackend<MemoryDB<H>, H>
112where
113 H::Out: Codec + Ord,
114{
115 fn from(inner: HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>) -> Self {
116 let mut backend = new_in_mem();
117 backend.insert(
118 inner.into_iter().map(|(k, m)| (k, m.into_iter().map(|(k, v)| (k, Some(v))).collect())),
119 );
120 backend
121 }
122}
123
124impl<H: Hasher> From<Storage> for TrieBackend<MemoryDB<H>, H>
125where
126 H::Out: Codec + Ord,
127{
128 fn from(inners: Storage) -> Self {
129 let mut inner: HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>
130 = inners.children_default.into_iter().map(|(_k, c)| (Some(c.child_info), c.data)).collect();
131 inner.insert(None, inners.top);
132 inner.into()
133 }
134}
135
136impl<H: Hasher> From<BTreeMap<StorageKey, StorageValue>> for TrieBackend<MemoryDB<H>, H>
137where
138 H::Out: Codec + Ord,
139{
140 fn from(inner: BTreeMap<StorageKey, StorageValue>) -> Self {
141 let mut expanded = HashMap::new();
142 expanded.insert(None, inner);
143 expanded.into()
144 }
145}
146
147impl<H: Hasher> From<Vec<(Option<ChildInfo>, StorageCollection)>>
148 for TrieBackend<MemoryDB<H>, H>
149where
150 H::Out: Codec + Ord,
151{
152 fn from(
153 inner: Vec<(Option<ChildInfo>, StorageCollection)>,
154 ) -> Self {
155 let mut expanded: HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>
156 = HashMap::new();
157 for (child_info, key_values) in inner {
158 let entry = expanded.entry(child_info).or_default();
159 for (key, value) in key_values {
160 if let Some(value) = value {
161 entry.insert(key, value);
162 }
163 }
164 }
165 expanded.into()
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172 use tp_runtime::traits::BlakeTwo256;
173 use crate::backend::Backend;
174
175 #[test]
177 fn in_memory_with_child_trie_only() {
178 let storage = new_in_mem::<BlakeTwo256>();
179 let child_info = ChildInfo::new_default(b"1");
180 let child_info = &child_info;
181 let mut storage = storage.update(
182 vec![(
183 Some(child_info.clone()),
184 vec![(b"2".to_vec(), Some(b"3".to_vec()))]
185 )]
186 );
187 let trie_backend = storage.as_trie_backend().unwrap();
188 assert_eq!(trie_backend.child_storage(child_info, b"2").unwrap(),
189 Some(b"3".to_vec()));
190 let storage_key = child_info.prefixed_storage_key();
191 assert!(trie_backend.storage(storage_key.as_slice()).unwrap().is_some());
192 }
193
194 #[test]
195 fn insert_multiple_times_child_data_works() {
196 let mut storage = new_in_mem::<BlakeTwo256>();
197 let child_info = ChildInfo::new_default(b"1");
198
199 storage.insert(vec![(Some(child_info.clone()), vec![(b"2".to_vec(), Some(b"3".to_vec()))])]);
200 storage.insert(vec![(Some(child_info.clone()), vec![(b"1".to_vec(), Some(b"3".to_vec()))])]);
201
202 assert_eq!(storage.child_storage(&child_info, &b"2"[..]), Ok(Some(b"3".to_vec())));
203 assert_eq!(storage.child_storage(&child_info, &b"1"[..]), Ok(Some(b"3".to_vec())));
204 }
205}