1use crate::{
21 hash::ReversibleStorageHasher,
22 storage::{storage_prefix, unhashed},
23 StorageHasher, Twox128,
24};
25use alloc::{vec, vec::Vec};
26use codec::{Decode, Encode};
27
28use super::PrefixIterator;
29
30pub struct StorageIterator<T> {
32 prefix: Vec<u8>,
33 previous_key: Vec<u8>,
34 drain: bool,
35 _phantom: ::core::marker::PhantomData<T>,
36}
37
38impl<T> StorageIterator<T> {
39 #[deprecated(note = "Will be removed after July 2023; Please use the storage_iter or \
41 storage_iter_with_suffix functions instead")]
42 pub fn new(module: &[u8], item: &[u8]) -> Self {
43 #[allow(deprecated)]
44 Self::with_suffix(module, item, &[][..])
45 }
46
47 #[deprecated(note = "Will be removed after July 2023; Please use the storage_iter or \
49 storage_iter_with_suffix functions instead")]
50 pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
51 let mut prefix = Vec::new();
52 let storage_prefix = storage_prefix(module, item);
53 prefix.extend_from_slice(&storage_prefix);
54 prefix.extend_from_slice(suffix);
55 let previous_key = prefix.clone();
56 Self { prefix, previous_key, drain: false, _phantom: Default::default() }
57 }
58
59 pub fn drain(mut self) -> Self {
61 self.drain = true;
62 self
63 }
64}
65
66impl<T: Decode + Sized> Iterator for StorageIterator<T> {
67 type Item = (Vec<u8>, T);
68
69 fn next(&mut self) -> Option<(Vec<u8>, T)> {
70 loop {
71 let maybe_next = sp_io::storage::next_key(&self.previous_key)
72 .filter(|n| n.starts_with(&self.prefix));
73 break match maybe_next {
74 Some(next) => {
75 self.previous_key = next.clone();
76 let maybe_value = frame_support::storage::unhashed::get::<T>(&next);
77 match maybe_value {
78 Some(value) => {
79 if self.drain {
80 frame_support::storage::unhashed::kill(&next);
81 }
82 Some((self.previous_key[self.prefix.len()..].to_vec(), value))
83 },
84 None => continue,
85 }
86 },
87 None => None,
88 }
89 }
90 }
91}
92
93pub struct StorageKeyIterator<K, T, H: ReversibleStorageHasher> {
95 prefix: Vec<u8>,
96 previous_key: Vec<u8>,
97 drain: bool,
98 _phantom: ::core::marker::PhantomData<(K, T, H)>,
99}
100
101impl<K, T, H: ReversibleStorageHasher> StorageKeyIterator<K, T, H> {
102 #[deprecated(note = "Will be removed after July 2023; Please use the storage_key_iter or \
104 storage_key_iter_with_suffix functions instead")]
105 pub fn new(module: &[u8], item: &[u8]) -> Self {
106 #[allow(deprecated)]
107 Self::with_suffix(module, item, &[][..])
108 }
109
110 #[deprecated(note = "Will be removed after July 2023; Please use the storage_key_iter or \
112 storage_key_iter_with_suffix functions instead")]
113 pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
114 let mut prefix = Vec::new();
115 let storage_prefix = storage_prefix(module, item);
116 prefix.extend_from_slice(&storage_prefix);
117 prefix.extend_from_slice(suffix);
118 let previous_key = prefix.clone();
119 Self { prefix, previous_key, drain: false, _phantom: Default::default() }
120 }
121
122 pub fn drain(mut self) -> Self {
124 self.drain = true;
125 self
126 }
127}
128
129impl<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher> Iterator
130 for StorageKeyIterator<K, T, H>
131{
132 type Item = (K, T);
133
134 fn next(&mut self) -> Option<(K, T)> {
135 loop {
136 let maybe_next = sp_io::storage::next_key(&self.previous_key)
137 .filter(|n| n.starts_with(&self.prefix));
138 break match maybe_next {
139 Some(next) => {
140 self.previous_key = next.clone();
141 let mut key_material = H::reverse(&next[self.prefix.len()..]);
142 match K::decode(&mut key_material) {
143 Ok(key) => {
144 let maybe_value = frame_support::storage::unhashed::get::<T>(&next);
145 match maybe_value {
146 Some(value) => {
147 if self.drain {
148 frame_support::storage::unhashed::kill(&next);
149 }
150 Some((key, value))
151 },
152 None => continue,
153 }
154 },
155 Err(_) => continue,
156 }
157 },
158 None => None,
159 }
160 }
161 }
162}
163
164pub fn storage_iter<T: Decode + Sized>(module: &[u8], item: &[u8]) -> PrefixIterator<(Vec<u8>, T)> {
166 storage_iter_with_suffix(module, item, &[][..])
167}
168
169pub fn storage_iter_with_suffix<T: Decode + Sized>(
171 module: &[u8],
172 item: &[u8],
173 suffix: &[u8],
174) -> PrefixIterator<(Vec<u8>, T)> {
175 let mut prefix = Vec::new();
176 let storage_prefix = storage_prefix(module, item);
177 prefix.extend_from_slice(&storage_prefix);
178 prefix.extend_from_slice(suffix);
179 let previous_key = prefix.clone();
180 let closure = |raw_key_without_prefix: &[u8], mut raw_value: &[u8]| {
181 let value = T::decode(&mut raw_value)?;
182 Ok((raw_key_without_prefix.to_vec(), value))
183 };
184
185 PrefixIterator { prefix, previous_key, drain: false, closure, phantom: Default::default() }
186}
187
188pub fn storage_key_iter<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher>(
190 module: &[u8],
191 item: &[u8],
192) -> PrefixIterator<(K, T)> {
193 storage_key_iter_with_suffix::<K, T, H>(module, item, &[][..])
194}
195
196pub fn storage_key_iter_with_suffix<
198 K: Decode + Sized,
199 T: Decode + Sized,
200 H: ReversibleStorageHasher,
201>(
202 module: &[u8],
203 item: &[u8],
204 suffix: &[u8],
205) -> PrefixIterator<(K, T)> {
206 let mut prefix = Vec::new();
207 let storage_prefix = storage_prefix(module, item);
208
209 prefix.extend_from_slice(&storage_prefix);
210 prefix.extend_from_slice(suffix);
211 let previous_key = prefix.clone();
212 let closure = |raw_key_without_prefix: &[u8], mut raw_value: &[u8]| {
213 let mut key_material = H::reverse(raw_key_without_prefix);
214 let key = K::decode(&mut key_material)?;
215 let value = T::decode(&mut raw_value)?;
216 Ok((key, value))
217 };
218 PrefixIterator { prefix, previous_key, drain: false, closure, phantom: Default::default() }
219}
220
221pub fn have_storage_value(module: &[u8], item: &[u8], hash: &[u8]) -> bool {
223 get_storage_value::<()>(module, item, hash).is_some()
224}
225
226pub fn get_storage_value<T: Decode + Sized>(module: &[u8], item: &[u8], hash: &[u8]) -> Option<T> {
228 let mut key = vec![0u8; 32 + hash.len()];
229 let storage_prefix = storage_prefix(module, item);
230 key[0..32].copy_from_slice(&storage_prefix);
231 key[32..].copy_from_slice(hash);
232 frame_support::storage::unhashed::get::<T>(&key)
233}
234
235pub fn take_storage_value<T: Decode + Sized>(module: &[u8], item: &[u8], hash: &[u8]) -> Option<T> {
237 let mut key = vec![0u8; 32 + hash.len()];
238 let storage_prefix = storage_prefix(module, item);
239 key[0..32].copy_from_slice(&storage_prefix);
240 key[32..].copy_from_slice(hash);
241 frame_support::storage::unhashed::take::<T>(&key)
242}
243
244pub fn put_storage_value<T: Encode>(module: &[u8], item: &[u8], hash: &[u8], value: T) {
246 let mut key = vec![0u8; 32 + hash.len()];
247 let storage_prefix = storage_prefix(module, item);
248 key[0..32].copy_from_slice(&storage_prefix);
249 key[32..].copy_from_slice(hash);
250 frame_support::storage::unhashed::put(&key, &value);
251}
252
253#[deprecated = "Use `clear_storage_prefix` instead"]
256pub fn remove_storage_prefix(module: &[u8], item: &[u8], hash: &[u8]) {
257 let mut key = vec![0u8; 32 + hash.len()];
258 let storage_prefix = storage_prefix(module, item);
259 key[0..32].copy_from_slice(&storage_prefix);
260 key[32..].copy_from_slice(hash);
261 let _ = frame_support::storage::unhashed::clear_prefix(&key, None, None);
262}
263
264pub fn clear_storage_prefix(
281 module: &[u8],
282 item: &[u8],
283 hash: &[u8],
284 maybe_limit: Option<u32>,
285 maybe_cursor: Option<&[u8]>,
286) -> sp_io::MultiRemovalResults {
287 let mut key = vec![0u8; 32 + hash.len()];
288 let storage_prefix = storage_prefix(module, item);
289 key[0..32].copy_from_slice(&storage_prefix);
290 key[32..].copy_from_slice(hash);
291 frame_support::storage::unhashed::clear_prefix(&key, maybe_limit, maybe_cursor)
292}
293
294pub fn take_storage_item<K: Encode + Sized, T: Decode + Sized, H: StorageHasher>(
296 module: &[u8],
297 item: &[u8],
298 key: K,
299) -> Option<T> {
300 take_storage_value(module, item, key.using_encoded(H::hash).as_ref())
301}
302
303pub fn move_storage_from_pallet(
324 storage_name: &[u8],
325 old_pallet_name: &[u8],
326 new_pallet_name: &[u8],
327) {
328 let new_prefix = storage_prefix(new_pallet_name, storage_name);
329 let old_prefix = storage_prefix(old_pallet_name, storage_name);
330
331 move_prefix(&old_prefix, &new_prefix);
332
333 if let Some(value) = unhashed::get_raw(&old_prefix) {
334 unhashed::put_raw(&new_prefix, &value);
335 unhashed::kill(&old_prefix);
336 }
337}
338
339pub fn move_pallet(old_pallet_name: &[u8], new_pallet_name: &[u8]) {
360 move_prefix(&Twox128::hash(old_pallet_name), &Twox128::hash(new_pallet_name))
361}
362
363pub fn move_prefix(from_prefix: &[u8], to_prefix: &[u8]) {
370 if from_prefix == to_prefix {
371 return
372 }
373
374 let iter = PrefixIterator::<_> {
375 prefix: from_prefix.to_vec(),
376 previous_key: from_prefix.to_vec(),
377 drain: true,
378 closure: |key, value| Ok((key.to_vec(), value.to_vec())),
379 phantom: Default::default(),
380 };
381
382 for (key, value) in iter {
383 let full_key = [to_prefix, &key].concat();
384 unhashed::put_raw(&full_key, &value);
385 }
386}
387
388#[cfg(test)]
389mod tests {
390 use super::{
391 move_pallet, move_prefix, move_storage_from_pallet, storage_iter, storage_key_iter,
392 };
393 use crate::{
394 hash::StorageHasher,
395 pallet_prelude::{StorageMap, StorageValue, Twox128, Twox64Concat},
396 };
397 use sp_io::TestExternalities;
398
399 struct OldPalletStorageValuePrefix;
400 impl frame_support::traits::StorageInstance for OldPalletStorageValuePrefix {
401 const STORAGE_PREFIX: &'static str = "foo_value";
402 fn pallet_prefix() -> &'static str {
403 "my_old_pallet"
404 }
405 }
406 type OldStorageValue = StorageValue<OldPalletStorageValuePrefix, u32>;
407
408 struct OldPalletStorageMapPrefix;
409 impl frame_support::traits::StorageInstance for OldPalletStorageMapPrefix {
410 const STORAGE_PREFIX: &'static str = "foo_map";
411 fn pallet_prefix() -> &'static str {
412 "my_old_pallet"
413 }
414 }
415 type OldStorageMap = StorageMap<OldPalletStorageMapPrefix, Twox64Concat, u32, u32>;
416
417 struct NewPalletStorageValuePrefix;
418 impl frame_support::traits::StorageInstance for NewPalletStorageValuePrefix {
419 const STORAGE_PREFIX: &'static str = "foo_value";
420 fn pallet_prefix() -> &'static str {
421 "my_new_pallet"
422 }
423 }
424 type NewStorageValue = StorageValue<NewPalletStorageValuePrefix, u32>;
425
426 struct NewPalletStorageMapPrefix;
427 impl frame_support::traits::StorageInstance for NewPalletStorageMapPrefix {
428 const STORAGE_PREFIX: &'static str = "foo_map";
429 fn pallet_prefix() -> &'static str {
430 "my_new_pallet"
431 }
432 }
433 type NewStorageMap = StorageMap<NewPalletStorageMapPrefix, Twox64Concat, u32, u32>;
434
435 #[test]
436 fn test_move_prefix() {
437 TestExternalities::new_empty().execute_with(|| {
438 OldStorageValue::put(3);
439 OldStorageMap::insert(1, 2);
440 OldStorageMap::insert(3, 4);
441
442 move_prefix(&Twox128::hash(b"my_old_pallet"), &Twox128::hash(b"my_new_pallet"));
443
444 assert_eq!(OldStorageValue::get(), None);
445 assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
446 assert_eq!(NewStorageValue::get(), Some(3));
447 assert_eq!(NewStorageMap::iter().collect::<Vec<_>>(), vec![(1, 2), (3, 4)]);
448 })
449 }
450
451 #[test]
452 fn test_move_storage() {
453 TestExternalities::new_empty().execute_with(|| {
454 OldStorageValue::put(3);
455 OldStorageMap::insert(1, 2);
456 OldStorageMap::insert(3, 4);
457
458 move_storage_from_pallet(b"foo_map", b"my_old_pallet", b"my_new_pallet");
459
460 assert_eq!(OldStorageValue::get(), Some(3));
461 assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
462 assert_eq!(NewStorageValue::get(), None);
463 assert_eq!(NewStorageMap::iter().collect::<Vec<_>>(), vec![(1, 2), (3, 4)]);
464
465 move_storage_from_pallet(b"foo_value", b"my_old_pallet", b"my_new_pallet");
466
467 assert_eq!(OldStorageValue::get(), None);
468 assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
469 assert_eq!(NewStorageValue::get(), Some(3));
470 assert_eq!(NewStorageMap::iter().collect::<Vec<_>>(), vec![(1, 2), (3, 4)]);
471 })
472 }
473
474 #[test]
475 fn test_move_pallet() {
476 TestExternalities::new_empty().execute_with(|| {
477 OldStorageValue::put(3);
478 OldStorageMap::insert(1, 2);
479 OldStorageMap::insert(3, 4);
480
481 move_pallet(b"my_old_pallet", b"my_new_pallet");
482
483 assert_eq!(OldStorageValue::get(), None);
484 assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
485 assert_eq!(NewStorageValue::get(), Some(3));
486 assert_eq!(NewStorageMap::iter().collect::<Vec<_>>(), vec![(1, 2), (3, 4)]);
487 })
488 }
489
490 #[test]
491 fn test_storage_iter() {
492 TestExternalities::new_empty().execute_with(|| {
493 OldStorageValue::put(3);
494 OldStorageMap::insert(1, 2);
495 OldStorageMap::insert(3, 4);
496
497 assert_eq!(
498 storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map")
499 .collect::<Vec<_>>(),
500 vec![(1, 2), (3, 4)],
501 );
502
503 assert_eq!(
504 storage_iter(b"my_old_pallet", b"foo_map")
505 .drain()
506 .map(|t| t.1)
507 .collect::<Vec<i32>>(),
508 vec![2, 4],
509 );
510 assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
511
512 assert_eq!(storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(), None);
514 assert_eq!(OldStorageValue::get(), Some(3));
515 });
516 }
517}