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

pallet macro: always generate storage info on pallet struct #9246

Merged
4 commits merged into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
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 @@ -483,6 +483,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 @@ -368,6 +368,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 @@ -410,6 +410,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