tp_state_machine/changes_trie/
storage.rs1use std::collections::{BTreeMap, HashSet, HashMap};
21use tetsy_hash_db::{Hasher, Prefix, EMPTY_PREFIX};
22use tet_core::storage::PrefixedStorageKey;
23use tp_trie::DBValue;
24use tp_trie::MemoryDB;
25use parking_lot::RwLock;
26use crate::{
27 StorageKey,
28 trie_backend_essence::TrieBackendStorage,
29 changes_trie::{BuildCache, RootsStorage, Storage, AnchorBlockId, BlockNumber},
30};
31
32#[cfg(test)]
33use crate::backend::insert_into_memory_db;
34#[cfg(test)]
35use crate::changes_trie::input::{InputPair, ChildIndex};
36
37pub struct InMemoryStorage<H: Hasher, Number: BlockNumber> {
39 data: RwLock<InMemoryStorageData<H, Number>>,
40 cache: BuildCache<H::Out, Number>,
41}
42
43pub struct TrieBackendAdapter<'a, H: Hasher, Number: BlockNumber> {
45 storage: &'a dyn Storage<H, Number>,
46 _hasher: std::marker::PhantomData<(H, Number)>,
47}
48
49struct InMemoryStorageData<H: Hasher, Number: BlockNumber> {
50 roots: BTreeMap<Number, H::Out>,
51 mdb: MemoryDB<H>,
52}
53
54impl<H: Hasher, Number: BlockNumber> InMemoryStorage<H, Number> {
55 pub fn with_db(mdb: MemoryDB<H>) -> Self {
57 Self {
58 data: RwLock::new(InMemoryStorageData {
59 roots: BTreeMap::new(),
60 mdb,
61 }),
62 cache: BuildCache::new(),
63 }
64 }
65
66 pub fn new() -> Self {
68 Self::with_db(Default::default())
69 }
70
71 pub fn with_proof(proof: Vec<Vec<u8>>) -> Self {
73 use tetsy_hash_db::HashDB;
74
75 let mut proof_db = MemoryDB::<H>::default();
76 for item in proof {
77 proof_db.insert(EMPTY_PREFIX, &item);
78 }
79 Self::with_db(proof_db)
80 }
81
82 pub fn cache_mut(&mut self) -> &mut BuildCache<H::Out, Number> {
84 &mut self.cache
85 }
86
87 pub fn with_blocks(blocks: Vec<(Number, H::Out)>) -> Self {
89 Self {
90 data: RwLock::new(InMemoryStorageData {
91 roots: blocks.into_iter().collect(),
92 mdb: MemoryDB::default(),
93 }),
94 cache: BuildCache::new(),
95 }
96 }
97
98 #[cfg(test)]
99 pub fn with_inputs(
100 mut top_inputs: Vec<(Number, Vec<InputPair<Number>>)>,
101 children_inputs: Vec<(PrefixedStorageKey, Vec<(Number, Vec<InputPair<Number>>)>)>,
102 ) -> Self {
103 let mut mdb = MemoryDB::default();
104 let mut roots = BTreeMap::new();
105 for (storage_key, child_input) in children_inputs {
106 for (block, pairs) in child_input {
107 let root = insert_into_memory_db::<H, _>(&mut mdb, pairs.into_iter().map(Into::into));
108
109 if let Some(root) = root {
110 let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) {
111 ix
112 } else {
113 top_inputs.push((block.clone(), Default::default()));
114 top_inputs.len() - 1
115 };
116 top_inputs[ix].1.push(InputPair::ChildIndex(
117 ChildIndex { block: block.clone(), storage_key: storage_key.clone() },
118 root.as_ref().to_vec(),
119 ));
120 }
121 }
122 }
123
124 for (block, pairs) in top_inputs {
125 let root = insert_into_memory_db::<H, _>(&mut mdb, pairs.into_iter().map(Into::into));
126 if let Some(root) = root {
127 roots.insert(block, root);
128 }
129 }
130
131 InMemoryStorage {
132 data: RwLock::new(InMemoryStorageData {
133 roots,
134 mdb,
135 }),
136 cache: BuildCache::new(),
137 }
138 }
139
140 #[cfg(test)]
141 pub fn clear_storage(&self) {
142 self.data.write().mdb = MemoryDB::default(); }
144
145 #[cfg(test)]
146 pub fn remove_from_storage(&self, keys: &HashSet<H::Out>) {
147 let mut data = self.data.write();
148 for key in keys {
149 data.mdb.remove_and_purge(key, tetsy_hash_db::EMPTY_PREFIX);
150 }
151 }
152
153 #[cfg(test)]
154 pub fn into_mdb(self) -> MemoryDB<H> {
155 self.data.into_inner().mdb
156 }
157
158 pub fn insert(&self, block: Number, changes_trie_root: H::Out, trie: MemoryDB<H>) {
160 let mut data = self.data.write();
161 data.roots.insert(block, changes_trie_root);
162 data.mdb.consolidate(trie);
163 }
164}
165
166impl<H: Hasher, Number: BlockNumber> RootsStorage<H, Number> for InMemoryStorage<H, Number> {
167 fn build_anchor(&self, parent_hash: H::Out) -> Result<AnchorBlockId<H::Out, Number>, String> {
168 self.data.read().roots.iter()
169 .find(|(_, v)| **v == parent_hash)
170 .map(|(k, _)| AnchorBlockId { hash: parent_hash, number: k.clone() })
171 .ok_or_else(|| format!("Can't find associated number for block {:?}", parent_hash))
172 }
173
174 fn root(&self, _anchor_block: &AnchorBlockId<H::Out, Number>, block: Number) -> Result<Option<H::Out>, String> {
175 Ok(self.data.read().roots.get(&block).cloned())
176 }
177}
178
179impl<H: Hasher, Number: BlockNumber> Storage<H, Number> for InMemoryStorage<H, Number> {
180 fn as_roots_storage(&self) -> &dyn RootsStorage<H, Number> {
181 self
182 }
183
184 fn with_cached_changed_keys(
185 &self,
186 root: &H::Out,
187 functor: &mut dyn FnMut(&HashMap<Option<PrefixedStorageKey>, HashSet<StorageKey>>),
188 ) -> bool {
189 self.cache.with_changed_keys(root, functor)
190 }
191
192 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>, String> {
193 MemoryDB::<H>::get(&self.data.read().mdb, key, prefix)
194 }
195}
196
197impl<'a, H: Hasher, Number: BlockNumber> TrieBackendAdapter<'a, H, Number> {
198 pub fn new(storage: &'a dyn Storage<H, Number>) -> Self {
199 Self { storage, _hasher: Default::default() }
200 }
201}
202
203impl<'a, H, Number> TrieBackendStorage<H> for TrieBackendAdapter<'a, H, Number>
204 where
205 Number: BlockNumber,
206 H: Hasher,
207{
208 type Overlay = MemoryDB<H>;
209
210 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>, String> {
211 self.storage.get(key, prefix)
212 }
213}