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

Commit c2d6fa7

Browse files
authored
Support NMap in generate_storage_alias (#9147)
* Support NMap in generate_storage_alias * Verify that 2-key NMap is identical to DoubleMap * Also compare key hashes and make sure they're identical * Fix and add tests for 1-tuple NMap generated by generate_storage_alias
1 parent eae82ab commit c2d6fa7

File tree

4 files changed

+69
-10
lines changed

4 files changed

+69
-10
lines changed

frame/support/src/lib.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ impl TypeId for PalletId {
100100
}
101101

102102
/// Generate a new type alias for [`storage::types::StorageValue`],
103-
/// [`storage::types::StorageMap`] and [`storage::types::StorageDoubleMap`].
103+
/// [`storage::types::StorageMap`], [`storage::types::StorageDoubleMap`]
104+
/// and [`storage::types::StorageNMap`].
104105
///
105106
/// Useful for creating a *storage-like* struct for test and migrations.
106107
///
@@ -154,6 +155,18 @@ macro_rules! generate_storage_alias {
154155
>;
155156
}
156157
};
158+
($pallet:ident, $name:ident => NMap<$(($key:ty, $hasher:ty),)+ $value:ty>) => {
159+
$crate::paste::paste! {
160+
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
161+
type $name = $crate::storage::types::StorageNMap<
162+
[<$name Instance>],
163+
(
164+
$( $crate::storage::types::Key<$hasher, $key>, )+
165+
),
166+
$value,
167+
>;
168+
}
169+
};
157170
($pallet:ident, $name:ident => Value<$value:ty>) => {
158171
$crate::paste::paste! {
159172
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
@@ -193,6 +206,22 @@ macro_rules! generate_storage_alias {
193206
>;
194207
}
195208
};
209+
(
210+
$pallet:ident,
211+
$name:ident<$t:ident : $bounds:tt> => NMap<$(($key:ty, $hasher:ty),)+ $value:ty>
212+
) => {
213+
$crate::paste::paste! {
214+
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
215+
#[allow(type_alias_bounds)]
216+
type $name<$t : $bounds> = $crate::storage::types::StorageNMap<
217+
[<$name Instance>],
218+
(
219+
$( $crate::storage::types::Key<$hasher, $key>, )+
220+
),
221+
$value,
222+
>;
223+
}
224+
};
196225
($pallet:ident, $name:ident<$t:ident : $bounds:tt> => Value<$value:ty>) => {
197226
$crate::paste::paste! {
198227
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);

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

+20
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,26 @@ mod test_iterators {
433433
prefix
434434
}
435435

436+
#[test]
437+
fn n_map_double_map_identical_key() {
438+
sp_io::TestExternalities::default().execute_with(|| {
439+
NMap::insert((1, 2), 50);
440+
let key_hash = NMap::hashed_key_for((1, 2));
441+
442+
{
443+
crate::generate_storage_alias!(Test, NMap => DoubleMap<
444+
(u16, crate::Blake2_128Concat),
445+
(u32, crate::Twox64Concat),
446+
u64
447+
>);
448+
449+
let value = NMap::get(1, 2).unwrap();
450+
assert_eq!(value, 50);
451+
assert_eq!(NMap::hashed_key_for(1, 2), key_hash);
452+
}
453+
});
454+
}
455+
436456
#[test]
437457
fn n_map_reversible_reversible_iteration() {
438458
sp_io::TestExternalities::default().execute_with(|| {

frame/support/src/storage/types/key.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<H: StorageHasher, K: FullCodec> KeyGeneratorInner for Key<H, K> {
110110
}
111111
}
112112

113-
#[impl_trait_for_tuples::impl_for_tuples(2, 18)]
113+
#[impl_trait_for_tuples::impl_for_tuples(1, 18)]
114114
#[tuple_types_custom_trait_bound(KeyGeneratorInner)]
115115
impl KeyGenerator for Tuple {
116116
for_tuples!( type Key = ( #(Tuple::Key),* ); );
@@ -150,7 +150,7 @@ impl KeyGenerator for Tuple {
150150
}
151151
}
152152

153-
#[impl_trait_for_tuples::impl_for_tuples(2, 18)]
153+
#[impl_trait_for_tuples::impl_for_tuples(1, 18)]
154154
#[tuple_types_custom_trait_bound(KeyGeneratorInner + KeyGeneratorMaxEncodedLen)]
155155
impl KeyGeneratorMaxEncodedLen for Tuple {
156156
fn key_max_encoded_len() -> usize {

frame/support/src/storage/types/nmap.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ mod test {
423423
fn pallet_prefix() -> &'static str {
424424
"test"
425425
}
426-
const STORAGE_PREFIX: &'static str = "foo";
426+
const STORAGE_PREFIX: &'static str = "Foo";
427427
}
428428

429429
struct ADefault;
@@ -445,7 +445,7 @@ mod test {
445445
TestExternalities::default().execute_with(|| {
446446
let mut k: Vec<u8> = vec![];
447447
k.extend(&twox_128(b"test"));
448-
k.extend(&twox_128(b"foo"));
448+
k.extend(&twox_128(b"Foo"));
449449
k.extend(&3u16.blake2_128_concat());
450450
assert_eq!(A::hashed_key_for((&3,)).to_vec(), k);
451451

@@ -458,6 +458,16 @@ mod test {
458458
assert_eq!(A::get((3,)), Some(10));
459459
assert_eq!(AValueQueryWithAnOnEmpty::get((3,)), 10);
460460

461+
{
462+
crate::generate_storage_alias!(test, Foo => NMap<
463+
(u16, Blake2_128Concat),
464+
u32
465+
>);
466+
467+
assert_eq!(Foo::contains_key((3,)), true);
468+
assert_eq!(Foo::get((3,)), Some(10));
469+
}
470+
461471
A::swap::<Key<Blake2_128Concat, u16>, _, _>((3,), (2,));
462472
assert_eq!(A::contains_key((3,)), false);
463473
assert_eq!(A::contains_key((2,)), true);
@@ -575,7 +585,7 @@ mod test {
575585
AValueQueryWithAnOnEmpty::MODIFIER,
576586
StorageEntryModifier::Default
577587
);
578-
assert_eq!(A::NAME, "foo");
588+
assert_eq!(A::NAME, "Foo");
579589
assert_eq!(
580590
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
581591
98u32.encode()
@@ -617,7 +627,7 @@ mod test {
617627
TestExternalities::default().execute_with(|| {
618628
let mut k: Vec<u8> = vec![];
619629
k.extend(&twox_128(b"test"));
620-
k.extend(&twox_128(b"foo"));
630+
k.extend(&twox_128(b"Foo"));
621631
k.extend(&3u16.blake2_128_concat());
622632
k.extend(&30u8.twox_64_concat());
623633
assert_eq!(A::hashed_key_for((3, 30)).to_vec(), k);
@@ -761,7 +771,7 @@ mod test {
761771
AValueQueryWithAnOnEmpty::MODIFIER,
762772
StorageEntryModifier::Default
763773
);
764-
assert_eq!(A::NAME, "foo");
774+
assert_eq!(A::NAME, "Foo");
765775
assert_eq!(
766776
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
767777
98u32.encode()
@@ -844,7 +854,7 @@ mod test {
844854
TestExternalities::default().execute_with(|| {
845855
let mut k: Vec<u8> = vec![];
846856
k.extend(&twox_128(b"test"));
847-
k.extend(&twox_128(b"foo"));
857+
k.extend(&twox_128(b"Foo"));
848858
k.extend(&1u16.blake2_128_concat());
849859
k.extend(&10u16.blake2_128_concat());
850860
k.extend(&100u16.twox_64_concat());
@@ -996,7 +1006,7 @@ mod test {
9961006
AValueQueryWithAnOnEmpty::MODIFIER,
9971007
StorageEntryModifier::Default
9981008
);
999-
assert_eq!(A::NAME, "foo");
1009+
assert_eq!(A::NAME, "Foo");
10001010
assert_eq!(
10011011
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
10021012
98u32.encode()

0 commit comments

Comments
 (0)