1mod changeset;
21mod offchain;
22
23pub use offchain::OffchainOverlayedChanges;
24use crate::{
25 backend::Backend,
26 stats::StateMachineStats,
27};
28use tetcore_std::{vec::Vec, any::{TypeId, Any}, boxed::Box};
29use self::changeset::OverlayedChangeSet;
30
31#[cfg(feature = "std")]
32use crate::{
33 ChangesTrieTransaction,
34 changes_trie::{
35 build_changes_trie,
36 State as ChangesTrieState,
37 },
38};
39use crate::changes_trie::BlockNumber;
40#[cfg(feature = "std")]
41use std::collections::{HashMap as Map, hash_map::Entry as MapEntry};
42#[cfg(not(feature = "std"))]
43use tetcore_std::collections::btree_map::{BTreeMap as Map, Entry as MapEntry};
44use tetcore_std::collections::btree_set::BTreeSet;
45use codec::{Decode, Encode};
46use tet_core::storage::{well_known_keys::EXTRINSIC_INDEX, ChildInfo};
47use tet_core::offchain::OffchainOverlayedChange;
48use tetsy_hash_db::Hasher;
49use crate::DefaultError;
50use externalities::{Extensions, Extension};
51
52pub use self::changeset::{OverlayedValue, NoOpenTransaction, AlreadyInRuntime, NotInRuntime};
53
54pub const NO_EXTRINSIC_INDEX: u32 = 0xffffffff;
56
57pub type StorageKey = Vec<u8>;
59
60pub type StorageValue = Vec<u8>;
62
63pub type StorageCollection = Vec<(StorageKey, Option<StorageValue>)>;
65
66pub type ChildStorageCollection = Vec<(StorageKey, StorageCollection)>;
68
69pub type OffchainChangesCollection = Vec<((Vec<u8>, Vec<u8>), OffchainOverlayedChange)>;
71
72#[derive(Debug, Default, Eq, PartialEq, Clone)]
74pub struct Extrinsics(Vec<u32>);
75
76impl Extrinsics {
77 fn copy_extrinsics_into(&self, dest: &mut BTreeSet<u32>) {
79 dest.extend(self.0.iter())
80 }
81
82 fn insert(&mut self, ext: u32) {
84 if Some(&ext) != self.0.last() {
85 self.0.push(ext);
86 }
87 }
88
89 fn extend(&mut self, other: Self) {
91 self.0.extend(other.0.into_iter());
92 }
93}
94
95#[derive(Debug, Default, Clone)]
99pub struct OverlayedChanges {
100 top: OverlayedChangeSet,
102 children: Map<StorageKey, (OverlayedChangeSet, ChildInfo)>,
104 offchain: OffchainOverlayedChanges,
106 collect_extrinsics: bool,
108 stats: StateMachineStats,
110}
111
112pub struct StorageChanges<Transaction, H: Hasher, N: BlockNumber> {
117 pub main_storage_changes: StorageCollection,
121 pub child_storage_changes: ChildStorageCollection,
123 pub offchain_storage_changes: OffchainChangesCollection,
125 pub transaction: Transaction,
130 pub transaction_storage_root: H::Out,
132 #[cfg(feature = "std")]
136 pub changes_trie_transaction: Option<ChangesTrieTransaction<H, N>>,
137 #[cfg(not(feature = "std"))]
139 pub _ph: tetcore_std::marker::PhantomData<N>,
140}
141
142#[cfg(feature = "std")]
143impl<Transaction, H: Hasher, N: BlockNumber> StorageChanges<Transaction, H, N> {
144 pub fn into_inner(self) -> (
146 StorageCollection,
147 ChildStorageCollection,
148 OffchainChangesCollection,
149 Transaction,
150 H::Out,
151 Option<ChangesTrieTransaction<H, N>>,
152 ) {
153 (
154 self.main_storage_changes,
155 self.child_storage_changes,
156 self.offchain_storage_changes,
157 self.transaction,
158 self.transaction_storage_root,
159 self.changes_trie_transaction,
160 )
161 }
162}
163
164pub struct StorageTransactionCache<Transaction, H: Hasher, N: BlockNumber> {
168 pub(crate) transaction: Option<Transaction>,
170 pub(crate) transaction_storage_root: Option<H::Out>,
172 #[cfg(feature = "std")]
174 pub(crate) changes_trie_transaction: Option<Option<ChangesTrieTransaction<H, N>>>,
175 #[cfg(feature = "std")]
177 pub(crate) changes_trie_transaction_storage_root: Option<Option<H::Out>>,
178 #[cfg(not(feature = "std"))]
180 pub(crate) _ph: tetcore_std::marker::PhantomData<N>,
181}
182
183impl<Transaction, H: Hasher, N: BlockNumber> StorageTransactionCache<Transaction, H, N> {
184 pub fn reset(&mut self) {
186 *self = Self::default();
187 }
188}
189
190impl<Transaction, H: Hasher, N: BlockNumber> Default for StorageTransactionCache<Transaction, H, N> {
191 fn default() -> Self {
192 Self {
193 transaction: None,
194 transaction_storage_root: None,
195 #[cfg(feature = "std")]
196 changes_trie_transaction: None,
197 #[cfg(feature = "std")]
198 changes_trie_transaction_storage_root: None,
199 #[cfg(not(feature = "std"))]
200 _ph: Default::default(),
201 }
202 }
203}
204
205impl<Transaction: Default, H: Hasher, N: BlockNumber> Default for StorageChanges<Transaction, H, N> {
206 fn default() -> Self {
207 Self {
208 main_storage_changes: Default::default(),
209 child_storage_changes: Default::default(),
210 offchain_storage_changes: Default::default(),
211 transaction: Default::default(),
212 transaction_storage_root: Default::default(),
213 #[cfg(feature = "std")]
214 changes_trie_transaction: None,
215 #[cfg(not(feature = "std"))]
216 _ph: Default::default(),
217 }
218 }
219}
220
221impl OverlayedChanges {
222 pub fn is_empty(&self) -> bool {
224 self.top.is_empty() && self.children.is_empty()
225 }
226
227 pub fn set_collect_extrinsics(&mut self, collect_extrinsics: bool) {
229 self.collect_extrinsics = collect_extrinsics;
230 }
231
232 pub fn storage(&self, key: &[u8]) -> Option<Option<&[u8]>> {
236 self.top.get(key).map(|x| {
237 let value = x.value();
238 let size_read = value.map(|x| x.len() as u64).unwrap_or(0);
239 self.stats.tally_read_modified(size_read);
240 value.map(AsRef::as_ref)
241 })
242 }
243
244 #[must_use = "A change was registered, so this value MUST be modified."]
250 pub fn value_mut_or_insert_with(
251 &mut self,
252 key: &[u8],
253 init: impl Fn() -> StorageValue,
254 ) -> &mut StorageValue {
255 let value = self.top.modify(key.to_vec(), init, self.extrinsic_index());
256
257 value.get_or_insert_with(StorageValue::default)
259 }
260
261 pub fn child_storage(&self, child_info: &ChildInfo, key: &[u8]) -> Option<Option<&[u8]>> {
265 let map = self.children.get(child_info.storage_key())?;
266 let value = map.0.get(key)?.value();
267 let size_read = value.map(|x| x.len() as u64).unwrap_or(0);
268 self.stats.tally_read_modified(size_read);
269 Some(value.map(AsRef::as_ref))
270 }
271
272 pub(crate) fn set_storage(&mut self, key: StorageKey, val: Option<StorageValue>) {
276 let size_write = val.as_ref().map(|x| x.len() as u64).unwrap_or(0);
277 self.stats.tally_write_overlay(size_write);
278 self.top.set(key, val, self.extrinsic_index());
279 }
280
281 pub(crate) fn set_child_storage(
287 &mut self,
288 child_info: &ChildInfo,
289 key: StorageKey,
290 val: Option<StorageValue>,
291 ) {
292 let extrinsic_index = self.extrinsic_index();
293 let size_write = val.as_ref().map(|x| x.len() as u64).unwrap_or(0);
294 self.stats.tally_write_overlay(size_write);
295 let storage_key = child_info.storage_key().to_vec();
296 let top = &self.top;
297 let (changeset, info) = self.children.entry(storage_key).or_insert_with(||
298 (
299 top.spawn_child(),
300 child_info.clone()
301 )
302 );
303 let updatable = info.try_update(child_info);
304 debug_assert!(updatable);
305 changeset.set(key, val, extrinsic_index);
306 }
307
308 pub(crate) fn clear_child_storage(
312 &mut self,
313 child_info: &ChildInfo,
314 ) {
315 let extrinsic_index = self.extrinsic_index();
316 let storage_key = child_info.storage_key().to_vec();
317 let top = &self.top;
318 let (changeset, info) = self.children.entry(storage_key).or_insert_with(||
319 (
320 top.spawn_child(),
321 child_info.clone()
322 )
323 );
324 let updatable = info.try_update(child_info);
325 debug_assert!(updatable);
326 changeset.clear_where(|_, _| true, extrinsic_index);
327 }
328
329 pub(crate) fn clear_prefix(&mut self, prefix: &[u8]) {
333 self.top.clear_where(|key, _| key.starts_with(prefix), self.extrinsic_index());
334 }
335
336 pub(crate) fn clear_child_prefix(
340 &mut self,
341 child_info: &ChildInfo,
342 prefix: &[u8],
343 ) {
344 let extrinsic_index = self.extrinsic_index();
345 let storage_key = child_info.storage_key().to_vec();
346 let top = &self.top;
347 let (changeset, info) = self.children.entry(storage_key).or_insert_with(||
348 (
349 top.spawn_child(),
350 child_info.clone()
351 )
352 );
353 let updatable = info.try_update(child_info);
354 debug_assert!(updatable);
355 changeset.clear_where(|key, _| key.starts_with(prefix), extrinsic_index);
356 }
357
358 pub fn transaction_depth(&self) -> usize {
362 self.top.transaction_depth()
365 }
366
367 pub fn start_transaction(&mut self) {
375 self.top.start_transaction();
376 for (_, (changeset, _)) in self.children.iter_mut() {
377 changeset.start_transaction();
378 }
379 self.offchain.overlay_mut().start_transaction();
380 }
381
382 pub fn rollback_transaction(&mut self) -> Result<(), NoOpenTransaction> {
387 self.top.rollback_transaction()?;
388 retain_map(&mut self.children, |_, (changeset, _)| {
389 changeset.rollback_transaction()
390 .expect("Top and children changesets are started in lockstep; qed");
391 !changeset.is_empty()
392 });
393 self.offchain.overlay_mut().rollback_transaction()
394 .expect("Top and offchain changesets are started in lockstep; qed");
395 Ok(())
396 }
397
398 pub fn commit_transaction(&mut self) -> Result<(), NoOpenTransaction> {
403 self.top.commit_transaction()?;
404 for (_, (changeset, _)) in self.children.iter_mut() {
405 changeset.commit_transaction()
406 .expect("Top and children changesets are started in lockstep; qed");
407 }
408 self.offchain.overlay_mut().commit_transaction()
409 .expect("Top and offchain changesets are started in lockstep; qed");
410 Ok(())
411 }
412
413 pub fn enter_runtime(&mut self) -> Result<(), AlreadyInRuntime> {
418 self.top.enter_runtime()?;
419 for (_, (changeset, _)) in self.children.iter_mut() {
420 changeset.enter_runtime()
421 .expect("Top and children changesets are entering runtime in lockstep; qed")
422 }
423 self.offchain.overlay_mut().enter_runtime()
424 .expect("Top and offchain changesets are started in lockstep; qed");
425 Ok(())
426 }
427
428 pub fn exit_runtime(&mut self) -> Result<(), NotInRuntime> {
433 self.top.exit_runtime()?;
434 for (_, (changeset, _)) in self.children.iter_mut() {
435 changeset.exit_runtime()
436 .expect("Top and children changesets are entering runtime in lockstep; qed");
437 }
438 self.offchain.overlay_mut().exit_runtime()
439 .expect("Top and offchain changesets are started in lockstep; qed");
440 Ok(())
441 }
442
443 fn drain_committed(&mut self) -> (
450 impl Iterator<Item=(StorageKey, Option<StorageValue>)>,
451 impl Iterator<Item=(StorageKey, (impl Iterator<Item=(StorageKey, Option<StorageValue>)>, ChildInfo))>,
452 ) {
453 use tetcore_std::mem::take;
454 (
455 take(&mut self.top).drain_commited(),
456 take(&mut self.children).into_iter()
457 .map(|(key, (val, info))| (
458 key,
459 (val.drain_commited(), info)
460 )
461 ),
462 )
463 }
464
465 pub fn offchain_drain_committed(&mut self) -> impl Iterator<Item=((StorageKey, StorageKey), OffchainOverlayedChange)> {
472 self.offchain.drain()
473 }
474
475 pub fn children(&self)
477 -> impl Iterator<Item=(impl Iterator<Item=(&StorageKey, &OverlayedValue)>, &ChildInfo)> {
478 self.children.iter().map(|(_, v)| (v.0.changes(), &v.1))
479 }
480
481 pub fn changes(&self) -> impl Iterator<Item=(&StorageKey, &OverlayedValue)> {
483 self.top.changes()
484 }
485
486 pub fn child_changes(&self, key: &[u8])
488 -> Option<(impl Iterator<Item=(&StorageKey, &OverlayedValue)>, &ChildInfo)> {
489 self.children.get(key).map(|(overlay, info)| (overlay.changes(), info))
490 }
491
492 #[cfg(feature = "std")]
494 pub fn into_storage_changes<
495 B: Backend<H>, H: Hasher, N: BlockNumber
496 >(
497 mut self,
498 backend: &B,
499 changes_trie_state: Option<&ChangesTrieState<H, N>>,
500 parent_hash: H::Out,
501 mut cache: StorageTransactionCache<B::Transaction, H, N>,
502 ) -> Result<StorageChanges<B::Transaction, H, N>, DefaultError>
503 where H::Out: Ord + Encode + 'static {
504 self.drain_storage_changes(backend, changes_trie_state, parent_hash, &mut cache)
505 }
506
507 pub fn drain_storage_changes<B: Backend<H>, H: Hasher, N: BlockNumber>(
509 &mut self,
510 backend: &B,
511 #[cfg(feature = "std")]
512 changes_trie_state: Option<&ChangesTrieState<H, N>>,
513 parent_hash: H::Out,
514 mut cache: &mut StorageTransactionCache<B::Transaction, H, N>,
515 ) -> Result<StorageChanges<B::Transaction, H, N>, DefaultError>
516 where H::Out: Ord + Encode + 'static {
517 if cache.transaction.is_none() {
519 self.storage_root(backend, &mut cache);
520 }
521
522 let (transaction, transaction_storage_root) = cache.transaction.take()
523 .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr)))
524 .expect("Transaction was be generated as part of `storage_root`; qed");
525
526 #[cfg(feature = "std")]
528 if cache.changes_trie_transaction.is_none() {
529 self.changes_trie_root(
530 backend,
531 changes_trie_state,
532 parent_hash,
533 false,
534 &mut cache,
535 ).map_err(|_| "Failed to generate changes trie transaction")?;
536 }
537
538 #[cfg(feature = "std")]
539 let changes_trie_transaction = cache.changes_trie_transaction
540 .take()
541 .expect("Changes trie transaction was generated by `changes_trie_root`; qed");
542
543 let (main_storage_changes, child_storage_changes) = self.drain_committed();
544 let offchain_storage_changes = self.offchain_drain_committed().collect();
545
546 Ok(StorageChanges {
547 main_storage_changes: main_storage_changes.collect(),
548 child_storage_changes: child_storage_changes.map(|(sk, it)| (sk, it.0.collect())).collect(),
549 offchain_storage_changes,
550 transaction,
551 transaction_storage_root,
552 #[cfg(feature = "std")]
553 changes_trie_transaction,
554 #[cfg(not(feature = "std"))]
555 _ph: Default::default(),
556 })
557 }
558
559 #[cfg(test)]
561 pub(crate) fn set_extrinsic_index(&mut self, extrinsic_index: u32) {
562 self.top.set(EXTRINSIC_INDEX.to_vec(), Some(extrinsic_index.encode()), None);
563 }
564
565 fn extrinsic_index(&self) -> Option<u32> {
572 match self.collect_extrinsics {
573 true => Some(
574 self.storage(EXTRINSIC_INDEX)
575 .and_then(|idx| idx.and_then(|idx| Decode::decode(&mut &*idx).ok()))
576 .unwrap_or(NO_EXTRINSIC_INDEX)),
577 false => None,
578 }
579 }
580
581 pub fn storage_root<H: Hasher, N: BlockNumber, B: Backend<H>>(
586 &self,
587 backend: &B,
588 cache: &mut StorageTransactionCache<B::Transaction, H, N>,
589 ) -> H::Out
590 where H::Out: Ord + Encode,
591 {
592 let delta = self.changes().map(|(k, v)| (&k[..], v.value().map(|v| &v[..])));
593 let child_delta = self.children()
594 .map(|(changes, info)| (info, changes.map(
595 |(k, v)| (&k[..], v.value().map(|v| &v[..]))
596 )));
597
598 let (root, transaction) = backend.full_storage_root(delta, child_delta);
599
600 cache.transaction = Some(transaction);
601 cache.transaction_storage_root = Some(root);
602
603 root
604 }
605
606 #[cfg(feature = "std")]
614 pub fn changes_trie_root<'a, H: Hasher, N: BlockNumber, B: Backend<H>>(
615 &self,
616 backend: &B,
617 changes_trie_state: Option<&'a ChangesTrieState<'a, H, N>>,
618 parent_hash: H::Out,
619 panic_on_storage_error: bool,
620 cache: &mut StorageTransactionCache<B::Transaction, H, N>,
621 ) -> Result<Option<H::Out>, ()> where H::Out: Ord + Encode + 'static {
622 build_changes_trie::<_, H, N>(
623 backend,
624 changes_trie_state,
625 self,
626 parent_hash,
627 panic_on_storage_error,
628 ).map(|r| {
629 let root = r.as_ref().map(|r| r.1).clone();
630 cache.changes_trie_transaction = Some(r.map(|(db, _, cache)| (db, cache)));
631 cache.changes_trie_transaction_storage_root = Some(root);
632 root
633 })
634 }
635
636 pub fn next_storage_key_change(&self, key: &[u8]) -> Option<(&[u8], &OverlayedValue)> {
639 self.top.next_change(key)
640 }
641
642 pub fn next_child_storage_key_change(
645 &self,
646 storage_key: &[u8],
647 key: &[u8]
648 ) -> Option<(&[u8], &OverlayedValue)> {
649 self.children
650 .get(storage_key)
651 .and_then(|(overlay, _)|
652 overlay.next_change(key)
653 )
654 }
655
656 pub fn offchain(&self) -> &OffchainOverlayedChanges {
658 &self.offchain
659 }
660
661 pub fn set_offchain_storage(&mut self, key: &[u8], value: Option<&[u8]>) {
663 use tet_core::offchain::STORAGE_PREFIX;
664 match value {
665 Some(value) => self.offchain.set(STORAGE_PREFIX, key, value),
666 None => self.offchain.remove(STORAGE_PREFIX, key),
667 }
668 }
669}
670
671#[cfg(feature = "std")]
672fn retain_map<K, V, F>(map: &mut Map<K, V>, f: F)
673 where
674 K: std::cmp::Eq + std::hash::Hash,
675 F: FnMut(&K, &mut V) -> bool,
676{
677 map.retain(f);
678}
679
680#[cfg(not(feature = "std"))]
681fn retain_map<K, V, F>(map: &mut Map<K, V>, mut f: F)
682 where
683 K: Ord,
684 F: FnMut(&K, &mut V) -> bool,
685{
686 let old = tetcore_std::mem::replace(map, Map::default());
687 for (k, mut v) in old.into_iter() {
688 if f(&k, &mut v) {
689 map.insert(k, v);
690 }
691 }
692}
693
694pub enum OverlayedExtension<'a> {
697 MutRef(&'a mut Box<dyn Extension>),
698 Owned(Box<dyn Extension>),
699}
700
701pub struct OverlayedExtensions<'a> {
709 extensions: Map<TypeId, OverlayedExtension<'a>>,
710}
711
712impl<'a> OverlayedExtensions<'a> {
713 pub fn new(extensions: &'a mut Extensions) -> Self {
715 Self {
716 extensions: extensions
717 .iter_mut()
718 .map(|(k, v)| (*k, OverlayedExtension::MutRef(v)))
719 .collect(),
720 }
721 }
722
723 pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> {
725 self.extensions.get_mut(&ext_type_id).map(|ext| match ext {
726 OverlayedExtension::MutRef(ext) => ext.as_mut_any(),
727 OverlayedExtension::Owned(ext) => ext.as_mut_any(),
728 })
729 }
730
731 pub fn register(
733 &mut self,
734 type_id: TypeId,
735 extension: Box<dyn Extension>,
736 ) -> Result<(), externalities::Error> {
737 match self.extensions.entry(type_id) {
738 MapEntry::Vacant(vacant) => {
739 vacant.insert(OverlayedExtension::Owned(extension));
740 Ok(())
741 },
742 MapEntry::Occupied(_) => Err(externalities::Error::ExtensionAlreadyRegistered),
743 }
744 }
745
746 pub fn deregister(&mut self, type_id: TypeId) -> bool {
750 self.extensions.remove(&type_id).is_some()
751 }
752}
753
754#[cfg(test)]
755mod tests {
756 use hex_literal::hex;
757 use tet_core::{Blake2Hasher, traits::Externalities};
758 use crate::InMemoryBackend;
759 use crate::ext::Ext;
760 use super::*;
761 use std::collections::BTreeMap;
762
763 fn assert_extrinsics(
764 overlay: &OverlayedChangeSet,
765 key: impl AsRef<[u8]>,
766 expected: Vec<u32>,
767 ) {
768 assert_eq!(
769 overlay.get(key.as_ref()).unwrap().extrinsics().into_iter().collect::<Vec<_>>(),
770 expected
771 )
772 }
773
774 #[test]
775 fn overlayed_storage_works() {
776 let mut overlayed = OverlayedChanges::default();
777
778 let key = vec![42, 69, 169, 142];
779
780 assert!(overlayed.storage(&key).is_none());
781
782 overlayed.start_transaction();
783
784 overlayed.set_storage(key.clone(), Some(vec![1, 2, 3]));
785 assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..]));
786
787 overlayed.commit_transaction().unwrap();
788
789 assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..]));
790
791 overlayed.start_transaction();
792
793 overlayed.set_storage(key.clone(), Some(vec![]));
794 assert_eq!(overlayed.storage(&key).unwrap(), Some(&[][..]));
795
796 overlayed.set_storage(key.clone(), None);
797 assert!(overlayed.storage(&key).unwrap().is_none());
798
799 overlayed.rollback_transaction().unwrap();
800
801 assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..]));
802
803 overlayed.set_storage(key.clone(), None);
804 assert!(overlayed.storage(&key).unwrap().is_none());
805 }
806
807 #[test]
808 fn offchain_overlayed_storage_transactions_works() {
809 use tet_core::offchain::STORAGE_PREFIX;
810 fn check_offchain_content(
811 state: &OverlayedChanges,
812 nb_commit: usize,
813 expected: Vec<(Vec<u8>, Option<Vec<u8>>)>,
814 ) {
815 let mut state = state.clone();
816 for _ in 0..nb_commit {
817 state.commit_transaction().unwrap();
818 }
819 let offchain_data: Vec<_> = state.offchain_drain_committed().collect();
820 let expected: Vec<_> = expected.into_iter().map(|(key, value)| {
821 let change = match value {
822 Some(value) => OffchainOverlayedChange::SetValue(value),
823 None => OffchainOverlayedChange::Remove,
824 };
825 ((STORAGE_PREFIX.to_vec(), key), change)
826 }).collect();
827 assert_eq!(offchain_data, expected);
828 }
829
830 let mut overlayed = OverlayedChanges::default();
831
832 let key = vec![42, 69, 169, 142];
833
834 check_offchain_content(&overlayed, 0, vec![]);
835
836 overlayed.start_transaction();
837
838 overlayed.set_offchain_storage(key.as_slice(), Some(&[1, 2, 3][..]));
839 check_offchain_content(&overlayed, 1, vec![(key.clone(), Some(vec![1, 2, 3]))]);
840
841 overlayed.commit_transaction().unwrap();
842
843 check_offchain_content(&overlayed, 0, vec![(key.clone(), Some(vec![1, 2, 3]))]);
844
845 overlayed.start_transaction();
846
847 overlayed.set_offchain_storage(key.as_slice(), Some(&[][..]));
848 check_offchain_content(&overlayed, 1, vec![(key.clone(), Some(vec![]))]);
849
850 overlayed.set_offchain_storage(key.as_slice(), None);
851 check_offchain_content(&overlayed, 1, vec![(key.clone(), None)]);
852
853 overlayed.rollback_transaction().unwrap();
854
855 check_offchain_content(&overlayed, 0, vec![(key.clone(), Some(vec![1, 2, 3]))]);
856
857 overlayed.set_offchain_storage(key.as_slice(), None);
858 check_offchain_content(&overlayed, 0, vec![(key.clone(), None)]);
859 }
860
861
862 #[test]
863 fn overlayed_storage_root_works() {
864 let initial: BTreeMap<_, _> = vec![
865 (b"doe".to_vec(), b"reindeer".to_vec()),
866 (b"dog".to_vec(), b"puppyXXX".to_vec()),
867 (b"dogglesworth".to_vec(), b"catXXX".to_vec()),
868 (b"doug".to_vec(), b"notadog".to_vec()),
869 ].into_iter().collect();
870 let backend = InMemoryBackend::<Blake2Hasher>::from(initial);
871 let mut overlay = OverlayedChanges::default();
872 overlay.set_collect_extrinsics(false);
873
874 overlay.start_transaction();
875 overlay.set_storage(b"dog".to_vec(), Some(b"puppy".to_vec()));
876 overlay.set_storage(b"dogglesworth".to_vec(), Some(b"catYYY".to_vec()));
877 overlay.set_storage(b"doug".to_vec(), Some(vec![]));
878 overlay.commit_transaction().unwrap();
879
880 overlay.start_transaction();
881 overlay.set_storage(b"dogglesworth".to_vec(), Some(b"cat".to_vec()));
882 overlay.set_storage(b"doug".to_vec(), None);
883
884 let mut cache = StorageTransactionCache::default();
885 let mut ext = Ext::new(
886 &mut overlay,
887 &mut cache,
888 &backend,
889 crate::changes_trie::disabled_state::<_, u64>(),
890 None,
891 );
892 const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa");
893
894 assert_eq!(&ext.storage_root()[..], &ROOT);
895 }
896
897 #[test]
898 fn extrinsic_changes_are_collected() {
899 let mut overlay = OverlayedChanges::default();
900 overlay.set_collect_extrinsics(true);
901
902 overlay.start_transaction();
903
904 overlay.set_storage(vec![100], Some(vec![101]));
905
906 overlay.set_extrinsic_index(0);
907 overlay.set_storage(vec![1], Some(vec![2]));
908
909 overlay.set_extrinsic_index(1);
910 overlay.set_storage(vec![3], Some(vec![4]));
911
912 overlay.set_extrinsic_index(2);
913 overlay.set_storage(vec![1], Some(vec![6]));
914
915 assert_extrinsics(&overlay.top, vec![1], vec![0, 2]);
916 assert_extrinsics(&overlay.top, vec![3], vec![1]);
917 assert_extrinsics(&overlay.top, vec![100], vec![NO_EXTRINSIC_INDEX]);
918
919 overlay.start_transaction();
920
921 overlay.set_extrinsic_index(3);
922 overlay.set_storage(vec![3], Some(vec![7]));
923
924 overlay.set_extrinsic_index(4);
925 overlay.set_storage(vec![1], Some(vec![8]));
926
927 assert_extrinsics(&overlay.top, vec![1], vec![0, 2, 4]);
928 assert_extrinsics(&overlay.top, vec![3], vec![1, 3]);
929 assert_extrinsics(&overlay.top, vec![100], vec![NO_EXTRINSIC_INDEX]);
930
931 overlay.rollback_transaction().unwrap();
932
933 assert_extrinsics(&overlay.top, vec![1], vec![0, 2]);
934 assert_extrinsics(&overlay.top, vec![3], vec![1]);
935 assert_extrinsics(&overlay.top, vec![100], vec![NO_EXTRINSIC_INDEX]);
936 }
937
938 #[test]
939 fn next_storage_key_change_works() {
940 let mut overlay = OverlayedChanges::default();
941 overlay.start_transaction();
942 overlay.set_storage(vec![20], Some(vec![20]));
943 overlay.set_storage(vec![30], Some(vec![30]));
944 overlay.set_storage(vec![40], Some(vec![40]));
945 overlay.commit_transaction().unwrap();
946 overlay.set_storage(vec![10], Some(vec![10]));
947 overlay.set_storage(vec![30], None);
948
949 let next_to_5 = overlay.next_storage_key_change(&[5]).unwrap();
951 assert_eq!(next_to_5.0.to_vec(), vec![10]);
952 assert_eq!(next_to_5.1.value(), Some(&vec![10]));
953
954 let next_to_10 = overlay.next_storage_key_change(&[10]).unwrap();
956 assert_eq!(next_to_10.0.to_vec(), vec![20]);
957 assert_eq!(next_to_10.1.value(), Some(&vec![20]));
958
959 let next_to_20 = overlay.next_storage_key_change(&[20]).unwrap();
961 assert_eq!(next_to_20.0.to_vec(), vec![30]);
962 assert_eq!(next_to_20.1.value(), None);
963
964 let next_to_30 = overlay.next_storage_key_change(&[30]).unwrap();
966 assert_eq!(next_to_30.0.to_vec(), vec![40]);
967 assert_eq!(next_to_30.1.value(), Some(&vec![40]));
968
969 overlay.set_storage(vec![50], Some(vec![50]));
970 let next_to_40 = overlay.next_storage_key_change(&[40]).unwrap();
972 assert_eq!(next_to_40.0.to_vec(), vec![50]);
973 assert_eq!(next_to_40.1.value(), Some(&vec![50]));
974 }
975
976 #[test]
977 fn next_child_storage_key_change_works() {
978 let child_info = ChildInfo::new_default(b"Child1");
979 let child_info = &child_info;
980 let child = child_info.storage_key();
981 let mut overlay = OverlayedChanges::default();
982 overlay.start_transaction();
983 overlay.set_child_storage(child_info, vec![20], Some(vec![20]));
984 overlay.set_child_storage(child_info, vec![30], Some(vec![30]));
985 overlay.set_child_storage(child_info, vec![40], Some(vec![40]));
986 overlay.commit_transaction().unwrap();
987 overlay.set_child_storage(child_info, vec![10], Some(vec![10]));
988 overlay.set_child_storage(child_info, vec![30], None);
989
990 let next_to_5 = overlay.next_child_storage_key_change(child, &[5]).unwrap();
992 assert_eq!(next_to_5.0.to_vec(), vec![10]);
993 assert_eq!(next_to_5.1.value(), Some(&vec![10]));
994
995 let next_to_10 = overlay.next_child_storage_key_change(child, &[10]).unwrap();
997 assert_eq!(next_to_10.0.to_vec(), vec![20]);
998 assert_eq!(next_to_10.1.value(), Some(&vec![20]));
999
1000 let next_to_20 = overlay.next_child_storage_key_change(child, &[20]).unwrap();
1002 assert_eq!(next_to_20.0.to_vec(), vec![30]);
1003 assert_eq!(next_to_20.1.value(), None);
1004
1005 let next_to_30 = overlay.next_child_storage_key_change(child, &[30]).unwrap();
1007 assert_eq!(next_to_30.0.to_vec(), vec![40]);
1008 assert_eq!(next_to_30.1.value(), Some(&vec![40]));
1009
1010 overlay.set_child_storage(child_info, vec![50], Some(vec![50]));
1011 let next_to_40 = overlay.next_child_storage_key_change(child, &[40]).unwrap();
1013 assert_eq!(next_to_40.0.to_vec(), vec![50]);
1014 assert_eq!(next_to_40.1.value(), Some(&vec![50]));
1015 }
1016}