1use crate::{Backend, OverlayedChanges, StorageKey, StorageValue};
21use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
22use codec::Encode;
23use core::{
24 any::{Any, TypeId},
25 iter::FromIterator,
26};
27use hash_db::Hasher;
28use log::warn;
29use sp_core::{
30 storage::{
31 well_known_keys::is_child_storage_key, ChildInfo, StateVersion, Storage, TrackedStorageKey,
32 },
33 traits::Externalities,
34 Blake2Hasher,
35};
36use sp_externalities::{Extension, Extensions, MultiRemovalResults};
37use sp_trie::{empty_child_trie_root, LayoutV0, LayoutV1, TrieConfiguration};
38
39#[derive(Debug)]
41pub struct BasicExternalities {
42 overlay: OverlayedChanges<Blake2Hasher>,
43 extensions: Extensions,
44 state_version: StateVersion,
45}
46
47impl BasicExternalities {
48 pub fn new(inner: Storage) -> Self {
50 BasicExternalities {
51 overlay: inner.into(),
52 extensions: Default::default(),
53 state_version: StateVersion::default(),
54 }
55 }
56
57 pub fn new_empty() -> Self {
59 Self::new(Storage::default())
60 }
61
62 pub fn with_state_version(mut self, state_version: StateVersion) -> Self {
64 self.state_version = state_version;
65 self
66 }
67
68 pub fn insert(&mut self, k: StorageKey, v: StorageValue) {
70 self.overlay.set_storage(k, Some(v));
71 }
72
73 #[cfg(feature = "std")]
75 pub fn into_storages(mut self) -> Storage {
76 Storage {
77 top: self
78 .overlay
79 .changes_mut()
80 .filter_map(|(k, v)| v.value().map(|v| (k.to_vec(), v.to_vec())))
81 .collect(),
82 children_default: self
83 .overlay
84 .children_mut()
85 .map(|(iter, i)| {
86 (
87 i.storage_key().to_vec(),
88 sp_core::storage::StorageChild {
89 data: iter
90 .filter_map(|(k, v)| v.value().map(|v| (k.to_vec(), v.to_vec())))
91 .collect(),
92 child_info: i.clone(),
93 },
94 )
95 })
96 .collect(),
97 }
98 }
99
100 #[cfg(feature = "std")]
104 pub fn execute_with_storage<R>(
105 storage: &mut sp_core::storage::Storage,
106 f: impl FnOnce() -> R,
107 ) -> R {
108 let mut ext = Self::new(core::mem::take(storage));
109
110 let r = ext.execute_with(f);
111
112 *storage = ext.into_storages();
113
114 r
115 }
116
117 pub fn execute_with<R>(&mut self, f: impl FnOnce() -> R) -> R {
121 sp_externalities::set_and_run_with_externalities(self, f)
122 }
123
124 pub fn extensions(&mut self) -> &mut Extensions {
126 &mut self.extensions
127 }
128
129 pub fn register_extension(&mut self, ext: impl Extension) {
131 self.extensions.register(ext);
132 }
133}
134
135#[cfg(test)]
136impl PartialEq for BasicExternalities {
137 fn eq(&self, other: &Self) -> bool {
138 self.overlay
139 .changes()
140 .map(|(k, v)| (k, v.value_ref().materialize()))
141 .collect::<BTreeMap<_, _>>() ==
142 other
143 .overlay
144 .changes()
145 .map(|(k, v)| (k, v.value_ref().materialize()))
146 .collect::<BTreeMap<_, _>>() &&
147 self.overlay
148 .children()
149 .map(|(iter, i)| {
150 (
151 i,
152 iter.map(|(k, v)| (k, v.value_ref().materialize()))
153 .collect::<BTreeMap<_, _>>(),
154 )
155 })
156 .collect::<BTreeMap<_, _>>() ==
157 other
158 .overlay
159 .children()
160 .map(|(iter, i)| {
161 (
162 i,
163 iter.map(|(k, v)| (k, v.value_ref().materialize()))
164 .collect::<BTreeMap<_, _>>(),
165 )
166 })
167 .collect::<BTreeMap<_, _>>()
168 }
169}
170
171impl FromIterator<(StorageKey, StorageValue)> for BasicExternalities {
172 fn from_iter<I: IntoIterator<Item = (StorageKey, StorageValue)>>(iter: I) -> Self {
173 let mut t = Self::default();
174 iter.into_iter().for_each(|(k, v)| t.insert(k, v));
175 t
176 }
177}
178
179impl Default for BasicExternalities {
180 fn default() -> Self {
181 Self::new(Default::default())
182 }
183}
184
185impl From<BTreeMap<StorageKey, StorageValue>> for BasicExternalities {
186 fn from(map: BTreeMap<StorageKey, StorageValue>) -> Self {
187 Self::from_iter(map.into_iter())
188 }
189}
190
191impl Externalities for BasicExternalities {
192 fn set_offchain_storage(&mut self, _key: &[u8], _value: Option<&[u8]>) {}
193
194 fn storage(&mut self, key: &[u8]) -> Option<StorageValue> {
195 self.overlay.storage(key).and_then(|v| v.map(|v| v.to_vec()))
196 }
197
198 fn storage_hash(&mut self, key: &[u8]) -> Option<Vec<u8>> {
199 self.storage(key).map(|v| Blake2Hasher::hash(&v).encode())
200 }
201
202 fn child_storage(&mut self, child_info: &ChildInfo, key: &[u8]) -> Option<StorageValue> {
203 self.overlay.child_storage(child_info, key).and_then(|v| v.map(|v| v.to_vec()))
204 }
205
206 fn child_storage_hash(&mut self, child_info: &ChildInfo, key: &[u8]) -> Option<Vec<u8>> {
207 self.child_storage(child_info, key).map(|v| Blake2Hasher::hash(&v).encode())
208 }
209
210 fn next_storage_key(&mut self, key: &[u8]) -> Option<StorageKey> {
211 self.overlay.iter_after(key).find_map(|(k, v)| v.value().map(|_| k.to_vec()))
212 }
213
214 fn next_child_storage_key(&mut self, child_info: &ChildInfo, key: &[u8]) -> Option<StorageKey> {
215 self.overlay
216 .child_iter_after(child_info.storage_key(), key)
217 .find_map(|(k, v)| v.value().map(|_| k.to_vec()))
218 }
219
220 fn place_storage(&mut self, key: StorageKey, maybe_value: Option<StorageValue>) {
221 if is_child_storage_key(&key) {
222 warn!(target: "trie", "Refuse to set child storage key via main storage");
223 return;
224 }
225
226 self.overlay.set_storage(key, maybe_value)
227 }
228
229 fn place_child_storage(
230 &mut self,
231 child_info: &ChildInfo,
232 key: StorageKey,
233 value: Option<StorageValue>,
234 ) {
235 self.overlay.set_child_storage(child_info, key, value);
236 }
237
238 fn kill_child_storage(
239 &mut self,
240 child_info: &ChildInfo,
241 _maybe_limit: Option<u32>,
242 _maybe_cursor: Option<&[u8]>,
243 ) -> MultiRemovalResults {
244 let count = self.overlay.clear_child_storage(child_info);
245 MultiRemovalResults { maybe_cursor: None, backend: count, unique: count, loops: count }
246 }
247
248 fn clear_prefix(
249 &mut self,
250 prefix: &[u8],
251 _maybe_limit: Option<u32>,
252 _maybe_cursor: Option<&[u8]>,
253 ) -> MultiRemovalResults {
254 if is_child_storage_key(prefix) {
255 warn!(
256 target: "trie",
257 "Refuse to clear prefix that is part of child storage key via main storage"
258 );
259 let maybe_cursor = Some(prefix.to_vec());
260 return MultiRemovalResults { maybe_cursor, backend: 0, unique: 0, loops: 0 };
261 }
262
263 let count = self.overlay.clear_prefix(prefix);
264 MultiRemovalResults { maybe_cursor: None, backend: count, unique: count, loops: count }
265 }
266
267 fn clear_child_prefix(
268 &mut self,
269 child_info: &ChildInfo,
270 prefix: &[u8],
271 _maybe_limit: Option<u32>,
272 _maybe_cursor: Option<&[u8]>,
273 ) -> MultiRemovalResults {
274 let count = self.overlay.clear_child_prefix(child_info, prefix);
275 MultiRemovalResults { maybe_cursor: None, backend: count, unique: count, loops: count }
276 }
277
278 fn storage_append(&mut self, key: Vec<u8>, element: Vec<u8>) {
279 self.overlay.append_storage(key, element, Default::default);
280 }
281
282 fn storage_root(&mut self) -> Vec<u8> {
283 self.storage_root_with_version(self.state_version)
284 }
285
286 fn storage_root_with_version(&mut self, state_version: StateVersion) -> Vec<u8> {
287 let mut top = self
288 .overlay
289 .changes_mut()
290 .filter_map(|(k, v)| v.value().map(|v| (k.clone(), v.clone())))
291 .collect::<BTreeMap<_, _>>();
292 let empty_hash = empty_child_trie_root::<LayoutV1<Blake2Hasher>>();
296 for child_info in self.overlay.children().map(|d| d.1.clone()).collect::<Vec<_>>() {
297 let child_root = self.child_storage_root_with_version(&child_info, state_version);
298 if empty_hash[..] == child_root[..] {
299 top.remove(child_info.prefixed_storage_key().as_slice());
300 } else {
301 top.insert(child_info.prefixed_storage_key().into_inner(), child_root);
302 }
303 }
304
305 match state_version {
306 StateVersion::V0 => LayoutV0::<Blake2Hasher>::trie_root(top).as_ref().into(),
307 StateVersion::V1 => LayoutV1::<Blake2Hasher>::trie_root(top).as_ref().into(),
308 }
309 }
310
311 fn child_storage_root(&mut self, child_info: &ChildInfo) -> Vec<u8> {
312 self.child_storage_root_with_version(child_info, self.state_version)
313 }
314
315 fn child_storage_root_with_version(
316 &mut self,
317 child_info: &ChildInfo,
318 state_version: StateVersion,
319 ) -> Vec<u8> {
320 if let Some((data, child_info)) = self.overlay.child_changes_mut(child_info.storage_key()) {
321 let delta =
322 data.into_iter().map(|(k, v)| (k.as_ref(), v.value().map(|v| v.as_slice())));
323 crate::in_memory_backend::new_in_mem::<Blake2Hasher>()
324 .child_storage_root(&child_info, delta, state_version)
325 .0
326 } else {
327 empty_child_trie_root::<LayoutV1<Blake2Hasher>>()
328 }
329 .encode()
330 }
331
332 fn storage_start_transaction(&mut self) {
333 self.overlay.start_transaction()
334 }
335
336 fn storage_rollback_transaction(&mut self) -> Result<(), ()> {
337 self.overlay.rollback_transaction().map_err(drop)
338 }
339
340 fn storage_commit_transaction(&mut self) -> Result<(), ()> {
341 self.overlay.commit_transaction().map_err(drop)
342 }
343
344 fn wipe(&mut self) {}
345
346 fn commit(&mut self) {}
347
348 fn read_write_count(&self) -> (u32, u32, u32, u32) {
349 unimplemented!("read_write_count is not supported in Basic")
350 }
351
352 fn reset_read_write_count(&mut self) {
353 unimplemented!("reset_read_write_count is not supported in Basic")
354 }
355
356 fn get_whitelist(&self) -> Vec<TrackedStorageKey> {
357 unimplemented!("get_whitelist is not supported in Basic")
358 }
359
360 fn set_whitelist(&mut self, _: Vec<TrackedStorageKey>) {
361 unimplemented!("set_whitelist is not supported in Basic")
362 }
363
364 fn get_read_and_written_keys(&self) -> Vec<(Vec<u8>, u32, u32, bool)> {
365 unimplemented!("get_read_and_written_keys is not supported in Basic")
366 }
367}
368
369impl sp_externalities::ExtensionStore for BasicExternalities {
370 fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> {
371 self.extensions.get_mut(type_id)
372 }
373
374 fn register_extension_with_type_id(
375 &mut self,
376 type_id: TypeId,
377 extension: Box<dyn sp_externalities::Extension>,
378 ) -> Result<(), sp_externalities::Error> {
379 self.extensions.register_with_type_id(type_id, extension)
380 }
381
382 fn deregister_extension_by_type_id(
383 &mut self,
384 type_id: TypeId,
385 ) -> Result<(), sp_externalities::Error> {
386 if self.extensions.deregister(type_id) {
387 Ok(())
388 } else {
389 Err(sp_externalities::Error::ExtensionIsNotRegistered(type_id))
390 }
391 }
392}
393
394#[cfg(test)]
395mod tests {
396 use super::*;
397 use sp_core::{
398 map,
399 storage::{well_known_keys::CODE, Storage, StorageChild},
400 };
401
402 #[test]
403 fn commit_should_work() {
404 let mut ext = BasicExternalities::default();
405 ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec());
406 ext.set_storage(b"dog".to_vec(), b"puppy".to_vec());
407 ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
408 let root = array_bytes::hex2bytes_unchecked(
409 "39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa",
410 );
411
412 assert_eq!(&ext.storage_root()[..], &root);
413 }
414
415 #[test]
416 fn storage_root_follows_runtime_state_version() {
417 let mut ext = BasicExternalities::default();
418 let key = b"key".to_vec();
421 let value = vec![0x42; sp_core::storage::TRIE_VALUE_NODE_THRESHOLD as usize + 1];
422 ext.set_storage(key.clone(), value.clone());
423
424 let root_v1 = ext.storage_root();
425 let mut ext = ext.with_state_version(StateVersion::V0);
426 let root_v0 = ext.storage_root();
427
428 assert_ne!(root_v0, root_v1);
429 let expected_v0 = LayoutV0::<Blake2Hasher>::trie_root(
430 vec![(key, value)].into_iter().collect::<BTreeMap<_, _>>(),
431 )
432 .as_ref()
433 .to_vec();
434 assert_eq!(root_v0, expected_v0);
435 }
436
437 #[test]
438 fn set_and_retrieve_code() {
439 let mut ext = BasicExternalities::default();
440
441 let code = vec![1, 2, 3];
442 ext.set_storage(CODE.to_vec(), code.clone());
443
444 assert_eq!(&ext.storage(CODE).unwrap(), &code);
445 }
446
447 #[test]
448 fn children_works() {
449 let child_info = ChildInfo::new_default(b"storage_key");
450 let child_info = &child_info;
451 let mut ext = BasicExternalities::new(Storage {
452 top: Default::default(),
453 children_default: map![
454 child_info.storage_key().to_vec() => StorageChild {
455 data: map![ b"doe".to_vec() => b"reindeer".to_vec() ],
456 child_info: child_info.to_owned(),
457 }
458 ],
459 });
460
461 assert_eq!(ext.child_storage(child_info, b"doe"), Some(b"reindeer".to_vec()));
462
463 ext.set_child_storage(child_info, b"dog".to_vec(), b"puppy".to_vec());
464 assert_eq!(ext.child_storage(child_info, b"dog"), Some(b"puppy".to_vec()));
465
466 ext.clear_child_storage(child_info, b"dog");
467 assert_eq!(ext.child_storage(child_info, b"dog"), None);
468
469 let _ = ext.kill_child_storage(child_info, None, None);
470 assert_eq!(ext.child_storage(child_info, b"doe"), None);
471 }
472
473 #[test]
474 fn kill_child_storage_returns_num_elements_removed() {
475 let child_info = ChildInfo::new_default(b"storage_key");
476 let child_info = &child_info;
477 let mut ext = BasicExternalities::new(Storage {
478 top: Default::default(),
479 children_default: map![
480 child_info.storage_key().to_vec() => StorageChild {
481 data: map![
482 b"doe".to_vec() => b"reindeer".to_vec(),
483 b"dog".to_vec() => b"puppy".to_vec(),
484 b"hello".to_vec() => b"world".to_vec(),
485 ],
486 child_info: child_info.to_owned(),
487 }
488 ],
489 });
490
491 let res = ext.kill_child_storage(child_info, None, None);
492 assert_eq!(res.deconstruct(), (None, 3, 3, 3));
493 }
494
495 #[test]
496 fn basic_externalities_is_empty() {
497 let storage = BasicExternalities::new_empty().into_storages();
499 assert!(storage.top.is_empty());
500 assert!(storage.children_default.is_empty());
501 }
502}