pallet_storage_overlay_checks/
lib.rs

1//! Test pallet to check the overlay changes during the block execution and post block execution.
2
3#![cfg_attr(not(feature = "std"), no_std)]
4
5#[cfg(not(feature = "std"))]
6extern crate alloc;
7
8use frame_system::pallet_prelude::BlockNumberFor;
9pub use pallet::*;
10use sp_core::H256;
11
12const LOG_TARGET: &str = "runtime::storage_overlay_checks";
13
14#[frame_support::pallet]
15mod pallet {
16    use crate::StorageParams;
17    use frame_support::pallet_prelude::*;
18    use frame_system::pallet_prelude::BlockNumberFor;
19    use sp_core::H256;
20    use sp_runtime::traits::Zero;
21
22    #[pallet::config]
23    pub trait Config: frame_system::Config {}
24
25    #[pallet::storage]
26    pub(super) type Svvq<T> = StorageValue<_, H256, ValueQuery>;
27
28    #[pallet::storage]
29    pub(super) type Svoq<T> = StorageValue<_, H256, OptionQuery>;
30
31    #[pallet::storage]
32    pub(super) type Smvq<T> = StorageMap<_, Identity, H256, H256, ValueQuery>;
33
34    #[pallet::storage]
35    pub(super) type Smoq<T> = StorageMap<_, Identity, H256, H256, OptionQuery>;
36
37    #[pallet::storage]
38    pub(super) type Sdmvq<T> =
39        StorageDoubleMap<_, Identity, H256, Identity, H256, H256, ValueQuery>;
40
41    #[pallet::storage]
42    pub(super) type Sdmoq<T> =
43        StorageDoubleMap<_, Identity, H256, Identity, H256, H256, OptionQuery>;
44
45    #[pallet::storage]
46    pub(super) type Snmvq<T> = StorageNMap<
47        _,
48        (
49            NMapKey<Identity, H256>,
50            NMapKey<Identity, H256>,
51            NMapKey<Identity, H256>,
52        ),
53        H256,
54        ValueQuery,
55    >;
56
57    #[pallet::storage]
58    pub(super) type Snmoq<T> = StorageNMap<
59        _,
60        (
61            NMapKey<Identity, H256>,
62            NMapKey<Identity, H256>,
63            NMapKey<Identity, H256>,
64        ),
65        H256,
66        OptionQuery,
67    >;
68
69    #[pallet::pallet]
70    #[pallet::without_storage_info]
71    pub struct Pallet<T>(_);
72
73    #[pallet::hooks]
74    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
75        fn on_initialize(n: BlockNumberFor<T>) -> Weight {
76            // even blocks, storages must be set already and are emptied
77            // odd block, storages must be empty and are set
78            let params = StorageParams::default();
79            if n % BlockNumberFor::<T>::from(2u32) == Zero::zero() {
80                Pallet::<T>::check_storage_exists(n, params);
81                Pallet::<T>::clear_storage(n);
82            } else {
83                Pallet::<T>::check_storage_empty(n, params);
84                Pallet::<T>::set_storage(n, params);
85            }
86
87            Weight::zero()
88        }
89
90        fn on_finalize(n: BlockNumberFor<T>) {
91            // even blocks, storages must be emptied during initialize
92            // odd block, storages must be set during initialize
93            let params = StorageParams::default();
94            if n % BlockNumberFor::<T>::from(2u32) == Zero::zero() {
95                Pallet::<T>::check_storage_empty(n, params);
96            } else {
97                Pallet::<T>::check_storage_exists(n, params);
98            }
99        }
100    }
101}
102
103#[derive(Clone, Copy)]
104struct StorageParams {
105    key1: H256,
106    key2: H256,
107    key3: H256,
108    value: H256,
109}
110
111impl Default for StorageParams {
112    fn default() -> Self {
113        Self {
114            key1: H256::repeat_byte(1),
115            key2: H256::repeat_byte(2),
116            key3: H256::repeat_byte(3),
117            value: H256::repeat_byte(4),
118        }
119    }
120}
121
122impl<T: Config> Pallet<T> {
123    fn set_storage(n: BlockNumberFor<T>, params: StorageParams) {
124        log::debug!(target: LOG_TARGET, "Setting storages at: {:?}", n);
125        let StorageParams {
126            key1,
127            key2,
128            key3,
129            value,
130        } = params;
131
132        Svvq::<T>::set(value);
133        Svoq::<T>::set(Some(value));
134        Smvq::<T>::set(key1, value);
135        Smoq::<T>::set(key1, Some(value));
136        Sdmvq::<T>::set(key1, key2, value);
137        Sdmoq::<T>::set(key1, key2, Some(value));
138        Snmvq::<T>::set((key1, key2, key3), value);
139        Snmoq::<T>::set((key1, key2, key3), Some(value));
140    }
141
142    fn clear_storage(n: BlockNumberFor<T>) {
143        log::debug!(target: LOG_TARGET, "Clearing storages at: {:?}", n);
144        Svvq::<T>::kill();
145        Svoq::<T>::kill();
146        let _ = Smvq::<T>::clear(u32::MAX, None);
147        let _ = Smoq::<T>::clear(u32::MAX, None);
148        let _ = Sdmvq::<T>::clear(u32::MAX, None);
149        let _ = Sdmoq::<T>::clear(u32::MAX, None);
150        let _ = Snmvq::<T>::clear(u32::MAX, None);
151        let _ = Snmoq::<T>::clear(u32::MAX, None);
152    }
153
154    fn check_storage_exists(n: BlockNumberFor<T>, params: StorageParams) {
155        log::debug!(target: LOG_TARGET, "Checking storages exists at: {:?}", n);
156        let StorageParams {
157            key1,
158            key2,
159            key3,
160            value,
161        } = params;
162
163        assert_eq!(Svvq::<T>::get(), value);
164        assert_eq!(Svoq::<T>::get(), Some(value));
165        assert_eq!(Smvq::<T>::get(key1), value);
166        assert_eq!(Smoq::<T>::get(key1), Some(value));
167        assert_eq!(Sdmvq::<T>::get(key1, key2), value);
168        assert_eq!(Sdmoq::<T>::get(key1, key2), Some(value));
169        assert_eq!(Snmvq::<T>::get((key1, key2, key3)), value);
170        assert_eq!(Snmoq::<T>::get((key1, key2, key3)), Some(value));
171    }
172
173    fn check_storage_empty(n: BlockNumberFor<T>, params: StorageParams) {
174        log::debug!(target: LOG_TARGET, "Checking storages empty at: {:?}", n);
175        let StorageParams {
176            key1,
177            key2,
178            key3,
179            value: _,
180        } = params;
181
182        assert!(!Svvq::<T>::exists());
183
184        assert!(!Svoq::<T>::exists());
185        assert_eq!(Svoq::<T>::get(), None);
186
187        assert!(!Smvq::<T>::contains_key(key1));
188
189        assert!(!Smoq::<T>::contains_key(key1));
190        assert_eq!(Smoq::<T>::get(key1), None);
191
192        assert!(!Sdmvq::<T>::contains_key(key1, key2));
193
194        assert!(!Sdmoq::<T>::contains_key(key1, key2));
195        assert_eq!(Sdmoq::<T>::get(key1, key2), None);
196
197        assert!(!Snmvq::<T>::contains_key((key1, key2, key3)));
198
199        assert!(!Snmoq::<T>::contains_key((key1, key2, key3)));
200        assert_eq!(Snmoq::<T>::get((key1, key2, key3)), None);
201    }
202}