pallet_storage_overlay_checks/
lib.rs1#![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 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 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}