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

Implement iter_keys function for all types of storage maps #9238

Merged
5 commits merged into from
Jul 1, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion frame/support/src/storage/generator/double_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use sp_std::prelude::*;
use sp_std::borrow::Borrow;
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
use crate::{storage::{self, unhashed, StorageAppend, PrefixIterator}, Never};
use crate::{storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator}, Never};
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};

/// Generator for `StorageDoubleMap` used by `decl_storage`.
Expand Down Expand Up @@ -340,7 +340,9 @@ impl<
G::Hasher1: ReversibleStorageHasher,
G::Hasher2: ReversibleStorageHasher
{
type PartialKeyIterator = KeyPrefixIterator<K2>;
type PrefixIterator = PrefixIterator<(K2, V)>;
type FullKeyIterator = KeyPrefixIterator<(K1, K2)>;
type Iterator = PrefixIterator<(K1, K2, V)>;

fn iter_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator {
Expand All @@ -356,6 +358,19 @@ impl<
}
}

fn iter_key_prefix(k1: impl EncodeLike<K1>) -> Self::PartialKeyIterator {
let prefix = G::storage_double_map_final_key1(k1);
Self::PartialKeyIterator {
prefix: prefix.clone(),
previous_key: prefix,
drain: false,
closure: |raw_key_without_prefix| {
let mut key_material = G::Hasher2::reverse(raw_key_without_prefix);
K2::decode(&mut key_material)
}
}
}

fn drain_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator {
let mut iterator = Self::iter_prefix(k1);
iterator.drain = true;
Expand All @@ -378,6 +393,22 @@ impl<
}
}

fn iter_keys() -> Self::FullKeyIterator {
let prefix = G::prefix_hash();
Self::FullKeyIterator {
prefix: prefix.clone(),
previous_key: prefix,
drain: false,
closure: |raw_key_without_prefix| {
let mut k1_k2_material = G::Hasher1::reverse(raw_key_without_prefix);
let k1 = K1::decode(&mut k1_k2_material)?;
let mut k2_material = G::Hasher2::reverse(k1_k2_material);
let k2 = K2::decode(&mut k2_material)?;
Ok((k1, k2))
}
}
}

fn drain() -> Self::Iterator {
let mut iterator = Self::iter();
iterator.drain = true;
Expand Down Expand Up @@ -485,6 +516,11 @@ mod test_iterators {
vec![(3, 3, 3), (0, 0, 0), (2, 2, 2), (1, 1, 1)],
);

assert_eq!(
DoubleMap::iter_keys().collect::<Vec<_>>(),
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
);

assert_eq!(
DoubleMap::iter_values().collect::<Vec<_>>(),
vec![3, 0, 2, 1],
Expand Down Expand Up @@ -515,6 +551,11 @@ mod test_iterators {
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
);

assert_eq!(
DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
);

assert_eq!(
DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
Expand Down
19 changes: 18 additions & 1 deletion frame/support/src/storage/generator/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use sp_std::prelude::*;
use sp_std::borrow::Borrow;
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
use crate::{
storage::{self, unhashed, StorageAppend, PrefixIterator},
storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator},
Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher},
};

Expand Down Expand Up @@ -140,6 +140,7 @@ impl<
G::Hasher: ReversibleStorageHasher
{
type Iterator = PrefixIterator<(K, V)>;
type KeyIterator = KeyPrefixIterator<K>;

/// Enumerate all elements in the map.
fn iter() -> Self::Iterator {
Expand All @@ -155,6 +156,20 @@ impl<
}
}

/// Enumerate all keys in the map.
fn iter_keys() -> Self::KeyIterator {
let prefix = G::prefix_hash();
KeyPrefixIterator {
prefix: prefix.clone(),
previous_key: prefix,
drain: false,
closure: |raw_key_without_prefix| {
let mut key_material = G::Hasher::reverse(raw_key_without_prefix);
K::decode(&mut key_material)
}
}
}

/// Enumerate all elements in the map.
fn drain() -> Self::Iterator {
let mut iterator = Self::iter();
Expand Down Expand Up @@ -378,6 +393,8 @@ mod test_iterators {

assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)]);

assert_eq!(Map::iter_keys().collect::<Vec<_>>(), vec![3, 0, 2, 1]);

assert_eq!(Map::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1]);

assert_eq!(Map::drain().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)]);
Expand Down
39 changes: 38 additions & 1 deletion frame/support/src/storage/generator/nmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, KeyGenerator,
ReversibleKeyGenerator, TupleToEncodedIter,
},
unhashed, PrefixIterator, StorageAppend,
unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend,
},
Never,
};
Expand Down Expand Up @@ -310,6 +310,7 @@ where
impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
storage::IterableStorageNMap<K, V> for G
{
type KeyIterator = KeyPrefixIterator<K::Key>;
type Iterator = PrefixIterator<(K::Key, V)>;

fn iter_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
Expand All @@ -328,6 +329,19 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
}
}

fn iter_key_prefix<KP>(kp: KP) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
where
K: HasReversibleKeyPrefix<KP>,
{
let prefix = G::storage_n_map_partial_key(kp);
KeyPrefixIterator {
prefix: prefix.clone(),
previous_key: prefix,
drain: false,
closure: K::decode_partial_key,
}
}

fn drain_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
where
K: HasReversibleKeyPrefix<KP>,
Expand All @@ -350,6 +364,19 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
}
}

fn iter_keys() -> Self::KeyIterator {
let prefix = G::prefix_hash();
Self::KeyIterator {
prefix: prefix.clone(),
previous_key: prefix,
drain: false,
closure: |raw_key_without_prefix| {
let (final_key, _) = K::decode_final_key(raw_key_without_prefix)?;
Ok(final_key)
}
}
}

fn drain() -> Self::Iterator {
let mut iterator = Self::iter();
iterator.drain = true;
Expand Down Expand Up @@ -471,6 +498,11 @@ mod test_iterators {
vec![((3, 3), 3), ((0, 0), 0), ((2, 2), 2), ((1, 1), 1)],
);

assert_eq!(
NMap::iter_keys().collect::<Vec<_>>(),
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
);

assert_eq!(NMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);

assert_eq!(
Expand Down Expand Up @@ -501,6 +533,11 @@ mod test_iterators {
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
);

assert_eq!(
NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
);

assert_eq!(
NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
Expand Down
86 changes: 85 additions & 1 deletion frame/support/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,17 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
pub trait IterableStorageMap<K: FullEncode, V: FullCodec>: StorageMap<K, V> {
/// The type that iterates over all `(key, value)`.
type Iterator: Iterator<Item = (K, V)>;
/// The type that itereates over all `key`s.
type KeyIterator: Iterator<Item = K>;

/// Enumerate all elements in the map in no particular order. If you alter the map while doing
/// this, you'll get undefined results.
fn iter() -> Self::Iterator;

/// Enumerate all keys in the map in no particular order, skipping over the elements. If you
/// alter the map while doing this, you'll get undefined results.
fn iter_keys() -> Self::KeyIterator;

/// Remove all elements from the map and iterate through them in no particular order. If you
/// add elements to the map while doing this, you'll get undefined results.
fn drain() -> Self::Iterator;
Expand All @@ -336,9 +342,15 @@ pub trait IterableStorageDoubleMap<
K2: FullCodec,
V: FullCodec
>: StorageDoubleMap<K1, K2, V> {
/// The type that iterates over all `key2`.
type PartialKeyIterator: Iterator<Item = K2>;

/// The type that iterates over all `(key2, value)`.
type PrefixIterator: Iterator<Item = (K2, V)>;

/// The type that iterates over all `(key1, key2)`.
type FullKeyIterator: Iterator<Item = (K1, K2)>;

/// The type that iterates over all `(key1, key2, value)`.
type Iterator: Iterator<Item = (K1, K2, V)>;

Expand All @@ -347,6 +359,11 @@ pub trait IterableStorageDoubleMap<
/// results.
fn iter_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator;

/// Enumerate all second keys `k2` in the map with the same first key `k1` in no particular
/// order. If you add or remove values whose first key is `k1` to the map while doing this,
/// you'll get undefined results.
fn iter_key_prefix(k1: impl EncodeLike<K1>) -> Self::PartialKeyIterator;

/// Remove all elements from the map with first key `k1` and iterate through them in no
/// particular order. If you add elements with first key `k1` to the map while doing this,
/// you'll get undefined results.
Expand All @@ -355,6 +372,10 @@ pub trait IterableStorageDoubleMap<
/// Enumerate all elements in the map in no particular order. If you add or remove values to
/// the map while doing this, you'll get undefined results.
fn iter() -> Self::Iterator;

/// Enumerate all keys `k1` and `k2` in the map in no particular order. If you add or remove
/// values to the map while doing this, you'll get undefined results.
fn iter_keys() -> Self::FullKeyIterator;

/// Remove all elements from the map and iterate through them in no particular order. If you
/// add elements to the map while doing this, you'll get undefined results.
Expand All @@ -370,7 +391,10 @@ pub trait IterableStorageDoubleMap<
/// A strongly-typed map with arbitrary number of keys in storage whose keys and values can be
/// iterated over.
pub trait IterableStorageNMap<K: ReversibleKeyGenerator, V: FullCodec>: StorageNMap<K, V> {
/// The type that iterates over all `(key1, (key2, (key3, ... (keyN, ()))), value)` tuples
/// The type that iterates over all `(key1, key2, key3, ... keyN)` tuples.
type KeyIterator: Iterator<Item = K::Key>;

/// The type that iterates over all `(key1, key2, key3, ... keyN), value)` tuples.
type Iterator: Iterator<Item = (K::Key, V)>;

/// Enumerate all elements in the map with prefix key `kp` in no particular order. If you add or
Expand All @@ -379,6 +403,12 @@ pub trait IterableStorageNMap<K: ReversibleKeyGenerator, V: FullCodec>: StorageN
fn iter_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
where K: HasReversibleKeyPrefix<KP>;

/// Enumerate all suffix keys in the map with prefix key `kp` in no particular order. If you
/// add or remove values whose prefix is `kp` to the map while doing this, you'll get undefined
/// results.
fn iter_key_prefix<KP>(kp: KP) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
where K: HasReversibleKeyPrefix<KP>;

/// Remove all elements from the map with prefix key `kp` and iterate through them in no
/// particular order. If you add elements with prefix key `kp` to the map while doing this,
/// you'll get undefined results.
Expand All @@ -389,6 +419,10 @@ pub trait IterableStorageNMap<K: ReversibleKeyGenerator, V: FullCodec>: StorageN
/// the map while doing this, you'll get undefined results.
fn iter() -> Self::Iterator;

/// Enumerate all keys in the map in no particular order. If you add or remove values to the
/// map while doing this, you'll get undefined results.
fn iter_keys() -> Self::KeyIterator;

/// Remove all elements from the map and iterate through them in no particular order. If you
/// add elements to the map while doing this, you'll get undefined results.
fn drain() -> Self::Iterator;
Expand Down Expand Up @@ -733,6 +767,56 @@ impl<T> Iterator for PrefixIterator<T> {
}
}

/// Iterate over a prefix and decode raw_key into `T`.
///
/// If any decoding fails it skips it and continues to the next key.
pub struct KeyPrefixIterator<T> {
prefix: Vec<u8>,
previous_key: Vec<u8>,
/// If true then value are removed while iterating
drain: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a normal way of doing this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do similar for PrefixIterator, that would allow use to create drain_keys easily if we want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually spend a few minutes trying to see if we can merge this with PrefixIterator, the impls are pretty similar, only the decoding closure is different.

Copy link
Member

@shawntabrizi shawntabrizi Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kianenigma seems hard to have the output be only keys or also keys and values. (i.e. making an API that makes sense and works in both scenarios?)

/// Function that take `raw_key_without_prefix` and decode `T`.
/// `raw_key_without_prefix` is the raw storage key without the prefix iterated on.
closure: fn(&[u8]) -> Result<T, codec::Error>,
}

impl<T> KeyPrefixIterator<T> {
/// Mutate this iterator into a draining iterator; items iterated are removed from storage.
pub fn drain(mut self) -> Self {
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
self.drain = true;
self
}
}

impl<T> Iterator for KeyPrefixIterator<T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
loop {
let maybe_next = sp_io::storage::next_key(&self.previous_key)
.filter(|n| n.starts_with(&self.prefix));

if let Some(next) = maybe_next {
self.previous_key = next;
if self.drain {
unhashed::kill(&self.previous_key);
}
let raw_key_without_prefix = &self.previous_key[self.prefix.len()..];

match (self.closure)(raw_key_without_prefix) {
Ok(item) => return Some(item),
Err(e) => {
log::error!("key failed to decode at {:?}: {:?}", self.previous_key, e);
continue;
}
}
}

return None;
}
}
}

/// Iterate over a prefix of a child trie and decode raw_key and raw_value into `T`.
///
/// If any decoding fails it skips the key and continues to the next one.
Expand Down
16 changes: 16 additions & 0 deletions frame/support/src/storage/types/double_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,15 @@ where
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_prefix(k1)
}

/// Enumerate all second keys `k2` in the map with the same first key `k1` in no particular
/// order.
///
/// If you add or remove values whose first key is `k1` to the map while doing this, you'll get
/// undefined results.
pub fn iter_key_prefix(k1: impl EncodeLike<Key1>) -> crate::storage::KeyPrefixIterator<Key2> {
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_key_prefix(k1)
}

/// Remove all elements from the map with first key `k1` and iterate through them in no
/// particular order.
///
Expand All @@ -403,6 +412,13 @@ where
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter()
}

/// Enumerate all keys `k1` and `k2` in the map in no particular order.
///
/// If you add or remove values to the map while doing this, you'll get undefined results.
pub fn iter_keys() -> crate::storage::KeyPrefixIterator<(Key1, Key2)> {
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_keys()
}

/// Remove all elements from the map and iterate through them in no particular order.
///
/// If you add elements to the map while doing this, you'll get undefined results.
Expand Down
Loading