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

Commit

Permalink
pallet macro: always generate storage info on pallet struct (#9246)
Browse files Browse the repository at this point in the history
* always implement storage info on Pallet

* fix UI test

* Fold span computation into trait and method computation

Co-authored-by: Keith Yeung <[email protected]>
  • Loading branch information
gui1117 and KiChjang authored Jul 5, 2021
1 parent 19c6dd2 commit cd48bac
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 35 deletions.
80 changes: 49 additions & 31 deletions frame/support/procedural/src/pallet/expand/pallet_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,41 +102,59 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
)
};

let storage_info = if let Some(storage_info_span) = def.pallet_struct.generate_storage_info {
let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::<Vec<_>>();
let storage_cfg_attrs = &def.storages.iter()
.map(|storage| &storage.cfg_attrs)
.collect::<Vec<_>>();

quote::quote_spanned!(storage_info_span =>
impl<#type_impl_gen> #frame_support::traits::StorageInfoTrait
for #pallet_ident<#type_use_gen>
#storages_where_clauses
{
fn storage_info()
-> #frame_support::sp_std::vec::Vec<#frame_support::traits::StorageInfo>
{
let mut res = #frame_support::sp_std::vec![];

#(
#(#storage_cfg_attrs)*
{
let mut storage_info = <
#storage_names<#type_use_gen>
as #frame_support::traits::StorageInfoTrait
>::storage_info();
res.append(&mut storage_info);
}
)*

res
}
}
// Depending on the flag `generate_storage_info` we use partial or full storage info from
// storage.
let (
storage_info_span,
storage_info_trait,
storage_info_method,
) = if let Some(span) = def.pallet_struct.generate_storage_info {
(
span,
quote::quote_spanned!(span => StorageInfoTrait),
quote::quote_spanned!(span => storage_info),
)
} else {
Default::default()
let span = def.pallet_struct.attr_span;
(
span,
quote::quote_spanned!(span => PartialStorageInfoTrait),
quote::quote_spanned!(span => partial_storage_info),
)
};

let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::<Vec<_>>();
let storage_cfg_attrs = &def.storages.iter()
.map(|storage| &storage.cfg_attrs)
.collect::<Vec<_>>();

let storage_info = quote::quote_spanned!(storage_info_span =>
impl<#type_impl_gen> #frame_support::traits::StorageInfoTrait
for #pallet_ident<#type_use_gen>
#storages_where_clauses
{
fn storage_info()
-> #frame_support::sp_std::vec::Vec<#frame_support::traits::StorageInfo>
{
#[allow(unused_mut)]
let mut res = #frame_support::sp_std::vec![];

#(
#(#storage_cfg_attrs)*
{
let mut storage_info = <
#storage_names<#type_use_gen>
as #frame_support::traits::#storage_info_trait
>::#storage_info_method();
res.append(&mut storage_info);
}
)*

res
}
}
);

quote::quote_spanned!(def.pallet_struct.attr_span =>
#module_error_metadata

Expand Down
10 changes: 8 additions & 2 deletions frame/support/procedural/src/storage/storage_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream {
for line in def.storage_lines.iter() {
let storage_struct = &line.storage_struct;

let (trait_, method) = if def.generate_storage_info {
(quote!(#scrate::traits::StorageInfoTrait), quote!(storage_info))
} else {
(quote!(#scrate::traits::PartialStorageInfoTrait), quote!(partial_storage_info))
};

res_append_storage.extend(quote!(
let mut storage_info = <
#storage_struct as #scrate::traits::StorageInfoTrait
>::storage_info();
#storage_struct as #trait_
>::#method();
res.append(&mut storage_info);
));
}
Expand Down
96 changes: 95 additions & 1 deletion frame/support/procedural/src/storage/storage_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,101 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
},
}
} else {
TokenStream::default()
// Implement `__partial_storage_info` which doesn't require MaxEncodedLen on keys and
// values.
match &line.storage_type {
StorageLineTypeDef::Simple(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
prefix: <
#storage_struct as #scrate::#storage_generator_trait
>::storage_value_final_key(),
max_values: Some(1),
max_size: None,
}
]
}
}
)
},
StorageLineTypeDef::Map(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix(),
max_values: #max_values,
max_size: None,
}
]
}
}
)
},
StorageLineTypeDef::DoubleMap(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix(),
max_values: #max_values,
max_size: None,
}
]
}
}
)
},
StorageLineTypeDef::NMap(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix(),
max_values: #max_values,
max_size: None,
}
]
}
}
)
},
}
};

impls.extend(quote!(
Expand Down
2 changes: 2 additions & 0 deletions frame/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,8 @@ pub mod pallet_prelude {
/// If the attribute set_storage_max_encoded_len is set then the macro call
/// [`traits::StorageInfoTrait`] for each storage in the implementation of
/// [`traits::StorageInfoTrait`] for the pallet.
/// Otherwise it implements [`traits::StorageInfoTrait`] for the pallet using the
/// [`traits::PartialStorageInfoTrait`] implementation of storages.
///
/// # Hooks: `#[pallet::hooks]` optional
///
Expand Down
26 changes: 26 additions & 0 deletions frame/support/src/storage/types/double_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,32 @@ where
}
}

/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait for
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher1: crate::hash::StorageHasher,
Hasher2: crate::hash::StorageHasher,
Key1: FullCodec,
Key2: FullCodec,
Value: FullCodec,
QueryKind: QueryKindTrait<Value, OnEmpty>,
OnEmpty: Get<QueryKind::Query> + 'static,
MaxValues: Get<Option<u32>>,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
prefix: Self::final_prefix(),
max_values: MaxValues::get(),
max_size: None
}
]
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
24 changes: 24 additions & 0 deletions frame/support/src/storage/types/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,30 @@ where
}
}

/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait for
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher: crate::hash::StorageHasher,
Key: FullCodec,
Value: FullCodec,
QueryKind: QueryKindTrait<Value, OnEmpty>,
OnEmpty: Get<QueryKind::Query> + 'static,
MaxValues: Get<Option<u32>>,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
prefix: Self::final_prefix(),
max_values: MaxValues::get(),
max_size: None,
}
]
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
22 changes: 22 additions & 0 deletions frame/support/src/storage/types/nmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,28 @@ where
}
}

/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait for
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Key: super::key::KeyGenerator,
Value: FullCodec,
QueryKind: QueryKindTrait<Value, OnEmpty>,
OnEmpty: Get<QueryKind::Query> + 'static,
MaxValues: Get<Option<u32>>,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
prefix: Self::final_prefix(),
max_values: MaxValues::get(),
max_size: None,
}
]
}
}
#[cfg(test)]
mod test {
use super::*;
Expand Down
21 changes: 21 additions & 0 deletions frame/support/src/storage/types/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,27 @@ where
}
}

/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Value, QueryKind, OnEmpty>
crate::traits::PartialStorageInfoTrait for
StorageValue<Prefix, Value, QueryKind, OnEmpty>
where
Prefix: StorageInstance,
Value: FullCodec,
QueryKind: QueryKindTrait<Value, OnEmpty>,
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
prefix: Self::hashed_key(),
max_values: Some(1),
max_size: None,
}
]
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub use hooks::GenesisBuild;

pub mod schedule;
mod storage;
pub use storage::{Instance, StorageInstance, StorageInfo, StorageInfoTrait};
pub use storage::{Instance, PartialStorageInfoTrait, StorageInstance, StorageInfo, StorageInfoTrait};

mod dispatch;
pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable};
Expand Down
8 changes: 8 additions & 0 deletions frame/support/src/traits/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,11 @@ impl StorageInfoTrait for Tuple {
res
}
}

/// Similar to [`StorageInfoTrait`], a trait to give partial information about storage.
///
/// This is useful when a type can give some partial information with its generic parameter doesn't
/// implement some bounds.
pub trait PartialStorageInfoTrait {
fn partial_storage_info() -> Vec<StorageInfo>;
}
14 changes: 14 additions & 0 deletions frame/support/test/tests/pallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ pub mod pallet2 {
{
}

#[pallet::storage]
pub type SomeValue<T: Config> = StorageValue<_, Vec<u32>>;

#[pallet::event]
pub enum Event {
/// Something
Expand Down Expand Up @@ -1247,4 +1250,15 @@ fn test_storage_info() {
},
],
);

assert_eq!(
Example2::storage_info(),
vec![
StorageInfo {
prefix: prefix(b"Example2", b"SomeValue"),
max_values: Some(1),
max_size: None,
},
],
);
}
Loading

0 comments on commit cd48bac

Please sign in to comment.