Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 42c73f7

Browse files
committed
implementation and factorisation
1 parent 896d4df commit 42c73f7

File tree

3 files changed

+301
-149
lines changed

3 files changed

+301
-149
lines changed

frame/support/src/storage/generator/double_map.rs

Lines changed: 79 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use sp_std::prelude::*;
1919
use sp_std::borrow::Borrow;
2020
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
21-
use crate::{storage::{self, unhashed, StorageAppend}, Never};
21+
use crate::{storage::{self, unhashed, StorageAppend, PrefixIterator}, Never};
2222
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};
2323

2424
/// Generator for `StorageDoubleMap` used by `decl_storage`.
@@ -213,10 +213,11 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
213213
KArg1: ?Sized + EncodeLike<K1>
214214
{
215215
let prefix = Self::storage_double_map_final_key1(k1);
216-
storage::PrefixIterator::<V> {
216+
storage::PrefixIterator {
217217
prefix: prefix.clone(),
218218
previous_key: prefix,
219-
phantom_data: Default::default(),
219+
drain: false,
220+
closure: |_raw_key, mut raw_value| V::decode(&mut raw_value),
220221
}
221222
}
222223

@@ -322,54 +323,6 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
322323
}
323324
}
324325

325-
/// Iterate over a prefix and decode raw_key and raw_value into `T`.
326-
pub struct MapIterator<T> {
327-
prefix: Vec<u8>,
328-
previous_key: Vec<u8>,
329-
/// If true then value are removed while iterating
330-
drain: bool,
331-
/// Function that take `(raw_key_without_prefix, raw_value)` and decode `T`.
332-
/// `raw_key_without_prefix` is the raw storage key without the prefix iterated on.
333-
closure: fn(&[u8], &[u8]) -> Result<T, codec::Error>,
334-
}
335-
336-
impl<T> Iterator for MapIterator<T> {
337-
type Item = T;
338-
339-
fn next(&mut self) -> Option<Self::Item> {
340-
loop {
341-
let maybe_next = sp_io::storage::next_key(&self.previous_key)
342-
.filter(|n| n.starts_with(&self.prefix));
343-
break match maybe_next {
344-
Some(next) => {
345-
self.previous_key = next;
346-
let raw_value = match unhashed::get_raw(&self.previous_key) {
347-
Some(raw_value) => raw_value,
348-
None => {
349-
frame_support::print("ERROR: next_key returned a key with no value in MapIterator");
350-
continue
351-
}
352-
};
353-
if self.drain {
354-
unhashed::kill(&self.previous_key)
355-
}
356-
let raw_key_without_prefix = &self.previous_key[self.prefix.len()..];
357-
let item = match (self.closure)(raw_key_without_prefix, &raw_value[..]) {
358-
Ok(item) => item,
359-
Err(_e) => {
360-
frame_support::print("ERROR: (key, value) failed to decode in MapIterator");
361-
continue
362-
}
363-
};
364-
365-
Some(item)
366-
}
367-
None => None,
368-
}
369-
}
370-
}
371-
}
372-
373326
impl<
374327
K1: FullCodec,
375328
K2: FullCodec,
@@ -379,8 +332,8 @@ impl<
379332
G::Hasher1: ReversibleStorageHasher,
380333
G::Hasher2: ReversibleStorageHasher
381334
{
382-
type PrefixIterator = MapIterator<(K2, V)>;
383-
type Iterator = MapIterator<(K1, K2, V)>;
335+
type PrefixIterator = PrefixIterator<(K2, V)>;
336+
type Iterator = PrefixIterator<(K1, K2, V)>;
384337

385338
fn iter_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator {
386339
let prefix = G::storage_double_map_final_key1(k1);
@@ -423,20 +376,41 @@ impl<
423376
iterator
424377
}
425378

426-
fn translate<O: Decode, F: Fn(O) -> Option<V>>(f: F) {
379+
fn translate<O: Decode, F: Fn(K1, K2, O) -> Option<V>>(f: F) {
427380
let prefix = G::prefix_hash();
428381
let mut previous_key = prefix.clone();
429382
loop {
430383
match sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix)) {
431384
Some(next) => {
432385
previous_key = next;
433-
let maybe_value = unhashed::get::<O>(&previous_key);
434-
match maybe_value {
435-
Some(value) => match f(value) {
436-
Some(new) => unhashed::put::<V>(&previous_key, &new),
437-
None => unhashed::kill(&previous_key),
386+
let value = match unhashed::get::<O>(&previous_key) {
387+
Some(value) => value,
388+
None => {
389+
crate::debug::error!("Invalid translate: fail to decode old value");
390+
continue
391+
},
392+
};
393+
let mut key_material = G::Hasher1::reverse(&previous_key[prefix.len()..]);
394+
let key1 = match K1::decode(&mut key_material) {
395+
Ok(key1) => key1,
396+
Err(_) => {
397+
crate::debug::error!("Invalid translate: fail to decode key1");
398+
continue
399+
},
400+
};
401+
402+
let mut key2_material = G::Hasher1::reverse(&key_material);
403+
let key2 = match K2::decode(&mut key2_material) {
404+
Ok(key2) => key2,
405+
Err(_) => {
406+
crate::debug::error!("Invalid translate: fail to decode key2");
407+
continue
438408
},
439-
None => continue,
409+
};
410+
411+
match f(key1, key2, value) {
412+
Some(new) => unhashed::put::<V>(&previous_key, &new),
413+
None => unhashed::kill(&previous_key),
440414
}
441415
}
442416
None => return,
@@ -450,7 +424,10 @@ impl<
450424
#[allow(dead_code)]
451425
mod test_iterators {
452426
use codec::{Encode, Decode};
453-
use crate::storage::{generator::StorageDoubleMap, IterableStorageDoubleMap, unhashed};
427+
use crate::{
428+
hash::StorageHasher,
429+
storage::{generator::StorageDoubleMap, IterableStorageDoubleMap, unhashed},
430+
};
454431

455432
pub trait Trait {
456433
type Origin;
@@ -484,11 +461,6 @@ mod test_iterators {
484461
prefix
485462
}
486463

487-
fn key_in_prefix(mut prefix: Vec<u8>) -> Vec<u8> {
488-
prefix.push(0);
489-
prefix
490-
}
491-
492464
#[test]
493465
fn double_map_reversible_reversible_iteration() {
494466
sp_io::TestExternalities::default().execute_with(|| {
@@ -550,6 +522,47 @@ mod test_iterators {
550522
assert_eq!(DoubleMap::iter_prefix(k1).collect::<Vec<_>>(), vec![]);
551523
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
552524
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
525+
526+
// Translate
527+
let prefix = DoubleMap::prefix_hash();
528+
529+
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
530+
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
531+
for i in 0..4 {
532+
DoubleMap::insert(i as u16, i as u32, i as u64);
533+
}
534+
535+
// Wrong key1
536+
unhashed::put(
537+
&[prefix.clone(), vec![1, 2, 3]].concat(),
538+
&3u64.encode()
539+
);
540+
// Wrong key2
541+
unhashed::put(
542+
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
543+
&3u64.encode()
544+
);
545+
546+
// Wrong value
547+
unhashed::put(
548+
&[
549+
prefix.clone(),
550+
crate::Blake2_128Concat::hash(&1u16.encode()),
551+
crate::Blake2_128Concat::hash(&2u32.encode()),
552+
].concat(),
553+
&vec![1],
554+
);
555+
556+
DoubleMap::translate(|_k1, _k2, v: u64| Some(v*2));
557+
assert_eq!(
558+
DoubleMap::iter().collect::<Vec<_>>(),
559+
vec![
560+
(3, 3, 6),
561+
(0, 0, 0),
562+
(2, 2, 4),
563+
(1, 1, 2),
564+
]
565+
);
553566
})
554567
}
555568
}

0 commit comments

Comments
 (0)