1use crate::{
8 hash::{ReversibleStorageHasher, StorageHasher},
9 storage::{self, storage_prefix, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
10 Never,
11};
12use alloc::vec::Vec;
13use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
14
15pub trait StorageMap<K: FullEncode, V: FullCodec> {
27 type Query;
29
30 type Hasher: StorageHasher;
32
33 fn pallet_prefix() -> &'static [u8];
35
36 fn storage_prefix() -> &'static [u8];
38
39 fn prefix_hash() -> [u8; 32];
42
43 fn from_optional_value_to_query(v: Option<V>) -> Self::Query;
45
46 fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
48
49 fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8>
51 where
52 KeyArg: EncodeLike<K>,
53 {
54 let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
55 let key_hashed = key.using_encoded(Self::Hasher::hash);
56
57 let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.as_ref().len());
58
59 final_key.extend_from_slice(&storage_prefix);
60 final_key.extend_from_slice(key_hashed.as_ref());
61
62 final_key
63 }
64}
65
66impl<K: FullCodec, V: FullCodec, G: StorageMap<K, V>> storage::IterableStorageMap<K, V> for G
67where
68 G::Hasher: ReversibleStorageHasher,
69{
70 type Iterator = PrefixIterator<(K, V)>;
71 type KeyIterator = KeyPrefixIterator<K>;
72
73 fn iter() -> Self::Iterator {
75 let prefix = G::prefix_hash().to_vec();
76 PrefixIterator {
77 prefix: prefix.clone(),
78 previous_key: prefix,
79 drain: false,
80 closure: |raw_key_without_prefix, mut raw_value| {
81 let mut key_material = G::Hasher::reverse(raw_key_without_prefix);
82 Ok((K::decode(&mut key_material)?, V::decode(&mut raw_value)?))
83 },
84 phantom: Default::default(),
85 }
86 }
87
88 fn iter_from(starting_raw_key: Vec<u8>) -> Self::Iterator {
90 let mut iter = Self::iter();
91 iter.set_last_raw_key(starting_raw_key);
92 iter
93 }
94
95 fn iter_keys() -> Self::KeyIterator {
97 let prefix = G::prefix_hash().to_vec();
98 KeyPrefixIterator {
99 prefix: prefix.clone(),
100 previous_key: prefix,
101 drain: false,
102 closure: |raw_key_without_prefix| {
103 let mut key_material = G::Hasher::reverse(raw_key_without_prefix);
104 K::decode(&mut key_material)
105 },
106 }
107 }
108
109 fn iter_keys_from(starting_raw_key: Vec<u8>) -> Self::KeyIterator {
111 let mut iter = Self::iter_keys();
112 iter.set_last_raw_key(starting_raw_key);
113 iter
114 }
115
116 fn drain() -> Self::Iterator {
118 let mut iterator = Self::iter();
119 iterator.drain = true;
120 iterator
121 }
122
123 fn translate<O: Decode, F: FnMut(K, O) -> Option<V>>(mut f: F) {
124 let mut previous_key = None;
125 loop {
126 previous_key = Self::translate_next(previous_key, &mut f);
127 if previous_key.is_none() {
128 break;
129 }
130 }
131 }
132
133 fn translate_next<O: Decode, F: FnMut(K, O) -> Option<V>>(
134 previous_key: Option<Vec<u8>>,
135 mut f: F,
136 ) -> Option<Vec<u8>> {
137 let prefix = G::prefix_hash().to_vec();
138 let previous_key = previous_key.unwrap_or_else(|| prefix.clone());
139
140 let current_key =
141 subsoil::io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))?;
142
143 let value = match unhashed::get::<O>(¤t_key) {
144 Some(value) => value,
145 None => {
146 crate::defensive!(
147 "Invalid translation: failed to decode old value for key",
148 array_bytes::bytes2hex("0x", ¤t_key)
149 );
150 return Some(current_key);
151 },
152 };
153
154 let mut key_material = G::Hasher::reverse(¤t_key[prefix.len()..]);
155 let key = match K::decode(&mut key_material) {
156 Ok(key) => key,
157 Err(_) => {
158 crate::defensive!(
159 "Invalid translation: failed to decode key",
160 array_bytes::bytes2hex("0x", ¤t_key)
161 );
162 return Some(current_key);
163 },
164 };
165
166 match f(key, value) {
167 Some(new) => unhashed::put::<V>(¤t_key, &new),
168 None => unhashed::kill(¤t_key),
169 }
170
171 Some(current_key)
172 }
173}
174
175impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {
176 type Query = G::Query;
177
178 fn hashed_key_for<KeyArg: EncodeLike<K>>(key: KeyArg) -> Vec<u8> {
179 Self::storage_map_final_key(key)
180 }
181
182 fn swap<KeyArg1: EncodeLike<K>, KeyArg2: EncodeLike<K>>(key1: KeyArg1, key2: KeyArg2) {
183 let k1 = Self::storage_map_final_key(key1);
184 let k2 = Self::storage_map_final_key(key2);
185
186 let v1 = unhashed::get_raw(k1.as_ref());
187 if let Some(val) = unhashed::get_raw(k2.as_ref()) {
188 unhashed::put_raw(k1.as_ref(), &val);
189 } else {
190 unhashed::kill(k1.as_ref())
191 }
192 if let Some(val) = v1 {
193 unhashed::put_raw(k2.as_ref(), &val);
194 } else {
195 unhashed::kill(k2.as_ref())
196 }
197 }
198
199 fn contains_key<KeyArg: EncodeLike<K>>(key: KeyArg) -> bool {
200 unhashed::exists(Self::storage_map_final_key(key).as_ref())
201 }
202
203 fn get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
204 G::from_optional_value_to_query(unhashed::get(Self::storage_map_final_key(key).as_ref()))
205 }
206
207 fn try_get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<V, ()> {
208 unhashed::get(Self::storage_map_final_key(key).as_ref()).ok_or(())
209 }
210
211 fn set<KeyArg: EncodeLike<K>>(key: KeyArg, q: Self::Query) {
212 match G::from_query_to_optional_value(q) {
213 Some(v) => Self::insert(key, v),
214 None => Self::remove(key),
215 }
216 }
217
218 fn insert<KeyArg: EncodeLike<K>, ValArg: EncodeLike<V>>(key: KeyArg, val: ValArg) {
219 unhashed::put(Self::storage_map_final_key(key).as_ref(), &val)
220 }
221
222 fn remove<KeyArg: EncodeLike<K>>(key: KeyArg) {
223 unhashed::kill(Self::storage_map_final_key(key).as_ref())
224 }
225
226 fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
227 Self::try_mutate(key, |v| Ok::<R, Never>(f(v)))
228 .expect("`Never` can not be constructed; qed")
229 }
230
231 fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
232 key: KeyArg,
233 f: F,
234 ) -> R {
235 Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v)))
236 .expect("`Never` can not be constructed; qed")
237 }
238
239 fn try_mutate<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Self::Query) -> Result<R, E>>(
240 key: KeyArg,
241 f: F,
242 ) -> Result<R, E> {
243 let final_key = Self::storage_map_final_key(key);
244 let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
245
246 let ret = f(&mut val);
247 if ret.is_ok() {
248 match G::from_query_to_optional_value(val) {
249 Some(ref val) => unhashed::put(final_key.as_ref(), &val),
250 None => unhashed::kill(final_key.as_ref()),
251 }
252 }
253 ret
254 }
255
256 fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
257 key: KeyArg,
258 f: F,
259 ) -> Result<R, E> {
260 let final_key = Self::storage_map_final_key(key);
261 let mut val = unhashed::get(final_key.as_ref());
262
263 let ret = f(&mut val);
264 if ret.is_ok() {
265 match val {
266 Some(ref val) => unhashed::put(final_key.as_ref(), &val),
267 None => unhashed::kill(final_key.as_ref()),
268 }
269 }
270 ret
271 }
272
273 fn take<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
274 let key = Self::storage_map_final_key(key);
275 let value = unhashed::take(key.as_ref());
276 G::from_optional_value_to_query(value)
277 }
278
279 fn append<Item, EncodeLikeItem, EncodeLikeKey>(key: EncodeLikeKey, item: EncodeLikeItem)
280 where
281 EncodeLikeKey: EncodeLike<K>,
282 Item: Encode,
283 EncodeLikeItem: EncodeLike<Item>,
284 V: StorageAppend<Item>,
285 {
286 let key = Self::storage_map_final_key(key);
287 subsoil::io::storage::append(&key, item.encode());
288 }
289
290 fn migrate_key<OldHasher: StorageHasher, KeyArg: EncodeLike<K>>(key: KeyArg) -> Option<V> {
291 let old_key = {
292 let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
293 let key_hashed = key.using_encoded(OldHasher::hash);
294
295 let mut final_key =
296 Vec::with_capacity(storage_prefix.len() + key_hashed.as_ref().len());
297
298 final_key.extend_from_slice(&storage_prefix);
299 final_key.extend_from_slice(key_hashed.as_ref());
300
301 final_key
302 };
303 unhashed::take(old_key.as_ref()).inspect(|value| {
304 unhashed::put(Self::storage_map_final_key(key).as_ref(), &value);
305 })
306 }
307}
308
309#[cfg(test)]
311mod test_iterators {
312 use crate::{
313 hash::StorageHasher,
314 storage::{
315 generator::{tests::*, StorageMap},
316 unhashed,
317 },
318 };
319 use alloc::vec;
320 use codec::Encode;
321
322 #[test]
323 fn map_iter_from() {
324 subsoil::io::TestExternalities::default().execute_with(|| {
325 use crate::hash::Identity;
326 #[crate::storage_alias]
327 type MyMap = StorageMap<MyModule, Identity, u64, u64>;
328
329 MyMap::insert(1, 10);
330 MyMap::insert(2, 20);
331 MyMap::insert(3, 30);
332 MyMap::insert(4, 40);
333 MyMap::insert(5, 50);
334
335 let starting_raw_key = MyMap::storage_map_final_key(3);
336 let iter = MyMap::iter_from(starting_raw_key);
337 assert_eq!(iter.collect::<Vec<_>>(), vec![(4, 40), (5, 50)]);
338
339 let starting_raw_key = MyMap::storage_map_final_key(2);
340 let iter = MyMap::iter_keys_from(starting_raw_key);
341 assert_eq!(iter.collect::<Vec<_>>(), vec![3, 4, 5]);
342 });
343 }
344
345 #[cfg(debug_assertions)]
346 #[test]
347 #[should_panic]
348 fn map_translate_with_bad_key_in_debug_mode() {
349 subsoil::io::TestExternalities::default().execute_with(|| {
350 type Map = topsoil_system::Map<Runtime>;
351 let prefix = Map::prefix_hash().to_vec();
352
353 unhashed::put(&[prefix.clone(), vec![1, 2, 3]].concat(), &3u64.encode());
355
356 Map::translate(|_k1, v: u64| Some(v * 2));
358 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 6), (0, 0), (2, 4), (1, 2)]);
359 })
360 }
361
362 #[cfg(debug_assertions)]
363 #[test]
364 #[should_panic]
365 fn map_translate_with_bad_value_in_debug_mode() {
366 subsoil::io::TestExternalities::default().execute_with(|| {
367 type Map = topsoil_system::Map<Runtime>;
368 let prefix = Map::prefix_hash().to_vec();
369
370 unhashed::put(
372 &[prefix.clone(), crate::Blake2_128Concat::hash(&6u16.encode())].concat(),
373 &vec![1],
374 );
375
376 Map::translate(|_k1, v: u64| Some(v * 2));
377 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 6), (0, 0), (2, 4), (1, 2)]);
378 })
379 }
380
381 #[cfg(not(debug_assertions))]
382 #[test]
383 fn map_translate_with_bad_key_in_production_mode() {
384 subsoil::io::TestExternalities::default().execute_with(|| {
385 type Map = topsoil_system::Map<Runtime>;
386 let prefix = Map::prefix_hash().to_vec();
387
388 unhashed::put(&[prefix.clone(), vec![1, 2, 3]].concat(), &3u64.encode());
390
391 Map::translate(|_k1, v: u64| Some(v * 2));
392 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![]);
393 })
394 }
395
396 #[cfg(not(debug_assertions))]
397 #[test]
398 fn map_translate_with_bad_value_in_production_mode() {
399 subsoil::io::TestExternalities::default().execute_with(|| {
400 type Map = topsoil_system::Map<Runtime>;
401 let prefix = Map::prefix_hash().to_vec();
402
403 unhashed::put(
405 &[prefix.clone(), crate::Blake2_128Concat::hash(&6u16.encode())].concat(),
406 &vec![1],
407 );
408
409 Map::translate(|_k1, v: u64| Some(v * 2));
410 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![]);
411 })
412 }
413
414 #[test]
415 fn map_reversible_reversible_iteration() {
416 subsoil::io::TestExternalities::default().execute_with(|| {
417 type Map = topsoil_system::Map<Runtime>;
418
419 let prefix = Map::prefix_hash().to_vec();
421
422 unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
423 unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
424
425 for i in 0..4 {
426 Map::insert(i as u16, i as u64);
427 }
428
429 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)]);
430
431 assert_eq!(Map::iter_keys().collect::<Vec<_>>(), vec![3, 0, 2, 1]);
432
433 assert_eq!(Map::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1]);
434
435 assert_eq!(Map::drain().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)]);
436
437 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![]);
438 assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
439 assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
440
441 let prefix = Map::prefix_hash().to_vec();
443
444 unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
445 unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
446 for i in 0..4 {
447 Map::insert(i as u16, i as u64);
448 }
449
450 Map::translate(|_k1, v: u64| Some(v * 2));
451 assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 6), (0, 0), (2, 4), (1, 2)]);
452 })
453 }
454}