frame_support/storage/generator/
mod.rs1pub(crate) mod double_map;
28pub(crate) mod map;
29pub(crate) mod nmap;
30pub(crate) mod value;
31
32pub use double_map::StorageDoubleMap;
33pub use map::StorageMap;
34pub use nmap::StorageNMap;
35pub use value::StorageValue;
36
37#[cfg(test)]
38mod tests {
39 use alloc::vec::Vec;
40 use codec::Encode;
41 use sp_io::TestExternalities;
42 use sp_runtime::{generic, traits::BlakeTwo256, BuildStorage};
43
44 use crate::{
45 assert_noop, assert_ok,
46 storage::{generator::StorageValue, unhashed},
47 };
48
49 #[crate::pallet]
50 pub mod frame_system {
51 #[allow(unused)]
52 use super::{frame_system, frame_system::pallet_prelude::*};
53 pub use crate::dispatch::RawOrigin;
54 use crate::pallet_prelude::*;
55
56 #[pallet::pallet]
57 pub struct Pallet<T>(_);
58
59 #[pallet::config]
60 #[pallet::disable_frame_system_supertrait_check]
61 pub trait Config: 'static {
62 type Block: sp_runtime::traits::Block;
63 type AccountId;
64 type BaseCallFilter: crate::traits::Contains<Self::RuntimeCall>;
65 type RuntimeOrigin;
66 type RuntimeCall;
67 type RuntimeTask;
68 type PalletInfo: crate::traits::PalletInfo;
69 type DbWeight: Get<crate::weights::RuntimeDbWeight>;
70 }
71
72 #[pallet::origin]
73 pub type Origin<T> = RawOrigin<<T as Config>::AccountId>;
74
75 #[pallet::error]
76 pub enum Error<T> {
77 CallFiltered,
79 }
80
81 #[pallet::call]
82 impl<T: Config> Pallet<T> {}
83
84 #[pallet::storage]
85 pub type Value<T> = StorageValue<_, (u64, u64), ValueQuery>;
86
87 #[pallet::storage]
88 pub type Map<T> = StorageMap<_, Blake2_128Concat, u16, u64, ValueQuery>;
89
90 #[pallet::storage]
91 pub type NumberMap<T> = StorageMap<_, Identity, u32, u64, ValueQuery>;
92
93 #[pallet::storage]
94 pub type DoubleMap<T> =
95 StorageDoubleMap<_, Blake2_128Concat, u16, Twox64Concat, u32, u64, ValueQuery>;
96
97 #[pallet::storage]
98 pub type NMap<T> = StorageNMap<
99 _,
100 (storage::Key<Blake2_128Concat, u16>, storage::Key<Twox64Concat, u32>),
101 u64,
102 ValueQuery,
103 >;
104
105 pub mod pallet_prelude {
106 pub type OriginFor<T> = <T as super::Config>::RuntimeOrigin;
107
108 pub type HeaderFor<T> =
109 <<T as super::Config>::Block as sp_runtime::traits::HeaderProvider>::HeaderT;
110
111 pub type BlockNumberFor<T> = <HeaderFor<T> as sp_runtime::traits::Header>::Number;
112 }
113 }
114
115 type BlockNumber = u32;
116 type AccountId = u32;
117 type Header = generic::Header<BlockNumber, BlakeTwo256>;
118 type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, RuntimeCall, (), ()>;
119 type Block = generic::Block<Header, UncheckedExtrinsic>;
120
121 crate::construct_runtime!(
122 pub enum Runtime
123 {
124 System: self::frame_system,
125 }
126 );
127
128 impl self::frame_system::Config for Runtime {
129 type AccountId = AccountId;
130 type Block = Block;
131 type BaseCallFilter = crate::traits::Everything;
132 type RuntimeOrigin = RuntimeOrigin;
133 type RuntimeCall = RuntimeCall;
134 type RuntimeTask = RuntimeTask;
135 type PalletInfo = PalletInfo;
136 type DbWeight = ();
137 }
138
139 pub fn key_before_prefix(mut prefix: Vec<u8>) -> Vec<u8> {
140 let last = prefix.iter_mut().last().unwrap();
141 assert_ne!(*last, 0, "mock function not implemented for this prefix");
142 *last -= 1;
143 prefix
144 }
145
146 pub fn key_after_prefix(mut prefix: Vec<u8>) -> Vec<u8> {
147 let last = prefix.iter_mut().last().unwrap();
148 assert_ne!(*last, 255, "mock function not implemented for this prefix");
149 *last += 1;
150 prefix
151 }
152
153 #[test]
154 fn value_translate_works() {
155 let t = RuntimeGenesisConfig::default().build_storage().unwrap();
156 TestExternalities::new(t).execute_with(|| {
157 type Value = self::frame_system::Value<Runtime>;
158
159 let key = Value::storage_value_final_key();
161 unhashed::put_raw(&key, &1111u32.encode());
162
163 let translate_fn = |old: Option<u32>| -> Option<(u64, u64)> {
165 old.map(|o| (o.into(), (o * 2).into()))
166 };
167 let res = Value::translate(translate_fn);
168 debug_assert!(res.is_ok());
169
170 assert_eq!(Value::get(), (1111, 2222));
172 })
173 }
174
175 #[test]
176 fn map_translate_works() {
177 let t = RuntimeGenesisConfig::default().build_storage().unwrap();
178 TestExternalities::new(t).execute_with(|| {
179 type NumberMap = self::frame_system::NumberMap<Runtime>;
180
181 for i in 0u32..100u32 {
183 unhashed::put(&NumberMap::hashed_key_for(&i), &(i as u64));
184 }
185
186 assert_eq!(
187 NumberMap::iter().collect::<Vec<_>>(),
188 (0..100).map(|x| (x as u32, x as u64)).collect::<Vec<_>>(),
189 );
190
191 NumberMap::translate(
193 |k: u32, v: u64| if k % 2 == 0 { Some(((k as u64) << 32) | v) } else { None },
194 );
195
196 assert_eq!(
197 NumberMap::iter().collect::<Vec<_>>(),
198 (0..50u32)
199 .map(|x| x * 2)
200 .map(|x| (x, ((x as u64) << 32) | x as u64))
201 .collect::<Vec<_>>(),
202 );
203 })
204 }
205
206 #[test]
207 fn try_mutate_works() {
208 let t = RuntimeGenesisConfig::default().build_storage().unwrap();
209 TestExternalities::new(t).execute_with(|| {
210 type Value = self::frame_system::Value<Runtime>;
211 type NumberMap = self::frame_system::NumberMap<Runtime>;
212 type DoubleMap = self::frame_system::DoubleMap<Runtime>;
213
214 assert_eq!(Value::get(), (0, 0));
215 assert_eq!(NumberMap::get(0), 0);
216 assert_eq!(DoubleMap::get(0, 0), 0);
217
218 assert_noop!(
220 Value::try_mutate(|value| -> Result<(), &'static str> {
221 *value = (2, 2);
222 Err("don't change value")
223 }),
224 "don't change value"
225 );
226
227 assert_noop!(
228 NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
229 *value = 4;
230 Err("don't change value")
231 }),
232 "don't change value"
233 );
234
235 assert_noop!(
236 DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
237 *value = 6;
238 Err("don't change value")
239 }),
240 "don't change value"
241 );
242
243 assert_eq!(Value::get(), (0, 0));
245 assert_eq!(NumberMap::get(0), 0);
246 assert_eq!(DoubleMap::get(0, 0), 0);
247
248 assert_ok!(Value::try_mutate(|value| -> Result<(), &'static str> {
249 *value = (2, 2);
250 Ok(())
251 }));
252
253 assert_ok!(NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
254 *value = 4;
255 Ok(())
256 }));
257
258 assert_ok!(DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
259 *value = 6;
260 Ok(())
261 }));
262
263 assert_eq!(Value::get(), (2, 2));
264 assert_eq!(NumberMap::get(0), 4);
265 assert_eq!(DoubleMap::get(0, 0), 6);
266 });
267 }
268}