mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 08:07:58 +00:00
generate_storage_alias: Rewrite as proc macro attribute (#11387)
* generate_storage_alias: Rewrite as proc macro attribute
This rewrites the `generate_storage_alias!` declarative macro as proc-macro attribute. While doing
this the name is changed to `storage_alias`. The prefix can now also be the name of a pallet. This
makes storage aliases work in migrations for all kind of chains and not just for the ones that use
predefined prefixes.
* Fix compilation and FMT
* Moare fixes
* 🤦
* ......
* Rework the syntax and support instancing
* FMT
* Prefix variants with `Storage`
* Make it compile
* Fix where clause on rust stable
This commit is contained in:
@@ -166,178 +166,74 @@ macro_rules! bounded_btree_map {
|
||||
/// Useful for creating a *storage-like* struct for test and migrations.
|
||||
///
|
||||
/// ```
|
||||
/// # use frame_support::generate_storage_alias;
|
||||
/// # use frame_support::storage_alias;
|
||||
/// use frame_support::codec;
|
||||
/// use frame_support::Twox64Concat;
|
||||
/// // generate a storage value with type u32.
|
||||
/// generate_storage_alias!(Prefix, StorageName => Value<u32>);
|
||||
/// #[storage_alias]
|
||||
/// type StorageName = StorageValue<Prefix, u32>;
|
||||
///
|
||||
/// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key)
|
||||
/// // to `Vec<u8>`
|
||||
/// generate_storage_alias!(
|
||||
/// OtherPrefix, OtherStorageName => DoubleMap<
|
||||
/// (Twox64Concat, u32),
|
||||
/// (Twox64Concat, u32),
|
||||
/// Vec<u8>
|
||||
/// >
|
||||
/// );
|
||||
/// #[storage_alias]
|
||||
/// type OtherStorageName = StorageDoubleMap<
|
||||
/// OtherPrefix,
|
||||
/// Twox64Concat,
|
||||
/// u32,
|
||||
/// Twox64Concat,
|
||||
/// u32,
|
||||
/// Vec<u8>,
|
||||
/// >;
|
||||
///
|
||||
/// // optionally specify the query type
|
||||
/// use frame_support::pallet_prelude::{ValueQuery, OptionQuery};
|
||||
/// generate_storage_alias!(Prefix, ValueName => Value<u32, OptionQuery>);
|
||||
/// generate_storage_alias!(
|
||||
/// Prefix, SomeStorageName => DoubleMap<
|
||||
/// (Twox64Concat, u32),
|
||||
/// (Twox64Concat, u32),
|
||||
/// Vec<u8>,
|
||||
/// ValueQuery
|
||||
/// >
|
||||
/// );
|
||||
/// #[storage_alias]
|
||||
/// type ValueName = StorageValue<Prefix, u32, OptionQuery>;
|
||||
/// #[storage_alias]
|
||||
/// type SomeStorageName = StorageMap<
|
||||
/// Prefix,
|
||||
/// Twox64Concat,
|
||||
/// u32,
|
||||
/// Vec<u8>,
|
||||
/// ValueQuery,
|
||||
/// >;
|
||||
///
|
||||
/// // generate a map from `Config::AccountId` (with hasher `Twox64Concat`) to `Vec<u8>`
|
||||
/// trait Config { type AccountId: codec::FullCodec; }
|
||||
/// generate_storage_alias!(
|
||||
/// Prefix, GenericStorage<T: Config> => Map<(Twox64Concat, T::AccountId), Vec<u8>>
|
||||
/// );
|
||||
/// #[storage_alias]
|
||||
/// type GenericStorage<T> = StorageMap<Prefix, Twox64Concat, <T as Config>::AccountId, Vec<u8>>;
|
||||
///
|
||||
/// // It also supports NMap
|
||||
/// use frame_support::storage::types::Key as NMapKey;
|
||||
///
|
||||
/// #[storage_alias]
|
||||
/// type SomeNMap = StorageNMap<Prefix, (NMapKey<Twox64Concat, u32>, NMapKey<Twox64Concat, u64>), Vec<u8>>;
|
||||
///
|
||||
/// // Using pallet name as prefix.
|
||||
/// //
|
||||
/// // When the first generic argument is taking generic arguments it is expected to be a pallet.
|
||||
/// // The prefix will then be the pallet name as configured in the runtime through
|
||||
/// // `construct_runtime!`.
|
||||
///
|
||||
/// # struct Pallet<T: Config, I = ()>(std::marker::PhantomData<(T, I)>);
|
||||
/// # impl<T: Config, I: 'static> frame_support::traits::PalletInfoAccess for Pallet<T, I> {
|
||||
/// # fn index() -> usize { 0 }
|
||||
/// # fn name() -> &'static str { "pallet" }
|
||||
/// # fn module_name() -> &'static str { "module" }
|
||||
/// # fn crate_version() -> frame_support::traits::CrateVersion { unimplemented!() }
|
||||
/// # }
|
||||
///
|
||||
/// #[storage_alias]
|
||||
/// type SomeValue<T: Config> = StorageValue<Pallet<T>, u64>;
|
||||
///
|
||||
/// // Pallet with instance
|
||||
///
|
||||
/// #[storage_alias]
|
||||
/// type SomeValue2<T: Config, I: 'static> = StorageValue<Pallet<T, I>, u64>;
|
||||
///
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! generate_storage_alias {
|
||||
// without generic for $name.
|
||||
($pallet:ident, $name:ident => Map<($hasher:ty, $key:ty), $value:ty $(, $querytype:ty)?>) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
type $name = $crate::storage::types::StorageMap<
|
||||
[<$name Instance>],
|
||||
$hasher,
|
||||
$key,
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
(
|
||||
$pallet:ident,
|
||||
$name:ident
|
||||
=> DoubleMap<($hasher1:ty, $key1:ty), ($hasher2:ty, $key2:ty), $value:ty $(, $querytype:ty)?>
|
||||
) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
type $name = $crate::storage::types::StorageDoubleMap<
|
||||
[<$name Instance>],
|
||||
$hasher1,
|
||||
$key1,
|
||||
$hasher2,
|
||||
$key2,
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
(
|
||||
$pallet:ident,
|
||||
$name:ident
|
||||
=> NMap<Key<$(($hasher:ty, $key:ty)),+>, $value:ty $(, $querytype:ty)?>
|
||||
) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
type $name = $crate::storage::types::StorageNMap<
|
||||
[<$name Instance>],
|
||||
(
|
||||
$( $crate::storage::types::Key<$hasher, $key>, )+
|
||||
),
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
($pallet:ident, $name:ident => Value<$value:ty $(, $querytype:ty)?>) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
type $name = $crate::storage::types::StorageValue<
|
||||
[<$name Instance>],
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
// with generic for $name.
|
||||
(
|
||||
$pallet:ident,
|
||||
$name:ident<$t:ident : $bounds:tt>
|
||||
=> Map<($hasher:ty, $key:ty), $value:ty $(, $querytype:ty)?>
|
||||
) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
#[allow(type_alias_bounds)]
|
||||
type $name<$t : $bounds> = $crate::storage::types::StorageMap<
|
||||
[<$name Instance>],
|
||||
$hasher,
|
||||
$key,
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
(
|
||||
$pallet:ident,
|
||||
$name:ident<$t:ident : $bounds:tt>
|
||||
=> DoubleMap<($hasher1:ty, $key1:ty), ($hasher2:ty, $key2:ty), $value:ty $(, $querytype:ty)?>
|
||||
) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
#[allow(type_alias_bounds)]
|
||||
type $name<$t : $bounds> = $crate::storage::types::StorageDoubleMap<
|
||||
[<$name Instance>],
|
||||
$hasher1,
|
||||
$key1,
|
||||
$hasher2,
|
||||
$key2,
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
(
|
||||
$pallet:ident,
|
||||
$name:ident<$t:ident : $bounds:tt>
|
||||
=> NMap<$(($hasher:ty, $key:ty),)+ $value:ty $(, $querytype:ty)?>
|
||||
) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
#[allow(type_alias_bounds)]
|
||||
type $name<$t : $bounds> = $crate::storage::types::StorageNMap<
|
||||
[<$name Instance>],
|
||||
(
|
||||
$( $crate::storage::types::Key<$hasher, $key>, )+
|
||||
),
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
($pallet:ident, $name:ident<$t:ident : $bounds:tt> => Value<$value:ty $(, $querytype:ty)?>) => {
|
||||
$crate::paste::paste! {
|
||||
$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
|
||||
#[allow(type_alias_bounds)]
|
||||
type $name<$t : $bounds> = $crate::storage::types::StorageValue<
|
||||
[<$name Instance>],
|
||||
$value,
|
||||
$( $querytype )?
|
||||
>;
|
||||
}
|
||||
};
|
||||
// helper used in all arms.
|
||||
(@GENERATE_INSTANCE_STRUCT $pallet:ident, $name:ident) => {
|
||||
$crate::paste::paste! {
|
||||
struct [<$name Instance>];
|
||||
impl $crate::traits::StorageInstance for [<$name Instance>] {
|
||||
fn pallet_prefix() -> &'static str { stringify!($pallet) }
|
||||
const STORAGE_PREFIX: &'static str = stringify!($name);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub use frame_support_procedural::storage_alias;
|
||||
|
||||
/// Create new implementations of the [`Get`](crate::traits::Get) trait.
|
||||
///
|
||||
@@ -995,16 +891,28 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_storage_alias_works() {
|
||||
fn storage_alias_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
generate_storage_alias!(
|
||||
#[crate::storage_alias]
|
||||
type GenericData2<T> = StorageMap<
|
||||
Test,
|
||||
GenericData2<T: Config> => Map<(Blake2_128Concat, T::BlockNumber), T::BlockNumber>
|
||||
);
|
||||
Blake2_128Concat,
|
||||
<T as Config>::BlockNumber,
|
||||
<T as Config>::BlockNumber,
|
||||
>;
|
||||
|
||||
assert_eq!(Module::<Test>::generic_data2(5), None);
|
||||
GenericData2::<Test>::insert(5, 5);
|
||||
assert_eq!(Module::<Test>::generic_data2(5), Some(5));
|
||||
|
||||
/// Some random docs that ensure that docs are accepted
|
||||
#[crate::storage_alias]
|
||||
pub type GenericData<T> = StorageMap<
|
||||
Test2,
|
||||
Blake2_128Concat,
|
||||
<T as Config>::BlockNumber,
|
||||
<T as Config>::BlockNumber,
|
||||
>;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -348,12 +348,15 @@ pub mod test {
|
||||
use frame_support::traits::ConstU32;
|
||||
use sp_io::TestExternalities;
|
||||
|
||||
crate::generate_storage_alias! { Prefix, Foo => Value<BoundedBTreeMap<u32, (), ConstU32<7>>> }
|
||||
crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeMap<u32, (), ConstU32<7>>> }
|
||||
crate::generate_storage_alias! {
|
||||
Prefix,
|
||||
FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedBTreeMap<u32, (), ConstU32<7>>>
|
||||
}
|
||||
#[crate::storage_alias]
|
||||
type Foo = StorageValue<Prefix, BoundedBTreeMap<u32, (), ConstU32<7>>>;
|
||||
|
||||
#[crate::storage_alias]
|
||||
type FooMap = StorageMap<Prefix, Twox128, u32, BoundedBTreeMap<u32, (), ConstU32<7>>>;
|
||||
|
||||
#[crate::storage_alias]
|
||||
type FooDoubleMap =
|
||||
StorageDoubleMap<Prefix, Twox128, u32, Twox128, u32, BoundedBTreeMap<u32, (), ConstU32<7>>>;
|
||||
|
||||
fn map_from_keys<K>(keys: &[K]) -> BTreeMap<K, ()>
|
||||
where
|
||||
|
||||
@@ -322,12 +322,15 @@ pub mod test {
|
||||
use frame_support::traits::ConstU32;
|
||||
use sp_io::TestExternalities;
|
||||
|
||||
crate::generate_storage_alias! { Prefix, Foo => Value<BoundedBTreeSet<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeSet<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! {
|
||||
Prefix,
|
||||
FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedBTreeSet<u32, ConstU32<7>>>
|
||||
}
|
||||
#[crate::storage_alias]
|
||||
type Foo = StorageValue<Prefix, BoundedBTreeSet<u32, ConstU32<7>>>;
|
||||
|
||||
#[crate::storage_alias]
|
||||
type FooMap = StorageMap<Prefix, Twox128, u32, BoundedBTreeSet<u32, ConstU32<7>>>;
|
||||
|
||||
#[crate::storage_alias]
|
||||
type FooDoubleMap =
|
||||
StorageDoubleMap<Prefix, Twox128, u32, Twox128, u32, BoundedBTreeSet<u32, ConstU32<7>>>;
|
||||
|
||||
fn set_from_keys<T>(keys: &[T]) -> BTreeSet<T>
|
||||
where
|
||||
|
||||
@@ -672,12 +672,15 @@ pub mod test {
|
||||
use crate::{bounded_vec, traits::ConstU32, Twox128};
|
||||
use sp_io::TestExternalities;
|
||||
|
||||
crate::generate_storage_alias! { Prefix, Foo => Value<BoundedVec<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedVec<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! {
|
||||
Prefix,
|
||||
FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedVec<u32, ConstU32<7>>>
|
||||
}
|
||||
#[crate::storage_alias]
|
||||
type Foo = StorageValue<Prefix, BoundedVec<u32, ConstU32<7>>>;
|
||||
|
||||
#[crate::storage_alias]
|
||||
type FooMap = StorageMap<Prefix, Twox128, u32, BoundedVec<u32, ConstU32<7>>>;
|
||||
|
||||
#[crate::storage_alias]
|
||||
type FooDoubleMap =
|
||||
StorageDoubleMap<Prefix, Twox128, u32, Twox128, u32, BoundedVec<u32, ConstU32<7>>>;
|
||||
|
||||
#[test]
|
||||
fn slide_works() {
|
||||
|
||||
@@ -525,10 +525,8 @@ mod test_iterators {
|
||||
fn double_map_iter_from() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
use crate::hash::Identity;
|
||||
crate::generate_storage_alias!(
|
||||
MyModule,
|
||||
MyDoubleMap => DoubleMap<(Identity, u64), (Identity, u64), u64>
|
||||
);
|
||||
#[crate::storage_alias]
|
||||
type MyDoubleMap = StorageDoubleMap<MyModule, Identity, u64, Identity, u64, u64>;
|
||||
|
||||
MyDoubleMap::insert(1, 10, 100);
|
||||
MyDoubleMap::insert(1, 21, 201);
|
||||
|
||||
@@ -384,7 +384,8 @@ mod test_iterators {
|
||||
fn map_iter_from() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
use crate::hash::Identity;
|
||||
crate::generate_storage_alias!(MyModule, MyMap => Map<(Identity, u64), u64>);
|
||||
#[crate::storage_alias]
|
||||
type MyMap = StorageMap<MyModule, Identity, u64, u64>;
|
||||
|
||||
MyMap::insert(1, 10);
|
||||
MyMap::insert(2, 20);
|
||||
|
||||
@@ -475,10 +475,12 @@ mod test_iterators {
|
||||
fn n_map_iter_from() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
use crate::{hash::Identity, storage::Key as NMapKey};
|
||||
crate::generate_storage_alias!(
|
||||
#[crate::storage_alias]
|
||||
type MyNMap = StorageNMap<
|
||||
MyModule,
|
||||
MyNMap => NMap<Key<(Identity, u64), (Identity, u64), (Identity, u64)>, u64>
|
||||
);
|
||||
(NMapKey<Identity, u64>, NMapKey<Identity, u64>, NMapKey<Identity, u64>),
|
||||
u64,
|
||||
>;
|
||||
|
||||
MyNMap::insert((1, 1, 1), 11);
|
||||
MyNMap::insert((1, 1, 2), 21);
|
||||
@@ -518,11 +520,15 @@ mod test_iterators {
|
||||
let key_hash = NMap::hashed_key_for((1, 2));
|
||||
|
||||
{
|
||||
crate::generate_storage_alias!(Test, NMap => DoubleMap<
|
||||
(crate::Blake2_128Concat, u16),
|
||||
(crate::Twox64Concat, u32),
|
||||
u64
|
||||
>);
|
||||
#[crate::storage_alias]
|
||||
type NMap = StorageDoubleMap<
|
||||
Test,
|
||||
crate::Blake2_128Concat,
|
||||
u16,
|
||||
crate::Twox64Concat,
|
||||
u32,
|
||||
u64,
|
||||
>;
|
||||
|
||||
let value = NMap::get(1, 2).unwrap();
|
||||
assert_eq!(value, 50);
|
||||
|
||||
@@ -1545,10 +1545,8 @@ mod test {
|
||||
fn prefix_iterator_pagination_works() {
|
||||
TestExternalities::default().execute_with(|| {
|
||||
use crate::{hash::Identity, storage::generator::map::StorageMap};
|
||||
crate::generate_storage_alias! {
|
||||
MyModule,
|
||||
MyStorageMap => Map<(Identity, u64), u64>
|
||||
}
|
||||
#[crate::storage_alias]
|
||||
type MyStorageMap = StorageMap<MyModule, Identity, u64, u64>;
|
||||
|
||||
MyStorageMap::insert(1, 10);
|
||||
MyStorageMap::insert(2, 20);
|
||||
@@ -1663,12 +1661,13 @@ mod test {
|
||||
});
|
||||
}
|
||||
|
||||
crate::generate_storage_alias! { Prefix, Foo => Value<WeakBoundedVec<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedVec<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! {
|
||||
Prefix,
|
||||
FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedVec<u32, ConstU32<7>>>
|
||||
}
|
||||
#[crate::storage_alias]
|
||||
type Foo = StorageValue<Prefix, WeakBoundedVec<u32, ConstU32<7>>>;
|
||||
#[crate::storage_alias]
|
||||
type FooMap = StorageMap<Prefix, Twox128, u32, BoundedVec<u32, ConstU32<7>>>;
|
||||
#[crate::storage_alias]
|
||||
type FooDoubleMap =
|
||||
StorageDoubleMap<Prefix, Twox128, u32, Twox128, u32, BoundedVec<u32, ConstU32<7>>>;
|
||||
|
||||
#[test]
|
||||
fn try_append_works() {
|
||||
|
||||
@@ -544,7 +544,7 @@ mod test {
|
||||
use crate::{
|
||||
hash::{StorageHasher as _, *},
|
||||
metadata::{StorageEntryModifier, StorageHasher},
|
||||
storage::types::{Key, ValueQuery},
|
||||
storage::types::{Key, Key as NMapKey, ValueQuery},
|
||||
};
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
@@ -589,10 +589,8 @@ mod test {
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::get((3,)), 10);
|
||||
|
||||
{
|
||||
crate::generate_storage_alias!(test, Foo => NMap<
|
||||
Key<(Blake2_128Concat, u16)>,
|
||||
u32
|
||||
>);
|
||||
#[crate::storage_alias]
|
||||
type Foo = StorageNMap<test, (NMapKey<Blake2_128Concat, u16>), u32>;
|
||||
|
||||
assert_eq!(Foo::contains_key((3,)), true);
|
||||
assert_eq!(Foo::get((3,)), Some(10));
|
||||
|
||||
@@ -321,12 +321,13 @@ pub mod test {
|
||||
use frame_support::traits::ConstU32;
|
||||
use sp_io::TestExternalities;
|
||||
|
||||
crate::generate_storage_alias! { Prefix, Foo => Value<WeakBoundedVec<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), WeakBoundedVec<u32, ConstU32<7>>> }
|
||||
crate::generate_storage_alias! {
|
||||
Prefix,
|
||||
FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), WeakBoundedVec<u32, ConstU32<7>>>
|
||||
}
|
||||
#[crate::storage_alias]
|
||||
type Foo = StorageValue<Prefix, WeakBoundedVec<u32, ConstU32<7>>>;
|
||||
#[crate::storage_alias]
|
||||
type FooMap = StorageMap<Prefix, Twox128, u32, WeakBoundedVec<u32, ConstU32<7>>>;
|
||||
#[crate::storage_alias]
|
||||
type FooDoubleMap =
|
||||
StorageDoubleMap<Prefix, Twox128, u32, Twox128, u32, WeakBoundedVec<u32, ConstU32<7>>>;
|
||||
|
||||
#[test]
|
||||
fn bound_returns_correct_value() {
|
||||
|
||||
Reference in New Issue
Block a user