From 0de47759c0071ac44bb373e5aa14c32b33c9ad9c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 6 May 2021 17:31:47 +0200 Subject: [PATCH 01/45] implement max_values + storages info --- frame/support/procedural/src/lib.rs | 3 + .../src/pallet/expand/pallet_struct.rs | 42 ++- .../src/pallet/parse/pallet_struct.rs | 76 +++-- frame/support/procedural/src/storage/mod.rs | 13 + frame/support/procedural/src/storage/parse.rs | 35 +++ .../procedural/src/storage/storage_struct.rs | 98 +++++++ .../procedural/src/storage/storages_info.rs | 55 ++++ frame/support/src/lib.rs | 24 +- frame/support/src/storage/types/double_map.rs | 90 ++++-- frame/support/src/storage/types/map.rs | 79 ++++-- frame/support/src/storage/types/value.rs | 24 +- frame/support/src/traits.rs | 4 +- frame/support/src/traits/misc.rs | 15 + frame/support/src/traits/storage.rs | 34 +++ frame/support/test/tests/decl_storage.rs | 259 ++++++++++++++---- frame/support/test/tests/pallet.rs | 93 ++++++- frame/support/test/tests/pallet_instance.rs | 2 +- .../pallet_ui/duplicate_store_attr.stderr | 6 +- .../pallet_ui/storage_info_unsatisfied.rs | 27 ++ .../pallet_ui/storage_info_unsatisfied.stderr | 8 + 20 files changed, 864 insertions(+), 123 deletions(-) create mode 100644 frame/support/procedural/src/storage/storages_info.rs create mode 100644 frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs create mode 100644 frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 4cedf798821a9..49c953ee02b7f 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -155,6 +155,9 @@ use proc_macro::TokenStream; /// * \[optional\] `config(#field_name)`: `field_name` is optional if get is set. /// Will include the item in `GenesisConfig`. /// * \[optional\] `build(#closure)`: Closure called with storage overlays. +/// * \[optional\] `max_values(#expr)`: `expr` is an expression returning a `u32`. It is used to +/// implement `StoragesInfo`. Note this attribute is not available for storage value as the maximum +/// number of values is 1. /// * `#type`: Storage type. /// * \[optional\] `#default`: Value returned when none. /// diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 556c6515d4706..2bf62e9e3c8db 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::pallet::{Def, parse::helper::get_doc_literals}; +use crate::pallet::{Def, expand::merge_where_clauses, parse::helper::get_doc_literals}; /// * Add derive trait on Pallet /// * Implement GetPalletVersion on Pallet @@ -24,6 +24,7 @@ use crate::pallet::{Def, parse::helper::get_doc_literals}; /// * declare Module type alias for construct_runtime /// * replace the first field type of `struct Pallet` with `PhantomData` if it is `_` /// * implementation of `PalletInfoAccess` information +/// * implementation of `StoragesInfo` on Pallet pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { let frame_support = &def.frame_support; let frame_system = &def.frame_system; @@ -33,6 +34,10 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { let pallet_ident = &def.pallet_struct.pallet; let config_where_clause = &def.config.where_clause; + let mut storages_where_clauses = vec![&def.config.where_clause]; + storages_where_clauses.extend(def.storages.iter().map(|storage| &storage.where_clause)); + let storages_where_clauses = merge_where_clauses(&storages_where_clauses); + let pallet_item = { let pallet_module_items = &mut def.item.content.as_mut().expect("Checked by def").1; let item = &mut pallet_module_items[def.pallet_struct.index]; @@ -97,6 +102,39 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { ) }; + let storages_info = if let Some(storages_info_span) = def.pallet_struct.generate_storages_info { + let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::>(); + let storage_cfg_attrs = &def.storages.iter() + .map(|storage| &storage.cfg_attrs) + .collect::>(); + + quote::quote_spanned!(storages_info_span => + impl<#type_impl_gen> #frame_support::traits::StoragesInfo + for #pallet_ident<#type_use_gen> + #storages_where_clauses + { + fn storages_info() + -> #frame_support::sp_std::vec::Vec<#frame_support::traits::StorageInfo> + { + #frame_support::sp_std::vec![ + #( + #(#storage_cfg_attrs)* + { + < + #storage_names<#type_use_gen> + as #frame_support::traits::StorageInfoTrait + >::storage_info() + }, + )* + ] + } + } + ) + } else { + Default::default() + }; + + quote::quote_spanned!(def.pallet_struct.attr_span => #module_error_metadata @@ -157,5 +195,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { implemented by the runtime") } } + + #storages_info ) } diff --git a/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/frame/support/procedural/src/pallet/parse/pallet_struct.rs index 6c2c90bd61a5f..3aeb70d201105 100644 --- a/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -24,6 +24,7 @@ mod keyword { syn::custom_keyword!(pallet); syn::custom_keyword!(Pallet); syn::custom_keyword!(generate_store); + syn::custom_keyword!(generate_storages_info); syn::custom_keyword!(Store); } @@ -39,12 +40,30 @@ pub struct PalletStructDef { pub store: Option<(syn::Visibility, keyword::Store)>, /// The span of the pallet::pallet attribute. pub attr_span: proc_macro2::Span, + /// Whether to specify the storages max encoded len when implementing `StoragesInfo`. + /// Contains the span of the attribute. + pub generate_storages_info: Option, } -/// Parse for `#[pallet::generate_store($vis trait Store)]` -pub struct PalletStructAttr { - vis: syn::Visibility, - keyword: keyword::Store, +/// Parse for one variant of: +/// * `#[pallet::generate_store($vis trait Store)]` +/// * `#[pallet::generate_storages_info]` +pub enum PalletStructAttr { + GenerateStore { + span: proc_macro2::Span, + vis: syn::Visibility, + keyword: keyword::Store, + }, + GenerateStoragesInfo(proc_macro2::Span), +} + +impl PalletStructAttr { + fn span(&self) -> proc_macro2::Span { + match self { + Self::GenerateStore { span, .. } => *span, + Self::GenerateStoragesInfo(span) => *span, + } + } } impl syn::parse::Parse for PalletStructAttr { @@ -54,14 +73,23 @@ impl syn::parse::Parse for PalletStructAttr { syn::bracketed!(content in input); content.parse::()?; content.parse::()?; - content.parse::()?; - - let generate_content; - syn::parenthesized!(generate_content in content); - let vis = generate_content.parse::()?; - generate_content.parse::()?; - let keyword = generate_content.parse::()?; - Ok(Self { vis, keyword }) + + let lookahead = content.lookahead1(); + if lookahead.peek(keyword::generate_store) { + let span = content.parse::()?.span(); + + let generate_content; + syn::parenthesized!(generate_content in content); + let vis = generate_content.parse::()?; + generate_content.parse::()?; + let keyword = generate_content.parse::()?; + Ok(Self::GenerateStore { vis, keyword, span }) + } else if lookahead.peek(keyword::generate_storages_info) { + let span = content.parse::()?.span(); + Ok(Self::GenerateStoragesInfo(span)) + } else { + Err(lookahead.error()) + } } } @@ -78,12 +106,24 @@ impl PalletStructDef { return Err(syn::Error::new(item.span(), msg)); }; - let mut event_attrs: Vec = helper::take_item_pallet_attrs(&mut item.attrs)?; - if event_attrs.len() > 1 { - let msg = "Invalid pallet::pallet, multiple argument pallet::generate_store found"; - return Err(syn::Error::new(event_attrs[1].keyword.span(), msg)); + let mut store = None; + let mut generate_storages_info = None; + + let struct_attrs: Vec = helper::take_item_pallet_attrs(&mut item.attrs)?; + for attr in struct_attrs { + match attr { + PalletStructAttr::GenerateStore { vis, keyword, .. } if store.is_none() => { + store = Some((vis, keyword)); + }, + PalletStructAttr::GenerateStoragesInfo(span) if generate_storages_info.is_none() => { + generate_storages_info = Some(span); + }, + attr => { + let msg = "Unexpected duplicated attribute"; + return Err(syn::Error::new(attr.span(), msg)); + }, + } } - let store = event_attrs.pop().map(|attr| (attr.vis, attr.keyword)); let pallet = syn::parse2::(item.ident.to_token_stream())?; @@ -100,6 +140,6 @@ impl PalletStructDef { let mut instances = vec![]; instances.push(helper::check_type_def_gen_no_bounds(&item.generics, item.ident.span())?); - Ok(Self { index, instances, pallet, store, attr_span }) + Ok(Self { index, instances, pallet, store, attr_span, generate_storages_info }) } } diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs index 2f9625d2c941e..556b7e92c5caa 100644 --- a/frame/support/procedural/src/storage/mod.rs +++ b/frame/support/procedural/src/storage/mod.rs @@ -18,6 +18,7 @@ //! `decl_storage` input definition and expansion. mod storage_struct; +mod storages_info; mod parse; mod store_trait; mod getters; @@ -35,6 +36,8 @@ use frame_support_procedural_tools::{ /// All information contained in input of decl_storage pub struct DeclStorageDef { + /// Whether to generate the storage info + generate_storage_info: bool, /// Name of the module used to import hidden imports. hidden_crate: Option, /// Visibility of store trait. @@ -69,6 +72,8 @@ impl syn::parse::Parse for DeclStorageDef { /// Extended version of `DeclStorageDef` with useful precomputed value. pub struct DeclStorageDefExt { + /// Whether to generate the storage info + generate_storage_info: bool, /// Name of the module used to import hidden imports. hidden_crate: Option, /// Visibility of store trait. @@ -144,6 +149,7 @@ impl From for DeclStorageDefExt { ); Self { + generate_storage_info: def.generate_storage_info, hidden_crate: def.hidden_crate, visibility: def.visibility, store_trait: def.store_trait, @@ -184,6 +190,8 @@ pub struct StorageLineDef { getter: Option, /// The name of the field to be used in genesis config if any. config: Option, + /// The given max values with `max_values` attribute, or a none if not specified. + max_values: Option, /// The build function of the storage if any. build: Option, /// Default value of genesis config field and also for storage when no value available. @@ -201,6 +209,8 @@ pub struct StorageLineDefExt { getter: Option, /// The name of the field to be used in genesis config if any. config: Option, + /// The given max values with `max_values` attribute, or a none if not specified. + max_values: Option, /// The build function of the storage if any. build: Option, /// Default value of genesis config field and also for storage when no value available. @@ -311,6 +321,7 @@ impl StorageLineDefExt { name: storage_def.name, getter: storage_def.getter, config: storage_def.config, + max_values: storage_def.max_values, build: storage_def.build, default_value: storage_def.default_value, storage_type: storage_def.storage_type, @@ -414,6 +425,7 @@ pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStr let instance_trait = instance_trait::decl_and_impl(&scrate, &def_ext); let genesis_config = genesis_config::genesis_config_and_build_storage(&scrate, &def_ext); let storage_struct = storage_struct::decl_and_impl(&scrate, &def_ext); + let storages_info = storages_info::impl_storages_info(&scrate, &def_ext); quote!( use #scrate::{ @@ -432,5 +444,6 @@ pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStr #instance_trait #genesis_config #storage_struct + #storages_info ).into() } diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 2ff7f1fbf38c9..523c7f2072383 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -21,10 +21,12 @@ use frame_support_procedural_tools::{ToTokens, Parse, syn_ext as ext}; use syn::{Ident, Token, spanned::Spanned}; mod keyword { + syn::custom_keyword!(generate_storage_info); syn::custom_keyword!(hiddencrate); syn::custom_keyword!(add_extra_genesis); syn::custom_keyword!(extra_genesis_skip_phantom_data_field); syn::custom_keyword!(config); + syn::custom_keyword!(max_values); syn::custom_keyword!(build); syn::custom_keyword!(get); syn::custom_keyword!(map); @@ -72,6 +74,7 @@ macro_rules! impl_parse_for_opt { /// Parsing usage only #[derive(Parse, ToTokens, Debug)] struct StorageDefinition { + pub generate_storage_info: Opt, pub hidden_crate: Opt, pub visibility: syn::Visibility, pub trait_token: Token![trait], @@ -96,6 +99,12 @@ struct StorageDefinition { pub extra_genesis: Opt, } +#[derive(Parse, ToTokens, Debug)] +struct GenerateStorageInfo { + pub keyword: keyword::generate_storage_info, +} +impl_parse_for_opt!(GenerateStorageInfo => keyword::generate_storage_info); + #[derive(Parse, ToTokens, Debug)] struct SpecificHiddenCrate { pub keyword: keyword::hiddencrate, @@ -159,6 +168,7 @@ struct DeclStorageLine { pub name: Ident, pub getter: Opt, pub config: Opt, + pub max_values: Opt, pub build: Opt, pub coldot_token: Token![:], pub storage_type: DeclStorageType, @@ -187,6 +197,14 @@ struct DeclStorageConfig { impl_parse_for_opt!(DeclStorageConfig => keyword::config); +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageMaxValues { + pub max_values_keyword: keyword::max_values, + pub expr: ext::Parens, +} + +impl_parse_for_opt!(DeclStorageMaxValues=> keyword::max_values); + #[derive(Parse, ToTokens, Debug)] struct DeclStorageBuild { pub build_keyword: keyword::build, @@ -419,6 +437,7 @@ pub fn parse(input: syn::parse::ParseStream) -> syn::Result { + line.max_values.inner.map(|i| i.expr.content) + }, + DeclStorageType::Simple(_) => { + if let Some(max_values) = line.max_values.inner { + let msg = "unexpected max_values attribute for storage value."; + let span = max_values.max_values_keyword.span(); + return Err(syn::Error::new(span, msg)); + } else { + Some(syn::parse_quote!(1u32)) + } + }, + }; + let span = line.storage_type.span(); let no_hasher_error = || syn::Error::new( span, @@ -504,6 +538,7 @@ fn parse_storage_line_defs( name: line.name, getter, config, + max_values, build: line.build.inner.map(|o| o.expr.content), default_value: line.default_value.inner.map(|o| o.expr), storage_type, diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index 9c049789f9bd9..6145a6b38aa11 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -207,9 +207,107 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } }; + let max_values = if let Some(max_values) = &line.max_values { + quote::quote!({ + let max_values: u32 = (|| #max_values)(); + Some(max_values) + }) + } else { + quote::quote!(None) + }; + + let storage_info_impl = if def.generate_storage_info { + match &line.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!( + impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct + #optional_storage_where_clause + { + fn storage_info() -> #scrate::traits::StorageInfo { + use #scrate::sp_runtime::SaturatedConversion; + + let max_size = < + #value_type as #scrate::traits::MaxEncodedLen + >::max_encoded_len() + .saturated_into(); + #scrate::traits::StorageInfo { + prefix: < + #storage_struct as #scrate::#storage_generator_trait + >::storage_value_final_key(), + max_values: Some(1), + max_size: Some(max_size), + } + } + } + ) + }, + StorageLineTypeDef::Map(map) => { + let key = &map.key; + quote!( + impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct + #optional_storage_where_clause + { + fn storage_info() -> #scrate::traits::StorageInfo { + use #scrate::sp_runtime::SaturatedConversion; + let max_size = < + #value_type as #scrate::traits::MaxEncodedLen + >::max_encoded_len() + .saturating_add( + <#key as #scrate::traits::MaxEncodedLen>::max_encoded_len() + ) + .saturated_into(); + #scrate::traits::StorageInfo { + prefix: < + #storage_struct + as #scrate::storage::StoragePrefixedMap<#value_type> + >::final_prefix(), + max_values: #max_values, + max_size: Some(max_size), + } + } + } + ) + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + quote!( + impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct + #optional_storage_where_clause + { + fn storage_info() -> #scrate::traits::StorageInfo { + use #scrate::sp_runtime::SaturatedConversion; + let max_size = < + #value_type as #scrate::traits::MaxEncodedLen + >::max_encoded_len() + .saturating_add( + <#key1 as #scrate::traits::MaxEncodedLen>::max_encoded_len() + ) + .saturating_add( + <#key2 as #scrate::traits::MaxEncodedLen>::max_encoded_len() + ) + .saturated_into(); + #scrate::traits::StorageInfo { + prefix: < + #storage_struct + as #scrate::storage::StoragePrefixedMap<#value_type> + >::final_prefix(), + max_values: #max_values, + max_size: Some(max_size), + } + } + } + ) + } + } + } else { + Default::default() + }; + impls.extend(quote!( #struct_decl #struct_impl + #storage_info_impl )) } diff --git a/frame/support/procedural/src/storage/storages_info.rs b/frame/support/procedural/src/storage/storages_info.rs new file mode 100644 index 0000000000000..fe4d45cf89f88 --- /dev/null +++ b/frame/support/procedural/src/storage/storages_info.rs @@ -0,0 +1,55 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Implementation of trait `StoragesInfo` on module structure. + +use proc_macro2::TokenStream; +use quote::quote; +use super::DeclStorageDefExt; + +pub fn impl_storages_info(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + if !def.generate_storage_info { + return Default::default() + } + + let mut entries = TokenStream::new(); + + for line in def.storage_lines.iter() { + let storage_struct = &line.storage_struct; + + let entry = quote!( + < + #storage_struct as #scrate::traits::StorageInfoTrait + >::storage_info(), + ); + entries.extend(entry); + } + + let module_struct = &def.module_struct; + let module_impl = &def.module_impl; + let where_clause = &def.where_clause; + + quote!( + impl#module_impl #scrate::traits::StoragesInfo for #module_struct #where_clause { + fn storages_info() -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { + #scrate::sp_std::vec![ + #entries + ] + } + } + ) +} diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 77163755ac56f..8d12c0cb64779 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1234,7 +1234,10 @@ pub mod pallet_prelude { EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, DebugNoBound, CloneNoBound, Twox256, Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, ensure, RuntimeDebug, storage, - traits::{Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess}, + traits::{ + Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, StoragesInfo, + ConstU32, GetDefault, + }, dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult}, weights::{DispatchClass, Pays, Weight}, storage::types::{StorageValue, StorageMap, StorageDoubleMap, ValueQuery, OptionQuery}, @@ -1343,6 +1346,17 @@ pub mod pallet_prelude { /// Thus when defining a storage named `Foo`, it can later be accessed from `Pallet` using /// `::Foo`. /// +/// To generate the full storage info (used for PoV calculation) use the attribute +/// `#[pallet::set_storage_max_encoded_len]`, e.g.: +/// ```ignore +/// #[pallet::pallet] +/// #[pallet::set_storage_max_encoded_len] +/// pub struct Pallet(_); +/// ``` +/// +/// This require all storage to implement the trait [`traits::StorageMaxEncodedLen`], thus all keys +/// and value types must bound [`traits::MaxEncodedLen`]. +/// /// ### Macro expansion: /// /// The macro add this attribute to the struct definition: @@ -1367,7 +1381,13 @@ pub mod pallet_prelude { /// given by [`frame_support::traits::PalletInfo`]. /// (The implementation use the associated type `frame_system::Config::PalletInfo`). /// -/// If attribute generate_store then macro create the trait `Store` and implement it on `Pallet`. +/// It implements [`traits::StoragesInfo`] on `Pallet` which give information about all storages. +/// +/// If the attribute generate_store is set then the macro creates the trait `Store` and implements +/// it on `Pallet`. +/// +/// If the attribute set_storage_max_encoded_len is set then the macro call +/// [`traits::StorageMaxEncodedLen`] in the implementation of [`StoragesInfo`]. /// /// # Hooks: `#[pallet::hooks]` mandatory /// diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index 184d96b3a54f9..20bebc6bb6075 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -21,13 +21,14 @@ use codec::{FullCodec, Decode, EncodeLike, Encode}; use crate::{ storage::{ - StorageAppend, StorageDecodeLength, + StorageAppend, StorageDecodeLength, StoragePrefixedMap, bounded_vec::{BoundedVec, BoundedVecValue}, types::{OptionQuery, QueryKindTrait, OnEmptyGetter}, }, - traits::{GetDefault, StorageInstance, Get}, + traits::{GetDefault, StorageInstance, Get, MaxEncodedLen, StorageInfo}, }; use frame_metadata::{DefaultByteGetter, StorageEntryModifier}; +use sp_arithmetic::traits::SaturatedConversion; use sp_std::vec::Vec; /// A type that allow to store values for `(key1, key2)` couple. Similar to `StorageMap` but allow @@ -47,14 +48,24 @@ use sp_std::vec::Vec; /// such as `blake2_128_concat` must be used for Hasher1 (resp. Hasher2). Otherwise, other values /// in storage can be compromised. pub struct StorageDoubleMap< - Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind=OptionQuery, OnEmpty=GetDefault + Prefix, + Hasher1, + Key1, + Hasher2, + Key2, + Value, + QueryKind=OptionQuery, + OnEmpty=GetDefault, + MaxValues=GetDefault, >( - core::marker::PhantomData<(Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty)> + core::marker::PhantomData< + (Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues) + > ); -impl +impl crate::storage::generator::StorageDoubleMap for - StorageDoubleMap + StorageDoubleMap where Prefix: StorageInstance, Hasher1: crate::hash::StorageHasher, @@ -63,7 +74,8 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static + OnEmpty: Get + 'static, + MaxValues: Get>, { type Query = QueryKind::Query; type Hasher1 = Hasher1; @@ -82,9 +94,9 @@ where } } -impl - crate::storage::StoragePrefixedMap for - StorageDoubleMap +impl + StoragePrefixedMap for + StorageDoubleMap where Prefix: StorageInstance, Hasher1: crate::hash::StorageHasher, @@ -93,7 +105,8 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static + OnEmpty: Get + 'static, + MaxValues: Get>, { fn module_prefix() -> &'static [u8] { >::module_prefix() @@ -103,7 +116,7 @@ where } } -impl +impl StorageDoubleMap< Prefix, Hasher1, @@ -113,6 +126,7 @@ impl, QueryKind, OnEmpty, + MaxValues, > where Prefix: StorageInstance, Hasher1: crate::hash::StorageHasher, @@ -121,6 +135,7 @@ impl, OnEmpty>, OnEmpty: crate::traits::Get + 'static, + MaxValues: Get>, VecValue: BoundedVecValue, VecBound: Get, { @@ -147,8 +162,8 @@ impl - StorageDoubleMap +impl + StorageDoubleMap where Prefix: StorageInstance, Hasher1: crate::hash::StorageHasher, @@ -157,7 +172,8 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static + OnEmpty: crate::traits::Get + 'static, + MaxValues: Get>, { /// Get the storage key used to fetch a value corresponding to a specific key. pub fn hashed_key_for(k1: KArg1, k2: KArg2) -> Vec @@ -376,8 +392,8 @@ where } } -impl - StorageDoubleMap +impl + StorageDoubleMap where Prefix: StorageInstance, Hasher1: crate::hash::StorageHasher + crate::ReversibleStorageHasher, @@ -386,7 +402,8 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static + OnEmpty: crate::traits::Get + 'static, + MaxValues: Get>, { /// Enumerate all elements in the map with first key `k1` in no particular order. /// @@ -440,8 +457,10 @@ pub trait StorageDoubleMapMetadata { const HASHER2: frame_metadata::StorageHasher; } -impl StorageDoubleMapMetadata - for StorageDoubleMap where +impl + StorageDoubleMapMetadata for + StorageDoubleMap +where Prefix: StorageInstance, Hasher1: crate::hash::StorageHasher, Hasher2: crate::hash::StorageHasher, @@ -449,7 +468,8 @@ impl StorageDou Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static + OnEmpty: crate::traits::Get + 'static, + MaxValues: Get>, { const MODIFIER: StorageEntryModifier = QueryKind::METADATA; const HASHER1: frame_metadata::StorageHasher = Hasher1::METADATA; @@ -459,6 +479,34 @@ impl StorageDou DefaultByteGetter(&OnEmptyGetter::(core::marker::PhantomData)); } +impl + crate::traits::StorageInfoTrait for + StorageDoubleMap +where + Prefix: StorageInstance, + Hasher1: crate::hash::StorageHasher, + Hasher2: crate::hash::StorageHasher, + Key1: FullCodec + MaxEncodedLen, + Key2: FullCodec + MaxEncodedLen, + Value: FullCodec + MaxEncodedLen, + QueryKind: QueryKindTrait, + OnEmpty: crate::traits::Get + 'static, + MaxValues: Get>, +{ + fn storage_info() -> StorageInfo { + StorageInfo { + prefix: Self::final_prefix(), + max_values: MaxValues::get(), + max_size: Some( + Key1::max_encoded_len() + .saturating_add(Key2::max_encoded_len()) + .saturating_add(Value::max_encoded_len()) + .saturated_into(), + ), + } + } +} + #[cfg(test)] mod test { use super::*; diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 187323b4ad1ee..dbd7a54c2edb3 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -21,13 +21,14 @@ use codec::{FullCodec, Decode, EncodeLike, Encode}; use crate::{ storage::{ - StorageAppend, StorageDecodeLength, + StorageAppend, StorageDecodeLength, StoragePrefixedMap, bounded_vec::{BoundedVec, BoundedVecValue}, types::{OptionQuery, QueryKindTrait, OnEmptyGetter}, }, - traits::{GetDefault, StorageInstance, Get}, + traits::{GetDefault, StorageInstance, Get, MaxEncodedLen, StorageInfo}, }; use frame_metadata::{DefaultByteGetter, StorageEntryModifier}; +use sp_arithmetic::traits::SaturatedConversion; use sp_std::prelude::*; /// A type that allow to store value for given key. Allowing to insert/remove/iterate on values. @@ -43,20 +44,23 @@ use sp_std::prelude::*; /// /// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as /// `blake2_128_concat` must be used. Otherwise, other values in storage can be compromised. -pub struct StorageMap( - core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty)> +pub struct StorageMap< + Prefix, Hasher, Key, Value, QueryKind=OptionQuery, OnEmpty=GetDefault, MaxValues=GetDefault, +>( + core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)> ); -impl +impl crate::storage::generator::StorageMap - for StorageMap + for StorageMap where Prefix: StorageInstance, Hasher: crate::hash::StorageHasher, Key: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, + MaxValues: Get>, { type Query = QueryKind::Query; type Hasher = Hasher; @@ -74,15 +78,17 @@ where } } -impl crate::storage::StoragePrefixedMap for - StorageMap +impl + StoragePrefixedMap for + StorageMap where Prefix: StorageInstance, Hasher: crate::hash::StorageHasher, Key: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, + MaxValues: Get>, { fn module_prefix() -> &'static [u8] { >::module_prefix() @@ -92,14 +98,15 @@ where } } -impl - StorageMap, QueryKind, OnEmpty> +impl + StorageMap, QueryKind, OnEmpty, MaxValues> where Prefix: StorageInstance, Hasher: crate::hash::StorageHasher, Key: FullCodec, QueryKind: QueryKindTrait, OnEmpty>, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, + MaxValues: Get>, VecValue: BoundedVecValue, VecBound: Get, { @@ -120,15 +127,16 @@ where } } -impl - StorageMap +impl + StorageMap where Prefix: StorageInstance, Hasher: crate::hash::StorageHasher, Key: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, + MaxValues: Get>, { /// Get the storage key used to fetch a value corresponding to a specific key. pub fn hashed_key_for>(key: KeyArg) -> Vec { @@ -283,15 +291,16 @@ where } } -impl - StorageMap +impl + StorageMap where Prefix: StorageInstance, Hasher: crate::hash::StorageHasher + crate::ReversibleStorageHasher, Key: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, + MaxValues: Get>, { /// Enumerate all elements in the map in no particular order. /// @@ -327,14 +336,15 @@ pub trait StorageMapMetadata { const HASHER: frame_metadata::StorageHasher; } -impl StorageMapMetadata - for StorageMap where +impl StorageMapMetadata + for StorageMap where Prefix: StorageInstance, Hasher: crate::hash::StorageHasher, Key: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, + MaxValues: Get>, { const MODIFIER: StorageEntryModifier = QueryKind::METADATA; const HASHER: frame_metadata::StorageHasher = Hasher::METADATA; @@ -343,6 +353,31 @@ impl StorageMapMetadata DefaultByteGetter(&OnEmptyGetter::(core::marker::PhantomData)); } +impl + crate::traits::StorageInfoTrait for + StorageMap +where + Prefix: StorageInstance, + Hasher: crate::hash::StorageHasher, + Key: FullCodec + MaxEncodedLen, + Value: FullCodec + MaxEncodedLen, + QueryKind: QueryKindTrait, + OnEmpty: Get + 'static, + MaxValues: Get>, +{ + fn storage_info() -> StorageInfo { + StorageInfo { + prefix: Self::final_prefix(), + max_values: MaxValues::get(), + max_size: Some( + Key::max_encoded_len() + .saturating_add(Value::max_encoded_len()) + .saturated_into(), + ), + } + } +} + #[cfg(test)] mod test { use super::*; diff --git a/frame/support/src/storage/types/value.rs b/frame/support/src/storage/types/value.rs index d536d76d76b8e..afb27c450fc6a 100644 --- a/frame/support/src/storage/types/value.rs +++ b/frame/support/src/storage/types/value.rs @@ -24,9 +24,10 @@ use crate::{ bounded_vec::{BoundedVec, BoundedVecValue}, types::{OptionQuery, QueryKindTrait, OnEmptyGetter}, }, - traits::{GetDefault, StorageInstance, Get}, + traits::{GetDefault, StorageInstance, Get, MaxEncodedLen, StorageInfo}, }; use frame_metadata::{DefaultByteGetter, StorageEntryModifier}; +use sp_arithmetic::traits::SaturatedConversion; /// A type that allow to store a value. /// @@ -212,6 +213,27 @@ impl StorageValueMetadata DefaultByteGetter(&OnEmptyGetter::(core::marker::PhantomData)); } +impl + crate::traits::StorageInfoTrait for + StorageValue +where + Prefix: StorageInstance, + Value: FullCodec + MaxEncodedLen, + QueryKind: QueryKindTrait, + OnEmpty: crate::traits::Get + 'static +{ + fn storage_info() -> StorageInfo { + StorageInfo { + prefix: Self::hashed_key(), + max_values: Some(1), + max_size: Some( + Value::max_encoded_len() + .saturated_into(), + ), + } + } +} + #[cfg(test)] mod test { use super::*; diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index d15356c1e1b09..7e89917c5dbb9 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -50,7 +50,7 @@ mod misc; pub use misc::{ Len, Get, GetDefault, HandleLifetime, TryDrop, Time, UnixTime, IsType, IsSubType, ExecuteBlock, SameOrOther, OnNewAccount, OnKilledAccount, OffchainWorker, GetBacking, Backing, ExtrinsicCall, - EnsureInherentsAreFirst, + EnsureInherentsAreFirst, ConstU32, }; mod stored_map; @@ -73,7 +73,7 @@ pub use hooks::GenesisBuild; pub mod schedule; mod storage; -pub use storage::{Instance, StorageInstance}; +pub use storage::{Instance, StorageInstance, StoragesInfo, StorageInfo, StorageInfoTrait}; mod dispatch; pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable}; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index d3010358dd883..7ec29522cbc75 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -53,6 +53,21 @@ impl Get for GetDefault { } } +/// Implement `Get` and `Get>` using the given const. +pub struct ConstU32; + +impl Get for ConstU32 { + fn get() -> u32 { + T + } +} + +impl Get> for ConstU32 { + fn get() -> Option { + Some(T) + } +} + /// A type for which some values make sense to be able to drop without further consideration. pub trait TryDrop: Sized { /// Drop an instance cleanly. Only works if its value represents "no-operation". diff --git a/frame/support/src/traits/storage.rs b/frame/support/src/traits/storage.rs index c42e1abf73ea3..205d20cd3c829 100644 --- a/frame/support/src/traits/storage.rs +++ b/frame/support/src/traits/storage.rs @@ -17,6 +17,8 @@ //! Traits for encoding data related to pallet's storage items. +use sp_std::prelude::*; + /// An instance of a pallet in the storage. /// /// It is required that these instances are unique, to support multiple instances per pallet in the same runtime! @@ -45,3 +47,35 @@ pub trait StorageInstance { /// Prefix given to a storage to isolate from other storages in the pallet. const STORAGE_PREFIX: &'static str; } + +/// Some info about a storage in a pallet. +#[derive(codec::Encode, codec::Decode, crate::RuntimeDebug, Eq, PartialEq, Clone)] +pub struct StorageInfo { + /// The prefix of the storage. All keys after the prefix are considered part of the storage + pub prefix: [u8; 32], + /// The maximum number of values in the storage, or none if no maximum specified. + pub max_values: Option, + /// The maximum size of key/values in the storage, or none if no maximum specified. + pub max_size: Option, +} + +/// A trait to give information about storages. +/// +/// It can be used to calculate PoV worst case size. +pub trait StoragesInfo { + fn storages_info() -> Vec; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl StoragesInfo for Tuple { + fn storages_info() -> Vec { + let mut res = vec![]; + for_tuples!( #( res.extend_from_slice(&Tuple::storages_info()); )* ); + res + } +} + +/// A trait for types which contains storage info. +pub trait StorageInfoTrait { + fn storage_info() -> StorageInfo; +} diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index a2690b1379db5..2e797731e14ff 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -27,9 +27,13 @@ mod tests { pub struct Module for enum Call where origin: T::Origin, system=frame_support_test {} } - pub trait Config: frame_support_test::Config {} + pub trait Config: frame_support_test::Config { + type Origin2: codec::Codec + codec::EncodeLike + Default + + frame_support::traits::MaxEncodedLen; + } frame_support::decl_storage! { + generate_storage_info trait Store for Module as TestStorage { // non-getters: pub / $default @@ -41,7 +45,7 @@ mod tests { // getters: pub / $default // we need at least one type which uses T, otherwise GenesisConfig will complain. - GETU32 get(fn u32_getter): T::Origin; + GETU32 get(fn u32_getter): T::Origin2; pub PUBGETU32 get(fn pub_u32_getter): u32; GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32; pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32; @@ -56,22 +60,26 @@ mod tests { GetOptU32WithBuilderNone get(fn opt_u32_with_builder_none) build(|_| None): Option; // map non-getters: pub / $default - MAPU32: map hasher(blake2_128_concat) u32 => Option; - pub PUBMAPU32: map hasher(blake2_128_concat) u32 => Option; - MAPU32MYDEF: map hasher(blake2_128_concat) u32 => Option; - pub PUBMAPU32MYDEF: map hasher(blake2_128_concat) u32 => Option; + MAPU32 max_values(3): map hasher(blake2_128_concat) u32 => Option<[u8; 4]>; + pub PUBMAPU32: map hasher(blake2_128_concat) u32 => Option<[u8; 4]>; // map getters: pub / $default - GETMAPU32 get(fn map_u32_getter): map hasher(blake2_128_concat) u32 => String; - pub PUBGETMAPU32 get(fn pub_map_u32_getter): map hasher(blake2_128_concat) u32 => String; + GETMAPU32 get(fn map_u32_getter): map hasher(blake2_128_concat) u32 => [u8; 4]; + pub PUBGETMAPU32 get(fn pub_map_u32_getter): map hasher(blake2_128_concat) u32 => [u8; 4]; GETMAPU32MYDEF get(fn map_u32_getter_mydef): - map hasher(blake2_128_concat) u32 => String = "map".into(); + map hasher(blake2_128_concat) u32 => [u8; 4] = *b"mapd"; pub PUBGETMAPU32MYDEF get(fn pub_map_u32_getter_mydef): - map hasher(blake2_128_concat) u32 => String = "pubmap".into(); + map hasher(blake2_128_concat) u32 => [u8; 4] = *b"pubm"; + + DOUBLEMAP max_values(3): double_map + hasher(blake2_128_concat) u32, hasher(blake2_128_concat) u32 => Option<[u8; 4]>; - COMPLEXTYPE1: ::std::vec::Vec; - COMPLEXTYPE2: (Vec)>>, u32); + DOUBLEMAP2: double_map + hasher(blake2_128_concat) u32, hasher(blake2_128_concat) u32 => Option<[u8; 4]>; + + COMPLEXTYPE1: (::std::option::Option,); + COMPLEXTYPE2: ([[(u16, Option<()>); 32]; 12], u32); COMPLEXTYPE3: [u32; 25]; } add_extra_genesis { @@ -88,7 +96,9 @@ mod tests { type DbWeight = (); } - impl Config for TraitImpl {} + impl Config for TraitImpl { + type Origin2 = u32; + } const EXPECTED_METADATA: StorageMetadata = StorageMetadata { prefix: DecodeDifferent::Encode("TestStorage"), @@ -133,7 +143,7 @@ mod tests { StorageEntryMetadata { name: DecodeDifferent::Encode("GETU32"), modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Origin")), + ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Origin2")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETU32(PhantomData::)) ), @@ -244,7 +254,7 @@ mod tests { ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), + value: DecodeDifferent::Encode("[u8; 4]"), unused: false, }, default: DecodeDifferent::Encode( @@ -258,7 +268,7 @@ mod tests { ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), + value: DecodeDifferent::Encode("[u8; 4]"), unused: false, }, default: DecodeDifferent::Encode( @@ -267,93 +277,95 @@ mod tests { documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { - name: DecodeDifferent::Encode("MAPU32MYDEF"), - modifier: StorageEntryModifier::Optional, + name: DecodeDifferent::Encode("GETMAPU32"), + modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), + value: DecodeDifferent::Encode("[u8; 4]"), unused: false, }, default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructMAPU32MYDEF(PhantomData::)) + DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBMAPU32MYDEF"), - modifier: StorageEntryModifier::Optional, + name: DecodeDifferent::Encode("PUBGETMAPU32"), + modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), + value: DecodeDifferent::Encode("[u8; 4]"), unused: false, }, default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBMAPU32MYDEF(PhantomData::)) + DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { - name: DecodeDifferent::Encode("GETMAPU32"), + name: DecodeDifferent::Encode("GETMAPU32MYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), + value: DecodeDifferent::Encode("[u8; 4]"), unused: false, }, default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) + DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETMAPU32"), + name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), + value: DecodeDifferent::Encode("[u8; 4]"), unused: false, }, default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) + DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { - name: DecodeDifferent::Encode("GETMAPU32MYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { + name: DecodeDifferent::Encode("DOUBLEMAP"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::DoubleMap { hasher: StorageHasher::Blake2_128Concat, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - unused: false, + key1: DecodeDifferent::Encode("u32"), + key2: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("[u8; 4]"), + key2_hasher: StorageHasher::Blake2_128Concat, }, default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) + DefaultByteGetter(&__GetByteStructDOUBLEMAP(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { + name: DecodeDifferent::Encode("DOUBLEMAP2"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::DoubleMap { hasher: StorageHasher::Blake2_128Concat, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - unused: false, + key1: DecodeDifferent::Encode("u32"), + key2: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("[u8; 4]"), + key2_hasher: StorageHasher::Blake2_128Concat, }, default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) + DefaultByteGetter(&__GetByteStructDOUBLEMAP2(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("COMPLEXTYPE1"), modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("::std::vec::Vec")), + ty: StorageEntryType::Plain(DecodeDifferent::Encode("(::std::option::Option,)")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructCOMPLEXTYPE1(PhantomData::)) ), @@ -362,7 +374,7 @@ mod tests { StorageEntryMetadata { name: DecodeDifferent::Encode("COMPLEXTYPE2"), modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("(Vec)>>, u32)")), + ty: StorageEntryType::Plain(DecodeDifferent::Encode("([[(u16, Option<()>); 32]; 12], u32)")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructCOMPLEXTYPE2(PhantomData::)) ), @@ -381,6 +393,161 @@ mod tests { ), }; + #[test] + fn storages_info() { + use frame_support::{ + StorageHasher, + traits::{StoragesInfo, StorageInfo}, + pallet_prelude::*, + }; + let prefix = |pallet_name, storage_name| { + let mut res = [0u8; 32]; + res[0..16].copy_from_slice(&Twox128::hash(pallet_name)); + res[16..32].copy_from_slice(&Twox128::hash(storage_name)); + res + }; + pretty_assertions::assert_eq!( + >::storages_info(), + vec![ + StorageInfo { + prefix: prefix(b"TestStorage", b"U32"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBU32"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"U32MYDEF"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBU32MYDEF"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GETU32"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETU32"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GETU32WITHCONFIG"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETU32WITHCONFIG"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GETU32MYDEF"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETU32MYDEF"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GETU32WITHCONFIGMYDEF"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETU32WITHCONFIGMYDEF"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETU32WITHCONFIGMYDEFOPT"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GetU32WithBuilder"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GetOptU32WithBuilderSome"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GetOptU32WithBuilderNone"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"MAPU32"), + max_values: Some(3), + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBMAPU32"), + max_values: None, + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GETMAPU32"), + max_values: None, + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETMAPU32"), + max_values: None, + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"GETMAPU32MYDEF"), + max_values: None, + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"PUBGETMAPU32MYDEF"), + max_values: None, + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"DOUBLEMAP"), + max_values: Some(3), + max_size: Some(12), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"DOUBLEMAP2"), + max_values: None, + max_size: Some(12), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"COMPLEXTYPE1"), + max_values: Some(1), + max_size: Some(5), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"COMPLEXTYPE2"), + max_values: Some(1), + max_size: Some(1156), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"COMPLEXTYPE3"), + max_values: Some(1), + max_size: Some(100), + }, + ], + ); + } + #[test] fn store_metadata() { let metadata = Module::::storage_metadata(); diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 3bde38c78e2c1..c5612b267982e 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -19,6 +19,7 @@ use frame_support::{ weights::{DispatchInfo, DispatchClass, Pays, GetDispatchInfo}, traits::{ GetCallName, OnInitialize, OnFinalize, OnRuntimeUpgrade, GetPalletVersion, OnGenesis, + MaxEncodedLen, }, dispatch::{UnfilteredDispatchable, Parameter}, storage::unhashed, @@ -47,10 +48,10 @@ impl From for u64 { fn from(_t: SomeType6) -> Self { 0u64 } } pub struct SomeType7; impl From for u64 { fn from(_t: SomeType7) -> Self { 0u64 } } -pub trait SomeAssociation1 { type _1: Parameter; } +pub trait SomeAssociation1 { type _1: Parameter + MaxEncodedLen; } impl SomeAssociation1 for u64 { type _1 = u64; } -pub trait SomeAssociation2 { type _2: Parameter; } +pub trait SomeAssociation2 { type _2: Parameter + MaxEncodedLen; } impl SomeAssociation2 for u64 { type _2 = u64; } #[frame_support::pallet] @@ -100,6 +101,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] + #[pallet::generate_storages_info] pub struct Pallet(_); #[pallet::hooks] @@ -209,13 +211,15 @@ pub mod pallet { StorageMap<_, Blake2_128Concat, u8, u16, ValueQuery, MyDefault>; #[pallet::storage] - pub type Map2 = StorageMap<_, Twox64Concat, u16, u32>; + pub type Map2 = StorageMap<_, Twox64Concat, u16, u32, OptionQuery, GetDefault, ConstU32<3>>; #[pallet::storage] pub type DoubleMap = StorageDoubleMap<_, Blake2_128Concat, u8, Twox64Concat, u16, u32>; #[pallet::storage] - pub type DoubleMap2 = StorageDoubleMap<_, Twox64Concat, u16, Blake2_128Concat, u32, u64>; + pub type DoubleMap2 = StorageDoubleMap< + _, Twox64Concat, u16, Blake2_128Concat, u32, u64, OptionQuery, GetDefault, ConstU32<5>, + >; #[pallet::storage] #[pallet::getter(fn conditional_value)] @@ -225,7 +229,8 @@ pub mod pallet { #[cfg(feature = "conditional-storage")] #[pallet::storage] #[pallet::getter(fn conditional_map)] - pub type ConditionalMap = StorageMap<_, Twox64Concat, u16, u32>; + pub type ConditionalMap = + StorageMap<_, Twox64Concat, u16, u32, OptionQuery, GetDefault, ConstU32<12>>; #[cfg(feature = "conditional-storage")] #[pallet::storage] @@ -533,7 +538,7 @@ fn pallet_expand_deposit_event() { #[test] fn storage_expand() { use frame_support::pallet_prelude::*; - use frame_support::StoragePrefixedMap; + use frame_support::storage::StoragePrefixedMap; fn twox_64_concat(d: &[u8]) -> Vec { let mut v = twox_64(d).to_vec(); @@ -881,3 +886,79 @@ fn test_pallet_info_access() { assert_eq!(::index(), 1); assert_eq!(::index(), 2); } + +#[test] +fn test_storages_info() { + use frame_support::{ + StorageHasher, + traits::{StoragesInfo, StorageInfo}, + pallet_prelude::*, + }; + + let prefix = |pallet_name, storage_name| { + let mut res = [0u8; 32]; + res[0..16].copy_from_slice(&Twox128::hash(pallet_name)); + res[16..32].copy_from_slice(&Twox128::hash(storage_name)); + res + }; + + assert_eq!( + Example::storages_info(), + vec![ + StorageInfo { + prefix: prefix(b"Example", b"ValueWhereClause"), + max_values: Some(1), + max_size: Some(8), + }, + StorageInfo { + prefix: prefix(b"Example", b"Value"), + max_values: Some(1), + max_size: Some(4), + }, + StorageInfo { + prefix: prefix(b"Example", b"Map"), + max_values: None, + max_size: Some(3), + }, + StorageInfo { + prefix: prefix(b"Example", b"Map2"), + max_values: Some(3), + max_size: Some(6), + }, + StorageInfo { + prefix: prefix(b"Example", b"DoubleMap"), + max_values: None, + max_size: Some(7), + }, + StorageInfo { + prefix: prefix(b"Example", b"DoubleMap2"), + max_values: Some(5), + max_size: Some(14), + }, + #[cfg(feature = "conditional-storage")] + { + StorageInfo { + prefix: prefix(b"Example", b"ConditionalValue"), + max_values: Some(1), + max_size: Some(4), + } + }, + #[cfg(feature = "conditional-storage")] + { + StorageInfo { + prefix: prefix(b"Example", b"ConditionalMap"), + max_values: Some(12), + max_size: Some(6), + } + }, + #[cfg(feature = "conditional-storage")] + { + StorageInfo { + prefix: prefix(b"Example", b"ConditionalDoubleMap"), + max_values: None, + max_size: Some(7), + } + }, + ], + ); +} diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index f0143b9c40d6c..ad88d3565aa5a 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -403,7 +403,7 @@ fn pallet_expand_deposit_event() { #[test] fn storage_expand() { use frame_support::pallet_prelude::*; - use frame_support::StoragePrefixedMap; + use frame_support::storage::StoragePrefixedMap; fn twox_64_concat(d: &[u8]) -> Vec { let mut v = twox_64(d).to_vec(); diff --git a/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr b/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr index eed6ad4494edc..232144b8deaca 100644 --- a/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr +++ b/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr @@ -1,5 +1,5 @@ -error: Invalid pallet::pallet, multiple argument pallet::generate_store found - --> $DIR/duplicate_store_attr.rs:12:33 +error: Unexpected duplicated attribute + --> $DIR/duplicate_store_attr.rs:12:12 | 12 | #[pallet::generate_store(trait Store)] - | ^^^^^ + | ^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs new file mode 100644 index 0000000000000..22b3658329b97 --- /dev/null +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs @@ -0,0 +1,27 @@ +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::{Hooks, StorageValue}; + use frame_system::pallet_prelude::BlockNumberFor; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + #[pallet::generate_storages_info] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::call] + impl Pallet {} + + #[derive(codec::Encode, codec::Decode)] + struct Bar; + + #[pallet::storage] + type Foo = StorageValue<_, Bar>; +} + +fn main() { +} diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr new file mode 100644 index 0000000000000..a0ecd4f6555c9 --- /dev/null +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr @@ -0,0 +1,8 @@ +error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied + --> $DIR/storage_info_unsatisfied.rs:10:12 + | +10 | #[pallet::generate_storages_info] + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` + = note: required by `storage_info` From 42c4f483496acf090724f7d61beec6be5a7e6c27 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 12 May 2021 13:25:03 +0200 Subject: [PATCH 02/45] some formatting + doc --- frame/support/procedural/src/lib.rs | 11 ++++++++++- .../procedural/src/pallet/expand/pallet_struct.rs | 1 - frame/support/procedural/src/storage/parse.rs | 1 - frame/support/src/storage/types/double_map.rs | 10 +++++----- frame/support/src/storage/types/map.rs | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 7f7584ac080e6..5146b8e78380e 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -237,11 +237,20 @@ use proc_macro::TokenStream; /// add_extra_genesis { /// config(phantom): std::marker::PhantomData, /// } -/// ... +/// ``` /// /// This adds a field to your `GenesisConfig` with the name `phantom` that you can initialize with /// `Default::default()`. /// +/// ## PoV information +/// +/// To implement the trait `StorageInfoTrait` for storages an additional attribute can be used +/// `generate_storage_info`: +/// ```nocompile +/// decl_storage! { generate_storage_info +/// trait Store for ... +/// } +/// ``` #[proc_macro] pub fn decl_storage(input: TokenStream) -> TokenStream { storage::decl_storage_impl(input) diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 2bf62e9e3c8db..cf0523a2899d5 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -134,7 +134,6 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { Default::default() }; - quote::quote_spanned!(def.pallet_struct.attr_span => #module_error_metadata diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 523c7f2072383..989496ad1c2ef 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -202,7 +202,6 @@ struct DeclStorageMaxValues { pub max_values_keyword: keyword::max_values, pub expr: ext::Parens, } - impl_parse_for_opt!(DeclStorageMaxValues=> keyword::max_values); #[derive(Parse, ToTokens, Debug)] diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index b95df9953ce2d..b88e6b8416c55 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -134,7 +134,7 @@ impl, OnEmpty>, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, MaxValues: Get>, VecValue: FullCodec, VecBound: Get, @@ -172,7 +172,7 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, MaxValues: Get>, { /// Get the storage key used to fetch a value corresponding to a specific key. @@ -402,7 +402,7 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, MaxValues: Get>, { /// Enumerate all elements in the map with first key `k1` in no particular order. @@ -468,7 +468,7 @@ where Key2: FullCodec, Value: FullCodec, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, MaxValues: Get>, { const MODIFIER: StorageEntryModifier = QueryKind::METADATA; @@ -490,7 +490,7 @@ where Key2: FullCodec + MaxEncodedLen, Value: FullCodec + MaxEncodedLen, QueryKind: QueryKindTrait, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, MaxValues: Get>, { fn storage_info() -> StorageInfo { diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index c44355e435c00..6e2e2221c4aae 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -105,7 +105,7 @@ where Hasher: crate::hash::StorageHasher, Key: FullCodec, QueryKind: QueryKindTrait, OnEmpty>, - OnEmpty: crate::traits::Get + 'static, + OnEmpty: Get + 'static, MaxValues: Get>, VecValue: FullCodec, VecBound: Get, From d1032a3f6988240910b410b7cf4876fd73400fe8 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 12 May 2021 21:16:43 -0400 Subject: [PATCH 03/45] sudo sanity check --- frame/sudo/src/lib.rs | 1 + frame/system/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index d840d45a7f430..7aa31bcca8da1 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -128,6 +128,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storages_info] pub struct Pallet(PhantomData); #[pallet::hooks] diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index c3fe688420097..47090059dae84 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -88,7 +88,7 @@ use frame_support::{ Parameter, storage, traits::{ SortedMembers, Get, PalletInfo, OnNewAccount, OnKilledAccount, HandleLifetime, - StoredMap, EnsureOrigin, OriginTrait, Filter, + StoredMap, EnsureOrigin, OriginTrait, Filter, MaxEncodedLen, }, weights::{ Weight, RuntimeDbWeight, DispatchInfo, DispatchClass, @@ -206,7 +206,7 @@ pub mod pallet { /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord - + Default; + + Default + MaxEncodedLen; /// Converting trait to take a source type and convert to `AccountId`. /// From f2582d5c4eed0336a3e906f2057674c3287f5848 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 12 May 2021 21:34:04 -0400 Subject: [PATCH 04/45] timestamp --- frame/support/src/lib.rs | 2 +- frame/timestamp/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index b62afbe27b3ea..f14ff808d574d 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1236,7 +1236,7 @@ pub mod pallet_prelude { RuntimeDebug, storage, traits::{ Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, StoragesInfo, - ConstU32, GetDefault, + ConstU32, GetDefault, MaxEncodedLen, }, dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult}, weights::{DispatchClass, Pays, Weight}, diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index dde635c6a8a30..1eb33acbd767a 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -116,7 +116,7 @@ pub mod pallet { pub trait Config: frame_system::Config { /// Type used for expressing timestamp. type Moment: Parameter + Default + AtLeast32Bit - + Scale + Copy; + + Scale + Copy + MaxEncodedLen; /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. type OnTimestampSet: OnTimestampSet; @@ -134,6 +134,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storages_info] pub struct Pallet(PhantomData); /// Current time for the current block. From bf354b0830c9fe35db56e22e5f75ab28c2ef9737 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 12 May 2021 23:15:14 -0400 Subject: [PATCH 05/45] assets (not working) --- frame/assets/src/lib.rs | 36 +++++++++++++-------- frame/assets/src/types.rs | 19 +++++------ frame/balances/src/lib.rs | 2 +- frame/support/src/traits/tokens/currency.rs | 4 +-- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 3a2b1a6ce21dd..59e6c698f576b 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -138,7 +138,7 @@ mod functions; mod types; pub use types::*; -use sp_std::{prelude::*, borrow::Borrow}; +use sp_std::{prelude::*, borrow::Borrow, convert::TryInto}; use sp_runtime::{ RuntimeDebug, TokenError, ArithmeticError, traits::{ AtLeast32BitUnsigned, Zero, StaticLookup, Saturating, CheckedSub, CheckedAdd, Bounded, @@ -147,7 +147,7 @@ use sp_runtime::{ }; use codec::{Encode, Decode, HasCompact}; use frame_support::{ensure, dispatch::{DispatchError, DispatchResult}}; -use frame_support::traits::{Currency, ReservableCurrency, BalanceStatus::Reserved, StoredMap}; +use frame_support::traits::{Currency, ReservableCurrency, BalanceStatus::Reserved, StoredMap, MaxEncodedLen}; use frame_support::traits::tokens::{WithdrawConsequence, DepositConsequence, fungibles}; use frame_system::Config as SystemConfig; @@ -165,6 +165,8 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storages_info] + //#[pallet::generate_storages_info] pub struct Pallet(_); #[pallet::config] @@ -174,10 +176,10 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// The units in which we record balances. - type Balance: Member + Parameter + AtLeast32BitUnsigned + Default + Copy; + type Balance: Member + Parameter + AtLeast32BitUnsigned + Default + Copy + MaxEncodedLen; /// Identifier for the class of asset. - type AssetId: Member + Parameter + Default + Copy + HasCompact; + type AssetId: Member + Parameter + Default + Copy + HasCompact + MaxEncodedLen; /// The currency mechanism. type Currency: ReservableCurrency; @@ -207,7 +209,7 @@ pub mod pallet { type Freezer: FrozenBalance; /// Additional data to be stored with an account's asset balance. - type Extra: Member + Parameter + Default; + type Extra: Member + Parameter + Default + MaxEncodedLen; /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; @@ -232,6 +234,8 @@ pub mod pallet { T::AccountId, AssetBalance, ValueQuery, + GetDefault, + ConstU32<300_000>, >; #[pallet::storage] @@ -245,6 +249,8 @@ pub mod pallet { ApprovalKey, Approval>, OptionQuery, + GetDefault, + ConstU32<300_000>, >; #[pallet::storage] @@ -253,8 +259,10 @@ pub mod pallet { _, Blake2_128Concat, T::AssetId, - AssetMetadata>, + AssetMetadata, BoundedVec>, ValueQuery, + GetDefault, + ConstU32<300_000>, >; #[pallet::event] @@ -900,8 +908,8 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - ensure!(name.len() <= T::StringLimit::get() as usize, Error::::BadMetadata); - ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::::BadMetadata); + let bounded_name: BoundedVec = name.clone().try_into().map_err(|_| Error::::BadMetadata)?; + let bounded_symbol: BoundedVec = symbol.clone().try_into().map_err(|_| Error::::BadMetadata)?; let d = Asset::::get(id).ok_or(Error::::Unknown)?; ensure!(&origin == &d.owner, Error::::NoPermission); @@ -925,8 +933,8 @@ pub mod pallet { *metadata = Some(AssetMetadata { deposit: new_deposit, - name: name.clone(), - symbol: symbol.clone(), + name: bounded_name, + symbol: bounded_symbol, decimals, is_frozen: false, }); @@ -990,16 +998,16 @@ pub mod pallet { ) -> DispatchResult { T::ForceOrigin::ensure_origin(origin)?; - ensure!(name.len() <= T::StringLimit::get() as usize, Error::::BadMetadata); - ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::::BadMetadata); + let bounded_name: BoundedVec = name.clone().try_into().map_err(|_| Error::::BadMetadata)?; + let bounded_symbol: BoundedVec = symbol.clone().try_into().map_err(|_| Error::::BadMetadata)?; ensure!(Asset::::contains_key(id), Error::::Unknown); Metadata::::try_mutate_exists(id, |metadata| { let deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit); *metadata = Some(AssetMetadata { deposit, - name: name.clone(), - symbol: symbol.clone(), + name: bounded_name, + symbol: bounded_symbol, decimals, is_frozen, }); diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index f3f17c00a218f..3a7f7bd6723d5 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -18,11 +18,12 @@ //! Various basic types for use in the assets pallet. use super::*; +use frame_support::pallet_prelude::*; pub(super) type DepositBalanceOf = <>::Currency as Currency<::AccountId>>::Balance; -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)] pub struct AssetDetails< Balance, AccountId, @@ -66,7 +67,7 @@ impl AssetDetails { /// The owner of the funds that are being approved. pub(super) owner: AccountId, @@ -75,7 +76,7 @@ pub struct ApprovalKey { } /// Data concerning an approval. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen)] pub struct Approval { /// The amount of funds approved for the balance transfer from the owner to some delegated /// target. @@ -84,7 +85,7 @@ pub struct Approval { pub(super) deposit: DepositBalance, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen)] pub struct AssetBalance { /// The balance. pub(super) balance: Balance, @@ -96,16 +97,16 @@ pub struct AssetBalance { pub(super) extra: Extra, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)] -pub struct AssetMetadata { +#[derive(Clone, Encode, Decode, Eq, PartialEq, Default, RuntimeDebug)] +pub struct AssetMetadata { /// The balance deposited for this metadata. /// /// This pays for the data stored in this struct. pub(super) deposit: DepositBalance, /// The user friendly name of this asset. Limited in length by `StringLimit`. - pub(super) name: Vec, + pub(super) name: BoundedString, /// The ticker symbol for this asset. Limited in length by `StringLimit`. - pub(super) symbol: Vec, + pub(super) symbol: BoundedString, /// The number of decimals this asset uses to represent one unit. pub(super) decimals: u8, /// Whether the asset metadata may be changed by a non Force origin. @@ -113,7 +114,7 @@ pub struct AssetMetadata { } /// Witness data for the destroy transactions. -#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)] pub struct DestroyWitness { /// The number of accounts holding the asset. #[codec(compact)] diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 0bfe43623c5da..38e29b8536b77 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -193,7 +193,7 @@ pub mod pallet { pub trait Config: frame_system::Config { /// The balance of an account. type Balance: Parameter + Member + AtLeast32BitUnsigned + Codec + Default + Copy + - MaybeSerializeDeserialize + Debug; + MaybeSerializeDeserialize + Debug + MaxEncodedLen; /// Handler for the unbalanced reduction when removing a dust account. type DustRemoval: OnUnbalanced>; diff --git a/frame/support/src/traits/tokens/currency.rs b/frame/support/src/traits/tokens/currency.rs index 567ca44aa78c7..a18e0b6593bc0 100644 --- a/frame/support/src/traits/tokens/currency.rs +++ b/frame/support/src/traits/tokens/currency.rs @@ -22,7 +22,7 @@ use sp_runtime::traits::MaybeSerializeDeserialize; use crate::dispatch::{DispatchResult, DispatchError}; use super::misc::{Balance, WithdrawReasons, ExistenceRequirement}; use super::imbalance::{Imbalance, SignedImbalance}; - +use frame_support::traits::MaxEncodedLen; mod reservable; pub use reservable::ReservableCurrency; @@ -32,7 +32,7 @@ pub use lockable::{LockableCurrency, VestingSchedule, LockIdentifier}; /// Abstraction over a fungible assets system. pub trait Currency { /// The balance of an account. - type Balance: Balance + MaybeSerializeDeserialize + Debug; + type Balance: Balance + MaybeSerializeDeserialize + Debug + MaxEncodedLen; /// The opaque token type for an imbalance. This is returned by unbalanced operations /// and must be dealt with. It may be dropped but cannot be cloned. From 38cecd6c7b994961fff3f5cb2189b112d399bac0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 13 May 2021 13:41:40 -0400 Subject: [PATCH 06/45] fix assets --- frame/assets/src/lib.rs | 7 ++++--- frame/assets/src/types.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 59e6c698f576b..e99c23c4f7c9e 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -140,14 +140,15 @@ pub use types::*; use sp_std::{prelude::*, borrow::Borrow, convert::TryInto}; use sp_runtime::{ - RuntimeDebug, TokenError, ArithmeticError, traits::{ + TokenError, ArithmeticError, + traits::{ AtLeast32BitUnsigned, Zero, StaticLookup, Saturating, CheckedSub, CheckedAdd, Bounded, StoredMapError, } }; -use codec::{Encode, Decode, HasCompact}; +use codec::HasCompact; use frame_support::{ensure, dispatch::{DispatchError, DispatchResult}}; -use frame_support::traits::{Currency, ReservableCurrency, BalanceStatus::Reserved, StoredMap, MaxEncodedLen}; +use frame_support::traits::{Currency, ReservableCurrency, BalanceStatus::Reserved, StoredMap}; use frame_support::traits::tokens::{WithdrawConsequence, DepositConsequence, fungibles}; use frame_system::Config as SystemConfig; diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index 3a7f7bd6723d5..2520db9c0ffa8 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -97,7 +97,7 @@ pub struct AssetBalance { pub(super) extra: Extra, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, Default, RuntimeDebug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen)] pub struct AssetMetadata { /// The balance deposited for this metadata. /// From 06b872af2f7c16a769442642693d5e8074145412 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 13 May 2021 21:41:18 -0400 Subject: [PATCH 07/45] impl for proxy --- frame/proxy/src/lib.rs | 76 +++++++++------------ frame/proxy/src/tests.rs | 35 ++++++---- frame/support/src/traits/max_encoded_len.rs | 3 +- frame/system/src/lib.rs | 5 +- 4 files changed, 56 insertions(+), 63 deletions(-) diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 5e63e0cd8d3d9..441faa9729d9c 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -33,7 +33,7 @@ mod tests; mod benchmarking; pub mod weights; -use sp_std::prelude::*; +use sp_std::{prelude::*, convert::TryInto}; use codec::{Encode, Decode}; use sp_io::hashing::blake2_256; use sp_runtime::{ @@ -43,8 +43,8 @@ use sp_runtime::{ use frame_support::{ RuntimeDebug, ensure, dispatch::{DispatchResultWithPostInfo, PostDispatchInfo}, - traits::{Get, ReservableCurrency, Currency, InstanceFilter, OriginTrait, IsType, IsSubType}, - weights::{Weight, GetDispatchInfo} + traits::{Get, ReservableCurrency, Currency, InstanceFilter, OriginTrait, IsType, IsSubType, MaxEncodedLen}, + weights::GetDispatchInfo, }; use frame_system::{self as system}; use frame_support::dispatch::DispatchError; @@ -58,7 +58,7 @@ type BalanceOf = <::Currency as Currency< { /// The account which may act on behalf of another. delegate: AccountId, @@ -70,7 +70,7 @@ pub struct ProxyDefinition { } /// Details surrounding a specific instance of an announcement to make a call. -#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)] pub struct Announcement { /// The account which made the announcement. real: AccountId, @@ -88,6 +88,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storages_info] pub struct Pallet(_); /// Configuration trait. @@ -109,7 +110,7 @@ pub mod pallet { /// /// IMPORTANT: `Default` must be provided and MUST BE the the *most permissive* value. type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<::Call> - + Default; + + Default + MaxEncodedLen; /// The base amount of currency needed to reserve for creating a proxy. /// @@ -128,7 +129,7 @@ pub mod pallet { /// The maximum amount of proxies allowed for a single account. #[pallet::constant] - type MaxProxies: Get; + type MaxProxies: Get; /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; @@ -296,14 +297,18 @@ pub mod pallet { let anonymous = Self::anonymous_account(&who, &proxy_type, index, None); ensure!(!Proxies::::contains_key(&anonymous), Error::::Duplicate); - let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get(); - T::Currency::reserve(&who, deposit)?; + let proxy_def = ProxyDefinition { delegate: who.clone(), proxy_type: proxy_type.clone(), delay, }; - Proxies::::insert(&anonymous, (vec![proxy_def], deposit)); + let bounded_proxies: BoundedVec<_, T::MaxProxies> = vec![proxy_def].try_into().map_err(|_| Error::::TooMany)?; + + let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get(); + T::Currency::reserve(&who, deposit)?; + + Proxies::::insert(&anonymous, (bounded_proxies, deposit)); Self::deposit_event(Event::AnonymousCreated(anonymous, who, proxy_type, index)); Ok(().into()) @@ -389,8 +394,7 @@ pub mod pallet { }; Announcements::::try_mutate(&who, |(ref mut pending, ref mut deposit)| { - ensure!(pending.len() < T::MaxPending::get() as usize, Error::::TooMany); - pending.push(announcement); + pending.try_push(announcement).map_err(|_| Error::::TooMany)?; Self::rejig_deposit( &who, *deposit, @@ -558,7 +562,13 @@ pub mod pallet { _, Twox64Concat, T::AccountId, - (Vec>, BalanceOf), + ( + BoundedVec< + ProxyDefinition, + T::MaxProxies, + >, + BalanceOf + ), ValueQuery >; @@ -569,7 +579,13 @@ pub mod pallet { _, Twox64Concat, T::AccountId, - (Vec, T::BlockNumber>>, BalanceOf), + ( + BoundedVec< + Announcement, T::BlockNumber>, + T::MaxPending, + >, + BalanceOf, + ), ValueQuery >; @@ -619,10 +635,9 @@ impl Pallet { ) -> DispatchResultWithPostInfo { ensure!(delegator != &delegatee, Error::::NoSelfProxy); Proxies::::try_mutate(delegator, |(ref mut proxies, ref mut deposit)| { - ensure!(proxies.len() < T::MaxProxies::get() as usize, Error::::TooMany); let proxy_def = ProxyDefinition { delegate: delegatee, proxy_type, delay }; let i = proxies.binary_search(&proxy_def).err().ok_or(Error::::Duplicate)?; - proxies.insert(i, proxy_def); + proxies.try_insert(i, proxy_def).map_err(|_| Error::::TooMany)?; let new_deposit = Self::deposit(proxies.len() as u32); if new_deposit > *deposit { T::Currency::reserve(delegator, new_deposit - *deposit)?; @@ -752,32 +767,3 @@ impl Pallet { Self::deposit_event(Event::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error))); } } - -/// Migration utilities for upgrading the Proxy pallet between its different versions. -pub mod migration { - use super::*; - - /// Migration code for - /// - /// Details: This migration was introduced between Substrate 2.0-RC6 and Substrate 2.0 releases. - /// Before this migration, the `Proxies` storage item used a tuple of `AccountId` and - /// `ProxyType` to represent the proxy definition. After #6770, we switched to use a struct - /// `ProxyDefinition` which additionally included a `BlockNumber` delay value. This function, - /// simply takes any existing proxies using the old tuple format, and migrates it to the new - /// struct by setting the delay to zero. - pub fn migrate_to_time_delayed_proxies() -> Weight { - Proxies::::translate::<(Vec<(T::AccountId, T::ProxyType)>, BalanceOf), _>( - |_, (targets, deposit)| Some(( - targets.into_iter() - .map(|(a, t)| ProxyDefinition { - delegate: a, - proxy_type: t, - delay: Zero::zero(), - }) - .collect::>(), - deposit, - )) - ); - T::BlockWeights::get().max_block - } -} diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 6f3b1f35e2ada..02b25b0a9d998 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -188,15 +188,17 @@ fn announcement_works() { assert_eq!(Balances::reserved_balance(3), 0); assert_ok!(Proxy::announce(Origin::signed(3), 1, [1; 32].into())); - assert_eq!(Announcements::::get(3), (vec![Announcement { + let announcements = Announcements::::get(3); + assert_eq!(announcements.0, vec![Announcement { real: 1, call_hash: [1; 32].into(), height: 1, - }], 2)); - assert_eq!(Balances::reserved_balance(3), 2); + }]); + assert_eq!(Balances::reserved_balance(3), announcements.1); assert_ok!(Proxy::announce(Origin::signed(3), 2, [2; 32].into())); - assert_eq!(Announcements::::get(3), (vec![ + let announcements = Announcements::::get(3); + assert_eq!(announcements.0, vec![ Announcement { real: 1, call_hash: [1; 32].into(), @@ -207,8 +209,8 @@ fn announcement_works() { call_hash: [2; 32].into(), height: 1, }, - ], 3)); - assert_eq!(Balances::reserved_balance(3), 3); + ]); + assert_eq!(Balances::reserved_balance(3), announcements.1); assert_noop!(Proxy::announce(Origin::signed(3), 2, [3; 32].into()), Error::::TooMany); }); @@ -224,12 +226,13 @@ fn remove_announcement_works() { let e = Error::::NotFound; assert_noop!(Proxy::remove_announcement(Origin::signed(3), 1, [0; 32].into()), e); assert_ok!(Proxy::remove_announcement(Origin::signed(3), 1, [1; 32].into())); - assert_eq!(Announcements::::get(3), (vec![Announcement { + let announcements = Announcements::::get(3); + assert_eq!(announcements.0, vec![Announcement { real: 2, call_hash: [2; 32].into(), height: 1, - }], 2)); - assert_eq!(Balances::reserved_balance(3), 2); + }]); + assert_eq!(Balances::reserved_balance(3), announcements.1); }); } @@ -245,12 +248,13 @@ fn reject_announcement_works() { let e = Error::::NotFound; assert_noop!(Proxy::reject_announcement(Origin::signed(4), 3, [1; 32].into()), e); assert_ok!(Proxy::reject_announcement(Origin::signed(1), 3, [1; 32].into())); - assert_eq!(Announcements::::get(3), (vec![Announcement { + let announcements = Announcements::::get(3); + assert_eq!(announcements.0, vec![Announcement { real: 2, call_hash: [2; 32].into(), height: 1, - }], 2)); - assert_eq!(Balances::reserved_balance(3), 2); + }]); + assert_eq!(Balances::reserved_balance(3), announcements.1); }); } @@ -292,12 +296,13 @@ fn proxy_announced_removes_announcement_and_returns_deposit() { system::Pallet::::set_block_number(2); assert_ok!(Proxy::proxy_announced(Origin::signed(0), 3, 1, None, call.clone())); - assert_eq!(Announcements::::get(3), (vec![Announcement { + let announcements = Announcements::::get(3); + assert_eq!(announcements.0, vec![Announcement { real: 2, call_hash, height: 1, - }], 2)); - assert_eq!(Balances::reserved_balance(3), 2); + }]); + assert_eq!(Balances::reserved_balance(3), announcements.1); }); } diff --git a/frame/support/src/traits/max_encoded_len.rs b/frame/support/src/traits/max_encoded_len.rs index 2cf9007d4d621..2f206ddcbe11d 100644 --- a/frame/support/src/traits/max_encoded_len.rs +++ b/frame/support/src/traits/max_encoded_len.rs @@ -18,6 +18,7 @@ use codec::{Compact, Encode}; use impl_trait_for_tuples::impl_for_tuples; use sp_std::{mem, marker::PhantomData}; +use sp_core::{H160, H256, H512}; /// Items implementing `MaxEncodedLen` have a statically known maximum encoded size. /// @@ -42,7 +43,7 @@ macro_rules! impl_primitives { }; } -impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool); +impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool, H160, H256, H512); macro_rules! impl_compact { ($( $t:ty => $e:expr; )*) => { diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 47090059dae84..770f9bc2a8426 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -194,12 +194,13 @@ pub mod pallet { type BlockNumber: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + AtLeast32BitUnsigned + Default + Bounded + Copy + sp_std::hash::Hash + - sp_std::str::FromStr + MaybeMallocSizeOf; + sp_std::str::FromStr + MaybeMallocSizeOf + MaxEncodedLen; /// The output of the `Hashing` function. type Hash: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps + Ord - + Default + Copy + CheckEqual + sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + MaybeMallocSizeOf; + + Default + Copy + CheckEqual + sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + MaybeMallocSizeOf + + MaxEncodedLen; /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). type Hashing: Hash; From 43edcacdd20876cc4871529b46591d7df5368352 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 13 May 2021 22:08:27 -0400 Subject: [PATCH 08/45] update balances --- frame/balances/src/lib.rs | 107 +++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 38e29b8536b77..d85d4596184cc 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -159,9 +159,9 @@ use sp_std::prelude::*; use sp_std::{cmp, result, mem, fmt::Debug, ops::BitOr}; use codec::{Codec, Encode, Decode}; use frame_support::{ - ensure, + ensure, BoundedVec, traits::{ - Currency, OnUnbalanced, TryDrop, StoredMap, + Currency, OnUnbalanced, TryDrop, StoredMap, MaxEncodedLen, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, Imbalance, SignedImbalance, ReservableCurrency, Get, ExistenceRequirement::KeepAlive, ExistenceRequirement::AllowDeath, @@ -218,6 +218,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storages_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] @@ -428,7 +429,9 @@ pub mod pallet { Blake2_128Concat, T::AccountId, AccountData, - ValueQuery + ValueQuery, + GetDefault, + ConstU32<300_000>, >; /// Any liquidity locks on some account balances. @@ -439,8 +442,10 @@ pub mod pallet { _, Blake2_128Concat, T::AccountId, - Vec>, - ValueQuery + BoundedVec, T::MaxLocks>, + ValueQuery, + GetDefault, + ConstU32<300_000>, >; /// Storage version of the pallet. @@ -517,7 +522,7 @@ impl, I: 'static> GenesisConfig { } /// Simplified reasons for withdrawing balance. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)] pub enum Reasons { /// Paying system transaction fees. Fee = 0, @@ -549,7 +554,7 @@ impl BitOr for Reasons { /// A single lock on a balance. There can be many of these on an account and they "overlap", so the /// same balance is frozen by multiple locks. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)] pub struct BalanceLock { /// An identifier for this lock. Only one lock may be in existence for each identifier. pub id: LockIdentifier, @@ -560,7 +565,7 @@ pub struct BalanceLock { } /// All balance information for an account. -#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen)] pub struct AccountData { /// Non-reserved part of the balance. There may still be restrictions on this, but it is the /// total pool what may in principle be transferred, reserved and used for tipping. @@ -606,7 +611,7 @@ impl AccountData { // A value placed in storage that represents the current version of the Balances storage. // This value is used by the `on_runtime_upgrade` logic to determine whether we run // storage migration logic. This should match directly with the semantic versions of the Rust crate. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)] enum Releases { V1_0_0, V2_0_0, @@ -826,48 +831,52 @@ impl, I: 'static> Pallet { /// Update the account entry for `who`, given the locks. fn update_locks(who: &T::AccountId, locks: &[BalanceLock]) { - if locks.len() as u32 > T::MaxLocks::get() { - log::warn!( - target: "runtime::balances", - "Warning: A user has more currency locks than expected. \ - A runtime configuration adjustment may be needed." - ); - } - // No way this can fail since we do not alter the existential balances. - let res = Self::mutate_account(who, |b| { - b.misc_frozen = Zero::zero(); - b.fee_frozen = Zero::zero(); - for l in locks.iter() { - if l.reasons == Reasons::All || l.reasons == Reasons::Misc { - b.misc_frozen = b.misc_frozen.max(l.amount); + unsafe { + let bounded_locks = BoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")); + + if locks.len() as u32 > T::MaxLocks::get() { + log::warn!( + target: "runtime::balances", + "Warning: A user has more currency locks than expected. \ + A runtime configuration adjustment may be needed." + ); + } + // No way this can fail since we do not alter the existential balances. + let res = Self::mutate_account(who, |b| { + b.misc_frozen = Zero::zero(); + b.fee_frozen = Zero::zero(); + for l in locks.iter() { + if l.reasons == Reasons::All || l.reasons == Reasons::Misc { + b.misc_frozen = b.misc_frozen.max(l.amount); + } + if l.reasons == Reasons::All || l.reasons == Reasons::Fee { + b.fee_frozen = b.fee_frozen.max(l.amount); + } } - if l.reasons == Reasons::All || l.reasons == Reasons::Fee { - b.fee_frozen = b.fee_frozen.max(l.amount); + }); + debug_assert!(res.is_ok()); + + let existed = Locks::::contains_key(who); + if locks.is_empty() { + Locks::::remove(who); + if existed { + // TODO: use Locks::::hashed_key + // https://github.com/paritytech/substrate/issues/4969 + system::Pallet::::dec_consumers(who); } - } - }); - debug_assert!(res.is_ok()); - - let existed = Locks::::contains_key(who); - if locks.is_empty() { - Locks::::remove(who); - if existed { - // TODO: use Locks::::hashed_key - // https://github.com/paritytech/substrate/issues/4969 - system::Pallet::::dec_consumers(who); - } - } else { - Locks::::insert(who, locks); - if !existed { - if system::Pallet::::inc_consumers(who).is_err() { - // No providers for the locks. This is impossible under normal circumstances - // since the funds that are under the lock will themselves be stored in the - // account and therefore will need a reference. - log::warn!( - target: "runtime::balances", - "Warning: Attempt to introduce lock consumer reference, yet no providers. \ - This is unexpected but should be safe." - ); + } else { + Locks::::insert(who, bounded_locks); + if !existed { + if system::Pallet::::inc_consumers(who).is_err() { + // No providers for the locks. This is impossible under normal circumstances + // since the funds that are under the lock will themselves be stored in the + // account and therefore will need a reference. + log::warn!( + target: "runtime::balances", + "Warning: Attempt to introduce lock consumer reference, yet no providers. \ + This is unexpected but should be safe." + ); + } } } } From ada719bc31e69ba51296116dd67ef91d11672332 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 14 May 2021 13:31:19 +0200 Subject: [PATCH 09/45] rename StoragesInfo -> PalletStorageInfo --- frame/support/procedural/src/lib.rs | 2 +- .../src/pallet/expand/pallet_struct.rs | 12 ++++----- .../src/pallet/parse/pallet_struct.rs | 26 +++++++++---------- frame/support/procedural/src/storage/mod.rs | 6 ++--- .../{storages_info.rs => storage_info.rs} | 8 +++--- frame/support/src/lib.rs | 6 ++--- frame/support/src/traits.rs | 2 +- frame/support/src/traits/storage.rs | 10 +++---- frame/support/test/tests/decl_storage.rs | 6 ++--- frame/support/test/tests/pallet.rs | 8 +++--- .../pallet_ui/storage_info_unsatisfied.rs | 2 +- .../pallet_ui/storage_info_unsatisfied.stderr | 6 ++--- .../storage_info_unsatisfied_nmap.rs | 2 +- .../storage_info_unsatisfied_nmap.stderr | 6 ++--- 14 files changed, 51 insertions(+), 51 deletions(-) rename frame/support/procedural/src/storage/{storages_info.rs => storage_info.rs} (81%) diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 5146b8e78380e..27395d9660dc8 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -157,7 +157,7 @@ use proc_macro::TokenStream; /// Will include the item in `GenesisConfig`. /// * \[optional\] `build(#closure)`: Closure called with storage overlays. /// * \[optional\] `max_values(#expr)`: `expr` is an expression returning a `u32`. It is used to -/// implement `StoragesInfo`. Note this attribute is not available for storage value as the maximum +/// implement `PalletStorageInfo`. Note this attribute is not available for storage value as the maximum /// number of values is 1. /// * `#type`: Storage type. /// * \[optional\] `#default`: Value returned when none. diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index cf0523a2899d5..48cdd8cef59de 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -24,7 +24,7 @@ use crate::pallet::{Def, expand::merge_where_clauses, parse::helper::get_doc_lit /// * declare Module type alias for construct_runtime /// * replace the first field type of `struct Pallet` with `PhantomData` if it is `_` /// * implementation of `PalletInfoAccess` information -/// * implementation of `StoragesInfo` on Pallet +/// * implementation of `PalletStorageInfo` on Pallet pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { let frame_support = &def.frame_support; let frame_system = &def.frame_system; @@ -102,18 +102,18 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { ) }; - let storages_info = if let Some(storages_info_span) = def.pallet_struct.generate_storages_info { + 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::>(); let storage_cfg_attrs = &def.storages.iter() .map(|storage| &storage.cfg_attrs) .collect::>(); - quote::quote_spanned!(storages_info_span => - impl<#type_impl_gen> #frame_support::traits::StoragesInfo + quote::quote_spanned!(storage_info_span => + impl<#type_impl_gen> #frame_support::traits::PalletStorageInfo for #pallet_ident<#type_use_gen> #storages_where_clauses { - fn storages_info() + fn storage_info() -> #frame_support::sp_std::vec::Vec<#frame_support::traits::StorageInfo> { #frame_support::sp_std::vec![ @@ -195,6 +195,6 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { } } - #storages_info + #storage_info ) } diff --git a/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/frame/support/procedural/src/pallet/parse/pallet_struct.rs index 3aeb70d201105..b76b10437466f 100644 --- a/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -24,7 +24,7 @@ mod keyword { syn::custom_keyword!(pallet); syn::custom_keyword!(Pallet); syn::custom_keyword!(generate_store); - syn::custom_keyword!(generate_storages_info); + syn::custom_keyword!(generate_storage_info); syn::custom_keyword!(Store); } @@ -40,28 +40,28 @@ pub struct PalletStructDef { pub store: Option<(syn::Visibility, keyword::Store)>, /// The span of the pallet::pallet attribute. pub attr_span: proc_macro2::Span, - /// Whether to specify the storages max encoded len when implementing `StoragesInfo`. + /// Whether to specify the storages max encoded len when implementing `PalletStorageInfo`. /// Contains the span of the attribute. - pub generate_storages_info: Option, + pub generate_storage_info: Option, } /// Parse for one variant of: /// * `#[pallet::generate_store($vis trait Store)]` -/// * `#[pallet::generate_storages_info]` +/// * `#[pallet::generate_storage_info]` pub enum PalletStructAttr { GenerateStore { span: proc_macro2::Span, vis: syn::Visibility, keyword: keyword::Store, }, - GenerateStoragesInfo(proc_macro2::Span), + GeneratePalletStorageInfo(proc_macro2::Span), } impl PalletStructAttr { fn span(&self) -> proc_macro2::Span { match self { Self::GenerateStore { span, .. } => *span, - Self::GenerateStoragesInfo(span) => *span, + Self::GeneratePalletStorageInfo(span) => *span, } } } @@ -84,9 +84,9 @@ impl syn::parse::Parse for PalletStructAttr { generate_content.parse::()?; let keyword = generate_content.parse::()?; Ok(Self::GenerateStore { vis, keyword, span }) - } else if lookahead.peek(keyword::generate_storages_info) { - let span = content.parse::()?.span(); - Ok(Self::GenerateStoragesInfo(span)) + } else if lookahead.peek(keyword::generate_storage_info) { + let span = content.parse::()?.span(); + Ok(Self::GeneratePalletStorageInfo(span)) } else { Err(lookahead.error()) } @@ -107,7 +107,7 @@ impl PalletStructDef { }; let mut store = None; - let mut generate_storages_info = None; + let mut generate_storage_info = None; let struct_attrs: Vec = helper::take_item_pallet_attrs(&mut item.attrs)?; for attr in struct_attrs { @@ -115,8 +115,8 @@ impl PalletStructDef { PalletStructAttr::GenerateStore { vis, keyword, .. } if store.is_none() => { store = Some((vis, keyword)); }, - PalletStructAttr::GenerateStoragesInfo(span) if generate_storages_info.is_none() => { - generate_storages_info = Some(span); + PalletStructAttr::GeneratePalletStorageInfo(span) if generate_storage_info.is_none() => { + generate_storage_info = Some(span); }, attr => { let msg = "Unexpected duplicated attribute"; @@ -140,6 +140,6 @@ impl PalletStructDef { let mut instances = vec![]; instances.push(helper::check_type_def_gen_no_bounds(&item.generics, item.ident.span())?); - Ok(Self { index, instances, pallet, store, attr_span, generate_storages_info }) + Ok(Self { index, instances, pallet, store, attr_span, generate_storage_info }) } } diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs index 1af0151f349cf..3a1915e43144d 100644 --- a/frame/support/procedural/src/storage/mod.rs +++ b/frame/support/procedural/src/storage/mod.rs @@ -18,7 +18,7 @@ //! `decl_storage` input definition and expansion. mod storage_struct; -mod storages_info; +mod storage_info; mod parse; mod store_trait; mod getters; @@ -480,7 +480,7 @@ pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStr let instance_trait = instance_trait::decl_and_impl(&def_ext); let genesis_config = genesis_config::genesis_config_and_build_storage(&def_ext); let storage_struct = storage_struct::decl_and_impl(&def_ext); - let storages_info = storages_info::impl_storages_info(&def_ext); + let storage_info = storage_info::impl_storage_info(&def_ext); quote!( use #scrate::{ @@ -501,6 +501,6 @@ pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStr #instance_trait #genesis_config #storage_struct - #storages_info + #storage_info ).into() } diff --git a/frame/support/procedural/src/storage/storages_info.rs b/frame/support/procedural/src/storage/storage_info.rs similarity index 81% rename from frame/support/procedural/src/storage/storages_info.rs rename to frame/support/procedural/src/storage/storage_info.rs index d6f79c5405ad5..2e59a96f146f2 100644 --- a/frame/support/procedural/src/storage/storages_info.rs +++ b/frame/support/procedural/src/storage/storage_info.rs @@ -15,13 +15,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Implementation of trait `StoragesInfo` on module structure. +//! Implementation of trait `PalletStorageInfo` on module structure. use proc_macro2::TokenStream; use quote::quote; use super::DeclStorageDefExt; -pub fn impl_storages_info(def: &DeclStorageDefExt) -> TokenStream { +pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream { if !def.generate_storage_info { return Default::default() } @@ -46,8 +46,8 @@ pub fn impl_storages_info(def: &DeclStorageDefExt) -> TokenStream { let where_clause = &def.where_clause; quote!( - impl#module_impl #scrate::traits::StoragesInfo for #module_struct #where_clause { - fn storages_info() -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { + impl#module_impl #scrate::traits::PalletStorageInfo for #module_struct #where_clause { + fn storage_info() -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { #scrate::sp_std::vec![ #entries ] diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 0d6257ac6295c..72ff840bf8a10 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1235,7 +1235,7 @@ pub mod pallet_prelude { Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, ensure, RuntimeDebug, storage, traits::{ - Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, StoragesInfo, + Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, PalletStorageInfo, ConstU32, GetDefault, }, dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult}, @@ -1384,13 +1384,13 @@ pub mod pallet_prelude { /// given by [`frame_support::traits::PalletInfo`]. /// (The implementation use the associated type `frame_system::Config::PalletInfo`). /// -/// It implements [`traits::StoragesInfo`] on `Pallet` which give information about all storages. +/// It implements [`traits::PalletStorageInfo`] on `Pallet` which give information about all storages. /// /// If the attribute generate_store is set then the macro creates the trait `Store` and implements /// it on `Pallet`. /// /// If the attribute set_storage_max_encoded_len is set then the macro call -/// [`traits::StorageMaxEncodedLen`] in the implementation of [`StoragesInfo`]. +/// [`traits::StorageMaxEncodedLen`] in the implementation of [`PalletStorageInfo`]. /// /// # Hooks: `#[pallet::hooks]` mandatory /// diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index cfac84aea865e..5b0a80df0ed28 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -73,7 +73,7 @@ pub use hooks::GenesisBuild; pub mod schedule; mod storage; -pub use storage::{Instance, StorageInstance, StoragesInfo, StorageInfo, StorageInfoTrait}; +pub use storage::{Instance, StorageInstance, PalletStorageInfo, StorageInfo, StorageInfoTrait}; mod dispatch; pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable}; diff --git a/frame/support/src/traits/storage.rs b/frame/support/src/traits/storage.rs index 205d20cd3c829..ab6fe96f1eeba 100644 --- a/frame/support/src/traits/storage.rs +++ b/frame/support/src/traits/storage.rs @@ -62,15 +62,15 @@ pub struct StorageInfo { /// A trait to give information about storages. /// /// It can be used to calculate PoV worst case size. -pub trait StoragesInfo { - fn storages_info() -> Vec; +pub trait PalletStorageInfo { + fn storage_info() -> Vec; } #[impl_trait_for_tuples::impl_for_tuples(30)] -impl StoragesInfo for Tuple { - fn storages_info() -> Vec { +impl PalletStorageInfo for Tuple { + fn storage_info() -> Vec { let mut res = vec![]; - for_tuples!( #( res.extend_from_slice(&Tuple::storages_info()); )* ); + for_tuples!( #( res.extend_from_slice(&Tuple::storage_info()); )* ); res } } diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index 2e797731e14ff..27813a76feec3 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -394,10 +394,10 @@ mod tests { }; #[test] - fn storages_info() { + fn storage_info() { use frame_support::{ StorageHasher, - traits::{StoragesInfo, StorageInfo}, + traits::{PalletStorageInfo, StorageInfo}, pallet_prelude::*, }; let prefix = |pallet_name, storage_name| { @@ -407,7 +407,7 @@ mod tests { res }; pretty_assertions::assert_eq!( - >::storages_info(), + >::storage_info(), vec![ StorageInfo { prefix: prefix(b"TestStorage", b"U32"), diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 4bb00d9f64087..114b975f8b502 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -101,7 +101,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::hooks] @@ -976,10 +976,10 @@ fn test_pallet_info_access() { } #[test] -fn test_storages_info() { +fn test_storage_info() { use frame_support::{ StorageHasher, - traits::{StoragesInfo, StorageInfo}, + traits::{PalletStorageInfo, StorageInfo}, pallet_prelude::*, }; @@ -991,7 +991,7 @@ fn test_storages_info() { }; assert_eq!( - Example::storages_info(), + Example::storage_info(), vec![ StorageInfo { prefix: prefix(b"Example", b"ValueWhereClause"), diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs index 22b3658329b97..569e59ef6ec27 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs @@ -7,7 +7,7 @@ mod pallet { pub trait Config: frame_system::Config {} #[pallet::pallet] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(core::marker::PhantomData); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr index a0ecd4f6555c9..b263bdf52b2d5 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied --> $DIR/storage_info_unsatisfied.rs:10:12 | -10 | #[pallet::generate_storages_info] - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` +10 | #[pallet::generate_storage_info] + | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` - = note: required by `storage_info` + = note: required by `frame_support::traits::StorageInfoTrait::storage_info` diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs index 8afe3162c0c71..3d03099c3c4b6 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs @@ -7,7 +7,7 @@ mod pallet { pub trait Config: frame_system::Config {} #[pallet::pallet] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(core::marker::PhantomData); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 1079036f2aaa0..8ffa8eb1756a7 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -1,9 +1,9 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied --> $DIR/storage_info_unsatisfied_nmap.rs:10:12 | -10 | #[pallet::generate_storages_info] - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` +10 | #[pallet::generate_storage_info] + | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | = note: required because of the requirements on the impl of `types::key::KeyGeneratorMaxEncodedLen` for `NMapKey` = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, NMapKey, u32>` - = note: required by `storage_info` + = note: required by `frame_support::traits::StorageInfoTrait::storage_info` From 341d3f578a4d5656ed0b7ae3348cc5baf7ab1f9d Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 14 May 2021 14:02:15 +0200 Subject: [PATCH 10/45] merge both StorageInfoTrait and PalletStorageInfo I think it is more future proof. In the future some storage could make use of multiple prefix. Like one to store how much value has been inserted, etc... --- frame/support/procedural/src/lib.rs | 2 +- .../src/pallet/expand/pallet_struct.rs | 29 +++--- .../src/pallet/parse/pallet_struct.rs | 10 +-- .../procedural/src/storage/storage_info.rs | 22 ++--- .../procedural/src/storage/storage_struct.rs | 90 +++++++++++-------- frame/support/src/lib.rs | 9 +- frame/support/src/storage/types/double_map.rs | 26 +++--- frame/support/src/storage/types/map.rs | 22 ++--- frame/support/src/storage/types/nmap.rs | 22 ++--- frame/support/src/storage/types/value.rs | 21 +++-- frame/support/src/traits.rs | 2 +- frame/support/src/traits/storage.rs | 13 +-- frame/support/test/tests/decl_storage.rs | 2 +- frame/support/test/tests/pallet.rs | 2 +- 14 files changed, 150 insertions(+), 122 deletions(-) diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 27395d9660dc8..6b163ed5d79e3 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -157,7 +157,7 @@ use proc_macro::TokenStream; /// Will include the item in `GenesisConfig`. /// * \[optional\] `build(#closure)`: Closure called with storage overlays. /// * \[optional\] `max_values(#expr)`: `expr` is an expression returning a `u32`. It is used to -/// implement `PalletStorageInfo`. Note this attribute is not available for storage value as the maximum +/// implement `StorageInfoTrait`. Note this attribute is not available for storage value as the maximum /// number of values is 1. /// * `#type`: Storage type. /// * \[optional\] `#default`: Value returned when none. diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 48cdd8cef59de..b655227cfc10d 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -24,7 +24,7 @@ use crate::pallet::{Def, expand::merge_where_clauses, parse::helper::get_doc_lit /// * declare Module type alias for construct_runtime /// * replace the first field type of `struct Pallet` with `PhantomData` if it is `_` /// * implementation of `PalletInfoAccess` information -/// * implementation of `PalletStorageInfo` on Pallet +/// * implementation of `StorageInfoTrait` on Pallet pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { let frame_support = &def.frame_support; let frame_system = &def.frame_system; @@ -109,24 +109,27 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { .collect::>(); quote::quote_spanned!(storage_info_span => - impl<#type_impl_gen> #frame_support::traits::PalletStorageInfo + 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> { - #frame_support::sp_std::vec![ - #( - #(#storage_cfg_attrs)* - { - < - #storage_names<#type_use_gen> - as #frame_support::traits::StorageInfoTrait - >::storage_info() - }, - )* - ] + 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 } } ) diff --git a/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/frame/support/procedural/src/pallet/parse/pallet_struct.rs index b76b10437466f..ba85da2d9e684 100644 --- a/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -40,7 +40,7 @@ pub struct PalletStructDef { pub store: Option<(syn::Visibility, keyword::Store)>, /// The span of the pallet::pallet attribute. pub attr_span: proc_macro2::Span, - /// Whether to specify the storages max encoded len when implementing `PalletStorageInfo`. + /// Whether to specify the storages max encoded len when implementing `StorageInfoTrait`. /// Contains the span of the attribute. pub generate_storage_info: Option, } @@ -54,14 +54,14 @@ pub enum PalletStructAttr { vis: syn::Visibility, keyword: keyword::Store, }, - GeneratePalletStorageInfo(proc_macro2::Span), + GenerateStorageInfoTrait(proc_macro2::Span), } impl PalletStructAttr { fn span(&self) -> proc_macro2::Span { match self { Self::GenerateStore { span, .. } => *span, - Self::GeneratePalletStorageInfo(span) => *span, + Self::GenerateStorageInfoTrait(span) => *span, } } } @@ -86,7 +86,7 @@ impl syn::parse::Parse for PalletStructAttr { Ok(Self::GenerateStore { vis, keyword, span }) } else if lookahead.peek(keyword::generate_storage_info) { let span = content.parse::()?.span(); - Ok(Self::GeneratePalletStorageInfo(span)) + Ok(Self::GenerateStorageInfoTrait(span)) } else { Err(lookahead.error()) } @@ -115,7 +115,7 @@ impl PalletStructDef { PalletStructAttr::GenerateStore { vis, keyword, .. } if store.is_none() => { store = Some((vis, keyword)); }, - PalletStructAttr::GeneratePalletStorageInfo(span) if generate_storage_info.is_none() => { + PalletStructAttr::GenerateStorageInfoTrait(span) if generate_storage_info.is_none() => { generate_storage_info = Some(span); }, attr => { diff --git a/frame/support/procedural/src/storage/storage_info.rs b/frame/support/procedural/src/storage/storage_info.rs index 2e59a96f146f2..ed07ccbfc71d6 100644 --- a/frame/support/procedural/src/storage/storage_info.rs +++ b/frame/support/procedural/src/storage/storage_info.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Implementation of trait `PalletStorageInfo` on module structure. +//! Implementation of trait `StorageInfoTrait` on module structure. use proc_macro2::TokenStream; use quote::quote; @@ -28,17 +28,17 @@ pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream { let scrate = &def.hidden_crate; - let mut entries = TokenStream::new(); + let mut res_append_storage = TokenStream::new(); for line in def.storage_lines.iter() { let storage_struct = &line.storage_struct; - let entry = quote!( - < + res_append_storage.extend(quote!( + let mut storage_info = < #storage_struct as #scrate::traits::StorageInfoTrait - >::storage_info(), - ); - entries.extend(entry); + >::storage_info(); + res.append(&mut storage_info); + )); } let module_struct = &def.module_struct; @@ -46,11 +46,11 @@ pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream { let where_clause = &def.where_clause; quote!( - impl#module_impl #scrate::traits::PalletStorageInfo for #module_struct #where_clause { + impl#module_impl #scrate::traits::StorageInfoTrait for #module_struct #where_clause { fn storage_info() -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { - #scrate::sp_std::vec![ - #entries - ] + let mut res = #scrate::sp_std::vec![]; + #res_append_storage + res } } ) diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index cec794913bcd3..cad92dc9ee44f 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -261,20 +261,25 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct #optional_storage_where_clause { - fn storage_info() -> #scrate::traits::StorageInfo { + fn storage_info() + -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> + { use #scrate::sp_runtime::SaturatedConversion; let max_size = < #value_type as #scrate::traits::MaxEncodedLen >::max_encoded_len() .saturated_into(); - #scrate::traits::StorageInfo { - prefix: < - #storage_struct as #scrate::#storage_generator_trait - >::storage_value_final_key(), - max_values: Some(1), - max_size: Some(max_size), - } + + #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: Some(max_size), + } + ] } } ) @@ -285,7 +290,9 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct #optional_storage_where_clause { - fn storage_info() -> #scrate::traits::StorageInfo { + fn storage_info() + -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> + { use #scrate::sp_runtime::SaturatedConversion; let max_size = < #value_type as #scrate::traits::MaxEncodedLen @@ -294,14 +301,17 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { <#key as #scrate::traits::MaxEncodedLen>::max_encoded_len() ) .saturated_into(); - #scrate::traits::StorageInfo { - prefix: < - #storage_struct - as #scrate::storage::StoragePrefixedMap<#value_type> - >::final_prefix(), - max_values: #max_values, - max_size: Some(max_size), - } + + #scrate::sp_std::vec![ + #scrate::traits::StorageInfo { + prefix: < + #storage_struct + as #scrate::storage::StoragePrefixedMap<#value_type> + >::final_prefix(), + max_values: #max_values, + max_size: Some(max_size), + } + ] } } ) @@ -313,7 +323,9 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct #optional_storage_where_clause { - fn storage_info() -> #scrate::traits::StorageInfo { + fn storage_info() + -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> + { use #scrate::sp_runtime::SaturatedConversion; let max_size = < #value_type as #scrate::traits::MaxEncodedLen @@ -325,14 +337,17 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { <#key2 as #scrate::traits::MaxEncodedLen>::max_encoded_len() ) .saturated_into(); - #scrate::traits::StorageInfo { - prefix: < - #storage_struct - as #scrate::storage::StoragePrefixedMap<#value_type> - >::final_prefix(), - max_values: #max_values, - max_size: Some(max_size), - } + + #scrate::sp_std::vec![ + #scrate::traits::StorageInfo { + prefix: < + #storage_struct + as #scrate::storage::StoragePrefixedMap<#value_type> + >::final_prefix(), + max_values: #max_values, + max_size: Some(max_size), + } + ] } } ) @@ -343,7 +358,9 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct #optional_storage_where_clause { - fn storage_info() -> #scrate::traits::StorageInfo { + fn storage_info() + -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> + { use #scrate::sp_runtime::SaturatedConversion; let max_size = < #value_type as #scrate::traits::MaxEncodedLen @@ -357,14 +374,17 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { ) )* .saturated_into(); - #scrate::traits::StorageInfo { - prefix: < - #storage_struct - as #scrate::storage::StoragePrefixedMap<#value_type> - >::final_prefix(), - max_values: #max_values, - max_size: Some(max_size), - } + + #scrate::sp_std::vec![ + #scrate::traits::StorageInfo { + prefix: < + #storage_struct + as #scrate::storage::StoragePrefixedMap<#value_type> + >::final_prefix(), + max_values: #max_values, + max_size: Some(max_size), + } + ] } } ) diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 72ff840bf8a10..0f96cdd023195 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1235,7 +1235,7 @@ pub mod pallet_prelude { Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, ensure, RuntimeDebug, storage, traits::{ - Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, PalletStorageInfo, + Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, StorageInfoTrait, ConstU32, GetDefault, }, dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult}, @@ -1357,7 +1357,7 @@ pub mod pallet_prelude { /// pub struct Pallet(_); /// ``` /// -/// This require all storage to implement the trait [`traits::StorageMaxEncodedLen`], thus all keys +/// This require all storage to implement the trait [`traits::StorageInfoTrait`], thus all keys /// and value types must bound [`traits::MaxEncodedLen`]. /// /// ### Macro expansion: @@ -1384,13 +1384,14 @@ pub mod pallet_prelude { /// given by [`frame_support::traits::PalletInfo`]. /// (The implementation use the associated type `frame_system::Config::PalletInfo`). /// -/// It implements [`traits::PalletStorageInfo`] on `Pallet` which give information about all storages. +/// It implements [`traits::StorageInfoTrait`] on `Pallet` which give information about all storages. /// /// If the attribute generate_store is set then the macro creates the trait `Store` and implements /// it on `Pallet`. /// /// If the attribute set_storage_max_encoded_len is set then the macro call -/// [`traits::StorageMaxEncodedLen`] in the implementation of [`PalletStorageInfo`]. +/// [`traits::StorageInfoTrait`] for each storage in the implementation of +/// [`traits::StorageInfoTrait`] for the pallet. /// /// # Hooks: `#[pallet::hooks]` mandatory /// diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index b88e6b8416c55..22d1ed3f8207b 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -29,7 +29,7 @@ use crate::{ }; use frame_metadata::{DefaultByteGetter, StorageEntryModifier}; use sp_arithmetic::traits::SaturatedConversion; -use sp_std::vec::Vec; +use sp_std::prelude::*; /// A type that allow to store values for `(key1, key2)` couple. Similar to `StorageMap` but allow /// to iterate and remove value associated to first key. @@ -493,17 +493,19 @@ where OnEmpty: Get + 'static, MaxValues: Get>, { - fn storage_info() -> StorageInfo { - StorageInfo { - prefix: Self::final_prefix(), - max_values: MaxValues::get(), - max_size: Some( - Key1::max_encoded_len() - .saturating_add(Key2::max_encoded_len()) - .saturating_add(Value::max_encoded_len()) - .saturated_into(), - ), - } + fn storage_info() -> Vec { + vec![ + StorageInfo { + prefix: Self::final_prefix(), + max_values: MaxValues::get(), + max_size: Some( + Key1::max_encoded_len() + .saturating_add(Key2::max_encoded_len()) + .saturating_add(Value::max_encoded_len()) + .saturated_into(), + ), + } + ] } } diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 6e2e2221c4aae..805737d7397d4 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -365,16 +365,18 @@ where OnEmpty: Get + 'static, MaxValues: Get>, { - fn storage_info() -> StorageInfo { - StorageInfo { - prefix: Self::final_prefix(), - max_values: MaxValues::get(), - max_size: Some( - Key::max_encoded_len() - .saturating_add(Value::max_encoded_len()) - .saturated_into(), - ), - } + fn storage_info() -> Vec { + vec![ + StorageInfo { + prefix: Self::final_prefix(), + max_values: MaxValues::get(), + max_size: Some( + Key::max_encoded_len() + .saturating_add(Value::max_encoded_len()) + .saturated_into(), + ), + } + ] } } diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 900e2a578d93c..f018ccc38b4fe 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -395,16 +395,18 @@ where OnEmpty: Get + 'static, MaxValues: Get>, { - fn storage_info() -> StorageInfo { - StorageInfo { - prefix: Self::final_prefix(), - max_values: MaxValues::get(), - max_size: Some( - Key::key_max_encoded_len() - .saturating_add(Value::max_encoded_len()) - .saturated_into(), - ), - } + fn storage_info() -> Vec { + vec![ + StorageInfo { + prefix: Self::final_prefix(), + max_values: MaxValues::get(), + max_size: Some( + Key::key_max_encoded_len() + .saturating_add(Value::max_encoded_len()) + .saturated_into(), + ), + } + ] } } diff --git a/frame/support/src/storage/types/value.rs b/frame/support/src/storage/types/value.rs index 0ece3b8713c5a..67d2e3741929e 100644 --- a/frame/support/src/storage/types/value.rs +++ b/frame/support/src/storage/types/value.rs @@ -28,6 +28,7 @@ use crate::{ }; use frame_metadata::{DefaultByteGetter, StorageEntryModifier}; use sp_arithmetic::traits::SaturatedConversion; +use sp_std::prelude::*; /// A type that allow to store a value. /// @@ -222,15 +223,17 @@ where QueryKind: QueryKindTrait, OnEmpty: crate::traits::Get + 'static { - fn storage_info() -> StorageInfo { - StorageInfo { - prefix: Self::hashed_key(), - max_values: Some(1), - max_size: Some( - Value::max_encoded_len() - .saturated_into(), - ), - } + fn storage_info() -> Vec { + vec![ + StorageInfo { + prefix: Self::hashed_key(), + max_values: Some(1), + max_size: Some( + Value::max_encoded_len() + .saturated_into(), + ), + } + ] } } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 5b0a80df0ed28..295995b1bfebd 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -73,7 +73,7 @@ pub use hooks::GenesisBuild; pub mod schedule; mod storage; -pub use storage::{Instance, StorageInstance, PalletStorageInfo, StorageInfo, StorageInfoTrait}; +pub use storage::{Instance, StorageInstance, StorageInfo, StorageInfoTrait}; mod dispatch; pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable}; diff --git a/frame/support/src/traits/storage.rs b/frame/support/src/traits/storage.rs index ab6fe96f1eeba..37957ceb67765 100644 --- a/frame/support/src/traits/storage.rs +++ b/frame/support/src/traits/storage.rs @@ -48,7 +48,7 @@ pub trait StorageInstance { const STORAGE_PREFIX: &'static str; } -/// Some info about a storage in a pallet. +/// Some info about an individual storage in a pallet. #[derive(codec::Encode, codec::Decode, crate::RuntimeDebug, Eq, PartialEq, Clone)] pub struct StorageInfo { /// The prefix of the storage. All keys after the prefix are considered part of the storage @@ -59,23 +59,18 @@ pub struct StorageInfo { pub max_size: Option, } -/// A trait to give information about storages. +/// A trait to give information about storage. /// /// It can be used to calculate PoV worst case size. -pub trait PalletStorageInfo { +pub trait StorageInfoTrait { fn storage_info() -> Vec; } #[impl_trait_for_tuples::impl_for_tuples(30)] -impl PalletStorageInfo for Tuple { +impl StorageInfoTrait for Tuple { fn storage_info() -> Vec { let mut res = vec![]; for_tuples!( #( res.extend_from_slice(&Tuple::storage_info()); )* ); res } } - -/// A trait for types which contains storage info. -pub trait StorageInfoTrait { - fn storage_info() -> StorageInfo; -} diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index 27813a76feec3..e7601f60c5444 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -397,7 +397,7 @@ mod tests { fn storage_info() { use frame_support::{ StorageHasher, - traits::{PalletStorageInfo, StorageInfo}, + traits::{StorageInfoTrait, StorageInfo}, pallet_prelude::*, }; let prefix = |pallet_name, storage_name| { diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 114b975f8b502..75ea1753c9ffa 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -979,7 +979,7 @@ fn test_pallet_info_access() { fn test_storage_info() { use frame_support::{ StorageHasher, - traits::{PalletStorageInfo, StorageInfo}, + traits::{StorageInfoTrait, StorageInfo}, pallet_prelude::*, }; From 5521953f8c3ae7168e30b52675b4b6648e99d93f Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Fri, 14 May 2021 14:09:54 +0200 Subject: [PATCH 11/45] Update frame/support/procedural/src/storage/parse.rs Co-authored-by: Peter Goodspeed-Niklaus --- frame/support/procedural/src/storage/parse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 164f0c1b11d29..ca97b7957c108 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -203,7 +203,7 @@ struct DeclStorageMaxValues { pub max_values_keyword: keyword::max_values, pub expr: ext::Parens, } -impl_parse_for_opt!(DeclStorageMaxValues=> keyword::max_values); +impl_parse_for_opt!(DeclStorageMaxValues => keyword::max_values); #[derive(Parse, ToTokens, Debug)] struct DeclStorageBuild { From 02b0cbb74d865315c8af731f4f98760ac2b32918 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Fri, 14 May 2021 14:10:19 +0200 Subject: [PATCH 12/45] Update frame/support/procedural/src/storage/storage_struct.rs Co-authored-by: Peter Goodspeed-Niklaus --- frame/support/procedural/src/storage/storage_struct.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index cad92dc9ee44f..23b6e3f311da4 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -391,7 +391,7 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { }, } } else { - Default::default() + TokenStream::default() }; impls.extend(quote!( From 999640b638d6255e6d7c70bd87ddec3407b862aa Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 14 May 2021 15:28:41 +0200 Subject: [PATCH 13/45] Fix max_size using hasher information hasher now expose `max_len` which allows to computes their maximum len. For hasher without concatenation, it is the size of the hash part, for hasher with concatenation, it is the size of the hash part + max encoded len of the key. --- .../procedural/src/storage/storage_struct.rs | 44 +++++++++------ frame/support/src/hash.rs | 36 ++++++++++++ frame/support/src/storage/types/double_map.rs | 4 +- frame/support/src/storage/types/key.rs | 4 +- frame/support/src/storage/types/map.rs | 2 +- frame/support/src/storage/types/mod.rs | 2 +- frame/support/test/tests/decl_storage.rs | 56 ++++++++++++++++--- frame/support/test/tests/pallet.rs | 18 +++--- 8 files changed, 124 insertions(+), 42 deletions(-) diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index 23b6e3f311da4..c1af0ee0701fb 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -294,12 +294,16 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { use #scrate::sp_runtime::SaturatedConversion; + use #scrate::StorageHasher; + + let key_max_size = < + Self as #scrate::storage::generator::StorageMap<_, _> + >::Hasher::max_len::<#key>(); + let max_size = < #value_type as #scrate::traits::MaxEncodedLen >::max_encoded_len() - .saturating_add( - <#key as #scrate::traits::MaxEncodedLen>::max_encoded_len() - ) + .saturating_add(key_max_size) .saturated_into(); #scrate::sp_std::vec![ @@ -327,15 +331,21 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { use #scrate::sp_runtime::SaturatedConversion; + use #scrate::StorageHasher; + + let key1_max_size = < + Self as #scrate::storage::generator::StorageDoubleMap<_, _, _> + >::Hasher1::max_len::<#key1>(); + + let key2_max_size = < + Self as #scrate::storage::generator::StorageDoubleMap<_, _, _> + >::Hasher2::max_len::<#key2>(); + let max_size = < #value_type as #scrate::traits::MaxEncodedLen >::max_encoded_len() - .saturating_add( - <#key1 as #scrate::traits::MaxEncodedLen>::max_encoded_len() - ) - .saturating_add( - <#key2 as #scrate::traits::MaxEncodedLen>::max_encoded_len() - ) + .saturating_add(key1_max_size) + .saturating_add(key2_max_size) .saturated_into(); #scrate::sp_std::vec![ @@ -353,7 +363,7 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { ) }, StorageLineTypeDef::NMap(map) => { - let keys = &map.keys; + let key = &map.to_keygen_struct(scrate); quote!( impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct #optional_storage_where_clause @@ -362,17 +372,15 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { use #scrate::sp_runtime::SaturatedConversion; + + let key_max_size = < + #key as #scrate::storage::types::KeyGeneratorMaxEncodedLen + >::key_max_encoded_len(); + let max_size = < #value_type as #scrate::traits::MaxEncodedLen >::max_encoded_len() - #( - .saturating_add( - < - #keys - as #scrate::traits::MaxEncodedLen - >::max_encoded_len() - ) - )* + .saturating_add(key_max_size) .saturated_into(); #scrate::sp_std::vec![ diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index 22ccbeb6ceee3..db45801607e0d 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -20,6 +20,7 @@ use codec::Codec; use sp_std::prelude::Vec; use sp_io::hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256}; +use crate::traits::MaxEncodedLen; // This trait must be kept coherent with frame-support-procedural HasherKind usage pub trait Hashable: Sized { @@ -59,6 +60,9 @@ pub trait StorageHasher: 'static { const METADATA: frame_metadata::StorageHasher; type Output: AsRef<[u8]>; fn hash(x: &[u8]) -> Self::Output; + + /// The max length of the final hash, for the given key type. + fn max_len() -> usize; } /// Hasher to use to hash keys to insert to storage. @@ -79,6 +83,9 @@ impl StorageHasher for Identity { fn hash(x: &[u8]) -> Vec { x.to_vec() } + fn max_len() -> usize { + K::max_encoded_len() + } } impl ReversibleStorageHasher for Identity { fn reverse(x: &[u8]) -> &[u8] { @@ -98,6 +105,9 @@ impl StorageHasher for Twox64Concat { .cloned() .collect::>() } + fn max_len() -> usize { + K::max_encoded_len().saturating_add(8) + } } impl ReversibleStorageHasher for Twox64Concat { fn reverse(x: &[u8]) -> &[u8] { @@ -121,6 +131,9 @@ impl StorageHasher for Blake2_128Concat { .cloned() .collect::>() } + fn max_len() -> usize { + K::max_encoded_len().saturating_add(16) + } } impl ReversibleStorageHasher for Blake2_128Concat { fn reverse(x: &[u8]) -> &[u8] { @@ -140,6 +153,9 @@ impl StorageHasher for Blake2_128 { fn hash(x: &[u8]) -> [u8; 16] { blake2_128(x) } + fn max_len() -> usize { + 16 + } } /// Hash storage keys with blake2 256 @@ -150,6 +166,9 @@ impl StorageHasher for Blake2_256 { fn hash(x: &[u8]) -> [u8; 32] { blake2_256(x) } + fn max_len() -> usize { + 32 + } } /// Hash storage keys with twox 128 @@ -160,6 +179,9 @@ impl StorageHasher for Twox128 { fn hash(x: &[u8]) -> [u8; 16] { twox_128(x) } + fn max_len() -> usize { + 16 + } } /// Hash storage keys with twox 256 @@ -170,6 +192,9 @@ impl StorageHasher for Twox256 { fn hash(x: &[u8]) -> [u8; 32] { twox_256(x) } + fn max_len() -> usize { + 32 + } } #[cfg(test)] @@ -187,4 +212,15 @@ mod tests { let r = Blake2_128Concat::hash(b"foo"); assert_eq!(r.split_at(16), (&blake2_128(b"foo")[..], &b"foo"[..])) } + + #[test] + fn max_lengths() { + assert_eq!(Twox64Concat::hash(0u32).len() == Twox64Concat::max_len::); + assert_eq!(Twox128::hash(0u32).len() == Twox128::max_len::); + assert_eq!(Twox256::hash(0u32).len() == Twox256::max_len::); + assert_eq!(Blake2_128::hash(0u32).len() == Blake2_128::max_len::); + assert_eq!(Blake2_128Concat::hash(0u32).len() == Blake2_128Concat::max_len::); + assert_eq!(Blake2_256::hash(0u32).len() == Blake2_256::max_len::); + assert_eq!(Identity::hash(0u32).len() == Identity::max_len::); + } } diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index 22d1ed3f8207b..8c23354817f4e 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -499,8 +499,8 @@ where prefix: Self::final_prefix(), max_values: MaxValues::get(), max_size: Some( - Key1::max_encoded_len() - .saturating_add(Key2::max_encoded_len()) + Hasher1::max_len::() + .saturating_add(Hasher2::max_len::()) .saturating_add(Value::max_encoded_len()) .saturated_into(), ), diff --git a/frame/support/src/storage/types/key.rs b/frame/support/src/storage/types/key.rs index 78e80ee49268f..59f280bd2573e 100755 --- a/frame/support/src/storage/types/key.rs +++ b/frame/support/src/storage/types/key.rs @@ -53,7 +53,7 @@ pub trait KeyGenerator { ) -> Vec; } -/// TODO TODO: the max encoded len of the final key without the hash part (only the concat part) +/// The maximum length used by the key in storage. pub trait KeyGeneratorMaxEncodedLen: KeyGenerator { fn key_max_encoded_len() -> usize; } @@ -98,7 +98,7 @@ impl KeyGenerator for Key { impl KeyGeneratorMaxEncodedLen for Key { fn key_max_encoded_len() -> usize { - K::max_encoded_len() + H::max_len::() } } diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 805737d7397d4..ac2817c6887fd 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -371,7 +371,7 @@ where prefix: Self::final_prefix(), max_values: MaxValues::get(), max_size: Some( - Key::max_encoded_len() + Hasher::max_len::() .saturating_add(Value::max_encoded_len()) .saturated_into(), ), diff --git a/frame/support/src/storage/types/mod.rs b/frame/support/src/storage/types/mod.rs index 5b7aa61d37693..f61065671315f 100644 --- a/frame/support/src/storage/types/mod.rs +++ b/frame/support/src/storage/types/mod.rs @@ -30,7 +30,7 @@ mod value; pub use double_map::{StorageDoubleMap, StorageDoubleMapMetadata}; pub use key::{ EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator, - ReversibleKeyGenerator, TupleToEncodedIter, + ReversibleKeyGenerator, TupleToEncodedIter, KeyGeneratorMaxEncodedLen, }; pub use map::{StorageMap, StorageMapMetadata}; pub use nmap::{StorageNMap, StorageNMapMetadata}; diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index e7601f60c5444..ef7b577ab6b8d 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -66,7 +66,6 @@ mod tests { // map getters: pub / $default GETMAPU32 get(fn map_u32_getter): map hasher(blake2_128_concat) u32 => [u8; 4]; pub PUBGETMAPU32 get(fn pub_map_u32_getter): map hasher(blake2_128_concat) u32 => [u8; 4]; - GETMAPU32MYDEF get(fn map_u32_getter_mydef): map hasher(blake2_128_concat) u32 => [u8; 4] = *b"mapd"; pub PUBGETMAPU32MYDEF get(fn pub_map_u32_getter_mydef): @@ -81,6 +80,9 @@ mod tests { COMPLEXTYPE1: (::std::option::Option,); COMPLEXTYPE2: ([[(u16, Option<()>); 32]; 12], u32); COMPLEXTYPE3: [u32; 25]; + + NMAP: nmap hasher(blake2_128_concat) u32, hasher(twox_64_concat) u16 => u8; + NMAP2: nmap hasher(blake2_128_concat) u32 => u8; } add_extra_genesis { build(|_| {}); @@ -389,6 +391,32 @@ mod tests { ), documentation: DecodeDifferent::Encode(&[]), }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("NMAP"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::NMap { + keys: DecodeDifferent::Encode(&["u32", "u16"]), + hashers: DecodeDifferent::Encode(&[StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat]), + value: DecodeDifferent::Encode("u8"), + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructNMAP(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("NMAP2"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::NMap { + keys: DecodeDifferent::Encode(&["u32"]), + hashers: DecodeDifferent::Encode(&[StorageHasher::Blake2_128Concat]), + value: DecodeDifferent::Encode("u8"), + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructNMAP(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, ] ), }; @@ -492,42 +520,42 @@ mod tests { StorageInfo { prefix: prefix(b"TestStorage", b"MAPU32"), max_values: Some(3), - max_size: Some(8), + max_size: Some(8 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"PUBMAPU32"), max_values: None, - max_size: Some(8), + max_size: Some(8 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"GETMAPU32"), max_values: None, - max_size: Some(8), + max_size: Some(8 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"PUBGETMAPU32"), max_values: None, - max_size: Some(8), + max_size: Some(8 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"GETMAPU32MYDEF"), max_values: None, - max_size: Some(8), + max_size: Some(8 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"PUBGETMAPU32MYDEF"), max_values: None, - max_size: Some(8), + max_size: Some(8 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"DOUBLEMAP"), max_values: Some(3), - max_size: Some(12), + max_size: Some(12 + 16 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"DOUBLEMAP2"), max_values: None, - max_size: Some(12), + max_size: Some(12 + 16 + 16), }, StorageInfo { prefix: prefix(b"TestStorage", b"COMPLEXTYPE1"), @@ -544,6 +572,16 @@ mod tests { max_values: Some(1), max_size: Some(100), }, + StorageInfo { + prefix: prefix(b"TestStorage", b"NMAP"), + max_values: None, + max_size: Some(16 + 4 + 8 + 2 + 1), + }, + StorageInfo { + prefix: prefix(b"TestStorage", b"NMAP2"), + max_values: None, + max_size: Some(16 + 4 + 1), + }, ], ); } diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 75ea1753c9ffa..0a768c79e779c 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -1006,32 +1006,32 @@ fn test_storage_info() { StorageInfo { prefix: prefix(b"Example", b"Map"), max_values: None, - max_size: Some(3), + max_size: Some(3 + 16), }, StorageInfo { prefix: prefix(b"Example", b"Map2"), max_values: Some(3), - max_size: Some(6), + max_size: Some(6 + 8), }, StorageInfo { prefix: prefix(b"Example", b"DoubleMap"), max_values: None, - max_size: Some(7), + max_size: Some(7 + 16 + 8), }, StorageInfo { prefix: prefix(b"Example", b"DoubleMap2"), max_values: Some(5), - max_size: Some(14), + max_size: Some(14 + 8 + 16), }, StorageInfo { prefix: prefix(b"Example", b"NMap"), max_values: None, - max_size: Some(5), + max_size: Some(5 + 16), }, StorageInfo { prefix: prefix(b"Example", b"NMap2"), max_values: Some(11), - max_size: Some(14), + max_size: Some(14 + 8 + 16), }, #[cfg(feature = "conditional-storage")] { @@ -1046,7 +1046,7 @@ fn test_storage_info() { StorageInfo { prefix: prefix(b"Example", b"ConditionalMap"), max_values: Some(12), - max_size: Some(6), + max_size: Some(6 + 8), } }, #[cfg(feature = "conditional-storage")] @@ -1054,7 +1054,7 @@ fn test_storage_info() { StorageInfo { prefix: prefix(b"Example", b"ConditionalDoubleMap"), max_values: None, - max_size: Some(7), + max_size: Some(7 + 16 + 8), } }, #[cfg(feature = "conditional-storage")] @@ -1062,7 +1062,7 @@ fn test_storage_info() { StorageInfo { prefix: prefix(b"Example", b"ConditionalNMap"), max_values: None, - max_size: Some(7), + max_size: Some(7 + 16 + 8), } }, ], From a7909d7744d00bad38541c885c6ccd4cd1b250a7 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 14 May 2021 15:55:36 +0200 Subject: [PATCH 14/45] fix tests --- frame/support/src/hash.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index db45801607e0d..5c4bfb34f5f96 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -215,12 +215,14 @@ mod tests { #[test] fn max_lengths() { - assert_eq!(Twox64Concat::hash(0u32).len() == Twox64Concat::max_len::); - assert_eq!(Twox128::hash(0u32).len() == Twox128::max_len::); - assert_eq!(Twox256::hash(0u32).len() == Twox256::max_len::); - assert_eq!(Blake2_128::hash(0u32).len() == Blake2_128::max_len::); - assert_eq!(Blake2_128Concat::hash(0u32).len() == Blake2_128Concat::max_len::); - assert_eq!(Blake2_256::hash(0u32).len() == Blake2_256::max_len::); - assert_eq!(Identity::hash(0u32).len() == Identity::max_len::); + use codec::Encode; + let encoded_0u32 = &0u32.encode()[..]; + assert_eq!(Twox64Concat::hash(encoded_0u32).len(), Twox64Concat::max_len::()); + assert_eq!(Twox128::hash(encoded_0u32).len(), Twox128::max_len::()); + assert_eq!(Twox256::hash(encoded_0u32).len(), Twox256::max_len::()); + assert_eq!(Blake2_128::hash(encoded_0u32).len(), Blake2_128::max_len::()); + assert_eq!(Blake2_128Concat::hash(encoded_0u32).len(), Blake2_128Concat::max_len::()); + assert_eq!(Blake2_256::hash(encoded_0u32).len(), Blake2_256::max_len::()); + assert_eq!(Identity::hash(encoded_0u32).len(), Identity::max_len::()); } } From e5964c029d461c231fedf4fa6a01c07d88ee8f5c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 14 May 2021 16:30:43 +0200 Subject: [PATCH 15/45] fix ui tests --- .../test/tests/pallet_ui/storage_info_unsatisfied.stderr | 2 +- .../test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr index b263bdf52b2d5..ad415911bc933 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr @@ -5,4 +5,4 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` - = note: required by `frame_support::traits::StorageInfoTrait::storage_info` + = note: required by `storage_info` diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 8ffa8eb1756a7..545520124bfee 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -4,6 +4,6 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied 10 | #[pallet::generate_storage_info] | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | - = note: required because of the requirements on the impl of `types::key::KeyGeneratorMaxEncodedLen` for `NMapKey` + = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `NMapKey` = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, NMapKey, u32>` - = note: required by `frame_support::traits::StorageInfoTrait::storage_info` + = note: required by `storage_info` From 2001d32103c78f537a2704bd456996525da42644 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Sat, 15 May 2021 03:37:15 +0200 Subject: [PATCH 16/45] Move `MaxBoundedLen` into its own crate (#8814) * move MaxEncodedLen into its own crate * remove MaxEncodedLen impl from frame-support * add to assets and balances * try more fixes * fix compile Co-authored-by: Shawn Tabrizi --- Cargo.lock | 35 ++++++++++++++++--- Cargo.toml | 2 ++ bin/node/runtime/Cargo.toml | 3 ++ bin/node/runtime/src/lib.rs | 4 +-- frame/assets/Cargo.toml | 2 ++ frame/balances/Cargo.toml | 2 ++ frame/max-encoded-len/Cargo.toml | 35 +++++++++++++++++++ frame/max-encoded-len/derive/Cargo.toml | 25 +++++++++++++ .../derive/src/lib.rs} | 8 +++-- .../src/lib.rs} | 13 +++++-- .../tests/max_encoded_len.rs | 4 ++- .../tests/max_encoded_len_ui.rs | 1 + .../tests/max_encoded_len_ui/not_encode.rs | 2 +- .../max_encoded_len_ui/not_encode.stderr | 8 ++--- .../tests/max_encoded_len_ui/not_mel.rs | 2 +- .../tests/max_encoded_len_ui/not_mel.stderr | 0 .../tests/max_encoded_len_ui/union.rs | 2 +- .../tests/max_encoded_len_ui/union.stderr | 0 .../max_encoded_len_ui/unsupported_variant.rs | 2 +- .../unsupported_variant.stderr | 0 frame/proxy/Cargo.toml | 4 ++- frame/support/Cargo.toml | 2 ++ frame/support/procedural/src/lib.rs | 7 ---- frame/support/src/traits.rs | 30 +--------------- primitives/core/Cargo.toml | 2 ++ primitives/core/src/crypto.rs | 3 +- primitives/runtime/Cargo.toml | 2 ++ primitives/runtime/src/traits.rs | 3 +- 28 files changed, 143 insertions(+), 60 deletions(-) create mode 100644 frame/max-encoded-len/Cargo.toml create mode 100644 frame/max-encoded-len/derive/Cargo.toml rename frame/{support/procedural/src/max_encoded_len.rs => max-encoded-len/derive/src/lib.rs} (96%) rename frame/{support/src/traits/max_encoded_len.rs => max-encoded-len/src/lib.rs} (92%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len.rs (98%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui.rs (97%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/not_encode.rs (58%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/not_encode.stderr (53%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/not_mel.rs (80%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/not_mel.stderr (100%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/union.rs (70%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/union.stderr (100%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/unsupported_variant.rs (77%) rename frame/{support/test => max-encoded-len}/tests/max_encoded_len_ui/unsupported_variant.stderr (100%) diff --git a/Cargo.lock b/Cargo.lock index f11953213d01e..a3c3f3b65c0e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "Inflector" version = "0.11.4" @@ -1810,6 +1808,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log", + "max-encoded-len", "once_cell", "parity-scale-codec", "parity-util-mem", @@ -3719,6 +3718,28 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "max-encoded-len" +version = "3.0.0" +dependencies = [ + "impl-trait-for-tuples", + "max-encoded-len-derive", + "parity-scale-codec", + "primitive-types", + "rustversion", + "trybuild", +] + +[[package]] +name = "max-encoded-len-derive" +version = "3.0.0" +dependencies = [ + "frame-support-procedural-tools", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -4291,6 +4312,7 @@ dependencies = [ "frame-try-runtime", "hex-literal", "log", + "max-encoded-len", "node-primitives", "pallet-assets", "pallet-authority-discovery", @@ -4624,6 +4646,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "max-encoded-len", "pallet-balances", "parity-scale-codec", "sp-core", @@ -4734,6 +4757,7 @@ dependencies = [ "frame-support", "frame-system", "log", + "max-encoded-len", "pallet-transaction-payment", "parity-scale-codec", "sp-core", @@ -5260,6 +5284,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "max-encoded-len", "pallet-balances", "pallet-utility", "parity-scale-codec", @@ -8783,6 +8808,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log", + "max-encoded-len", "merlin", "num-traits", "parity-scale-codec", @@ -9008,6 +9034,7 @@ dependencies = [ "hash256-std-hasher", "impl-trait-for-tuples", "log", + "max-encoded-len", "parity-scale-codec", "parity-util-mem", "paste 1.0.4", @@ -10433,9 +10460,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b" +checksum = "1768998d9a3b179411618e377dbb134c58a88cda284b0aa71c42c40660127d46" dependencies = [ "dissimilar", "glob", diff --git a/Cargo.toml b/Cargo.toml index 1b35c7181d17d..76c9d9a7b2169 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,8 @@ members = [ "frame/im-online", "frame/indices", "frame/lottery", + "frame/max-encoded-len", + "frame/max-encoded-len/derive", "frame/membership", "frame/merkle-mountain-range", "frame/merkle-mountain-range/primitives", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 512f32d66a66c..a0659db84ea11 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -87,6 +87,8 @@ pallet-transaction-payment = { version = "3.0.0", default-features = false, path pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } pallet-vesting = { version = "3.0.0", default-features = false, path = "../../../frame/vesting" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } + [build-dependencies] substrate-wasm-builder = { version = "4.0.0", path = "../../../utils/wasm-builder" } @@ -159,6 +161,7 @@ std = [ "log/std", "frame-try-runtime/std", "sp-npos-elections/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 05f75b14b9603..eb544337e3795 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -33,7 +33,7 @@ use frame_support::{ }, traits::{ Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, LockIdentifier, - U128CurrencyToVote, + U128CurrencyToVote, MaxEncodedLen, }, }; use frame_system::{ @@ -252,7 +252,7 @@ parameter_types! { } /// The type used to represent the kinds of proxying allowed. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen)] pub enum ProxyType { Any, NonTransfer, diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 7137cf1d789a2..db03959616475 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -22,6 +22,7 @@ frame-support = { version = "3.0.0", default-features = false, path = "../suppor # `system` module provides us with all sorts of useful stuff and macros depend on it being around. frame-system = { version = "3.0.0", default-features = false, path = "../system" } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-core = { version = "3.0.0", path = "../../primitives/core" } @@ -38,6 +39,7 @@ std = [ "frame-support/std", "frame-system/std", "frame-benchmarking/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 116a52151583a..667724ae3d0cc 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -20,6 +20,7 @@ frame-benchmarking = { version = "3.1.0", default-features = false, path = "../b frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-io = { version = "3.0.0", path = "../../primitives/io" } @@ -36,6 +37,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "max-encoded-len/std", ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/max-encoded-len/Cargo.toml b/frame/max-encoded-len/Cargo.toml new file mode 100644 index 0000000000000..b5f97e54ad0f0 --- /dev/null +++ b/frame/max-encoded-len/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "max-encoded-len" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Trait MaxEncodedLen bounds the max encoded length of an item." + + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +impl-trait-for-tuples = "0.2.1" +max-encoded-len-derive = { package = "max-encoded-len-derive", version = "3.0.0", path = "derive", default-features = false, optional = true } +primitive-types = { version = "0.9.0", default-features = false, features = ["codec"] } + +[dev-dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] } +rustversion = "1.0.4" +trybuild = "1.0.42" + +[features] +default = [ + "derive", + "std", +] +derive = [ + "max-encoded-len-derive", +] +std = [ + "codec/std", + "max-encoded-len-derive/std", + "primitive-types/std", +] diff --git a/frame/max-encoded-len/derive/Cargo.toml b/frame/max-encoded-len/derive/Cargo.toml new file mode 100644 index 0000000000000..c8d33bef1c6a5 --- /dev/null +++ b/frame/max-encoded-len/derive/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "max-encoded-len-derive" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Derive support for MaxEncodedLen" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +proc-macro = true + +[dependencies] +frame-support-procedural-tools = { version = "3.0.0", path = "../../support/procedural/tools" } +proc-macro2 = "1.0.6" +quote = "1.0.3" +syn = { version = "1.0.58", features = ["full"] } + +[features] +default = ["std"] +std = [] diff --git a/frame/support/procedural/src/max_encoded_len.rs b/frame/max-encoded-len/derive/src/lib.rs similarity index 96% rename from frame/support/procedural/src/max_encoded_len.rs rename to frame/max-encoded-len/derive/src/lib.rs index 72efa446b3f4d..75484ad963204 100644 --- a/frame/support/procedural/src/max_encoded_len.rs +++ b/frame/max-encoded-len/derive/src/lib.rs @@ -22,7 +22,9 @@ use syn::{ parse_quote, spanned::Spanned, }; -/// impl for `#[derive(MaxEncodedLen)]` + +/// Derive `MaxEncodedLen`. +#[proc_macro_derive(MaxEncodedLen)] pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input: DeriveInput = match syn::parse(input) { Ok(input) => input, @@ -53,8 +55,8 @@ pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::Tok } fn max_encoded_len_trait() -> syn::Result { - let frame_support = generate_crate_access_2018("frame-support")?; - Ok(parse_quote!(#frame_support::traits::MaxEncodedLen)) + let mel = generate_crate_access_2018("max-encoded-len")?; + Ok(parse_quote!(#mel::MaxEncodedLen)) } // Add a bound `T: MaxEncodedLen` to every type parameter T. diff --git a/frame/support/src/traits/max_encoded_len.rs b/frame/max-encoded-len/src/lib.rs similarity index 92% rename from frame/support/src/traits/max_encoded_len.rs rename to frame/max-encoded-len/src/lib.rs index 2f206ddcbe11d..13c99f4e5b0ce 100644 --- a/frame/support/src/traits/max_encoded_len.rs +++ b/frame/max-encoded-len/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,10 +15,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! `trait MaxEncodedLen` bounds the max encoded length of items. + +#![cfg_attr(not(feature = "std"), no_std)] + use codec::{Compact, Encode}; use impl_trait_for_tuples::impl_for_tuples; -use sp_std::{mem, marker::PhantomData}; -use sp_core::{H160, H256, H512}; +use core::{mem, marker::PhantomData}; +use primitive_types::{H160, H256, H512}; + +#[cfg(feature = "derive")] +pub use max_encoded_len_derive::MaxEncodedLen; /// Items implementing `MaxEncodedLen` have a statically known maximum encoded size. /// diff --git a/frame/support/test/tests/max_encoded_len.rs b/frame/max-encoded-len/tests/max_encoded_len.rs similarity index 98% rename from frame/support/test/tests/max_encoded_len.rs rename to frame/max-encoded-len/tests/max_encoded_len.rs index e9e74929108d4..665ac8fa98a4f 100644 --- a/frame/support/test/tests/max_encoded_len.rs +++ b/frame/max-encoded-len/tests/max_encoded_len.rs @@ -17,7 +17,9 @@ //! Tests for MaxEncodedLen derive macro -use frame_support::traits::MaxEncodedLen; +#![cfg(feature = "derive")] + +use max_encoded_len::MaxEncodedLen; use codec::{Compact, Encode}; // These structs won't even compile if the macro isn't working right. diff --git a/frame/support/test/tests/max_encoded_len_ui.rs b/frame/max-encoded-len/tests/max_encoded_len_ui.rs similarity index 97% rename from frame/support/test/tests/max_encoded_len_ui.rs rename to frame/max-encoded-len/tests/max_encoded_len_ui.rs index c5c0489da924f..79d6d49234ff2 100644 --- a/frame/support/test/tests/max_encoded_len_ui.rs +++ b/frame/max-encoded-len/tests/max_encoded_len_ui.rs @@ -15,6 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(feature = "derive")] #[rustversion::attr(not(stable), ignore)] #[test] fn derive_no_bound_ui() { diff --git a/frame/support/test/tests/max_encoded_len_ui/not_encode.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs similarity index 58% rename from frame/support/test/tests/max_encoded_len_ui/not_encode.rs rename to frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs index ed6fe94471e58..5e8eb6035547a 100644 --- a/frame/support/test/tests/max_encoded_len_ui/not_encode.rs +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs @@ -1,4 +1,4 @@ -use frame_support::traits::MaxEncodedLen; +use max_encoded_len::MaxEncodedLen; #[derive(MaxEncodedLen)] struct NotEncode; diff --git a/frame/support/test/tests/max_encoded_len_ui/not_encode.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr similarity index 53% rename from frame/support/test/tests/max_encoded_len_ui/not_encode.stderr rename to frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr index f4dbeac040843..111e63e3f1e30 100644 --- a/frame/support/test/tests/max_encoded_len_ui/not_encode.stderr +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr @@ -1,13 +1,13 @@ -error[E0277]: the trait bound `NotEncode: WrapperTypeEncode` is not satisfied +error[E0277]: the trait bound `NotEncode: parity_scale_codec::codec::WrapperTypeEncode` is not satisfied --> $DIR/not_encode.rs:3:10 | 3 | #[derive(MaxEncodedLen)] - | ^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NotEncode` + | ^^^^^^^^^^^^^ the trait `parity_scale_codec::codec::WrapperTypeEncode` is not implemented for `NotEncode` | - ::: $WORKSPACE/frame/support/src/traits/max_encoded_len.rs + ::: $WORKSPACE/frame/max-encoded-len/src/lib.rs | | pub trait MaxEncodedLen: Encode { | ------ required by this bound in `MaxEncodedLen` | - = note: required because of the requirements on the impl of `frame_support::dispatch::Encode` for `NotEncode` + = note: required because of the requirements on the impl of `parity_scale_codec::codec::Encode` for `NotEncode` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/max_encoded_len_ui/not_mel.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs similarity index 80% rename from frame/support/test/tests/max_encoded_len_ui/not_mel.rs rename to frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs index 6116f30e5272b..cbaf820ff58e3 100644 --- a/frame/support/test/tests/max_encoded_len_ui/not_mel.rs +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs @@ -1,5 +1,5 @@ use codec::Encode; -use frame_support::traits::MaxEncodedLen; +use max_encoded_len::MaxEncodedLen; #[derive(Encode)] struct NotMel; diff --git a/frame/support/test/tests/max_encoded_len_ui/not_mel.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr similarity index 100% rename from frame/support/test/tests/max_encoded_len_ui/not_mel.stderr rename to frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr diff --git a/frame/support/test/tests/max_encoded_len_ui/union.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/union.rs similarity index 70% rename from frame/support/test/tests/max_encoded_len_ui/union.rs rename to frame/max-encoded-len/tests/max_encoded_len_ui/union.rs index c685b6939e9b8..932c484b9e670 100644 --- a/frame/support/test/tests/max_encoded_len_ui/union.rs +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/union.rs @@ -1,5 +1,5 @@ use codec::Encode; -use frame_support::traits::MaxEncodedLen; +use max_encoded_len::MaxEncodedLen; #[derive(Encode, MaxEncodedLen)] union Union { diff --git a/frame/support/test/tests/max_encoded_len_ui/union.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr similarity index 100% rename from frame/support/test/tests/max_encoded_len_ui/union.stderr rename to frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr diff --git a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs similarity index 77% rename from frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs rename to frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs index 675f62c168a69..2fa94867471b1 100644 --- a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs @@ -1,5 +1,5 @@ use codec::Encode; -use frame_support::traits::MaxEncodedLen; +use max_encoded_len::MaxEncodedLen; #[derive(Encode)] struct NotMel; diff --git a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr similarity index 100% rename from frame/support/test/tests/max_encoded_len_ui/unsupported_variant.stderr rename to frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index d8f7afe433cb3..992d18fcc3f86 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -20,6 +20,7 @@ sp-core = { version = "3.0.0", default-features = false, path = "../../primitive sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } @@ -36,7 +37,8 @@ std = [ "frame-support/std", "frame-system/std", "sp-std/std", - "sp-io/std" + "sp-io/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 7b1179122b973..9c2831af83423 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } frame-metadata = { version = "13.0.0", default-features = false, path = "../metadata" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } @@ -55,6 +56,7 @@ std = [ "sp-state-machine", "frame-support-procedural/std", "log/std", + "max-encoded-len/std", ] runtime-benchmarks = [] try-runtime = [] diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 5146b8e78380e..f6a2176d777c4 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -28,7 +28,6 @@ mod debug_no_bound; mod clone_no_bound; mod partial_eq_no_bound; mod default_no_bound; -mod max_encoded_len; pub(crate) use storage::INHERENT_INSTANCE_NAME; use proc_macro::TokenStream; @@ -445,9 +444,3 @@ pub fn crate_to_pallet_version(input: TokenStream) -> TokenStream { /// The number of module instances supported by the runtime, starting at index 1, /// and up to `NUMBER_OF_INSTANCE`. pub(crate) const NUMBER_OF_INSTANCE: u8 = 16; - -/// Derive `MaxEncodedLen`. -#[proc_macro_derive(MaxEncodedLen)] -pub fn derive_max_encoded_len(input: TokenStream) -> TokenStream { - max_encoded_len::derive_max_encoded_len(input) -} diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index cfac84aea865e..59ee29193e145 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -81,33 +81,5 @@ pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable}; mod voting; pub use voting::{CurrencyToVote, SaturatingCurrencyToVote, U128CurrencyToVote}; -mod max_encoded_len; -// This looks like an overlapping import/export, but it isn't: -// macros and traits live in distinct namespaces. +// for backwards-compatibility with existing imports pub use max_encoded_len::MaxEncodedLen; -/// Derive [`MaxEncodedLen`][max_encoded_len::MaxEncodedLen]. -/// -/// # Examples -/// -/// ``` -/// # use codec::Encode; -/// # use frame_support::traits::MaxEncodedLen; -/// #[derive(Encode, MaxEncodedLen)] -/// struct TupleStruct(u8, u32); -/// -/// assert_eq!(TupleStruct::max_encoded_len(), u8::max_encoded_len() + u32::max_encoded_len()); -/// ``` -/// -/// ``` -/// # use codec::Encode; -/// # use frame_support::traits::MaxEncodedLen; -/// #[derive(Encode, MaxEncodedLen)] -/// enum GenericEnum { -/// A, -/// B(T), -/// } -/// -/// assert_eq!(GenericEnum::::max_encoded_len(), u8::max_encoded_len() + u8::max_encoded_len()); -/// assert_eq!(GenericEnum::::max_encoded_len(), u8::max_encoded_len() + u128::max_encoded_len()); -/// ``` -pub use frame_support_procedural::MaxEncodedLen; diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 3d9cf1287e051..071f6821f2930 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -40,6 +40,7 @@ parity-util-mem = { version = "0.9.0", default-features = false, features = ["pr futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.21", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } # full crypto ed25519-dalek = { version = "1.0.1", default-features = false, features = ["u64_backend", "alloc"], optional = true } @@ -114,6 +115,7 @@ std = [ "futures/thread-pool", "libsecp256k1/std", "dyn-clonable", + "max-encoded-len/std", ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 7446ab25ce4be..8d8b7b967ac63 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -20,6 +20,7 @@ // end::description[] use crate::{sr25519, ed25519}; +use max_encoded_len::MaxEncodedLen; use sp_std::hash::Hash; use sp_std::vec::Vec; use sp_std::str; @@ -692,7 +693,7 @@ pub trait Public: } /// An opaque 32-byte cryptographic identifier. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Hash))] pub struct AccountId32([u8; 32]); diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7d33e7fa62d2d..646c7e4d10abe 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -29,6 +29,7 @@ impl-trait-for-tuples = "0.2.1" parity-util-mem = { version = "0.9.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } [dev-dependencies] serde_json = "1.0.41" @@ -55,4 +56,5 @@ std = [ "parity-util-mem/std", "hash256-std-hasher/std", "either/use_std", + "max-encoded-len/std", ] diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 41820d8cb4a1c..968f475f02252 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -40,6 +40,7 @@ pub use sp_arithmetic::traits::{ use sp_application_crypto::AppKey; use impl_trait_for_tuples::impl_for_tuples; use crate::DispatchResult; +use max_encoded_len::MaxEncodedLen; /// A lazy value. pub trait Lazy { @@ -386,7 +387,7 @@ impl::Output> { /// The hash type produced. type Output: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash - + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode; + + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode + MaxEncodedLen; /// Produce the hash of some byte-slice. fn hash(s: &[u8]) -> Self::Output { From 566425d2516cb219dde92decd4a0b0414df631e0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 14 May 2021 21:43:46 -0400 Subject: [PATCH 17/45] nits --- frame/assets/src/lib.rs | 10 ++++- frame/balances/src/lib.rs | 88 +++++++++++++++++++-------------------- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index e99c23c4f7c9e..400134cdb7e98 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -909,8 +909,14 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - let bounded_name: BoundedVec = name.clone().try_into().map_err(|_| Error::::BadMetadata)?; - let bounded_symbol: BoundedVec = symbol.clone().try_into().map_err(|_| Error::::BadMetadata)?; + let bounded_name: BoundedVec = name + .clone() + .try_into() + .map_err(|_| Error::::BadMetadata)?; + let bounded_symbol: BoundedVec = symbol + .clone() + .try_into() + .map_err(|_| Error::::BadMetadata)?; let d = Asset::::get(id).ok_or(Error::::Unknown)?; ensure!(&origin == &d.owner, Error::::NoPermission); diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index d85d4596184cc..76e65e4525aaa 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -831,52 +831,52 @@ impl, I: 'static> Pallet { /// Update the account entry for `who`, given the locks. fn update_locks(who: &T::AccountId, locks: &[BalanceLock]) { - unsafe { - let bounded_locks = BoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")); - - if locks.len() as u32 > T::MaxLocks::get() { - log::warn!( - target: "runtime::balances", - "Warning: A user has more currency locks than expected. \ - A runtime configuration adjustment may be needed." - ); - } - // No way this can fail since we do not alter the existential balances. - let res = Self::mutate_account(who, |b| { - b.misc_frozen = Zero::zero(); - b.fee_frozen = Zero::zero(); - for l in locks.iter() { - if l.reasons == Reasons::All || l.reasons == Reasons::Misc { - b.misc_frozen = b.misc_frozen.max(l.amount); - } - if l.reasons == Reasons::All || l.reasons == Reasons::Fee { - b.fee_frozen = b.fee_frozen.max(l.amount); - } + let bounded_locks = unsafe { + BoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")) + }; + + if locks.len() as u32 > T::MaxLocks::get() { + log::warn!( + target: "runtime::balances", + "Warning: A user has more currency locks than expected. \ + A runtime configuration adjustment may be needed." + ); + } + // No way this can fail since we do not alter the existential balances. + let res = Self::mutate_account(who, |b| { + b.misc_frozen = Zero::zero(); + b.fee_frozen = Zero::zero(); + for l in locks.iter() { + if l.reasons == Reasons::All || l.reasons == Reasons::Misc { + b.misc_frozen = b.misc_frozen.max(l.amount); } - }); - debug_assert!(res.is_ok()); - - let existed = Locks::::contains_key(who); - if locks.is_empty() { - Locks::::remove(who); - if existed { - // TODO: use Locks::::hashed_key - // https://github.com/paritytech/substrate/issues/4969 - system::Pallet::::dec_consumers(who); + if l.reasons == Reasons::All || l.reasons == Reasons::Fee { + b.fee_frozen = b.fee_frozen.max(l.amount); } - } else { - Locks::::insert(who, bounded_locks); - if !existed { - if system::Pallet::::inc_consumers(who).is_err() { - // No providers for the locks. This is impossible under normal circumstances - // since the funds that are under the lock will themselves be stored in the - // account and therefore will need a reference. - log::warn!( - target: "runtime::balances", - "Warning: Attempt to introduce lock consumer reference, yet no providers. \ - This is unexpected but should be safe." - ); - } + } + }); + debug_assert!(res.is_ok()); + + let existed = Locks::::contains_key(who); + if locks.is_empty() { + Locks::::remove(who); + if existed { + // TODO: use Locks::::hashed_key + // https://github.com/paritytech/substrate/issues/4969 + system::Pallet::::dec_consumers(who); + } + } else { + Locks::::insert(who, bounded_locks); + if !existed { + if system::Pallet::::inc_consumers(who).is_err() { + // No providers for the locks. This is impossible under normal circumstances + // since the funds that are under the lock will themselves be stored in the + // account and therefore will need a reference. + log::warn!( + target: "runtime::balances", + "Warning: Attempt to introduce lock consumer reference, yet no providers. \ + This is unexpected but should be safe." + ); } } } From 1a398cb0c970c4d962f9ccbfcad6f6a3b037a03d Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 14 May 2021 21:53:49 -0400 Subject: [PATCH 18/45] fix compile --- frame/support/procedural/src/storage/parse.rs | 3 +++ frame/support/procedural/src/storage/storage_struct.rs | 3 +++ frame/support/procedural/src/storage/storages_info.rs | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 9d4bb6d495ed6..59b4ec58ff508 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -521,6 +521,9 @@ fn parse_storage_line_defs( Some(syn::parse_quote!(1u32)) } }, + DeclStorageType::NMap(_) => { + unimplemented!("NMap not yet supported for max values") + } }; let span = line.storage_type.span(); diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index 11d0b88f6011e..ca21632f8220b 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -336,6 +336,9 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { } } ) + }, + StorageLineTypeDef::NMap(_) => { + unimplemented!("NMap not yet implemented for storage info") } } } else { diff --git a/frame/support/procedural/src/storage/storages_info.rs b/frame/support/procedural/src/storage/storages_info.rs index fe4d45cf89f88..5ccb1a42c8312 100644 --- a/frame/support/procedural/src/storage/storages_info.rs +++ b/frame/support/procedural/src/storage/storages_info.rs @@ -21,7 +21,9 @@ use proc_macro2::TokenStream; use quote::quote; use super::DeclStorageDefExt; -pub fn impl_storages_info(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { +pub fn impl_storages_info(def: &DeclStorageDefExt) -> TokenStream { + let scrate = &def.hidden_crate; + if !def.generate_storage_info { return Default::default() } From 3685d3c644a7c964692f9a07ba3c669397e58ac5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 14 May 2021 22:07:14 -0400 Subject: [PATCH 19/45] line width --- frame/proxy/src/lib.rs | 9 +++++++-- frame/system/src/lib.rs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 441faa9729d9c..20763740e9b19 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -43,7 +43,10 @@ use sp_runtime::{ use frame_support::{ RuntimeDebug, ensure, dispatch::{DispatchResultWithPostInfo, PostDispatchInfo}, - traits::{Get, ReservableCurrency, Currency, InstanceFilter, OriginTrait, IsType, IsSubType, MaxEncodedLen}, + traits::{ + Get, ReservableCurrency, Currency, InstanceFilter, OriginTrait, + IsType, IsSubType, MaxEncodedLen, + }, weights::GetDispatchInfo, }; use frame_system::{self as system}; @@ -303,7 +306,9 @@ pub mod pallet { proxy_type: proxy_type.clone(), delay, }; - let bounded_proxies: BoundedVec<_, T::MaxProxies> = vec![proxy_def].try_into().map_err(|_| Error::::TooMany)?; + let bounded_proxies: BoundedVec<_, T::MaxProxies> = vec![proxy_def] + .try_into() + .map_err(|_| Error::::TooMany)?; let deposit = T::ProxyDepositBase::get() + T::ProxyDepositFactor::get(); T::Currency::reserve(&who, deposit)?; diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 294d9616b21bc..6938df7e86c23 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -199,8 +199,8 @@ pub mod pallet { /// The output of the `Hashing` function. type Hash: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps + Ord - + Default + Copy + CheckEqual + sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + MaybeMallocSizeOf - + MaxEncodedLen; + + Default + Copy + CheckEqual + sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + + MaybeMallocSizeOf + MaxEncodedLen; /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). type Hashing: Hash; From e8841f5962d017521659a1094da4c23d96f2a6b4 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 17 May 2021 02:31:50 +0200 Subject: [PATCH 20/45] fix max-values-macro merge --- frame/assets/src/lib.rs | 3 +-- frame/balances/src/lib.rs | 2 +- frame/proxy/src/lib.rs | 2 +- frame/sudo/src/lib.rs | 2 +- frame/support/procedural/src/storage/mod.rs | 2 +- frame/support/procedural/src/storage/parse.rs | 3 --- frame/timestamp/src/lib.rs | 2 +- 7 files changed, 6 insertions(+), 10 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 400134cdb7e98..28a79836eabda 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -166,8 +166,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storages_info] - //#[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 76e65e4525aaa..2652936d03b12 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -218,7 +218,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 20763740e9b19..c56b91d697f86 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -91,7 +91,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(_); /// Configuration trait. diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index 7aa31bcca8da1..1d1fbb108d7fc 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -128,7 +128,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(PhantomData); #[pallet::hooks] diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs index 900514d48705c..570ef447a43cb 100644 --- a/frame/support/procedural/src/storage/mod.rs +++ b/frame/support/procedural/src/storage/mod.rs @@ -157,9 +157,9 @@ impl From for DeclStorageDefExt { ); Self { - generate_storage_info: def.generate_storage_info, hidden_crate, hidden_imports, + generate_storage_info: def.generate_storage_info, visibility: def.visibility, store_trait: def.store_trait, module_name: def.module_name, diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 0e04b9da1360a..ca97b7957c108 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -521,9 +521,6 @@ fn parse_storage_line_defs( Some(syn::parse_quote!(1u32)) } }, - DeclStorageType::NMap(_) => { - unimplemented!("NMap not yet supported for max values") - } }; let span = line.storage_type.span(); diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 1eb33acbd767a..3315fadb1c1cc 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -134,7 +134,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storages_info] + #[pallet::generate_storage_info] pub struct Pallet(PhantomData); /// Current time for the current block. From 1a3e03e24a8981f3da3a338805aff277a8748195 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 19 May 2021 18:58:58 +0200 Subject: [PATCH 21/45] Add some derive, needed for test and other purpose --- Cargo.lock | 8 ++++++++ bin/node/primitives/Cargo.toml | 2 ++ frame/example-offchain-worker/Cargo.toml | 2 ++ frame/im-online/Cargo.toml | 2 ++ frame/proxy/src/tests.rs | 5 ++++- primitives/application-crypto/Cargo.toml | 11 ++++++++++- primitives/application-crypto/src/lib.rs | 3 +++ primitives/authority-discovery/Cargo.toml | 4 +++- primitives/consensus/aura/Cargo.toml | 2 ++ primitives/consensus/babe/Cargo.toml | 2 ++ primitives/core/src/ecdsa.rs | 2 +- primitives/core/src/ed25519.rs | 5 ++++- primitives/core/src/sr25519.rs | 5 ++++- primitives/finality-grandpa/Cargo.toml | 2 ++ 14 files changed, 49 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5fc1e79b89343..aac23c6040de5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4247,6 +4247,7 @@ name = "node-primitives" version = "2.0.0" dependencies = [ "frame-system", + "max-encoded-len", "parity-scale-codec", "pretty_assertions 0.6.1", "sp-application-crypto", @@ -4988,6 +4989,7 @@ dependencies = [ "frame-system", "lite-json", "log", + "max-encoded-len", "parity-scale-codec", "sp-core", "sp-io", @@ -5080,6 +5082,7 @@ dependencies = [ "frame-support", "frame-system", "log", + "max-encoded-len", "pallet-authorship", "pallet-session", "parity-scale-codec", @@ -8589,6 +8592,7 @@ dependencies = [ name = "sp-application-crypto" version = "3.0.0" dependencies = [ + "max-encoded-len", "parity-scale-codec", "serde", "sp-core", @@ -8640,6 +8644,7 @@ dependencies = [ name = "sp-authority-discovery" version = "3.0.0" dependencies = [ + "max-encoded-len", "parity-scale-codec", "sp-api", "sp-application-crypto", @@ -8726,6 +8731,7 @@ name = "sp-consensus-aura" version = "0.9.0" dependencies = [ "async-trait", + "max-encoded-len", "parity-scale-codec", "sp-api", "sp-application-crypto", @@ -8742,6 +8748,7 @@ name = "sp-consensus-babe" version = "0.9.0" dependencies = [ "async-trait", + "max-encoded-len", "merlin", "parity-scale-codec", "serde", @@ -8872,6 +8879,7 @@ version = "3.0.0" dependencies = [ "finality-grandpa", "log", + "max-encoded-len", "parity-scale-codec", "serde", "sp-api", diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 043ec5ab21cec..a1ea46b2abce7 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -16,6 +16,7 @@ frame-system = { version = "3.0.0", default-features = false, path = "../../../f sp-application-crypto = { version = "3.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "3.0.0", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../../primitives/runtime" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-serializer = { version = "3.0.0", path = "../../../primitives/serializer" } @@ -29,4 +30,5 @@ std = [ "sp-application-crypto/std", "sp-core/std", "sp-runtime/std", + "max-encoded-len/std", ] diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index ea9fb9699ec64..75206ceee5cbd 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -23,6 +23,7 @@ sp-runtime = { version = "3.0.0", default-features = false, path = "../../primit sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } lite-json = { version = "0.1", default-features = false } log = { version = "0.4.14", default-features = false } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -37,5 +38,6 @@ std = [ "sp-runtime/std", "sp-std/std", "log/std", + "max-encoded-len/std", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 2e816a6bb8564..d3882610eedf7 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -24,6 +24,7 @@ sp-staking = { version = "3.0.0", default-features = false, path = "../../primit frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } @@ -44,6 +45,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "max-encoded-len/std", ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 04c90894eaaf6..fd632b91bb351 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -100,7 +100,10 @@ parameter_types! { pub const AnnouncementDepositBase: u64 = 1; pub const AnnouncementDepositFactor: u64 = 1; } -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)] +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, + max_encoded_len::MaxEncodedLen, +)] pub enum ProxyType { Any, JustTransfer, diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index fff289e9a1d86..3d0556d6bbbd2 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -20,10 +20,19 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = serde = { version = "1.0.101", optional = true, features = ["derive"] } sp-std = { version = "3.0.0", default-features = false, path = "../std" } sp-io = { version = "3.0.0", default-features = false, path = "../io" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } [features] default = [ "std" ] -std = [ "full_crypto", "sp-core/std", "codec/std", "serde", "sp-std/std", "sp-io/std" ] +std = [ + "full_crypto", + "sp-core/std", + "codec/std", + "serde", + "sp-std/std", + "sp-io/std", + "max-encoded-len/std", +] # This feature enables all crypto primitives for `no_std` builds like microcontrollers # or Intel SGX. diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index d085d961a1026..b40df128dbf25 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -39,6 +39,8 @@ pub use sp_std::{ ops::Deref, vec::Vec, }; +#[doc(hidden)] +pub use max_encoded_len; pub mod ed25519; pub mod sr25519; @@ -198,6 +200,7 @@ macro_rules! app_crypto_public_full_crypto { $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, + $crate::max_encoded_len::MaxEncodedLen, )] #[derive(Hash)] pub struct Public($public); diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index a32b13ca728d8..854ecc497c25b 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -18,6 +18,7 @@ codec = { package = "parity-scale-codec", default-features = false, version = "2 sp-std = { version = "3.0.0", default-features = false, path = "../std" } sp-api = { version = "3.0.0", default-features = false, path = "../api" } sp-runtime = { version = "3.0.0", default-features = false, path = "../runtime" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -26,5 +27,6 @@ std = [ "codec/std", "sp-std/std", "sp-api/std", - "sp-runtime/std" + "sp-runtime/std", + "max-encoded-len/std", ] diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 2ae4259a21e50..726cba0c0f988 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -23,6 +23,7 @@ sp-timestamp = { version = "3.0.0", default-features = false, path = "../../time sp-consensus-slots = { version = "0.9.0", default-features = false, path = "../slots" } sp-consensus = { version = "0.9.0", path = "../common", optional = true } async-trait = { version = "0.1.48", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -37,4 +38,5 @@ std = [ "sp-consensus-slots/std", "sp-consensus", "async-trait", + "max-encoded-len/std", ] diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 0fc09e11032b0..72497da550b42 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -28,6 +28,7 @@ sp-runtime = { version = "3.0.0", default-features = false, path = "../../runtim sp-timestamp = { version = "3.0.0", path = "../../timestamp", optional = true } serde = { version = "1.0.123", features = ["derive"], optional = true } async-trait = { version = "0.1.48", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -47,4 +48,5 @@ std = [ "serde", "sp-timestamp", "async-trait", + "max-encoded-len/std", ] diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index ee4f8f811bc4c..af8ff37822040 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -52,7 +52,7 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds"); type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[derive(Clone, Encode, Decode, PassByInner)] +#[derive(Clone, Encode, Decode, PassByInner, max_encoded_len::MaxEncodedLen)] pub struct Public(pub [u8; 33]); impl PartialOrd for Public { diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index 3269f70be1ee1..952201297b71f 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -54,7 +54,10 @@ type Seed = [u8; 32]; /// A public key. #[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner)] +#[derive( + PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner, + max_encoded_len::MaxEncodedLen, +)] pub struct Public(pub [u8; 32]); /// A key pair. diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 37926d8f801c5..c2ecef53a8826 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -60,7 +60,10 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25"); /// An Schnorrkel/Ristretto x25519 ("sr25519") public key. #[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner)] +#[derive( + PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner, + max_encoded_len::MaxEncodedLen, +)] pub struct Public(pub [u8; 32]); /// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 95aa65c930f78..e07c233da3577 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -25,6 +25,7 @@ sp-core = { version = "3.0.0", default-features = false, path = "../core" } sp-keystore = { version = "0.9.0", default-features = false, path = "../keystore", optional = true } sp-runtime = { version = "3.0.0", default-features = false, path = "../runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../std" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -39,4 +40,5 @@ std = [ "sp-keystore", "sp-runtime/std", "sp-std/std", + "max-encoded-len/std", ] From 5af7c4c08e0b2d6fe99ee9999b7673a95a9a3017 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 21 May 2021 11:19:26 +0200 Subject: [PATCH 22/45] use weak bounded vec in some cases --- frame/balances/src/lib.rs | 6 +++--- frame/support/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 2652936d03b12..927b95537b2d6 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -159,7 +159,7 @@ use sp_std::prelude::*; use sp_std::{cmp, result, mem, fmt::Debug, ops::BitOr}; use codec::{Codec, Encode, Decode}; use frame_support::{ - ensure, BoundedVec, + ensure, WeakBoundedVec, traits::{ Currency, OnUnbalanced, TryDrop, StoredMap, MaxEncodedLen, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, @@ -442,7 +442,7 @@ pub mod pallet { _, Blake2_128Concat, T::AccountId, - BoundedVec, T::MaxLocks>, + WeakBoundedVec, T::MaxLocks>, ValueQuery, GetDefault, ConstU32<300_000>, @@ -832,7 +832,7 @@ impl, I: 'static> Pallet { /// Update the account entry for `who`, given the locks. fn update_locks(who: &T::AccountId, locks: &[BalanceLock]) { let bounded_locks = unsafe { - BoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")) + WeakBoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")) }; if locks.len() as u32 > T::MaxLocks::get() { diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 20cac02e2bd4e..e599a1072304a 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -76,7 +76,7 @@ pub use self::hash::{ pub use self::storage::{ StorageValue, StorageMap, StorageDoubleMap, StorageNMap, StoragePrefixedMap, IterableStorageMap, IterableStorageDoubleMap, IterableStorageNMap, migration, - bounded_vec::{self, BoundedVec}, + bounded_vec::BoundedVec, weak_bounded_vec::WeakBoundedVec, }; pub use self::dispatch::{Parameter, Callable}; pub use sp_runtime::{self, ConsensusEngineId, print, traits::Printable}; From 7683f736a209f25540ae877eb9be1d07d8cc9626 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 22 May 2021 13:44:07 -0400 Subject: [PATCH 23/45] Update lib.rs --- frame/balances/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 927b95537b2d6..7850852374aec 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -831,9 +831,7 @@ impl, I: 'static> Pallet { /// Update the account entry for `who`, given the locks. fn update_locks(who: &T::AccountId, locks: &[BalanceLock]) { - let bounded_locks = unsafe { - WeakBoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")) - }; + let bounded_locks = WeakBoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")); if locks.len() as u32 > T::MaxLocks::get() { log::warn!( From 0c09750a3f3590c2171bd295c30e8612f3c9e5f0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 22 May 2021 14:02:53 -0400 Subject: [PATCH 24/45] move max-encoded-len crate --- Cargo.lock | 22 +- Cargo.toml | 6 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/example-offchain-worker/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- .../Cargo.toml | 0 .../derive/Cargo.toml | 2 +- .../derive/src/lib.rs | 2 +- max-encoded-len/derive/tools/Cargo.toml | 19 ++ .../derive/tools/derive/Cargo.toml | 20 ++ .../derive/tools/derive/src/lib.rs | 172 +++++++++++++ max-encoded-len/derive/tools/src/lib.rs | 106 ++++++++ max-encoded-len/derive/tools/src/syn_ext.rs | 239 ++++++++++++++++++ .../src/lib.rs | 0 .../tests/max_encoded_len.rs | 0 .../tests/max_encoded_len_ui.rs | 0 .../tests/max_encoded_len_ui/not_encode.rs | 0 .../max_encoded_len_ui/not_encode.stderr | 2 +- .../tests/max_encoded_len_ui/not_mel.rs | 0 .../tests/max_encoded_len_ui/not_mel.stderr | 0 .../tests/max_encoded_len_ui/union.rs | 0 .../tests/max_encoded_len_ui/union.stderr | 0 .../max_encoded_len_ui/unsupported_variant.rs | 0 .../unsupported_variant.stderr | 0 primitives/application-crypto/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 2 +- primitives/consensus/aura/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- 36 files changed, 599 insertions(+), 21 deletions(-) rename {frame/max-encoded-len => max-encoded-len}/Cargo.toml (100%) rename {frame/max-encoded-len => max-encoded-len}/derive/Cargo.toml (84%) rename {frame/max-encoded-len => max-encoded-len}/derive/src/lib.rs (98%) create mode 100644 max-encoded-len/derive/tools/Cargo.toml create mode 100644 max-encoded-len/derive/tools/derive/Cargo.toml create mode 100644 max-encoded-len/derive/tools/derive/src/lib.rs create mode 100644 max-encoded-len/derive/tools/src/lib.rs create mode 100644 max-encoded-len/derive/tools/src/syn_ext.rs rename {frame/max-encoded-len => max-encoded-len}/src/lib.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/not_encode.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/not_encode.stderr (92%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/not_mel.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/not_mel.stderr (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/union.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/union.stderr (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/unsupported_variant.rs (100%) rename {frame/max-encoded-len => max-encoded-len}/tests/max_encoded_len_ui/unsupported_variant.stderr (100%) diff --git a/Cargo.lock b/Cargo.lock index aac23c6040de5..bf553f9f5039f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3734,10 +3734,10 @@ dependencies = [ name = "max-encoded-len-derive" version = "3.0.0" dependencies = [ - "frame-support-procedural-tools", "proc-macro2", "quote", "syn", + "temp-procedural-tools", ] [[package]] @@ -9773,6 +9773,17 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" +[[package]] +name = "temp-procedural-tools" +version = "3.0.0" +dependencies = [ + "proc-macro-crate 1.0.0", + "proc-macro2", + "quote", + "syn", + "test-procedural-tools-derive", +] + [[package]] name = "tempfile" version = "3.2.0" @@ -9796,6 +9807,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-procedural-tools-derive" +version = "3.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "test-runner" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index bc56536647499..5dbb68a0fb91c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,8 +90,6 @@ members = [ "frame/im-online", "frame/indices", "frame/lottery", - "frame/max-encoded-len", - "frame/max-encoded-len/derive", "frame/membership", "frame/merkle-mountain-range", "frame/merkle-mountain-range/primitives", @@ -204,6 +202,10 @@ members = [ "utils/frame/rpc/system", "utils/prometheus", "utils/wasm-builder", + # temp deps + "max-encoded-len", + "max-encoded-len/derive", + "max-encoded-len/derive/tools", ] # The list of dependencies below (which can be both direct and indirect dependencies) are crates diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index a1ea46b2abce7..d4610b89c877e 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -16,7 +16,7 @@ frame-system = { version = "3.0.0", default-features = false, path = "../../../f sp-application-crypto = { version = "3.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "3.0.0", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../../primitives/runtime" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-serializer = { version = "3.0.0", path = "../../../primitives/serializer" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 792c4df7ab0e7..d1d95e4cb0c2f 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -87,7 +87,7 @@ pallet-transaction-payment = { version = "3.0.0", default-features = false, path pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } pallet-vesting = { version = "3.0.0", default-features = false, path = "../../../frame/vesting" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [build-dependencies] substrate-wasm-builder = { version = "4.0.0", path = "../../../utils/wasm-builder" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index db03959616475..7afd08d8c11f9 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { version = "3.0.0", default-features = false, path = "../suppor # `system` module provides us with all sorts of useful stuff and macros depend on it being around. frame-system = { version = "3.0.0", default-features = false, path = "../system" } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-core = { version = "3.0.0", path = "../../primitives/core" } diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 667724ae3d0cc..c4ab509aa0d4e 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -20,7 +20,7 @@ frame-benchmarking = { version = "3.1.0", default-features = false, path = "../b frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-io = { version = "3.0.0", path = "../../primitives/io" } diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index 75206ceee5cbd..3c4ca167b143f 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -23,7 +23,7 @@ sp-runtime = { version = "3.0.0", default-features = false, path = "../../primit sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } lite-json = { version = "0.1", default-features = false } log = { version = "0.4.14", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index d3882610eedf7..a63da50368983 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -24,7 +24,7 @@ sp-staking = { version = "3.0.0", default-features = false, path = "../../primit frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 992d18fcc3f86..deec8aab72682 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -20,7 +20,7 @@ sp-core = { version = "3.0.0", default-features = false, path = "../../primitive sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 5ef6ec3b4c1d9..0c9aacaf307b1 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "13.0.0", default-features = false, path = "../metadata" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/max-encoded-len/Cargo.toml b/max-encoded-len/Cargo.toml similarity index 100% rename from frame/max-encoded-len/Cargo.toml rename to max-encoded-len/Cargo.toml diff --git a/frame/max-encoded-len/derive/Cargo.toml b/max-encoded-len/derive/Cargo.toml similarity index 84% rename from frame/max-encoded-len/derive/Cargo.toml rename to max-encoded-len/derive/Cargo.toml index c8d33bef1c6a5..88338727ae6f7 100644 --- a/frame/max-encoded-len/derive/Cargo.toml +++ b/max-encoded-len/derive/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -frame-support-procedural-tools = { version = "3.0.0", path = "../../support/procedural/tools" } +temp-procedural-tools = { version = "3.0.0", path = "tools" } proc-macro2 = "1.0.6" quote = "1.0.3" syn = { version = "1.0.58", features = ["full"] } diff --git a/frame/max-encoded-len/derive/src/lib.rs b/max-encoded-len/derive/src/lib.rs similarity index 98% rename from frame/max-encoded-len/derive/src/lib.rs rename to max-encoded-len/derive/src/lib.rs index 75484ad963204..6cceefcdb7b7c 100644 --- a/frame/max-encoded-len/derive/src/lib.rs +++ b/max-encoded-len/derive/src/lib.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use frame_support_procedural_tools::generate_crate_access_2018; +use temp_procedural_tools::generate_crate_access_2018; use quote::{quote, quote_spanned}; use syn::{ Data, DeriveInput, Fields, GenericParam, Generics, TraitBound, Type, TypeParamBound, diff --git a/max-encoded-len/derive/tools/Cargo.toml b/max-encoded-len/derive/tools/Cargo.toml new file mode 100644 index 0000000000000..bdec9e3b6ffa8 --- /dev/null +++ b/max-encoded-len/derive/tools/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "temp-procedural-tools" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Proc macro helpers for procedural macros" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +test-procedural-tools-derive = { version = "3.0.0", path = "./derive" } +proc-macro2 = "1.0.6" +quote = "1.0.3" +syn = { version = "1.0.58", features = ["full", "visit"] } +proc-macro-crate = "1.0.0" diff --git a/max-encoded-len/derive/tools/derive/Cargo.toml b/max-encoded-len/derive/tools/derive/Cargo.toml new file mode 100644 index 0000000000000..03910a617e6d4 --- /dev/null +++ b/max-encoded-len/derive/tools/derive/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "test-procedural-tools-derive" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Use to derive parsing for parsing struct." + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.6" +quote = { version = "1.0.3", features = ["proc-macro"] } +syn = { version = "1.0.58", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/max-encoded-len/derive/tools/derive/src/lib.rs b/max-encoded-len/derive/tools/derive/src/lib.rs new file mode 100644 index 0000000000000..15394e0c559d4 --- /dev/null +++ b/max-encoded-len/derive/tools/derive/src/lib.rs @@ -0,0 +1,172 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// tag::description[] +//! Use to derive parsing for parsing struct. +// end::description[] + +#![recursion_limit = "128"] + +use proc_macro::TokenStream; +use proc_macro2::Span; +use syn::parse_macro_input; +use quote::quote; + +pub(crate) fn fields_idents( + fields: impl Iterator, +) -> impl Iterator { + fields.enumerate().map(|(ix, field)| { + field.ident.map(|i| quote!{#i}).unwrap_or_else(|| { + let f_ix: syn::Ident = syn::Ident::new(&format!("f_{}", ix), Span::call_site()); + quote!( #f_ix ) + }) + }) +} + +pub(crate) fn fields_access( + fields: impl Iterator, +) -> impl Iterator { + fields.enumerate().map(|(ix, field)| { + field.ident.map(|i| quote!( #i )).unwrap_or_else(|| { + let f_ix: syn::Index = syn::Index { + index: ix as u32, + span: Span::call_site(), + }; + quote!( #f_ix ) + }) + }) +} + +/// self defined parsing struct. +/// not meant for any struct, just for fast +/// parse implementation. +#[proc_macro_derive(Parse)] +pub fn derive_parse(input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as syn::Item); + match item { + syn::Item::Struct(input) => derive_parse_struct(input), + _ => TokenStream::new(), // ignore + } +} + +fn derive_parse_struct(input: syn::ItemStruct) -> TokenStream { + let syn::ItemStruct { + ident, + generics, + fields, + .. + } = input; + let field_names = { + let name = fields_idents(fields.iter().map(Clone::clone)); + quote!{ + #( + #name, + )* + } + }; + let field = fields_idents(fields.iter().map(Clone::clone)); + let tokens = quote! { + impl #generics syn::parse::Parse for #ident #generics { + fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { + #( + let #field = input.parse()?; + )* + Ok(Self { + #field_names + }) + } + } + }; + tokens.into() +} + +/// self defined parsing struct or enum. +/// not meant for any struct/enum, just for fast +/// parse implementation. +/// For enum: +/// it only output fields (empty field act as a None). +#[proc_macro_derive(ToTokens)] +pub fn derive_totokens(input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as syn::Item); + match item { + syn::Item::Enum(input) => derive_totokens_enum(input), + syn::Item::Struct(input) => derive_totokens_struct(input), + _ => TokenStream::new(), // ignore + } +} + +fn derive_totokens_struct(input: syn::ItemStruct) -> TokenStream { + let syn::ItemStruct { + ident, + generics, + fields, + .. + } = input; + + let fields = fields_access(fields.iter().map(Clone::clone)); + let tokens = quote! { + + impl #generics quote::ToTokens for #ident #generics { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + #( + self.#fields.to_tokens(tokens); + )* + } + } + + }; + tokens.into() +} + +fn derive_totokens_enum(input: syn::ItemEnum) -> TokenStream { + let syn::ItemEnum { + ident, + generics, + variants, + .. + } = input; + let variants = variants.iter().map(|v| { + let v_ident = v.ident.clone(); + let fields_build = if v.fields.iter().count() > 0 { + let fields_id = fields_idents(v.fields.iter().map(Clone::clone)); + quote!( (#(#fields_id), *) ) + } else { + quote!() + }; + let field = fields_idents(v.fields.iter().map(Clone::clone)); + quote! { + #ident::#v_ident#fields_build => { + #( + #field.to_tokens(tokens); + )* + }, + } + }); + let tokens = quote! { + impl #generics quote::ToTokens for #ident #generics { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match self { + #( + #variants + )* + } + } + } + }; + + tokens.into() +} diff --git a/max-encoded-len/derive/tools/src/lib.rs b/max-encoded-len/derive/tools/src/lib.rs new file mode 100644 index 0000000000000..38933490c6d98 --- /dev/null +++ b/max-encoded-len/derive/tools/src/lib.rs @@ -0,0 +1,106 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// tag::description[] +//! Proc macro helpers for procedural macros +// end::description[] + +// reexport proc macros +pub use test_procedural_tools_derive::*; + +use proc_macro_crate::{crate_name, FoundCrate}; +use syn::parse::Error; +use quote::quote; + +pub mod syn_ext; + +// FIXME #1569, remove the following functions, which are copied from sp-api-macros +use proc_macro2::{TokenStream, Span}; +use syn::Ident; + +fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident { + Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site()) +} + +/// Generates the access to the `frame-support` crate. +pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream { + if std::env::var("CARGO_PKG_NAME").unwrap() == def_crate { + quote::quote!( frame_support ) + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + quote::quote!( self::#mod_name::hidden_include ) + } +} + +/// Generate the crate access for the crate using 2018 syntax. +/// +/// for `frame-support` output will for example be `frame_support`. +pub fn generate_crate_access_2018(def_crate: &str) -> Result { + match crate_name(def_crate) { + Ok(FoundCrate::Itself) => { + let name = def_crate.to_string().replace("-", "_"); + Ok(syn::Ident::new(&name, Span::call_site())) + }, + Ok(FoundCrate::Name(name)) => { + Ok(Ident::new(&name, Span::call_site())) + }, + Err(e) => { + Err(Error::new(Span::call_site(), e)) + } + } +} + +/// Generates the hidden includes that are required to make the macro independent from its scope. +pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream { + let mod_name = generate_hidden_includes_mod_name(unique_id); + + match crate_name(def_crate) { + Ok(FoundCrate::Itself) => quote!(), + Ok(FoundCrate::Name(name)) => { + let name = Ident::new(&name, Span::call_site()); + quote::quote!( + #[doc(hidden)] + mod #mod_name { + pub extern crate #name as hidden_include; + } + ) + }, + Err(e) => { + let err = Error::new(Span::call_site(), e).to_compile_error(); + quote!( #err ) + } + } +} + +// fn to remove white spaces around string types +// (basically whitespaces around tokens) +pub fn clean_type_string(input: &str) -> String { + input + .replace(" ::", "::") + .replace(":: ", "::") + .replace(" ,", ",") + .replace(" ;", ";") + .replace(" [", "[") + .replace("[ ", "[") + .replace(" ]", "]") + .replace(" (", "(") + .replace("( ", "(") + .replace(" )", ")") + .replace(" <", "<") + .replace("< ", "<") + .replace(" >", ">") +} diff --git a/max-encoded-len/derive/tools/src/syn_ext.rs b/max-encoded-len/derive/tools/src/syn_ext.rs new file mode 100644 index 0000000000000..34b914ecc2a76 --- /dev/null +++ b/max-encoded-len/derive/tools/src/syn_ext.rs @@ -0,0 +1,239 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// tag::description[] +//! Extension to syn types, mainly for parsing +// end::description[] + +use syn::{visit::{Visit, self}, parse::{Parse, ParseStream, Result}, Ident}; +use proc_macro2::{TokenStream, TokenTree}; +use quote::ToTokens; +use std::iter::once; +use test_procedural_tools_derive::{ToTokens, Parse}; + +/// stop parsing here getting remaining token as content +/// Warn duplicate stream (part of) +#[derive(Parse, ToTokens, Debug)] +pub struct StopParse { + pub inner: TokenStream, +} + +// inner macro really dependant on syn naming convention, do not export +macro_rules! groups_impl { + ($name:ident, $tok:ident, $deli:ident, $parse:ident) => { + + #[derive(Debug)] + pub struct $name

{ + pub token: syn::token::$tok, + pub content: P, + } + + impl Parse for $name

{ + fn parse(input: ParseStream) -> Result { + let syn::group::$name { token, content } = syn::group::$parse(input)?; + let content = content.parse()?; + Ok($name { token, content, }) + } + } + + impl ToTokens for $name

{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut inner_stream = TokenStream::new(); + self.content.to_tokens(&mut inner_stream); + let token_tree: proc_macro2::TokenTree = + proc_macro2::Group::new(proc_macro2::Delimiter::$deli, inner_stream).into(); + tokens.extend(once(token_tree)); + } + } + + impl Clone for $name

{ + fn clone(&self) -> Self { + Self { token: self.token.clone(), content: self.content.clone() } + } + } + } +} + +groups_impl!(Braces, Brace, Brace, parse_braces); +groups_impl!(Brackets, Bracket, Bracket, parse_brackets); +groups_impl!(Parens, Paren, Parenthesis, parse_parens); + +#[derive(Debug)] +pub struct PunctuatedInner { + pub inner: syn::punctuated::Punctuated, + pub variant: V, +} + +#[derive(Debug, Clone)] +pub struct NoTrailing; + + +#[derive(Debug, Clone)] +pub struct Trailing; + +pub type Punctuated = PunctuatedInner; + +pub type PunctuatedTrailing = PunctuatedInner; + +impl Parse for PunctuatedInner { + fn parse(input: ParseStream) -> Result { + Ok(PunctuatedInner { + inner: syn::punctuated::Punctuated::parse_separated_nonempty(input)?, + variant: Trailing, + }) + } +} + +impl Parse for PunctuatedInner { + fn parse(input: ParseStream) -> Result { + Ok(PunctuatedInner { + inner: syn::punctuated::Punctuated::parse_terminated(input)?, + variant: NoTrailing, + }) + } +} + +impl ToTokens for PunctuatedInner { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.inner.to_tokens(tokens) + } +} + +impl Clone for PunctuatedInner { + fn clone(&self) -> Self { + Self { inner: self.inner.clone(), variant: self.variant.clone() } + } +} + +/// Note that syn Meta is almost fine for use case (lacks only `ToToken`) +#[derive(Debug, Clone)] +pub struct Meta { + pub inner: syn::Meta, +} + +impl Parse for Meta { + fn parse(input: ParseStream) -> Result { + Ok(Meta { + inner: syn::Meta::parse(input)?, + }) + } +} + +impl ToTokens for Meta { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self.inner { + syn::Meta::Path(ref path) => path.to_tokens(tokens), + syn::Meta::List(ref l) => l.to_tokens(tokens), + syn::Meta::NameValue(ref n) => n.to_tokens(tokens), + } + } +} + +#[derive(Debug)] +pub struct OuterAttributes { + pub inner: Vec, +} + +impl Parse for OuterAttributes { + fn parse(input: ParseStream) -> Result { + let inner = syn::Attribute::parse_outer(input)?; + Ok(OuterAttributes { + inner, + }) + } +} + +impl ToTokens for OuterAttributes { + fn to_tokens(&self, tokens: &mut TokenStream) { + for att in self.inner.iter() { + att.to_tokens(tokens); + } + } +} + +pub fn extract_type_option(typ: &syn::Type) -> Option { + if let syn::Type::Path(ref path) = typ { + let v = path.path.segments.last()?; + if v.ident == "Option" { + // Option has only one type argument in angle bracket. + if let syn::PathArguments::AngleBracketed(a) = &v.arguments { + if let syn::GenericArgument::Type(typ) = a.args.last()? { + return Some(typ.clone()) + } + } + } + } + + None +} + +/// Auxiliary structure to check if a given `Ident` is contained in an ast. +struct ContainsIdent<'a> { + ident: &'a Ident, + result: bool, +} + +impl<'ast> ContainsIdent<'ast> { + fn visit_tokenstream(&mut self, stream: TokenStream) { + stream.into_iter().for_each(|tt| + match tt { + TokenTree::Ident(id) => self.visit_ident(&id), + TokenTree::Group(ref group) => self.visit_tokenstream(group.stream()), + _ => {} + } + ) + } + + fn visit_ident(&mut self, ident: &Ident) { + if ident == self.ident { + self.result = true; + } + } +} + +impl<'ast> Visit<'ast> for ContainsIdent<'ast> { + fn visit_ident(&mut self, input: &'ast Ident) { + self.visit_ident(input); + } + + fn visit_macro(&mut self, input: &'ast syn::Macro) { + self.visit_tokenstream(input.tokens.clone()); + visit::visit_macro(self, input); + } +} + +/// Check if a `Type` contains the given `Ident`. +pub fn type_contains_ident(typ: &syn::Type, ident: &Ident) -> bool { + let mut visit = ContainsIdent { + result: false, + ident, + }; + + visit::visit_type(&mut visit, typ); + visit.result +} + +/// Check if a `Expr` contains the given `Ident`. +pub fn expr_contains_ident(expr: &syn::Expr, ident: &Ident) -> bool { + let mut visit = ContainsIdent { + result: false, + ident, + }; + + visit::visit_expr(&mut visit, expr); + visit.result +} diff --git a/frame/max-encoded-len/src/lib.rs b/max-encoded-len/src/lib.rs similarity index 100% rename from frame/max-encoded-len/src/lib.rs rename to max-encoded-len/src/lib.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len.rs b/max-encoded-len/tests/max_encoded_len.rs similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len.rs rename to max-encoded-len/tests/max_encoded_len.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui.rs b/max-encoded-len/tests/max_encoded_len_ui.rs similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui.rs rename to max-encoded-len/tests/max_encoded_len_ui.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs b/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs rename to max-encoded-len/tests/max_encoded_len_ui/not_encode.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr b/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr similarity index 92% rename from frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr rename to max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr index 111e63e3f1e30..1e0ead0854a0e 100644 --- a/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr +++ b/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `NotEncode: parity_scale_codec::codec::WrapperType 3 | #[derive(MaxEncodedLen)] | ^^^^^^^^^^^^^ the trait `parity_scale_codec::codec::WrapperTypeEncode` is not implemented for `NotEncode` | - ::: $WORKSPACE/frame/max-encoded-len/src/lib.rs + ::: $WORKSPACE/max-encoded-len/src/lib.rs | | pub trait MaxEncodedLen: Encode { | ------ required by this bound in `MaxEncodedLen` diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs b/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs rename to max-encoded-len/tests/max_encoded_len_ui/not_mel.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr b/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr rename to max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/union.rs b/max-encoded-len/tests/max_encoded_len_ui/union.rs similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/union.rs rename to max-encoded-len/tests/max_encoded_len_ui/union.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr b/max-encoded-len/tests/max_encoded_len_ui/union.stderr similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr rename to max-encoded-len/tests/max_encoded_len_ui/union.stderr diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs b/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs rename to max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr b/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr similarity index 100% rename from frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr rename to max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 3d0556d6bbbd2..7f3e48ae48255 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = serde = { version = "1.0.101", optional = true, features = ["derive"] } sp-std = { version = "3.0.0", default-features = false, path = "../std" } sp-io = { version = "3.0.0", default-features = false, path = "../io" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = [ "std" ] diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 854ecc497c25b..6c59b3782a545 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", default-features = false, version = "2 sp-std = { version = "3.0.0", default-features = false, path = "../std" } sp-api = { version = "3.0.0", default-features = false, path = "../api" } sp-runtime = { version = "3.0.0", default-features = false, path = "../runtime" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 726cba0c0f988..11d978912f6b9 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -23,7 +23,7 @@ sp-timestamp = { version = "3.0.0", default-features = false, path = "../../time sp-consensus-slots = { version = "0.9.0", default-features = false, path = "../slots" } sp-consensus = { version = "0.9.0", path = "../common", optional = true } async-trait = { version = "0.1.48", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 72497da550b42..a527d15af85a7 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -28,7 +28,7 @@ sp-runtime = { version = "3.0.0", default-features = false, path = "../../runtim sp-timestamp = { version = "3.0.0", path = "../../timestamp", optional = true } serde = { version = "1.0.123", features = ["derive"], optional = true } async-trait = { version = "0.1.48", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 071f6821f2930..79973bc78257c 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -40,7 +40,7 @@ parity-util-mem = { version = "0.9.0", default-features = false, features = ["pr futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.21", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } # full crypto ed25519-dalek = { version = "1.0.1", default-features = false, features = ["u64_backend", "alloc"], optional = true } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index e07c233da3577..5b6b7f60001ff 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -25,7 +25,7 @@ sp-core = { version = "3.0.0", default-features = false, path = "../core" } sp-keystore = { version = "0.9.0", default-features = false, path = "../keystore", optional = true } sp-runtime = { version = "3.0.0", default-features = false, path = "../runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../std" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 646c7e4d10abe..aec2bc416ee37 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -29,7 +29,7 @@ impl-trait-for-tuples = "0.2.1" parity-util-mem = { version = "0.9.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [dev-dependencies] serde_json = "1.0.41" From d93b50354cbe3083e5d9c05f19d26fa97608e4ce Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 22 May 2021 14:30:05 -0400 Subject: [PATCH 25/45] fix --- Cargo.lock | 1 + bin/node/executor/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index bf553f9f5039f..8f1083a188392 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4198,6 +4198,7 @@ dependencies = [ "frame-support", "frame-system", "futures 0.3.13", + "max-encoded-len", "node-primitives", "node-runtime", "node-testing", diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 54a44d59c2591..2581181f6e4f5 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -45,6 +45,7 @@ sp-externalities = { version = "0.9.0", path = "../../../primitives/externalitie substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } wat = "1.0" futures = "0.3.9" +max-encoded-len = { version = "3.0.0", path = "../../../max-encoded-len" } [features] wasmtime = [ From 73623e9933d50648e0e7fe90b6171a8e45d7f5a2 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 25 May 2021 17:36:36 -0400 Subject: [PATCH 26/45] remove app crypto for now --- primitives/application-crypto/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index b40df128dbf25..f1209fd83e011 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -200,7 +200,6 @@ macro_rules! app_crypto_public_full_crypto { $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, - $crate::max_encoded_len::MaxEncodedLen, )] #[derive(Hash)] pub struct Public($public); From 1bb36fd543cbe8379a91ef7954059cf7624aa435 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 25 May 2021 17:47:32 -0400 Subject: [PATCH 27/45] width --- frame/assets/src/lib.rs | 11 +++++++++-- frame/balances/src/lib.rs | 5 ++++- max-encoded-len/src/lib.rs | 10 +++++----- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 63f2d6ca830f7..ccbe1920e9974 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -1003,8 +1003,15 @@ pub mod pallet { ) -> DispatchResult { T::ForceOrigin::ensure_origin(origin)?; - let bounded_name: BoundedVec = name.clone().try_into().map_err(|_| Error::::BadMetadata)?; - let bounded_symbol: BoundedVec = symbol.clone().try_into().map_err(|_| Error::::BadMetadata)?; + let bounded_name: BoundedVec = name + .clone() + .try_into() + .map_err(|_| Error::::BadMetadata)?; + + let bounded_symbol: BoundedVec = symbol + .clone() + .try_into() + .map_err(|_| Error::::BadMetadata)?; ensure!(Asset::::contains_key(id), Error::::Unknown); Metadata::::try_mutate_exists(id, |metadata| { diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index f5eec4edc95ce..04dacc7858646 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -827,7 +827,10 @@ impl, I: 'static> Pallet { /// Update the account entry for `who`, given the locks. fn update_locks(who: &T::AccountId, locks: &[BalanceLock]) { - let bounded_locks = WeakBoundedVec::<_, T::MaxLocks>::force_from(locks.to_vec(), Some("Balances Update Locks")); + let bounded_locks = WeakBoundedVec::<_, T::MaxLocks>::force_from( + locks.to_vec(), + Some("Balances Update Locks"), + ); if locks.len() as u32 > T::MaxLocks::get() { log::warn!( diff --git a/max-encoded-len/src/lib.rs b/max-encoded-len/src/lib.rs index 13c99f4e5b0ce..c2287997f344d 100644 --- a/max-encoded-len/src/lib.rs +++ b/max-encoded-len/src/lib.rs @@ -65,15 +65,15 @@ macro_rules! impl_compact { } impl_compact!( - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L261 + // github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L261 u8 => 2; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L291 + // github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L291 u16 => 4; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L326 + // github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L326 u32 => 5; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L369 + // github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L369 u64 => 9; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L413 + // github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L413 u128 => 17; ); From f1e3ced92112f3c6e4f81d5ca3bf9b81f1d085ec Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 25 May 2021 18:42:33 -0400 Subject: [PATCH 28/45] Revert "remove app crypto for now" This reverts commit 73623e9933d50648e0e7fe90b6171a8e45d7f5a2. --- primitives/application-crypto/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index f1209fd83e011..b40df128dbf25 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -200,6 +200,7 @@ macro_rules! app_crypto_public_full_crypto { $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, + $crate::max_encoded_len::MaxEncodedLen, )] #[derive(Hash)] pub struct Public($public); From 747e613ec969b511aa57cacd3d8f9220c91eade5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 25 May 2021 22:47:29 -0400 Subject: [PATCH 29/45] unused variable --- frame/merkle-mountain-range/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/merkle-mountain-range/src/lib.rs b/frame/merkle-mountain-range/src/lib.rs index 6992341f6bbd1..a8e707c7ac4e0 100644 --- a/frame/merkle-mountain-range/src/lib.rs +++ b/frame/merkle-mountain-range/src/lib.rs @@ -154,7 +154,7 @@ decl_storage! { decl_module! { /// A public part of the pallet. pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { - fn on_initialize(n: T::BlockNumber) -> Weight { + fn on_initialize(_n: T::BlockNumber) -> Weight { use primitives::LeafDataProvider; let leaves = Self::mmr_leaves(); let peaks_before = mmr::utils::NodesUtils::new(leaves).number_of_peaks(); From 7af3dccbf3bb4184010427097f369e19c70089b7 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 25 May 2021 23:05:35 -0400 Subject: [PATCH 30/45] more unused variables --- frame/utility/src/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 1828418bd7fb8..def824c2421f6 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -42,13 +42,13 @@ pub mod example { decl_module! { pub struct Module for enum Call where origin: ::Origin { #[weight = *weight] - fn noop(_origin, weight: Weight) { } + fn noop(_origin, _weight: Weight) { } #[weight = *start_weight] fn foobar( origin, err: bool, - start_weight: Weight, + _start_weight: Weight, end_weight: Option, ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; From 0dd6403b64af54c4f36df03d77ee17ed1450ae1a Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 25 May 2021 23:23:24 -0400 Subject: [PATCH 31/45] more fixes --- frame/utility/src/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index def824c2421f6..6d9db2f0c612a 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -41,10 +41,10 @@ pub mod example { decl_module! { pub struct Module for enum Call where origin: ::Origin { - #[weight = *weight] + #[weight = *_weight] fn noop(_origin, _weight: Weight) { } - #[weight = *start_weight] + #[weight = *_start_weight] fn foobar( origin, err: bool, From b7620ef5812aa057ce216b97a58504e5fe453291 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Wed, 26 May 2021 13:03:19 +0200 Subject: [PATCH 32/45] Add #[max_encoded_len_crate(...)] helper attribute The purpose of this attribute is to reduce the surface area of max_encoded_len changes. Crates deriving `MaxEncodedLen` do not need to add it to `Cargo.toml`; they can instead just do ```rust \#[derive(Encode, MaxEncodedLen)] \#[max_encoded_len_crate(frame_support::max_encoded_len)] struct Example; ``` --- Cargo.lock | 5 +- frame/support/src/lib.rs | 4 ++ max-encoded-len/Cargo.toml | 1 + max-encoded-len/derive/src/lib.rs | 70 ++++++++++++++++--- max-encoded-len/src/lib.rs | 21 ++++++ .../max_encoded_len_ui/list_list_item.rs | 10 +++ .../max_encoded_len_ui/list_list_item.stderr | 18 +++++ .../max_encoded_len_ui/literal_list_item.rs | 10 +++ .../literal_list_item.stderr | 18 +++++ .../max_encoded_len_ui/name_value_attr.rs | 10 +++ .../max_encoded_len_ui/name_value_attr.stderr | 18 +++++ .../name_value_list_item.rs | 10 +++ .../name_value_list_item.stderr | 18 +++++ .../max_encoded_len_ui/no_path_list_items.rs | 10 +++ .../no_path_list_items.stderr | 18 +++++ .../tests/max_encoded_len_ui/path_attr.rs | 10 +++ .../tests/max_encoded_len_ui/path_attr.stderr | 18 +++++ .../max_encoded_len_ui/two_path_list_items.rs | 10 +++ .../two_path_list_items.stderr | 18 +++++ 19 files changed, 286 insertions(+), 11 deletions(-) create mode 100644 max-encoded-len/tests/max_encoded_len_ui/list_list_item.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/list_list_item.stderr create mode 100644 max-encoded-len/tests/max_encoded_len_ui/literal_list_item.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/literal_list_item.stderr create mode 100644 max-encoded-len/tests/max_encoded_len_ui/name_value_attr.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/name_value_attr.stderr create mode 100644 max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.stderr create mode 100644 max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.stderr create mode 100644 max-encoded-len/tests/max_encoded_len_ui/path_attr.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/path_attr.stderr create mode 100644 max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.rs create mode 100644 max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.stderr diff --git a/Cargo.lock b/Cargo.lock index 83f4023d1bfa4..2061dbc9fe688 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3727,6 +3727,7 @@ dependencies = [ name = "max-encoded-len" version = "3.0.0" dependencies = [ + "frame-support", "impl-trait-for-tuples", "max-encoded-len-derive", "parity-scale-codec", @@ -5668,9 +5669,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731f4d179ed52b1c7eeb29baf29c604ea9301b889b23ce93660220a5465d5c6f" +checksum = "e0f518afaa5a47d0d6386229b0a6e01e86427291d643aa4cabb4992219f504f8" dependencies = [ "arrayvec 0.7.0", "bitvec", diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index e599a1072304a..f7a9375839a1b 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -2341,3 +2341,7 @@ pub mod pallet_prelude { /// * use the newest nightly possible. /// pub use frame_support_procedural::pallet; + +/// The `max_encoded_len` module contains the `MaxEncodedLen` trait and derive macro, which is +/// useful for computing upper bounds on storage size. +pub use max_encoded_len; diff --git a/max-encoded-len/Cargo.toml b/max-encoded-len/Cargo.toml index b5f97e54ad0f0..994a3c6a5e132 100644 --- a/max-encoded-len/Cargo.toml +++ b/max-encoded-len/Cargo.toml @@ -17,6 +17,7 @@ primitive-types = { version = "0.9.0", default-features = false, features = ["co [dev-dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] } +frame-support = { path = "../frame/support" } rustversion = "1.0.4" trybuild = "1.0.42" diff --git a/max-encoded-len/derive/src/lib.rs b/max-encoded-len/derive/src/lib.rs index 6cceefcdb7b7c..13bea24ba4d50 100644 --- a/max-encoded-len/derive/src/lib.rs +++ b/max-encoded-len/derive/src/lib.rs @@ -18,20 +18,19 @@ use temp_procedural_tools::generate_crate_access_2018; use quote::{quote, quote_spanned}; use syn::{ - Data, DeriveInput, Fields, GenericParam, Generics, TraitBound, Type, TypeParamBound, - parse_quote, spanned::Spanned, + Data, DeriveInput, Error, Fields, GenericParam, Generics, Meta, TraitBound, Type, + TypeParamBound, parse_quote, spanned::Spanned, }; - /// Derive `MaxEncodedLen`. -#[proc_macro_derive(MaxEncodedLen)] +#[proc_macro_derive(MaxEncodedLen, attributes(max_encoded_len_crate))] pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input: DeriveInput = match syn::parse(input) { Ok(input) => input, Err(e) => return e.to_compile_error().into(), }; - let mel_trait = match max_encoded_len_trait() { + let mel_trait = match max_encoded_len_trait(&input) { Ok(mel_trait) => mel_trait, Err(e) => return e.to_compile_error().into(), }; @@ -54,8 +53,62 @@ pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::Tok .into() } -fn max_encoded_len_trait() -> syn::Result { - let mel = generate_crate_access_2018("max-encoded-len")?; +fn max_encoded_len_trait(input: &DeriveInput) -> syn::Result { + let mel = { + const EXPECT_LIST: &str = "expect: #[max_encoded_len_crate(path::to::crate)]"; + const EXPECT_PATH: &str = "expect: path::to::crate"; + + macro_rules! return_err { + ($wrong_style:expr, $err:expr) => { + return Err(Error::new($wrong_style.span(), $err)) + }; + } + + let mut mel_crates = Vec::with_capacity(2); + mel_crates.extend(input + .attrs + .iter() + .filter(|attr| attr.path == parse_quote!(max_encoded_len_crate)) + .take(2) + .map(|attr| { + let meta_list = match attr.parse_meta()? { + Meta::List(meta_list) => meta_list, + Meta::Path(wrong_style) => return_err!(wrong_style, EXPECT_LIST), + Meta::NameValue(wrong_style) => return_err!(wrong_style, EXPECT_LIST), + }; + if meta_list.nested.len() != 1 { + return_err!(meta_list, "expected exactly 1 item"); + } + let first_nested = + meta_list.nested.into_iter().next().expect("length checked above"); + let meta = match first_nested { + syn::NestedMeta::Lit(l) => { + return_err!(l, "expected a path item, not a literal") + } + syn::NestedMeta::Meta(meta) => meta, + }; + let path = match meta { + Meta::Path(path) => path, + Meta::List(ref wrong_style) => return_err!(wrong_style, EXPECT_PATH), + Meta::NameValue(ref wrong_style) => return_err!(wrong_style, EXPECT_PATH), + }; + Ok(path) + }) + .collect::, _>>()?); + + // we have to return `Result` here in order to satisfy the trait + // bounds for `.or_else` for `generate_crate_access_2018`, even though `Option` + // would be more natural in this circumstance. + match mel_crates.len() { + 0 => Err(Error::new( + input.span(), + "this error is spurious and swallowed by the or_else below", + )), + 1 => Ok(mel_crates.into_iter().next().expect("length is checked")), + _ => return_err!(mel_crates[1], "duplicate max_encoded_len_crate definition"), + } + } + .or_else(|_| generate_crate_access_2018("max-encoded-len").map(|ident| ident.into()))?; Ok(parse_quote!(#mel::MaxEncodedLen)) } @@ -128,8 +181,7 @@ fn data_length_expr(data: &Data) -> proc_macro2::TokenStream { Data::Union(ref data) => { // https://github.com/paritytech/parity-scale-codec/ // blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/derive/src/encode.rs#L290-L293 - syn::Error::new(data.union_token.span(), "Union types are not supported") - .to_compile_error() + Error::new(data.union_token.span(), "Union types are not supported").to_compile_error() } } } diff --git a/max-encoded-len/src/lib.rs b/max-encoded-len/src/lib.rs index c2287997f344d..e216d3b174159 100644 --- a/max-encoded-len/src/lib.rs +++ b/max-encoded-len/src/lib.rs @@ -24,6 +24,27 @@ use impl_trait_for_tuples::impl_for_tuples; use core::{mem, marker::PhantomData}; use primitive_types::{H160, H256, H512}; +/// Derive macro for `MaxEncodedLen`. +/// +/// ``` +/// # use max_encoded_len::MaxEncodedLen; +/// # use codec::Encode; +/// #[derive(Encode, MaxEncodedLen)] +/// struct Example; +/// ``` +/// +/// Sometimes the `MaxEncodedLen` trait and macro are accessed without explicitly importing its +/// crate, notably via the `frame_support::max_encoded_len` re-binding. In these circumstances, +/// the derive macro needs some help to understand where its crate should be: +/// +/// ``` +/// # use codec::Encode; +/// use frame_support::max_encoded_len::MaxEncodedLen; +/// +/// #[derive(Encode, MaxEncodedLen)] +/// #[max_encoded_len_crate(frame_support::max_encoded_len)] +/// struct Example; +/// ``` #[cfg(feature = "derive")] pub use max_encoded_len_derive::MaxEncodedLen; diff --git a/max-encoded-len/tests/max_encoded_len_ui/list_list_item.rs b/max-encoded-len/tests/max_encoded_len_ui/list_list_item.rs new file mode 100644 index 0000000000000..0cb12991fab45 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/list_list_item.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate(foo())] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/list_list_item.stderr b/max-encoded-len/tests/max_encoded_len_ui/list_list_item.stderr new file mode 100644 index 0000000000000..4ecd40440a461 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/list_list_item.stderr @@ -0,0 +1,18 @@ +error: expect: path::to::crate + --> $DIR/list_list_item.rs:5:25 + | +5 | #[max_encoded_len_crate(foo())] + | ^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/list_list_item.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/max-encoded-len/tests/max_encoded_len_ui/literal_list_item.rs b/max-encoded-len/tests/max_encoded_len_ui/literal_list_item.rs new file mode 100644 index 0000000000000..f3f7a72d813b6 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/literal_list_item.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate("frame_support::max_encoded_len")] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/literal_list_item.stderr b/max-encoded-len/tests/max_encoded_len_ui/literal_list_item.stderr new file mode 100644 index 0000000000000..1182599912992 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/literal_list_item.stderr @@ -0,0 +1,18 @@ +error: expected a path item, not a literal + --> $DIR/literal_list_item.rs:5:25 + | +5 | #[max_encoded_len_crate("frame_support::max_encoded_len")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/literal_list_item.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/max-encoded-len/tests/max_encoded_len_ui/name_value_attr.rs b/max-encoded-len/tests/max_encoded_len_ui/name_value_attr.rs new file mode 100644 index 0000000000000..382310d3a7ddf --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/name_value_attr.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate = "frame_support::max_encoded_len"] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/name_value_attr.stderr b/max-encoded-len/tests/max_encoded_len_ui/name_value_attr.stderr new file mode 100644 index 0000000000000..4949631049bab --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/name_value_attr.stderr @@ -0,0 +1,18 @@ +error: expect: #[max_encoded_len_crate(path::to::crate)] + --> $DIR/name_value_attr.rs:5:3 + | +5 | #[max_encoded_len_crate = "frame_support::max_encoded_len"] + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/name_value_attr.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.rs b/max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.rs new file mode 100644 index 0000000000000..44f92e8d5d994 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate(path = "frame_support::max_encoded_len")] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.stderr b/max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.stderr new file mode 100644 index 0000000000000..2faa1108c49d7 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/name_value_list_item.stderr @@ -0,0 +1,18 @@ +error: expect: path::to::crate + --> $DIR/name_value_list_item.rs:5:25 + | +5 | #[max_encoded_len_crate(path = "frame_support::max_encoded_len")] + | ^^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/name_value_list_item.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.rs b/max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.rs new file mode 100644 index 0000000000000..069c8af5a77e5 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.stderr b/max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.stderr new file mode 100644 index 0000000000000..4d36039d33b3c --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/no_path_list_items.stderr @@ -0,0 +1,18 @@ +error: expect: #[max_encoded_len_crate(path::to::crate)] + --> $DIR/no_path_list_items.rs:5:3 + | +5 | #[max_encoded_len_crate] + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/no_path_list_items.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/max-encoded-len/tests/max_encoded_len_ui/path_attr.rs b/max-encoded-len/tests/max_encoded_len_ui/path_attr.rs new file mode 100644 index 0000000000000..069c8af5a77e5 --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/path_attr.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/path_attr.stderr b/max-encoded-len/tests/max_encoded_len_ui/path_attr.stderr new file mode 100644 index 0000000000000..84745efc5e6ff --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/path_attr.stderr @@ -0,0 +1,18 @@ +error: expect: #[max_encoded_len_crate(path::to::crate)] + --> $DIR/path_attr.rs:5:3 + | +5 | #[max_encoded_len_crate] + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/path_attr.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.rs b/max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.rs new file mode 100644 index 0000000000000..2b29648cbaa2d --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use frame_support::max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +#[max_encoded_len_crate(max_encoded_len, frame_support::max_encoded_len)] +struct Example; + +fn main() { + let _ = Example::max_encoded_len(); +} diff --git a/max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.stderr b/max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.stderr new file mode 100644 index 0000000000000..9252a4065f25e --- /dev/null +++ b/max-encoded-len/tests/max_encoded_len_ui/two_path_list_items.stderr @@ -0,0 +1,18 @@ +error: expected exactly 1 item + --> $DIR/two_path_list_items.rs:5:3 + | +5 | #[max_encoded_len_crate(max_encoded_len, frame_support::max_encoded_len)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `max_encoded_len` found for struct `Example` in the current scope + --> $DIR/two_path_list_items.rs:9:19 + | +6 | struct Example; + | --------------- function or associated item `max_encoded_len` not found for this +... +9 | let _ = Example::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item not found in `Example` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` From 8a812bb2f431c8154cc3f99eec5e585443daad0d Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Wed, 26 May 2021 14:23:48 +0200 Subject: [PATCH 33/45] fix a ui test --- .../test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 545520124bfee..6c92423c6a7fe 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -4,6 +4,6 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied 10 | #[pallet::generate_storage_info] | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | - = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `NMapKey` - = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, NMapKey, u32>` + = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key` + = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, Key, u32>` = note: required by `storage_info` From 04375ac050c87ea79ab85632124beab7afcac4f4 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Wed, 26 May 2021 14:39:26 +0200 Subject: [PATCH 34/45] use #[max_encoded_len_crate(...)] helper in app_crypto --- primitives/application-crypto/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index b40df128dbf25..58e5c5b7a311f 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -196,13 +196,13 @@ macro_rules! app_crypto_public_full_crypto { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( - Clone, Default, Eq, PartialEq, Ord, PartialOrd, + Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord, $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, $crate::max_encoded_len::MaxEncodedLen, )] - #[derive(Hash)] + #[max_encoded_len_crate($crate::max_encoded_len)] pub struct Public($public); } From d5f3ee6c5d0b4cc1291727a441b79c3cb3acbdcd Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Wed, 26 May 2021 15:07:18 +0200 Subject: [PATCH 35/45] remove max_encoded_len import where not necessary --- bin/node/executor/Cargo.toml | 1 - bin/node/primitives/Cargo.toml | 2 -- frame/example-offchain-worker/Cargo.toml | 2 -- frame/im-online/Cargo.toml | 2 -- primitives/authority-discovery/Cargo.toml | 4 +--- primitives/consensus/aura/Cargo.toml | 2 -- primitives/consensus/babe/Cargo.toml | 2 -- primitives/finality-grandpa/Cargo.toml | 2 -- 8 files changed, 1 insertion(+), 16 deletions(-) diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 2581181f6e4f5..54a44d59c2591 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -45,7 +45,6 @@ sp-externalities = { version = "0.9.0", path = "../../../primitives/externalitie substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } wat = "1.0" futures = "0.3.9" -max-encoded-len = { version = "3.0.0", path = "../../../max-encoded-len" } [features] wasmtime = [ diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index d4610b89c877e..043ec5ab21cec 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -16,7 +16,6 @@ frame-system = { version = "3.0.0", default-features = false, path = "../../../f sp-application-crypto = { version = "3.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "3.0.0", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../../primitives/runtime" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-serializer = { version = "3.0.0", path = "../../../primitives/serializer" } @@ -30,5 +29,4 @@ std = [ "sp-application-crypto/std", "sp-core/std", "sp-runtime/std", - "max-encoded-len/std", ] diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index 3c4ca167b143f..ea9fb9699ec64 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -23,7 +23,6 @@ sp-runtime = { version = "3.0.0", default-features = false, path = "../../primit sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } lite-json = { version = "0.1", default-features = false } log = { version = "0.4.14", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -38,6 +37,5 @@ std = [ "sp-runtime/std", "sp-std/std", "log/std", - "max-encoded-len/std", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index a63da50368983..2e816a6bb8564 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -24,7 +24,6 @@ sp-staking = { version = "3.0.0", default-features = false, path = "../../primit frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } @@ -45,7 +44,6 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "max-encoded-len/std", ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 6c59b3782a545..a32b13ca728d8 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -18,7 +18,6 @@ codec = { package = "parity-scale-codec", default-features = false, version = "2 sp-std = { version = "3.0.0", default-features = false, path = "../std" } sp-api = { version = "3.0.0", default-features = false, path = "../api" } sp-runtime = { version = "3.0.0", default-features = false, path = "../runtime" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -27,6 +26,5 @@ std = [ "codec/std", "sp-std/std", "sp-api/std", - "sp-runtime/std", - "max-encoded-len/std", + "sp-runtime/std" ] diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 11d978912f6b9..2ae4259a21e50 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -23,7 +23,6 @@ sp-timestamp = { version = "3.0.0", default-features = false, path = "../../time sp-consensus-slots = { version = "0.9.0", default-features = false, path = "../slots" } sp-consensus = { version = "0.9.0", path = "../common", optional = true } async-trait = { version = "0.1.48", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -38,5 +37,4 @@ std = [ "sp-consensus-slots/std", "sp-consensus", "async-trait", - "max-encoded-len/std", ] diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index a527d15af85a7..0fc09e11032b0 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -28,7 +28,6 @@ sp-runtime = { version = "3.0.0", default-features = false, path = "../../runtim sp-timestamp = { version = "3.0.0", path = "../../timestamp", optional = true } serde = { version = "1.0.123", features = ["derive"], optional = true } async-trait = { version = "0.1.48", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -48,5 +47,4 @@ std = [ "serde", "sp-timestamp", "async-trait", - "max-encoded-len/std", ] diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 5b6b7f60001ff..95aa65c930f78 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -25,7 +25,6 @@ sp-core = { version = "3.0.0", default-features = false, path = "../core" } sp-keystore = { version = "0.9.0", default-features = false, path = "../keystore", optional = true } sp-runtime = { version = "3.0.0", default-features = false, path = "../runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../std" } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../../max-encoded-len", features = [ "derive" ] } [features] default = ["std"] @@ -40,5 +39,4 @@ std = [ "sp-keystore", "sp-runtime/std", "sp-std/std", - "max-encoded-len/std", ] From 016cc1604043a915dfce40a858ec0f01822e9450 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Wed, 26 May 2021 15:22:46 +0200 Subject: [PATCH 36/45] update lockfile --- Cargo.lock | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 844526da85794..083d45da84500 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4204,7 +4204,6 @@ dependencies = [ "frame-support", "frame-system", "futures 0.3.13", - "max-encoded-len", "node-primitives", "node-runtime", "node-testing", @@ -4254,7 +4253,6 @@ name = "node-primitives" version = "2.0.0" dependencies = [ "frame-system", - "max-encoded-len", "parity-scale-codec", "pretty_assertions 0.6.1", "sp-application-crypto", @@ -4996,7 +4994,6 @@ dependencies = [ "frame-system", "lite-json", "log", - "max-encoded-len", "parity-scale-codec", "sp-core", "sp-io", @@ -5089,7 +5086,6 @@ dependencies = [ "frame-support", "frame-system", "log", - "max-encoded-len", "pallet-authorship", "pallet-session", "parity-scale-codec", @@ -8652,7 +8648,6 @@ dependencies = [ name = "sp-authority-discovery" version = "3.0.0" dependencies = [ - "max-encoded-len", "parity-scale-codec", "sp-api", "sp-application-crypto", @@ -8739,7 +8734,6 @@ name = "sp-consensus-aura" version = "0.9.0" dependencies = [ "async-trait", - "max-encoded-len", "parity-scale-codec", "sp-api", "sp-application-crypto", @@ -8756,7 +8750,6 @@ name = "sp-consensus-babe" version = "0.9.0" dependencies = [ "async-trait", - "max-encoded-len", "merlin", "parity-scale-codec", "serde", @@ -8887,7 +8880,6 @@ version = "3.0.0" dependencies = [ "finality-grandpa", "log", - "max-encoded-len", "parity-scale-codec", "serde", "sp-api", From e2a16cb282b3c812dd05450702100083be03154f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 26 May 2021 17:04:33 -0400 Subject: [PATCH 37/45] fix ui test --- .../test/tests/pallet_ui/call_argument_invalid_bound_2.stderr | 4 ++-- .../test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index e3e94f1fc3eb5..17cfefd4205f3 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is 20 | fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | - ::: /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.0/src/codec.rs:277:18 + ::: /Users/shawntabrizi/.cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.1/src/codec.rs:277:18 | 277 | fn decode(input: &mut I) -> Result; | ----- required by this bound in `pallet::_::_parity_scale_codec::Decode::decode` @@ -17,7 +17,7 @@ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is 20 | fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^ the trait `WrapperTypeEncode` is not implemented for `::Bar` | - ::: /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.0/src/codec.rs:216:21 + ::: /Users/shawntabrizi/.cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.1/src/codec.rs:216:21 | 216 | fn encode_to(&self, dest: &mut T) { | ------ required by this bound in `encode_to` diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 6c92423c6a7fe..545520124bfee 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -4,6 +4,6 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied 10 | #[pallet::generate_storage_info] | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | - = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key` - = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, Key, u32>` + = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `NMapKey` + = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, NMapKey, u32>` = note: required by `storage_info` From b71b2a7bb9239c32396f681c0cd8717720d6bc54 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 26 May 2021 19:07:05 -0400 Subject: [PATCH 38/45] ui --- .../pallet_ui/call_argument_invalid_bound_2.stderr | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index 17cfefd4205f3..00598cf265c35 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -4,26 +4,24 @@ error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is 20 | fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | - ::: /Users/shawntabrizi/.cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.1/src/codec.rs:277:18 + ::: /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.1/src/codec.rs:277:18 | 277 | fn decode(input: &mut I) -> Result; | ----- required by this bound in `pallet::_::_parity_scale_codec::Decode::decode` | = note: required because of the requirements on the impl of `Decode` for `::Bar` - error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is not satisfied --> $DIR/call_argument_invalid_bound_2.rs:20:37 | 20 | fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^ the trait `WrapperTypeEncode` is not implemented for `::Bar` | - ::: /Users/shawntabrizi/.cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.1/src/codec.rs:216:21 + ::: /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/parity-scale-codec-2.1.1/src/codec.rs:216:21 | 216 | fn encode_to(&self, dest: &mut T) { | ------ required by this bound in `encode_to` | = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `::Bar` - error[E0369]: binary operation `==` cannot be applied to type `&::Bar` --> $DIR/call_argument_invalid_bound_2.rs:20:37 | @@ -34,7 +32,6 @@ help: consider further restricting this bound | 17 | #[pallet::call + std::cmp::PartialEq] | ^^^^^^^^^^^^^^^^^^^^^ - error[E0277]: the trait bound `::Bar: Clone` is not satisfied --> $DIR/call_argument_invalid_bound_2.rs:20:37 | @@ -42,7 +39,6 @@ error[E0277]: the trait bound `::Bar: Clone` is not satisfi | ^ the trait `Clone` is not implemented for `::Bar` | = note: required by `clone` - error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` --> $DIR/call_argument_invalid_bound_2.rs:20:37 | @@ -51,4 +47,4 @@ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `::Bar` = note: required because of the requirements on the impl of `std::fmt::Debug` for `&::Bar` - = note: required for the cast to the object type `dyn std::fmt::Debug` + = note: required for the cast to the object type `dyn std::fmt::Debug` \ No newline at end of file From 3acfa75f49a19b316a202fcb8c1fb4ffda6efd4f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 26 May 2021 19:27:54 -0400 Subject: [PATCH 39/45] newline --- .../test/tests/pallet_ui/call_argument_invalid_bound_2.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index 00598cf265c35..250e213f6accc 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -47,4 +47,4 @@ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `::Bar` = note: required because of the requirements on the impl of `std::fmt::Debug` for `&::Bar` - = note: required for the cast to the object type `dyn std::fmt::Debug` \ No newline at end of file + = note: required for the cast to the object type `dyn std::fmt::Debug` From cf92608c1b503cdd510ea48e8e8147d23172de8d Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 26 May 2021 20:05:47 -0400 Subject: [PATCH 40/45] fix merge --- frame/support/procedural/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index e86327469276a..23cb557e6dd7c 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -29,7 +29,6 @@ mod clone_no_bound; mod partial_eq_no_bound; mod default_no_bound; mod key_prefix; -mod max_encoded_len; pub(crate) use storage::INHERENT_INSTANCE_NAME; use proc_macro::TokenStream; @@ -447,12 +446,6 @@ pub fn crate_to_pallet_version(input: TokenStream) -> TokenStream { /// and up to `NUMBER_OF_INSTANCE`. pub(crate) const NUMBER_OF_INSTANCE: u8 = 16; -/// Derive `MaxEncodedLen`. -#[proc_macro_derive(MaxEncodedLen)] -pub fn derive_max_encoded_len(input: TokenStream) -> TokenStream { - max_encoded_len::derive_max_encoded_len(input) -} - /// This macro is meant to be used by frame-support only. /// It implements the trait `HasKeyPrefix` and `HasReversibleKeyPrefix` for tuple of `Key`. #[proc_macro] From 2f739cd475454ebed45173eff7702eda19c8c8b8 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 26 May 2021 22:47:45 -0400 Subject: [PATCH 41/45] try fix ui again --- .../test/tests/pallet_ui/call_argument_invalid_bound_2.stderr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index 250e213f6accc..1d0e96be9edb9 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -10,6 +10,7 @@ error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is | ----- required by this bound in `pallet::_::_parity_scale_codec::Decode::decode` | = note: required because of the requirements on the impl of `Decode` for `::Bar` + error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is not satisfied --> $DIR/call_argument_invalid_bound_2.rs:20:37 | @@ -22,6 +23,7 @@ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is | ------ required by this bound in `encode_to` | = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `::Bar` + error[E0369]: binary operation `==` cannot be applied to type `&::Bar` --> $DIR/call_argument_invalid_bound_2.rs:20:37 | @@ -32,6 +34,7 @@ help: consider further restricting this bound | 17 | #[pallet::call + std::cmp::PartialEq] | ^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `::Bar: Clone` is not satisfied --> $DIR/call_argument_invalid_bound_2.rs:20:37 | @@ -39,6 +42,7 @@ error[E0277]: the trait bound `::Bar: Clone` is not satisfi | ^ the trait `Clone` is not implemented for `::Bar` | = note: required by `clone` + error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` --> $DIR/call_argument_invalid_bound_2.rs:20:37 | From 54839b714831585cb4b6282c8a2a5a9ed3d24df3 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 27 May 2021 18:54:25 -0400 Subject: [PATCH 42/45] Update max-encoded-len/derive/src/lib.rs Co-authored-by: Peter Goodspeed-Niklaus --- max-encoded-len/derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/max-encoded-len/derive/src/lib.rs b/max-encoded-len/derive/src/lib.rs index 13bea24ba4d50..7a78d7efcffed 100644 --- a/max-encoded-len/derive/src/lib.rs +++ b/max-encoded-len/derive/src/lib.rs @@ -94,7 +94,7 @@ fn max_encoded_len_trait(input: &DeriveInput) -> syn::Result { }; Ok(path) }) - .collect::, _>>()?); + .collect::>()?); // we have to return `Result` here in order to satisfy the trait // bounds for `.or_else` for `generate_crate_access_2018`, even though `Option` From 1fd92a4b5b6f068223be304a2d6d99920c26089c Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 27 May 2021 19:18:39 -0400 Subject: [PATCH 43/45] extract generate_crate_access_2018 --- Cargo.lock | 22 +- Cargo.toml | 1 - max-encoded-len/derive/Cargo.toml | 2 +- max-encoded-len/derive/src/lib.rs | 19 +- max-encoded-len/derive/tools/Cargo.toml | 19 -- .../derive/tools/derive/Cargo.toml | 20 -- .../derive/tools/derive/src/lib.rs | 172 ------------- max-encoded-len/derive/tools/src/lib.rs | 106 -------- max-encoded-len/derive/tools/src/syn_ext.rs | 239 ------------------ 9 files changed, 20 insertions(+), 580 deletions(-) delete mode 100644 max-encoded-len/derive/tools/Cargo.toml delete mode 100644 max-encoded-len/derive/tools/derive/Cargo.toml delete mode 100644 max-encoded-len/derive/tools/derive/src/lib.rs delete mode 100644 max-encoded-len/derive/tools/src/lib.rs delete mode 100644 max-encoded-len/derive/tools/src/syn_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 9d0d53c11f644..8020668a7077b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3740,10 +3740,10 @@ dependencies = [ name = "max-encoded-len-derive" version = "3.0.0" dependencies = [ + "proc-macro-crate 1.0.0", "proc-macro2", "quote", "syn", - "temp-procedural-tools", ] [[package]] @@ -9773,17 +9773,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" -[[package]] -name = "temp-procedural-tools" -version = "3.0.0" -dependencies = [ - "proc-macro-crate 1.0.0", - "proc-macro2", - "quote", - "syn", - "test-procedural-tools-derive", -] - [[package]] name = "tempfile" version = "3.2.0" @@ -9807,15 +9796,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "test-procedural-tools-derive" -version = "3.0.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "test-runner" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 5dbb68a0fb91c..5bd83b70f4c2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -205,7 +205,6 @@ members = [ # temp deps "max-encoded-len", "max-encoded-len/derive", - "max-encoded-len/derive/tools", ] # The list of dependencies below (which can be both direct and indirect dependencies) are crates diff --git a/max-encoded-len/derive/Cargo.toml b/max-encoded-len/derive/Cargo.toml index 88338727ae6f7..42c13dc50edd6 100644 --- a/max-encoded-len/derive/Cargo.toml +++ b/max-encoded-len/derive/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -temp-procedural-tools = { version = "3.0.0", path = "tools" } proc-macro2 = "1.0.6" +proc-macro-crate = "1.0.0" quote = "1.0.3" syn = { version = "1.0.58", features = ["full"] } diff --git a/max-encoded-len/derive/src/lib.rs b/max-encoded-len/derive/src/lib.rs index 13bea24ba4d50..34bf42f30cb33 100644 --- a/max-encoded-len/derive/src/lib.rs +++ b/max-encoded-len/derive/src/lib.rs @@ -15,12 +15,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -use temp_procedural_tools::generate_crate_access_2018; use quote::{quote, quote_spanned}; use syn::{ Data, DeriveInput, Error, Fields, GenericParam, Generics, Meta, TraitBound, Type, TypeParamBound, parse_quote, spanned::Spanned, }; +use proc_macro_crate::{crate_name, FoundCrate}; +use proc_macro2::{Ident, Span}; + +/// Generate the crate access for the crate using 2018 syntax. +fn generate_crate_access_2018(def_crate: &str) -> Result { + match crate_name(def_crate) { + Ok(FoundCrate::Itself) => { + let name = def_crate.to_string().replace("-", "_"); + Ok(syn::Ident::new(&name, Span::call_site())) + }, + Ok(FoundCrate::Name(name)) => { + Ok(Ident::new(&name, Span::call_site())) + }, + Err(e) => { + Err(Error::new(Span::call_site(), e)) + } + } +} /// Derive `MaxEncodedLen`. #[proc_macro_derive(MaxEncodedLen, attributes(max_encoded_len_crate))] diff --git a/max-encoded-len/derive/tools/Cargo.toml b/max-encoded-len/derive/tools/Cargo.toml deleted file mode 100644 index bdec9e3b6ffa8..0000000000000 --- a/max-encoded-len/derive/tools/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "temp-procedural-tools" -version = "3.0.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "Apache-2.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" -description = "Proc macro helpers for procedural macros" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -test-procedural-tools-derive = { version = "3.0.0", path = "./derive" } -proc-macro2 = "1.0.6" -quote = "1.0.3" -syn = { version = "1.0.58", features = ["full", "visit"] } -proc-macro-crate = "1.0.0" diff --git a/max-encoded-len/derive/tools/derive/Cargo.toml b/max-encoded-len/derive/tools/derive/Cargo.toml deleted file mode 100644 index 03910a617e6d4..0000000000000 --- a/max-encoded-len/derive/tools/derive/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "test-procedural-tools-derive" -version = "3.0.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "Apache-2.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" -description = "Use to derive parsing for parsing struct." - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1.0.6" -quote = { version = "1.0.3", features = ["proc-macro"] } -syn = { version = "1.0.58", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/max-encoded-len/derive/tools/derive/src/lib.rs b/max-encoded-len/derive/tools/derive/src/lib.rs deleted file mode 100644 index 15394e0c559d4..0000000000000 --- a/max-encoded-len/derive/tools/derive/src/lib.rs +++ /dev/null @@ -1,172 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// tag::description[] -//! Use to derive parsing for parsing struct. -// end::description[] - -#![recursion_limit = "128"] - -use proc_macro::TokenStream; -use proc_macro2::Span; -use syn::parse_macro_input; -use quote::quote; - -pub(crate) fn fields_idents( - fields: impl Iterator, -) -> impl Iterator { - fields.enumerate().map(|(ix, field)| { - field.ident.map(|i| quote!{#i}).unwrap_or_else(|| { - let f_ix: syn::Ident = syn::Ident::new(&format!("f_{}", ix), Span::call_site()); - quote!( #f_ix ) - }) - }) -} - -pub(crate) fn fields_access( - fields: impl Iterator, -) -> impl Iterator { - fields.enumerate().map(|(ix, field)| { - field.ident.map(|i| quote!( #i )).unwrap_or_else(|| { - let f_ix: syn::Index = syn::Index { - index: ix as u32, - span: Span::call_site(), - }; - quote!( #f_ix ) - }) - }) -} - -/// self defined parsing struct. -/// not meant for any struct, just for fast -/// parse implementation. -#[proc_macro_derive(Parse)] -pub fn derive_parse(input: TokenStream) -> TokenStream { - let item = parse_macro_input!(input as syn::Item); - match item { - syn::Item::Struct(input) => derive_parse_struct(input), - _ => TokenStream::new(), // ignore - } -} - -fn derive_parse_struct(input: syn::ItemStruct) -> TokenStream { - let syn::ItemStruct { - ident, - generics, - fields, - .. - } = input; - let field_names = { - let name = fields_idents(fields.iter().map(Clone::clone)); - quote!{ - #( - #name, - )* - } - }; - let field = fields_idents(fields.iter().map(Clone::clone)); - let tokens = quote! { - impl #generics syn::parse::Parse for #ident #generics { - fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { - #( - let #field = input.parse()?; - )* - Ok(Self { - #field_names - }) - } - } - }; - tokens.into() -} - -/// self defined parsing struct or enum. -/// not meant for any struct/enum, just for fast -/// parse implementation. -/// For enum: -/// it only output fields (empty field act as a None). -#[proc_macro_derive(ToTokens)] -pub fn derive_totokens(input: TokenStream) -> TokenStream { - let item = parse_macro_input!(input as syn::Item); - match item { - syn::Item::Enum(input) => derive_totokens_enum(input), - syn::Item::Struct(input) => derive_totokens_struct(input), - _ => TokenStream::new(), // ignore - } -} - -fn derive_totokens_struct(input: syn::ItemStruct) -> TokenStream { - let syn::ItemStruct { - ident, - generics, - fields, - .. - } = input; - - let fields = fields_access(fields.iter().map(Clone::clone)); - let tokens = quote! { - - impl #generics quote::ToTokens for #ident #generics { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - #( - self.#fields.to_tokens(tokens); - )* - } - } - - }; - tokens.into() -} - -fn derive_totokens_enum(input: syn::ItemEnum) -> TokenStream { - let syn::ItemEnum { - ident, - generics, - variants, - .. - } = input; - let variants = variants.iter().map(|v| { - let v_ident = v.ident.clone(); - let fields_build = if v.fields.iter().count() > 0 { - let fields_id = fields_idents(v.fields.iter().map(Clone::clone)); - quote!( (#(#fields_id), *) ) - } else { - quote!() - }; - let field = fields_idents(v.fields.iter().map(Clone::clone)); - quote! { - #ident::#v_ident#fields_build => { - #( - #field.to_tokens(tokens); - )* - }, - } - }); - let tokens = quote! { - impl #generics quote::ToTokens for #ident #generics { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - match self { - #( - #variants - )* - } - } - } - }; - - tokens.into() -} diff --git a/max-encoded-len/derive/tools/src/lib.rs b/max-encoded-len/derive/tools/src/lib.rs deleted file mode 100644 index 38933490c6d98..0000000000000 --- a/max-encoded-len/derive/tools/src/lib.rs +++ /dev/null @@ -1,106 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// tag::description[] -//! Proc macro helpers for procedural macros -// end::description[] - -// reexport proc macros -pub use test_procedural_tools_derive::*; - -use proc_macro_crate::{crate_name, FoundCrate}; -use syn::parse::Error; -use quote::quote; - -pub mod syn_ext; - -// FIXME #1569, remove the following functions, which are copied from sp-api-macros -use proc_macro2::{TokenStream, Span}; -use syn::Ident; - -fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident { - Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site()) -} - -/// Generates the access to the `frame-support` crate. -pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream { - if std::env::var("CARGO_PKG_NAME").unwrap() == def_crate { - quote::quote!( frame_support ) - } else { - let mod_name = generate_hidden_includes_mod_name(unique_id); - quote::quote!( self::#mod_name::hidden_include ) - } -} - -/// Generate the crate access for the crate using 2018 syntax. -/// -/// for `frame-support` output will for example be `frame_support`. -pub fn generate_crate_access_2018(def_crate: &str) -> Result { - match crate_name(def_crate) { - Ok(FoundCrate::Itself) => { - let name = def_crate.to_string().replace("-", "_"); - Ok(syn::Ident::new(&name, Span::call_site())) - }, - Ok(FoundCrate::Name(name)) => { - Ok(Ident::new(&name, Span::call_site())) - }, - Err(e) => { - Err(Error::new(Span::call_site(), e)) - } - } -} - -/// Generates the hidden includes that are required to make the macro independent from its scope. -pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream { - let mod_name = generate_hidden_includes_mod_name(unique_id); - - match crate_name(def_crate) { - Ok(FoundCrate::Itself) => quote!(), - Ok(FoundCrate::Name(name)) => { - let name = Ident::new(&name, Span::call_site()); - quote::quote!( - #[doc(hidden)] - mod #mod_name { - pub extern crate #name as hidden_include; - } - ) - }, - Err(e) => { - let err = Error::new(Span::call_site(), e).to_compile_error(); - quote!( #err ) - } - } -} - -// fn to remove white spaces around string types -// (basically whitespaces around tokens) -pub fn clean_type_string(input: &str) -> String { - input - .replace(" ::", "::") - .replace(":: ", "::") - .replace(" ,", ",") - .replace(" ;", ";") - .replace(" [", "[") - .replace("[ ", "[") - .replace(" ]", "]") - .replace(" (", "(") - .replace("( ", "(") - .replace(" )", ")") - .replace(" <", "<") - .replace("< ", "<") - .replace(" >", ">") -} diff --git a/max-encoded-len/derive/tools/src/syn_ext.rs b/max-encoded-len/derive/tools/src/syn_ext.rs deleted file mode 100644 index 34b914ecc2a76..0000000000000 --- a/max-encoded-len/derive/tools/src/syn_ext.rs +++ /dev/null @@ -1,239 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// tag::description[] -//! Extension to syn types, mainly for parsing -// end::description[] - -use syn::{visit::{Visit, self}, parse::{Parse, ParseStream, Result}, Ident}; -use proc_macro2::{TokenStream, TokenTree}; -use quote::ToTokens; -use std::iter::once; -use test_procedural_tools_derive::{ToTokens, Parse}; - -/// stop parsing here getting remaining token as content -/// Warn duplicate stream (part of) -#[derive(Parse, ToTokens, Debug)] -pub struct StopParse { - pub inner: TokenStream, -} - -// inner macro really dependant on syn naming convention, do not export -macro_rules! groups_impl { - ($name:ident, $tok:ident, $deli:ident, $parse:ident) => { - - #[derive(Debug)] - pub struct $name

{ - pub token: syn::token::$tok, - pub content: P, - } - - impl Parse for $name

{ - fn parse(input: ParseStream) -> Result { - let syn::group::$name { token, content } = syn::group::$parse(input)?; - let content = content.parse()?; - Ok($name { token, content, }) - } - } - - impl ToTokens for $name

{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let mut inner_stream = TokenStream::new(); - self.content.to_tokens(&mut inner_stream); - let token_tree: proc_macro2::TokenTree = - proc_macro2::Group::new(proc_macro2::Delimiter::$deli, inner_stream).into(); - tokens.extend(once(token_tree)); - } - } - - impl Clone for $name

{ - fn clone(&self) -> Self { - Self { token: self.token.clone(), content: self.content.clone() } - } - } - } -} - -groups_impl!(Braces, Brace, Brace, parse_braces); -groups_impl!(Brackets, Bracket, Bracket, parse_brackets); -groups_impl!(Parens, Paren, Parenthesis, parse_parens); - -#[derive(Debug)] -pub struct PunctuatedInner { - pub inner: syn::punctuated::Punctuated, - pub variant: V, -} - -#[derive(Debug, Clone)] -pub struct NoTrailing; - - -#[derive(Debug, Clone)] -pub struct Trailing; - -pub type Punctuated = PunctuatedInner; - -pub type PunctuatedTrailing = PunctuatedInner; - -impl Parse for PunctuatedInner { - fn parse(input: ParseStream) -> Result { - Ok(PunctuatedInner { - inner: syn::punctuated::Punctuated::parse_separated_nonempty(input)?, - variant: Trailing, - }) - } -} - -impl Parse for PunctuatedInner { - fn parse(input: ParseStream) -> Result { - Ok(PunctuatedInner { - inner: syn::punctuated::Punctuated::parse_terminated(input)?, - variant: NoTrailing, - }) - } -} - -impl ToTokens for PunctuatedInner { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.inner.to_tokens(tokens) - } -} - -impl Clone for PunctuatedInner { - fn clone(&self) -> Self { - Self { inner: self.inner.clone(), variant: self.variant.clone() } - } -} - -/// Note that syn Meta is almost fine for use case (lacks only `ToToken`) -#[derive(Debug, Clone)] -pub struct Meta { - pub inner: syn::Meta, -} - -impl Parse for Meta { - fn parse(input: ParseStream) -> Result { - Ok(Meta { - inner: syn::Meta::parse(input)?, - }) - } -} - -impl ToTokens for Meta { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self.inner { - syn::Meta::Path(ref path) => path.to_tokens(tokens), - syn::Meta::List(ref l) => l.to_tokens(tokens), - syn::Meta::NameValue(ref n) => n.to_tokens(tokens), - } - } -} - -#[derive(Debug)] -pub struct OuterAttributes { - pub inner: Vec, -} - -impl Parse for OuterAttributes { - fn parse(input: ParseStream) -> Result { - let inner = syn::Attribute::parse_outer(input)?; - Ok(OuterAttributes { - inner, - }) - } -} - -impl ToTokens for OuterAttributes { - fn to_tokens(&self, tokens: &mut TokenStream) { - for att in self.inner.iter() { - att.to_tokens(tokens); - } - } -} - -pub fn extract_type_option(typ: &syn::Type) -> Option { - if let syn::Type::Path(ref path) = typ { - let v = path.path.segments.last()?; - if v.ident == "Option" { - // Option has only one type argument in angle bracket. - if let syn::PathArguments::AngleBracketed(a) = &v.arguments { - if let syn::GenericArgument::Type(typ) = a.args.last()? { - return Some(typ.clone()) - } - } - } - } - - None -} - -/// Auxiliary structure to check if a given `Ident` is contained in an ast. -struct ContainsIdent<'a> { - ident: &'a Ident, - result: bool, -} - -impl<'ast> ContainsIdent<'ast> { - fn visit_tokenstream(&mut self, stream: TokenStream) { - stream.into_iter().for_each(|tt| - match tt { - TokenTree::Ident(id) => self.visit_ident(&id), - TokenTree::Group(ref group) => self.visit_tokenstream(group.stream()), - _ => {} - } - ) - } - - fn visit_ident(&mut self, ident: &Ident) { - if ident == self.ident { - self.result = true; - } - } -} - -impl<'ast> Visit<'ast> for ContainsIdent<'ast> { - fn visit_ident(&mut self, input: &'ast Ident) { - self.visit_ident(input); - } - - fn visit_macro(&mut self, input: &'ast syn::Macro) { - self.visit_tokenstream(input.tokens.clone()); - visit::visit_macro(self, input); - } -} - -/// Check if a `Type` contains the given `Ident`. -pub fn type_contains_ident(typ: &syn::Type, ident: &Ident) -> bool { - let mut visit = ContainsIdent { - result: false, - ident, - }; - - visit::visit_type(&mut visit, typ); - visit.result -} - -/// Check if a `Expr` contains the given `Ident`. -pub fn expr_contains_ident(expr: &syn::Expr, ident: &Ident) -> bool { - let mut visit = ContainsIdent { - result: false, - ident, - }; - - visit::visit_expr(&mut visit, expr); - visit.result -} From f6d5db304e95a0253123746b1d70cfb8db7bd716 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 27 May 2021 19:20:33 -0400 Subject: [PATCH 44/45] Update lib.rs --- bin/node/runtime/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d528feb0e5a1e..c51799d11a943 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -114,8 +114,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 265, - impl_version: 1, + spec_version: 266, + impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 2, }; From c329b065c404525bc8a845fb5713af79c21336df Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 27 May 2021 19:39:34 -0400 Subject: [PATCH 45/45] compiler isnt smart enough --- max-encoded-len/derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/max-encoded-len/derive/src/lib.rs b/max-encoded-len/derive/src/lib.rs index a951486a1233d..34bf42f30cb33 100644 --- a/max-encoded-len/derive/src/lib.rs +++ b/max-encoded-len/derive/src/lib.rs @@ -111,7 +111,7 @@ fn max_encoded_len_trait(input: &DeriveInput) -> syn::Result { }; Ok(path) }) - .collect::>()?); + .collect::, _>>()?); // we have to return `Result` here in order to satisfy the trait // bounds for `.or_else` for `generate_crate_access_2018`, even though `Option`