From f8360a82bd35fdb7d00ac25e4887ec484effa39e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 10 May 2022 13:47:41 +0200 Subject: [PATCH 01/10] generate_storage_alias: Rewrite as proc macro attribute This rewrites the `generate_storage_alias!` declarative macro as proc-macro attribute. While doing this the name is changed to `storage_alias`. The prefix can now also be the name of a pallet. This makes storage aliases work in migrations for all kind of chains and not just for the ones that use predefined prefixes. --- frame/bags-list/src/list/tests.rs | 8 +- frame/bags-list/src/migrations.rs | 5 +- frame/contracts/src/migration.rs | 52 +- frame/elections-phragmen/src/migrations/v3.rs | 95 ++-- frame/offences/src/migration.rs | 8 +- frame/staking/src/migrations.rs | 28 +- frame/support/procedural/src/lib.rs | 8 + frame/support/procedural/src/storage_alias.rs | 524 ++++++++++++++++++ frame/support/src/lib.rs | 221 ++------ .../support/src/storage/bounded_btree_map.rs | 14 +- .../support/src/storage/bounded_btree_set.rs | 15 +- frame/support/src/storage/bounded_vec.rs | 14 +- .../src/storage/generator/double_map.rs | 6 +- frame/support/src/storage/generator/map.rs | 3 +- frame/support/src/storage/generator/nmap.rs | 16 +- frame/support/src/storage/mod.rs | 18 +- frame/support/src/storage/types/nmap.rs | 8 +- frame/support/src/storage/weak_bounded_vec.rs | 13 +- frame/system/src/migrations/mod.rs | 66 +-- 19 files changed, 762 insertions(+), 360 deletions(-) create mode 100644 frame/support/procedural/src/storage_alias.rs diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index ff7dd2871c237..66c2ad8ab95b5 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -368,11 +368,9 @@ mod list { assert_eq!(crate::ListNodes::::count(), 4); // we do some wacky stuff here to get access to the counter, since it is (reasonably) // not exposed as mutable in any sense. - frame_support::generate_storage_alias!( - BagsList, - CounterForListNodes - => Value - ); + #[frame_support::storage_alias] + type CounterForListNodes = + Value, u32, frame_support::pallet_prelude::ValueQuery>; CounterForListNodes::mutate(|counter| *counter += 1); assert_eq!(crate::ListNodes::::count(), 5); diff --git a/frame/bags-list/src/migrations.rs b/frame/bags-list/src/migrations.rs index 696733e8c7ba5..42606ff7e635d 100644 --- a/frame/bags-list/src/migrations.rs +++ b/frame/bags-list/src/migrations.rs @@ -30,11 +30,12 @@ impl OnRuntimeUpgrade for CheckCounterPrefix { fn pre_upgrade() -> Result<(), &'static str> { use frame_support::ensure; // The old explicit storage item. - frame_support::generate_storage_alias!(BagsList, CounterForListNodes => Value); + #[frame_support::storage_alias] + type CounterForListNodes = Value, u32>; // ensure that a value exists in the counter struct. ensure!( - crate::ListNodes::::count() == CounterForListNodes::get().unwrap(), + crate::ListNodes::::count() == CounterForListNodes::::get().unwrap(), "wrong list node counter" ); diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 035e3b4409cf9..827120a9ab96a 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -18,11 +18,8 @@ use crate::{BalanceOf, CodeHash, Config, Pallet, TrieId, Weight}; use codec::{Decode, Encode}; use frame_support::{ - codec, generate_storage_alias, - pallet_prelude::*, - storage::migration, - traits::{Get, PalletInfoAccess}, - Identity, Twox64Concat, + codec, pallet_prelude::*, storage::migration, storage_alias, traits::Get, Identity, + Twox64Concat, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -119,15 +116,12 @@ mod v5 { trie_id: TrieId, } - generate_storage_alias!( - Contracts, - ContractInfoOf => Map<(Twox64Concat, T::AccountId), ContractInfo> - ); + #[storage_alias] + type ContractInfoOf = + Map, Twox64Concat, ::AccountId, ContractInfo>; - generate_storage_alias!( - Contracts, - DeletionQueue => Value> - ); + #[storage_alias] + type DeletionQueue = Value, Vec>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -204,20 +198,15 @@ mod v6 { type ContractInfo = RawContractInfo, BalanceOf>; - generate_storage_alias!( - Contracts, - ContractInfoOf => Map<(Twox64Concat, T::AccountId), ContractInfo> - ); + #[storage_alias] + type ContractInfoOf = + Map, Twox64Concat, ::AccountId, ContractInfo>; - generate_storage_alias!( - Contracts, - CodeStorage => Map<(Identity, CodeHash), PrefabWasmModule> - ); + #[storage_alias] + type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; - generate_storage_alias!( - Contracts, - OwnerInfoOf => Map<(Identity, CodeHash), OwnerInfo> - ); + #[storage_alias] + type OwnerInfoOf = Map, Identity, CodeHash, OwnerInfo>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -261,14 +250,11 @@ mod v7 { use super::*; pub fn migrate() -> Weight { - generate_storage_alias!( - Contracts, - AccountCounter => Value - ); - generate_storage_alias!( - Contracts, - Nonce => Value - ); + #[storage_alias] + type AccountCounter = Value, u64, ValueQuery>; + #[storage_alias] + type Nonce = Value, u64, ValueQuery>; + Nonce::set(AccountCounter::take()); T::DbWeight::get().reads_writes(1, 2) } diff --git a/frame/elections-phragmen/src/migrations/v3.rs b/frame/elections-phragmen/src/migrations/v3.rs index c6a7ce7e7ca1b..815bdf71591ea 100644 --- a/frame/elections-phragmen/src/migrations/v3.rs +++ b/frame/elections-phragmen/src/migrations/v3.rs @@ -17,12 +17,10 @@ //! Migrations to version [`3.0.0`], as denoted by the changelog. +use crate::{Config, Pallet}; use codec::{Decode, Encode, FullCodec}; use frame_support::{ - pallet_prelude::ValueQuery, - traits::{PalletInfoAccess, StorageVersion}, - weights::Weight, - RuntimeDebug, Twox64Concat, + pallet_prelude::ValueQuery, traits::StorageVersion, weights::Weight, RuntimeDebug, Twox64Concat, }; use sp_std::prelude::*; @@ -42,9 +40,6 @@ struct Voter { /// Trait to implement to give information about types used for migration pub trait V2ToV3 { - /// The elections-phragmen pallet. - type Pallet: 'static + PalletInfoAccess; - /// System config account id type AccountId: 'static + FullCodec; @@ -52,30 +47,30 @@ pub trait V2ToV3 { type Balance: 'static + FullCodec + Copy; } -frame_support::generate_storage_alias!( - PhragmenElection, Candidates => Value< - Vec<(T::AccountId, T::Balance)>, - ValueQuery - > -); -frame_support::generate_storage_alias!( - PhragmenElection, Members => Value< - Vec>, - ValueQuery - > -); -frame_support::generate_storage_alias!( - PhragmenElection, RunnersUp => Value< - Vec>, - ValueQuery - > -); -frame_support::generate_storage_alias!( - PhragmenElection, Voting => Map< - (Twox64Concat, T::AccountId), - Voter - > -); +#[frame_support::storage_alias] +type Candidates = + Value, Vec<(::AccountId, ::Balance)>, ValueQuery>; + +#[frame_support::storage_alias] +type Members = Value< + Pallet, + Vec::AccountId, ::Balance>>, + ValueQuery, +>; + +#[frame_support::storage_alias] +type RunnersUp = Value< + Pallet, + Vec::AccountId, ::Balance>>, + ValueQuery, +>; + +#[frame_support::storage_alias] +type Voting = Map< + Pallet, + (Twox64Concat, T::AccountId), + Voter<::AccountId, ::Balance>, +>; /// Apply all of the migrations from 2 to 3. /// @@ -86,7 +81,10 @@ frame_support::generate_storage_alias!( /// /// Be aware that this migration is intended to be used only for the mentioned versions. Use /// with care and run at your own risk. -pub fn apply(old_voter_bond: T::Balance, old_candidacy_bond: T::Balance) -> Weight { +pub fn apply( + old_voter_bond: V::Balance, + old_candidacy_bond: V::Balance, +) -> Weight { let storage_version = StorageVersion::get::(); log::info!( target: "runtime::elections-phragmen", @@ -95,12 +93,12 @@ pub fn apply(old_voter_bond: T::Balance, old_candidacy_bond: T::Balan ); if storage_version <= 2 { - migrate_voters_to_recorded_deposit::(old_voter_bond); - migrate_candidates_to_recorded_deposit::(old_candidacy_bond); - migrate_runners_up_to_recorded_deposit::(old_candidacy_bond); - migrate_members_to_recorded_deposit::(old_candidacy_bond); + migrate_voters_to_recorded_deposit::(old_voter_bond); + migrate_candidates_to_recorded_deposit::(old_candidacy_bond); + migrate_runners_up_to_recorded_deposit::(old_candidacy_bond); + migrate_members_to_recorded_deposit::(old_candidacy_bond); - StorageVersion::new(3).put::(); + StorageVersion::new(3).put::>(); Weight::max_value() } else { @@ -114,21 +112,21 @@ pub fn apply(old_voter_bond: T::Balance, old_candidacy_bond: T::Balan } /// Migrate from the old legacy voting bond (fixed) to the new one (per-vote dynamic). -pub fn migrate_voters_to_recorded_deposit(old_deposit: T::Balance) { - >::translate::<(T::Balance, Vec), _>(|_who, (stake, votes)| { +pub fn migrate_voters_to_recorded_deposit(old_deposit: V::Balance) { + >::translate::<(V::Balance, Vec), _>(|_who, (stake, votes)| { Some(Voter { votes, stake, deposit: old_deposit }) }); log::info!( target: "runtime::elections-phragmen", "migrated {} voter accounts.", - >::iter().count(), + >::iter().count(), ); } /// Migrate all candidates to recorded deposit. -pub fn migrate_candidates_to_recorded_deposit(old_deposit: T::Balance) { - let _ = >::translate::, _>(|maybe_old_candidates| { +pub fn migrate_candidates_to_recorded_deposit(old_deposit: V::Balance) { + let _ = >::translate::, _>(|maybe_old_candidates| { maybe_old_candidates.map(|old_candidates| { log::info!( target: "runtime::elections-phragmen", @@ -141,8 +139,8 @@ pub fn migrate_candidates_to_recorded_deposit(old_deposit: T::Balance } /// Migrate all members to recorded deposit. -pub fn migrate_members_to_recorded_deposit(old_deposit: T::Balance) { - let _ = >::translate::, _>(|maybe_old_members| { +pub fn migrate_members_to_recorded_deposit(old_deposit: V::Balance) { + let _ = >::translate::, _>(|maybe_old_members| { maybe_old_members.map(|old_members| { log::info!( target: "runtime::elections-phragmen", @@ -158,9 +156,9 @@ pub fn migrate_members_to_recorded_deposit(old_deposit: T::Balance) { } /// Migrate all runners-up to recorded deposit. -pub fn migrate_runners_up_to_recorded_deposit(old_deposit: T::Balance) { - let _ = - >::translate::, _>(|maybe_old_runners_up| { +pub fn migrate_runners_up_to_recorded_deposit(old_deposit: V::Balance) { + let _ = >::translate::, _>( + |maybe_old_runners_up| { maybe_old_runners_up.map(|old_runners_up| { log::info!( target: "runtime::elections-phragmen", @@ -172,5 +170,6 @@ pub fn migrate_runners_up_to_recorded_deposit(old_deposit: T::Balance .map(|(who, stake)| SeatHolder { who, stake, deposit: old_deposit }) .collect::>() }) - }); + }, + ); } diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index 0d6c98b564cb1..72178fe389568 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -17,7 +17,7 @@ use super::{Config, OffenceDetails, Perbill, SessionIndex}; use frame_support::{ - generate_storage_alias, pallet_prelude::ValueQuery, traits::Get, weights::Weight, + storage_alias, pallet_prelude::ValueQuery, traits::Get, weights::Weight, }; use sp_staking::offence::{DisableStrategy, OnOffenceHandler}; use sp_std::vec::Vec; @@ -31,10 +31,8 @@ type DeferredOffenceOf = ( // Deferred reports that have been rejected by the offence handler and need to be submitted // at a later time. -generate_storage_alias!( - Offences, - DeferredOffences => Value>, ValueQuery> -); +#[storage_alias] +type DeferredOffences = Value, Vec>, ValueQuery>; pub fn remove_deferred_storage() -> Weight { let mut weight = T::DbWeight::get().reads_writes(1, 1); diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 96c905f4e5942..60666083644b0 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -139,10 +139,12 @@ pub mod v8 { pub mod v7 { use super::*; - use frame_support::generate_storage_alias; + use frame_support::storage_alias; - generate_storage_alias!(Staking, CounterForValidators => Value); - generate_storage_alias!(Staking, CounterForNominators => Value); + #[storage_alias] + type CounterForValidators = Value, u32>; + #[storage_alias] + type CounterForNominators = Value, u32>; pub fn pre_migrate() -> Result<(), &'static str> { assert!( @@ -176,15 +178,21 @@ pub mod v7 { pub mod v6 { use super::*; - use frame_support::{generate_storage_alias, traits::Get, weights::Weight}; + use frame_support::{storage_alias, traits::Get, weights::Weight}; // NOTE: value type doesn't matter, we just set it to () here. - generate_storage_alias!(Staking, SnapshotValidators => Value<()>); - generate_storage_alias!(Staking, SnapshotNominators => Value<()>); - generate_storage_alias!(Staking, QueuedElected => Value<()>); - generate_storage_alias!(Staking, QueuedScore => Value<()>); - generate_storage_alias!(Staking, EraElectionStatus => Value<()>); - generate_storage_alias!(Staking, IsCurrentSessionFinal => Value<()>); + #[storage_alias] + type SnapshotValidators = Value, ()>; + #[storage_alias] + type SnapshotNominators = Value, ()>; + #[storage_alias] + type QueuedElected = Value, ()>; + #[storage_alias] + type QueuedScore = Value, ()>; + #[storage_alias] + type EraElectionStatus = Value, ()>; + #[storage_alias] + type IsCurrentSessionFinal = Value, ()>; /// check to execute prior to migration. pub fn pre_migrate() -> Result<(), &'static str> { diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 92564e94493c1..f4e64cb949aa9 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -25,6 +25,7 @@ mod crate_version; mod debug_no_bound; mod default_no_bound; mod dummy_part_checker; +mod storage_alias; mod key_prefix; mod match_and_insert; mod pallet; @@ -575,3 +576,10 @@ pub fn derive_pallet_error(input: TokenStream) -> TokenStream { pub fn __create_tt_macro(input: TokenStream) -> TokenStream { tt_macro::create_tt_return_macro(input) } + +#[proc_macro_attribute] +pub fn storage_alias(_: TokenStream, input: TokenStream) -> TokenStream { + storage_alias::storage_alias(input.into()) + .unwrap_or_else(|r| r.into_compile_error()) + .into() +} diff --git a/frame/support/procedural/src/storage_alias.rs b/frame/support/procedural/src/storage_alias.rs new file mode 100644 index 0000000000000..39760661dd911 --- /dev/null +++ b/frame/support/procedural/src/storage_alias.rs @@ -0,0 +1,524 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2022 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 the `storage_alias` attribute macro. + +use frame_support_procedural_tools::generate_crate_access_2018; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, ToTokens}; +use syn::{ + ext::IdentExt, + parenthesized, + parse::{Parse, ParseStream}, + punctuated::Punctuated, + token, Attribute, Error, Ident, Result, Token, Type, TypeParam, Visibility, +}; + +/// Represents a path that only consists of [`Ident`] separated by `::`. +struct SimplePath { + leading_colon: Option, + segments: Punctuated, +} + +impl SimplePath { + /// Returns the [`Ident`] of this path. + /// + /// It only returns `Some(_)` if there is exactly one element and no leading colon. + fn get_ident(&self) -> Option<&Ident> { + if self.segments.len() != 1 || self.leading_colon.is_some() { + None + } else { + self.segments.first() + } + } +} + +impl Parse for SimplePath { + fn parse(input: ParseStream<'_>) -> Result { + Ok(Self { + leading_colon: if input.peek(Token![::]) { Some(input.parse()?) } else { None }, + segments: Punctuated::parse_separated_nonempty_with(input, |p| Ident::parse_any(p))?, + }) + } +} + +impl ToTokens for SimplePath { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.leading_colon.to_tokens(tokens); + self.segments.to_tokens(tokens); + } +} + +/// Represents generics which only support [`TypeParam`] separated by commas. +struct SimpleGenerics { + lt_token: Token![<], + params: Punctuated, + gt_token: Token![>], +} + +impl SimpleGenerics { + /// Returns the generics for types declarations etc. + fn type_generics(&self) -> impl Iterator { + self.params.iter().map(|p| &p.ident) + } + + /// Returns the generics for the `impl` block. + fn impl_generics(&self) -> impl Iterator { + self.params.iter() + } + + /// Returns `true` if all parameters have at least one trait bound. + fn all_have_trait_bounds(&self) -> bool { + self.params + .iter() + .all(|p| p.bounds.iter().any(|b| matches!(b, syn::TypeParamBound::Trait(_)))) + } +} + +impl Parse for SimpleGenerics { + fn parse(input: ParseStream<'_>) -> Result { + Ok(Self { + lt_token: input.parse()?, + params: Punctuated::parse_separated_nonempty(input)?, + gt_token: input.parse()?, + }) + } +} + +impl ToTokens for SimpleGenerics { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.lt_token.to_tokens(tokens); + self.params.to_tokens(tokens); + self.gt_token.to_tokens(tokens); + } +} + +mod storage_types { + syn::custom_keyword!(Value); + syn::custom_keyword!(Map); + syn::custom_keyword!(DoubleMap); + syn::custom_keyword!(NMap); +} + +/// The supported storage types +enum StorageType { + Value { + _kw: storage_types::Value, + _lt_token: Token![<], + prefix: SimplePath, + prefix_generics: Option, + _value_comma: Token![,], + value_ty: Type, + query_type: Option<(Token![,], Type)>, + _trailing_comma: Option, + _gt_token: Token![>], + }, + Map { + _kw: storage_types::Map, + _lt_token: Token![<], + prefix: SimplePath, + prefix_generics: Option, + _hasher_comma: Token![,], + hasher_ty: Type, + _key_comma: Token![,], + key_ty: Type, + _value_comma: Token![,], + value_ty: Type, + query_type: Option<(Token![,], Type)>, + _trailing_comma: Option, + _gt_token: Token![>], + }, + DoubleMap { + _kw: storage_types::DoubleMap, + _lt_token: Token![<], + prefix: SimplePath, + prefix_generics: Option, + _hasher1_comma: Token![,], + hasher1_ty: Type, + _key1_comma: Token![,], + key1_ty: Type, + _hasher2_comma: Token![,], + hasher2_ty: Type, + _key2_comma: Token![,], + key2_ty: Type, + _value_comma: Token![,], + value_ty: Type, + query_type: Option<(Token![,], Type)>, + _trailing_comma: Option, + _gt_token: Token![>], + }, + NMap { + _kw: storage_types::NMap, + _lt_token: Token![<], + prefix: SimplePath, + prefix_generics: Option, + _paren_comma: Token![,], + _paren_token: token::Paren, + key_types: Punctuated, + _value_comma: Token![,], + value_ty: Type, + query_type: Option<(Token![,], Type)>, + _trailing_comma: Option, + _gt_token: Token![>], + }, +} + +impl StorageType { + /// Generate the actual type declaration. + fn generate_type_declaration( + &self, + crate_: &Ident, + storage_instance: &StorageInstance, + storage_name: &Ident, + storage_generics: Option<&SimpleGenerics>, + visibility: &Visibility, + attributes: &[Attribute], + ) -> TokenStream { + let storage_instance = &storage_instance.name; + let type_generics = self + .prefix_generics() + .map(|g| { + let g = g.type_generics(); + quote! { <#( #g ),*> } + }) + .unwrap_or_default(); + let attributes = attributes.iter(); + + match self { + Self::Value { value_ty, query_type, .. } => { + let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); + + quote! { + #( #attributes )* + #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageValue< + #storage_instance #type_generics, + #value_ty + #query_type + >; + } + }, + Self::Map { value_ty, query_type, hasher_ty, key_ty, .. } => { + let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); + + quote! { + #( #attributes )* + #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageMap< + #storage_instance #type_generics, + #hasher_ty, + #key_ty, + #value_ty + #query_type + >; + } + }, + Self::DoubleMap { + value_ty, + query_type, + hasher1_ty, + key1_ty, + hasher2_ty, + key2_ty, + .. + } => { + let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); + + quote! { + #( #attributes )* + #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageDoubleMap< + #storage_instance #type_generics, + #hasher1_ty, + #key1_ty, + #hasher2_ty, + #key2_ty, + #value_ty + #query_type + >; + } + }, + Self::NMap { value_ty, query_type, key_types, .. } => { + let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); + let key_types = key_types.iter(); + + quote! { + #( #attributes )* + #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageNMap< + #storage_instance #type_generics, + ( #( #key_types ),* ), + #value_ty + #query_type + >; + } + }, + } + } + + /// The prefix for this storage type. + fn prefix(&self) -> &SimplePath { + match self { + Self::Value { prefix, .. } | + Self::Map { prefix, .. } | + Self::NMap { prefix, .. } | + Self::DoubleMap { prefix, .. } => prefix, + } + } + + /// The prefix generics for this storage type. + fn prefix_generics(&self) -> Option<&SimpleGenerics> { + match self { + Self::Value { prefix_generics, .. } | + Self::Map { prefix_generics, .. } | + Self::NMap { prefix_generics, .. } | + Self::DoubleMap { prefix_generics, .. } => prefix_generics.as_ref(), + } + } +} + +impl Parse for StorageType { + fn parse(input: ParseStream<'_>) -> Result { + let lookahead = input.lookahead1(); + + let parse_query_type = |input: ParseStream<'_>| -> Result> { + if input.peek(Token![,]) && !input.peek2(Token![>]) { + Ok(Some((input.parse()?, input.parse()?))) + } else { + Ok(None) + } + }; + + let parse_pallet_generics = |input: ParseStream<'_>| -> Result> { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![<]) { + Some(input.parse()).transpose() + } else if lookahead.peek(Token![,]) { + Ok(None) + } else { + Err(lookahead.error()) + } + }; + + if lookahead.peek(storage_types::Value) { + Ok(Self::Value { + _kw: input.parse()?, + _lt_token: input.parse()?, + prefix: input.parse()?, + prefix_generics: parse_pallet_generics(input)?, + _value_comma: input.parse()?, + value_ty: input.parse()?, + query_type: parse_query_type(input)?, + _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, + _gt_token: input.parse()?, + }) + } else if lookahead.peek(storage_types::Map) { + Ok(Self::Map { + _kw: input.parse()?, + _lt_token: input.parse()?, + prefix: input.parse()?, + prefix_generics: parse_pallet_generics(input)?, + _hasher_comma: input.parse()?, + hasher_ty: input.parse()?, + _key_comma: input.parse()?, + key_ty: input.parse()?, + _value_comma: input.parse()?, + value_ty: input.parse()?, + query_type: parse_query_type(input)?, + _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, + _gt_token: input.parse()?, + }) + } else if lookahead.peek(storage_types::DoubleMap) { + Ok(Self::DoubleMap { + _kw: input.parse()?, + _lt_token: input.parse()?, + prefix: input.parse()?, + prefix_generics: parse_pallet_generics(input)?, + _hasher1_comma: input.parse()?, + hasher1_ty: input.parse()?, + _key1_comma: input.parse()?, + key1_ty: input.parse()?, + _hasher2_comma: input.parse()?, + hasher2_ty: input.parse()?, + _key2_comma: input.parse()?, + key2_ty: input.parse()?, + _value_comma: input.parse()?, + value_ty: input.parse()?, + query_type: parse_query_type(input)?, + _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, + _gt_token: input.parse()?, + }) + } else if lookahead.peek(storage_types::NMap) { + let content; + Ok(Self::NMap { + _kw: input.parse()?, + _lt_token: input.parse()?, + prefix: input.parse()?, + prefix_generics: parse_pallet_generics(input)?, + _paren_comma: input.parse()?, + _paren_token: parenthesized!(content in input), + key_types: Punctuated::parse_terminated(&content)?, + _value_comma: input.parse()?, + value_ty: input.parse()?, + query_type: parse_query_type(input)?, + _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, + _gt_token: input.parse()?, + }) + } else { + Err(lookahead.error()) + } + } +} + +/// The input expected by this macro. +struct Input { + attributes: Vec, + visibility: Visibility, + _type: Token![type], + storage_name: Ident, + storage_generics: Option, + _equal: Token![=], + storage_type: StorageType, + _semicolon: Token![;], +} + +impl Parse for Input { + fn parse(input: ParseStream<'_>) -> Result { + let attributes = input.call(Attribute::parse_outer)?; + let visibility = input.parse()?; + let _type = input.parse()?; + let storage_name = input.parse()?; + + let lookahead = input.lookahead1(); + let (storage_generics, _equal) = if lookahead.peek(Token![<]) { + (Some(input.parse()?), input.parse()?) + } else if lookahead.peek(Token![=]) { + (None, input.parse()?) + } else { + return Err(lookahead.error()) + }; + + let storage_type = input.parse()?; + + let _semicolon = input.parse()?; + + Ok(Self { + attributes, + visibility, + _type, + storage_name, + storage_generics, + _equal, + storage_type, + _semicolon, + }) + } +} + +/// Implementation of the `storage_alias` attribute macro. +pub fn storage_alias(input: TokenStream) -> Result { + let input = syn::parse2::(input)?; + let crate_ = generate_crate_access_2018("frame-support")?; + + if let Some(ref generics) = input.storage_generics { + if !generics.all_have_trait_bounds() { + return Err(Error::new_spanned( + generics, + "The pallet generics require to be bound by the \ + pallet `Config` trait and optional `Instance` trait.", + )) + } + } + + let storage_instance = generate_storage_instance( + &crate_, + &input.storage_name, + input.storage_type.prefix(), + input.storage_type.prefix_generics(), + &input.visibility, + )?; + + let definition = input.storage_type.generate_type_declaration( + &crate_, + &storage_instance, + &input.storage_name, + input.storage_generics.as_ref(), + &input.visibility, + &input.attributes, + ); + + let storage_instance_code = storage_instance.code; + + Ok(quote! { + #storage_instance_code + + #definition + }) +} + +/// The storage instance to use for the storage alias. +struct StorageInstance { + name: Ident, + code: TokenStream, +} + +/// Generate the [`StorageInstance`] for the storage alias. +fn generate_storage_instance( + crate_: &Ident, + storage_name: &Ident, + prefix: &SimplePath, + prefix_generics: Option<&SimpleGenerics>, + visibility: &Visibility, +) -> Result { + let (pallet_prefix, impl_generics, type_generics) = + if let Some(prefix_generics) = prefix_generics { + let type_generics = prefix_generics.type_generics(); + let type_generics2 = prefix_generics.type_generics(); + let impl_generics = prefix_generics.impl_generics(); + + ( + quote! { + <#prefix < #( #type_generics2 ),* > as #crate_::traits::PalletInfoAccess>::name() + }, + quote!( #( #impl_generics ),* ), + quote!( #( #type_generics ),* ), + ) + } else if let Some(prefix) = prefix.get_ident() { + let prefix_str = prefix.to_string(); + + (quote!(#prefix_str), quote!(), quote!()) + } else { + return Err(Error::new_spanned( + prefix, + "If there are no generics, the prefix is only allowed to be an identifier.", + )) + }; + + let name = Ident::new(&format!("{}_Storage_Instance", storage_name), Span::call_site()); + let storage_name_str = storage_name.to_string(); + + // Implement `StorageInstance` trait. + let code = quote! { + #visibility struct #name< #impl_generics >(#crate_::sp_std::marker::PhantomData<(#type_generics)>); + + impl<#impl_generics> #crate_::traits::StorageInstance for #name< #type_generics > { + fn pallet_prefix() -> &'static str { + #pallet_prefix + } + + const STORAGE_PREFIX: &'static str = #storage_name_str; + } + }; + + Ok(StorageInstance { name, code }) +} diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 3e84c009b5ca6..4cd740c52162a 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -166,178 +166,69 @@ macro_rules! bounded_btree_map { /// Useful for creating a *storage-like* struct for test and migrations. /// /// ``` -/// # use frame_support::generate_storage_alias; +/// # use frame_support::storage_alias; /// use frame_support::codec; /// use frame_support::Twox64Concat; /// // generate a storage value with type u32. -/// generate_storage_alias!(Prefix, StorageName => Value); +/// #[storage_alias] +/// type StorageName = Value; /// /// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key) /// // to `Vec` -/// generate_storage_alias!( -/// OtherPrefix, OtherStorageName => DoubleMap< -/// (Twox64Concat, u32), -/// (Twox64Concat, u32), -/// Vec -/// > -/// ); +/// #[storage_alias] +/// type OtherStorageName = DoubleMap< +/// OtherPrefix, +/// Twox64Concat, +/// u32, +/// Twox64Concat, +/// u32, +/// Vec, +/// >; /// /// // optionally specify the query type /// use frame_support::pallet_prelude::{ValueQuery, OptionQuery}; -/// generate_storage_alias!(Prefix, ValueName => Value); -/// generate_storage_alias!( -/// Prefix, SomeStorageName => DoubleMap< -/// (Twox64Concat, u32), -/// (Twox64Concat, u32), -/// Vec, -/// ValueQuery -/// > -/// ); +/// #[storage_alias] +/// type ValueName = Value; +/// #[storage_alias] +/// type SomeStorageName = Map< +/// Prefix, +/// Twox64Concat, +/// u32, +/// Vec, +/// ValueQuery, +/// >; /// /// // generate a map from `Config::AccountId` (with hasher `Twox64Concat`) to `Vec` /// trait Config { type AccountId: codec::FullCodec; } -/// generate_storage_alias!( -/// Prefix, GenericStorage => Map<(Twox64Concat, T::AccountId), Vec> -/// ); +/// #[storage_alias] +/// type GenericStorage = Map::AccountId, Vec>; +/// +/// // It also supports NMap +/// use frame_support::storage::types::Key as NMapKey; +/// +/// #[storage_alias] +/// type SomeNMap = NMap, NMapKey), Vec>; +/// +/// // Using pallet name as prefix. +/// // +/// // When the first generic argument is taking generic arguments it is expected to be a pallet. +/// // The prefix will then be the pallet name as configured in the runtime through +/// // `construct_runtime!`. +/// +/// # struct Pallet(std::marker::PhantomData); +/// # impl frame_support::traits::PalletInfoAccess for Pallet { +/// # fn index() -> usize { 0 } +/// # fn name() -> &'static str { "pallet" } +/// # fn module_name() -> &'static str { "module" } +/// # fn crate_version() -> frame_support::traits::CrateVersion { unimplemented!() } +/// # } +/// +/// #[storage_alias] +/// type SomeValue = Value, u64>; +/// /// # fn main() {} /// ``` -#[macro_export] -macro_rules! generate_storage_alias { - // without generic for $name. - ($pallet:ident, $name:ident => Map<($hasher:ty, $key:ty), $value:ty $(, $querytype:ty)?>) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - type $name = $crate::storage::types::StorageMap< - [<$name Instance>], - $hasher, - $key, - $value, - $( $querytype )? - >; - } - }; - ( - $pallet:ident, - $name:ident - => DoubleMap<($hasher1:ty, $key1:ty), ($hasher2:ty, $key2:ty), $value:ty $(, $querytype:ty)?> - ) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - type $name = $crate::storage::types::StorageDoubleMap< - [<$name Instance>], - $hasher1, - $key1, - $hasher2, - $key2, - $value, - $( $querytype )? - >; - } - }; - ( - $pallet:ident, - $name:ident - => NMap, $value:ty $(, $querytype:ty)?> - ) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - type $name = $crate::storage::types::StorageNMap< - [<$name Instance>], - ( - $( $crate::storage::types::Key<$hasher, $key>, )+ - ), - $value, - $( $querytype )? - >; - } - }; - ($pallet:ident, $name:ident => Value<$value:ty $(, $querytype:ty)?>) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - type $name = $crate::storage::types::StorageValue< - [<$name Instance>], - $value, - $( $querytype )? - >; - } - }; - // with generic for $name. - ( - $pallet:ident, - $name:ident<$t:ident : $bounds:tt> - => Map<($hasher:ty, $key:ty), $value:ty $(, $querytype:ty)?> - ) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - #[allow(type_alias_bounds)] - type $name<$t : $bounds> = $crate::storage::types::StorageMap< - [<$name Instance>], - $hasher, - $key, - $value, - $( $querytype )? - >; - } - }; - ( - $pallet:ident, - $name:ident<$t:ident : $bounds:tt> - => DoubleMap<($hasher1:ty, $key1:ty), ($hasher2:ty, $key2:ty), $value:ty $(, $querytype:ty)?> - ) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - #[allow(type_alias_bounds)] - type $name<$t : $bounds> = $crate::storage::types::StorageDoubleMap< - [<$name Instance>], - $hasher1, - $key1, - $hasher2, - $key2, - $value, - $( $querytype )? - >; - } - }; - ( - $pallet:ident, - $name:ident<$t:ident : $bounds:tt> - => NMap<$(($hasher:ty, $key:ty),)+ $value:ty $(, $querytype:ty)?> - ) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - #[allow(type_alias_bounds)] - type $name<$t : $bounds> = $crate::storage::types::StorageNMap< - [<$name Instance>], - ( - $( $crate::storage::types::Key<$hasher, $key>, )+ - ), - $value, - $( $querytype )? - >; - } - }; - ($pallet:ident, $name:ident<$t:ident : $bounds:tt> => Value<$value:ty $(, $querytype:ty)?>) => { - $crate::paste::paste! { - $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); - #[allow(type_alias_bounds)] - type $name<$t : $bounds> = $crate::storage::types::StorageValue< - [<$name Instance>], - $value, - $( $querytype )? - >; - } - }; - // helper used in all arms. - (@GENERATE_INSTANCE_STRUCT $pallet:ident, $name:ident) => { - $crate::paste::paste! { - struct [<$name Instance>]; - impl $crate::traits::StorageInstance for [<$name Instance>] { - fn pallet_prefix() -> &'static str { stringify!($pallet) } - const STORAGE_PREFIX: &'static str = stringify!($name); - } - } - }; -} +pub use frame_support_procedural::storage_alias; /// Create new implementations of the [`Get`](crate::traits::Get) trait. /// @@ -995,16 +886,20 @@ pub mod tests { } #[test] - fn generate_storage_alias_works() { + fn storage_alias_works() { new_test_ext().execute_with(|| { - generate_storage_alias!( - Test, - GenericData2 => Map<(Blake2_128Concat, T::BlockNumber), T::BlockNumber> - ); + #[crate::storage_alias] + type GenericData2 = + Map::BlockNumber, ::BlockNumber>; assert_eq!(Module::::generic_data2(5), None); GenericData2::::insert(5, 5); assert_eq!(Module::::generic_data2(5), Some(5)); + + /// Some random docs that ensure that docs are accepted + #[crate::storage_alias] + pub type GenericData = + Map::BlockNumber, ::BlockNumber>; }); } diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 0d589994bcc2c..df7abebe1956b 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -348,12 +348,14 @@ pub mod test { use frame_support::traits::ConstU32; use sp_io::TestExternalities; - crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeMap>> } - crate::generate_storage_alias! { - Prefix, - FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedBTreeMap>> - } + #[crate::storage_alias] + type Foo = Value>>; + + #[crate::storage_alias] + type FooMap = Map>>; + + #[crate::storage_alias] + type FooDoubleMap = DoubleMap>>; fn map_from_keys(keys: &[K]) -> BTreeMap where diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index f38952bf545d9..f674c9b2c0bf3 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -322,12 +322,15 @@ pub mod test { use frame_support::traits::ConstU32; use sp_io::TestExternalities; - crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeSet>> } - crate::generate_storage_alias! { - Prefix, - FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedBTreeSet>> - } + #[crate::storage_alias] + type Foo = Value>>; + + #[crate::storage_alias] + type FooMap = Map>>; + + #[crate::storage_alias] + type FooDoubleMap = + DoubleMap>>; fn set_from_keys(keys: &[T]) -> BTreeSet where diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 92ca167f98436..2024d99771b3d 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -609,12 +609,14 @@ pub mod test { use crate::{bounded_vec, traits::ConstU32, Twox128}; use sp_io::TestExternalities; - crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedVec>> } - crate::generate_storage_alias! { - Prefix, - FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedVec>> - } + #[crate::storage_alias] + type Foo = Value>>; + + #[crate::storage_alias] + type FooMap = Map>>; + + #[crate::storage_alias] + type FooDoubleMap = DoubleMap>>; #[test] fn slide_works() { diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index 16fcaf940c62a..6264738265678 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -525,10 +525,8 @@ mod test_iterators { fn double_map_iter_from() { sp_io::TestExternalities::default().execute_with(|| { use crate::hash::Identity; - crate::generate_storage_alias!( - MyModule, - MyDoubleMap => DoubleMap<(Identity, u64), (Identity, u64), u64> - ); + #[crate::storage_alias] + type MyDoubleMap = DoubleMap; MyDoubleMap::insert(1, 10, 100); MyDoubleMap::insert(1, 21, 201); diff --git a/frame/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs index da48952bcba87..f054c5c36b84a 100644 --- a/frame/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -384,7 +384,8 @@ mod test_iterators { fn map_iter_from() { sp_io::TestExternalities::default().execute_with(|| { use crate::hash::Identity; - crate::generate_storage_alias!(MyModule, MyMap => Map<(Identity, u64), u64>); + #[crate::storage_alias] + type MyMap = Map; MyMap::insert(1, 10); MyMap::insert(2, 20); diff --git a/frame/support/src/storage/generator/nmap.rs b/frame/support/src/storage/generator/nmap.rs index be085ca2d9db6..ef243cead7580 100755 --- a/frame/support/src/storage/generator/nmap.rs +++ b/frame/support/src/storage/generator/nmap.rs @@ -475,10 +475,12 @@ mod test_iterators { fn n_map_iter_from() { sp_io::TestExternalities::default().execute_with(|| { use crate::{hash::Identity, storage::Key as NMapKey}; - crate::generate_storage_alias!( + #[crate::storage_alias] + type MyNMap = NMap< MyModule, - MyNMap => NMap, u64> - ); + (NMapKey, NMapKey, NMapKey), + u64, + >; MyNMap::insert((1, 1, 1), 11); MyNMap::insert((1, 1, 2), 21); @@ -518,11 +520,9 @@ mod test_iterators { let key_hash = NMap::hashed_key_for((1, 2)); { - crate::generate_storage_alias!(Test, NMap => DoubleMap< - (crate::Blake2_128Concat, u16), - (crate::Twox64Concat, u32), - u64 - >); + #[crate::storage_alias] + type NMap = + DoubleMap; let value = NMap::get(1, 2).unwrap(); assert_eq!(value, 50); diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 115f179d803a7..d181ba12ca869 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1545,10 +1545,8 @@ mod test { fn prefix_iterator_pagination_works() { TestExternalities::default().execute_with(|| { use crate::{hash::Identity, storage::generator::map::StorageMap}; - crate::generate_storage_alias! { - MyModule, - MyStorageMap => Map<(Identity, u64), u64> - } + #[crate::storage_alias] + type MyStorageMap = Map; MyStorageMap::insert(1, 10); MyStorageMap::insert(2, 20); @@ -1663,12 +1661,12 @@ mod test { }); } - crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedVec>> } - crate::generate_storage_alias! { - Prefix, - FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedVec>> - } + #[crate::storage_alias] + type Foo = Value>>; + #[crate::storage_alias] + type FooMap = Map>>; + #[crate::storage_alias] + type FooDoubleMap = DoubleMap>>; #[test] fn try_append_works() { diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 16dc30ea03903..349d9eea3bede 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -544,7 +544,7 @@ mod test { use crate::{ hash::{StorageHasher as _, *}, metadata::{StorageEntryModifier, StorageHasher}, - storage::types::{Key, ValueQuery}, + storage::types::{Key, Key as NMapKey, ValueQuery}, }; use sp_io::{hashing::twox_128, TestExternalities}; @@ -589,10 +589,8 @@ mod test { assert_eq!(AValueQueryWithAnOnEmpty::get((3,)), 10); { - crate::generate_storage_alias!(test, Foo => NMap< - Key<(Blake2_128Concat, u16)>, - u32 - >); + #[crate::storage_alias] + type Foo = NMap), u32>; assert_eq!(Foo::contains_key((3,)), true); assert_eq!(Foo::get((3,)), Some(10)); diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index 21cc487b49082..ddbde380147db 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -321,12 +321,13 @@ pub mod test { use frame_support::traits::ConstU32; use sp_io::TestExternalities; - crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), WeakBoundedVec>> } - crate::generate_storage_alias! { - Prefix, - FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), WeakBoundedVec>> - } + #[crate::storage_alias] + type Foo = Value>>; + #[crate::storage_alias] + type FooMap = Map>>; + #[crate::storage_alias] + type FooDoubleMap = + DoubleMap>>; #[test] fn bound_returns_correct_value() { diff --git a/frame/system/src/migrations/mod.rs b/frame/system/src/migrations/mod.rs index 872cf389d246c..7e1e2ab05ffcf 100644 --- a/frame/system/src/migrations/mod.rs +++ b/frame/system/src/migrations/mod.rs @@ -17,6 +17,7 @@ //! Migrate the reference counting state. +use crate::{Config, Pallet}; use codec::{Decode, Encode, FullCodec}; use frame_support::{ pallet_prelude::ValueQuery, traits::PalletInfoAccess, weights::Weight, Blake2_128Concat, @@ -52,43 +53,24 @@ pub trait V2ToV3 { type AccountData: 'static + FullCodec; } -// ### Warning -// -// The call below is only valid because the name System is enforced -// at runtime construction level for the system pallet. -frame_support::generate_storage_alias!( - System, UpgradedToU32RefCount => Value< - bool, - ValueQuery - > -); - -// ### Warning -// -// The call below is only valid because the name System is enforced -// at runtime construction level for the system pallet. -frame_support::generate_storage_alias!( - System, UpgradedToTripleRefCount => Value< - bool, - ValueQuery - > -); - -// ### Warning -// -// The call below is only valid because the name System is enforced -// at runtime construction level for the system pallet. -frame_support::generate_storage_alias!( - System, Account => Map< - (Blake2_128Concat, T::AccountId), - AccountInfo - > -); +#[frame_support::storage_alias] +type UpgradedToU32RefCount = Value, bool, ValueQuery>; + +#[frame_support::storage_alias] +type UpgradedToTripleRefCount = Value, bool, ValueQuery>; + +#[frame_support::storage_alias] +type Account = Map< + Pallet, + Blake2_128Concat, + ::AccountId, + AccountInfo<::Index, ::AccountData>, +>; /// Migrate from unique `u8` reference counting to triple `u32` reference counting. -pub fn migrate_from_single_u8_to_triple_ref_count() -> Weight { +pub fn migrate_from_single_u8_to_triple_ref_count() -> Weight { let mut translated: usize = 0; - >::translate::<(T::Index, u8, T::AccountData), _>(|_key, (nonce, rc, data)| { + >::translate::<(V::Index, u8, V::AccountData), _>(|_key, (nonce, rc, data)| { translated += 1; Some(AccountInfo { nonce, consumers: rc as RefCount, providers: 1, sufficients: 0, data }) }); @@ -97,15 +79,15 @@ pub fn migrate_from_single_u8_to_triple_ref_count() -> Weight { "Applied migration from single u8 to triple reference counting to {:?} elements.", translated ); - ::put(true); - ::put(true); + >::put(true); + >::put(true); Weight::max_value() } /// Migrate from unique `u32` reference counting to triple `u32` reference counting. -pub fn migrate_from_single_to_triple_ref_count() -> Weight { +pub fn migrate_from_single_to_triple_ref_count() -> Weight { let mut translated: usize = 0; - >::translate::<(T::Index, RefCount, T::AccountData), _>( + >::translate::<(V::Index, RefCount, V::AccountData), _>( |_key, (nonce, consumers, data)| { translated += 1; Some(AccountInfo { nonce, consumers, providers: 1, sufficients: 0, data }) @@ -116,14 +98,14 @@ pub fn migrate_from_single_to_triple_ref_count() -> Weight { "Applied migration from single to triple reference counting to {:?} elements.", translated ); - ::put(true); + >::put(true); Weight::max_value() } /// Migrate from dual `u32` reference counting to triple `u32` reference counting. -pub fn migrate_from_dual_to_triple_ref_count() -> Weight { +pub fn migrate_from_dual_to_triple_ref_count() -> Weight { let mut translated: usize = 0; - >::translate::<(T::Index, RefCount, RefCount, T::AccountData), _>( + >::translate::<(V::Index, RefCount, RefCount, V::AccountData), _>( |_key, (nonce, consumers, providers, data)| { translated += 1; Some(AccountInfo { nonce, consumers, providers, sufficients: 0, data }) @@ -134,6 +116,6 @@ pub fn migrate_from_dual_to_triple_ref_count() -> Weight { "Applied migration from dual to triple reference counting to {:?} elements.", translated ); - ::put(true); + >::put(true); Weight::max_value() } From b12cbb2cd29c0f0a8b3b19f1ee3df8193fc0d44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 10 May 2022 17:04:12 +0200 Subject: [PATCH 02/10] Fix compilation and FMT --- frame/offences/src/migration.rs | 4 +--- frame/support/procedural/src/lib.rs | 2 +- frame/support/procedural/src/storage_alias.rs | 22 +++++++++---------- frame/support/src/lib.rs | 8 +++++-- .../support/src/storage/bounded_btree_map.rs | 3 ++- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index 72178fe389568..9b883b2809138 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -16,9 +16,7 @@ // limitations under the License. use super::{Config, OffenceDetails, Perbill, SessionIndex}; -use frame_support::{ - storage_alias, pallet_prelude::ValueQuery, traits::Get, weights::Weight, -}; +use frame_support::{pallet_prelude::ValueQuery, storage_alias, traits::Get, weights::Weight}; use sp_staking::offence::{DisableStrategy, OnOffenceHandler}; use sp_std::vec::Vec; diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index f4e64cb949aa9..f8aaa5fe37749 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -25,13 +25,13 @@ mod crate_version; mod debug_no_bound; mod default_no_bound; mod dummy_part_checker; -mod storage_alias; mod key_prefix; mod match_and_insert; mod pallet; mod pallet_error; mod partial_eq_no_bound; mod storage; +mod storage_alias; mod transactional; mod tt_macro; diff --git a/frame/support/procedural/src/storage_alias.rs b/frame/support/procedural/src/storage_alias.rs index 39760661dd911..6fe98700385de 100644 --- a/frame/support/procedural/src/storage_alias.rs +++ b/frame/support/procedural/src/storage_alias.rs @@ -302,7 +302,17 @@ impl Parse for StorageType { let parse_pallet_generics = |input: ParseStream<'_>| -> Result> { let lookahead = input.lookahead1(); if lookahead.peek(Token![<]) { - Some(input.parse()).transpose() + let generics = input.parse::()?; + + if generics.all_have_trait_bounds() { + Ok(Some(generics)) + } else { + Err(Error::new_spanned( + generics, + "The pallet generics require to be bound by the \ + pallet `Config` trait and optional `Instance` trait.", + )) + } } else if lookahead.peek(Token![,]) { Ok(None) } else { @@ -430,16 +440,6 @@ pub fn storage_alias(input: TokenStream) -> Result { let input = syn::parse2::(input)?; let crate_ = generate_crate_access_2018("frame-support")?; - if let Some(ref generics) = input.storage_generics { - if !generics.all_have_trait_bounds() { - return Err(Error::new_spanned( - generics, - "The pallet generics require to be bound by the \ - pallet `Config` trait and optional `Instance` trait.", - )) - } - } - let storage_instance = generate_storage_instance( &crate_, &input.storage_name, diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 4cd740c52162a..0453c5339f80d 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -898,8 +898,12 @@ pub mod tests { /// Some random docs that ensure that docs are accepted #[crate::storage_alias] - pub type GenericData = - Map::BlockNumber, ::BlockNumber>; + pub type GenericData = Map< + Test2, + Blake2_128Concat, + ::BlockNumber, + ::BlockNumber, + >; }); } diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index df7abebe1956b..6afc786aeb987 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -355,7 +355,8 @@ pub mod test { type FooMap = Map>>; #[crate::storage_alias] - type FooDoubleMap = DoubleMap>>; + type FooDoubleMap = + DoubleMap>>; fn map_from_keys(keys: &[K]) -> BTreeMap where From 249b664bf5d1e6e61dbecf6431f0be08b37afa27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 10 May 2022 17:30:45 +0200 Subject: [PATCH 03/10] Moare fixes --- frame/elections-phragmen/src/migrations/v3.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/elections-phragmen/src/migrations/v3.rs b/frame/elections-phragmen/src/migrations/v3.rs index 815bdf71591ea..34b8486183ff0 100644 --- a/frame/elections-phragmen/src/migrations/v3.rs +++ b/frame/elections-phragmen/src/migrations/v3.rs @@ -68,7 +68,8 @@ type RunnersUp = Value< #[frame_support::storage_alias] type Voting = Map< Pallet, - (Twox64Concat, T::AccountId), + Twox64Concat, + ::AccountId, Voter<::AccountId, ::Balance>, >; @@ -85,7 +86,7 @@ pub fn apply( old_voter_bond: V::Balance, old_candidacy_bond: V::Balance, ) -> Weight { - let storage_version = StorageVersion::get::(); + let storage_version = StorageVersion::get::>(); log::info!( target: "runtime::elections-phragmen", "Running migration for elections-phragmen with storage version {:?}", From 985d85e075c53dac545d3f3c30eebfea8a2af87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 10 May 2022 19:45:01 +0200 Subject: [PATCH 04/10] :facepalm: --- frame/bags-list/src/list/tests.rs | 4 ++-- frame/contracts/src/migration.rs | 14 +++++++------- frame/offences/src/migration.rs | 2 +- frame/staking/src/migrations.rs | 32 +++++++++++++++---------------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index 66c2ad8ab95b5..87edc4e297a5a 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -370,8 +370,8 @@ mod list { // not exposed as mutable in any sense. #[frame_support::storage_alias] type CounterForListNodes = - Value, u32, frame_support::pallet_prelude::ValueQuery>; - CounterForListNodes::mutate(|counter| *counter += 1); + Value, u32, frame_support::pallet_prelude::ValueQuery>; + CounterForListNodes::::mutate(|counter| *counter += 1); assert_eq!(crate::ListNodes::::count(), 5); assert_eq!(List::::sanity_check(), Err("iter_count != stored_count")); diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 827120a9ab96a..1bcdb89e7fbf7 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -118,10 +118,10 @@ mod v5 { #[storage_alias] type ContractInfoOf = - Map, Twox64Concat, ::AccountId, ContractInfo>; + Map, Twox64Concat, ::AccountId, ContractInfo>; #[storage_alias] - type DeletionQueue = Value, Vec>; + type DeletionQueue = Value, Vec>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -138,7 +138,7 @@ mod v5 { } }); - DeletionQueue::translate(|old: Option>| { + DeletionQueue::::translate(|old: Option>| { weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); old.map(|old| old.into_iter().map(|o| DeletedContract { trie_id: o.trie_id }).collect()) }) @@ -200,13 +200,13 @@ mod v6 { #[storage_alias] type ContractInfoOf = - Map, Twox64Concat, ::AccountId, ContractInfo>; + Map, Twox64Concat, ::AccountId, ContractInfo>; #[storage_alias] - type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; + type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; #[storage_alias] - type OwnerInfoOf = Map, Identity, CodeHash, OwnerInfo>; + type OwnerInfoOf = Map, Identity, CodeHash, OwnerInfo>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -255,7 +255,7 @@ mod v7 { #[storage_alias] type Nonce = Value, u64, ValueQuery>; - Nonce::set(AccountCounter::take()); + Nonce::::set(AccountCounter::::take()); T::DbWeight::get().reads_writes(1, 2) } } diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index 9b883b2809138..54989555343c8 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -30,7 +30,7 @@ type DeferredOffenceOf = ( // Deferred reports that have been rejected by the offence handler and need to be submitted // at a later time. #[storage_alias] -type DeferredOffences = Value, Vec>, ValueQuery>; +type DeferredOffences = Value, Vec>, ValueQuery>; pub fn remove_deferred_storage() -> Weight { let mut weight = T::DbWeight::get().reads_writes(1, 1); diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 60666083644b0..7b8b325c44238 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -148,11 +148,11 @@ pub mod v7 { pub fn pre_migrate() -> Result<(), &'static str> { assert!( - CounterForValidators::get().unwrap().is_zero(), + CounterForValidators::::get().unwrap().is_zero(), "CounterForValidators already set." ); assert!( - CounterForNominators::get().unwrap().is_zero(), + CounterForNominators::::get().unwrap().is_zero(), "CounterForNominators already set." ); assert!(Validators::::count().is_zero(), "Validators already set."); @@ -166,8 +166,8 @@ pub mod v7 { let validator_count = Validators::::iter().count() as u32; let nominator_count = Nominators::::iter().count() as u32; - CounterForValidators::put(validator_count); - CounterForNominators::put(nominator_count); + CounterForValidators::::put(validator_count); + CounterForNominators::::put(nominator_count); StorageVersion::::put(Releases::V7_0_0); log!(info, "Completed staking migration to Releases::V7_0_0"); @@ -197,13 +197,13 @@ pub mod v6 { /// check to execute prior to migration. pub fn pre_migrate() -> Result<(), &'static str> { // these may or may not exist. - log!(info, "SnapshotValidators.exits()? {:?}", SnapshotValidators::exists()); - log!(info, "SnapshotNominators.exits()? {:?}", SnapshotNominators::exists()); - log!(info, "QueuedElected.exits()? {:?}", QueuedElected::exists()); - log!(info, "QueuedScore.exits()? {:?}", QueuedScore::exists()); + log!(info, "SnapshotValidators.exits()? {:?}", SnapshotValidators::::exists()); + log!(info, "SnapshotNominators.exits()? {:?}", SnapshotNominators::::exists()); + log!(info, "QueuedElected.exits()? {:?}", QueuedElected::::exists()); + log!(info, "QueuedScore.exits()? {:?}", QueuedScore::::exists()); // these must exist. - assert!(IsCurrentSessionFinal::exists(), "IsCurrentSessionFinal storage item not found!"); - assert!(EraElectionStatus::exists(), "EraElectionStatus storage item not found!"); + assert!(IsCurrentSessionFinal::::exists(), "IsCurrentSessionFinal storage item not found!"); + assert!(EraElectionStatus::::exists(), "EraElectionStatus storage item not found!"); Ok(()) } @@ -211,12 +211,12 @@ pub mod v6 { pub fn migrate() -> Weight { log!(info, "Migrating staking to Releases::V6_0_0"); - SnapshotValidators::kill(); - SnapshotNominators::kill(); - QueuedElected::kill(); - QueuedScore::kill(); - EraElectionStatus::kill(); - IsCurrentSessionFinal::kill(); + SnapshotValidators::::kill(); + SnapshotNominators::::kill(); + QueuedElected::::kill(); + QueuedScore::::kill(); + EraElectionStatus::::kill(); + IsCurrentSessionFinal::::kill(); StorageVersion::::put(Releases::V6_0_0); log!(info, "Done."); From f176279da1cd464e8d75b2ec9b5601f1cc82ce72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 10 May 2022 20:05:23 +0200 Subject: [PATCH 05/10] ...... --- frame/contracts/src/migration.rs | 16 ++++++++++++---- frame/staking/src/migrations.rs | 5 ++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 1bcdb89e7fbf7..64218061d4930 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -117,8 +117,12 @@ mod v5 { } #[storage_alias] - type ContractInfoOf = - Map, Twox64Concat, ::AccountId, ContractInfo>; + type ContractInfoOf = Map< + Pallet, + Twox64Concat, + ::AccountId, + ContractInfo, + >; #[storage_alias] type DeletionQueue = Value, Vec>; @@ -199,8 +203,12 @@ mod v6 { type ContractInfo = RawContractInfo, BalanceOf>; #[storage_alias] - type ContractInfoOf = - Map, Twox64Concat, ::AccountId, ContractInfo>; + type ContractInfoOf = Map< + Pallet, + Twox64Concat, + ::AccountId, + ContractInfo, + >; #[storage_alias] type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 7b8b325c44238..66bb7e959b483 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -202,7 +202,10 @@ pub mod v6 { log!(info, "QueuedElected.exits()? {:?}", QueuedElected::::exists()); log!(info, "QueuedScore.exits()? {:?}", QueuedScore::::exists()); // these must exist. - assert!(IsCurrentSessionFinal::::exists(), "IsCurrentSessionFinal storage item not found!"); + assert!( + IsCurrentSessionFinal::::exists(), + "IsCurrentSessionFinal storage item not found!" + ); assert!(EraElectionStatus::::exists(), "EraElectionStatus storage item not found!"); Ok(()) } From 4ab6ace2d31f872aaec842e7a5c4bbdf5ca2512e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 11 May 2022 16:58:20 +0200 Subject: [PATCH 06/10] Rework the syntax and support instancing --- frame/bags-list/src/list/tests.rs | 4 +- frame/contracts/src/migration.rs | 18 +-- frame/elections-phragmen/src/migrations/v3.rs | 22 ++- frame/offences/src/migration.rs | 2 +- frame/staking/src/migrations.rs | 16 +-- frame/support/procedural/src/storage_alias.rs | 125 +++++++++++------- frame/support/src/lib.rs | 11 +- frame/support/test/tests/pallet.rs | 14 ++ frame/support/test/tests/pallet_instance.rs | 12 ++ frame/system/src/migrations/mod.rs | 8 +- 10 files changed, 145 insertions(+), 87 deletions(-) diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index 87edc4e297a5a..17d17459d1ff1 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -369,8 +369,8 @@ mod list { // we do some wacky stuff here to get access to the counter, since it is (reasonably) // not exposed as mutable in any sense. #[frame_support::storage_alias] - type CounterForListNodes = - Value, u32, frame_support::pallet_prelude::ValueQuery>; + type CounterForListNodes = + Value, u32, frame_support::pallet_prelude::ValueQuery>; CounterForListNodes::::mutate(|counter| *counter += 1); assert_eq!(crate::ListNodes::::count(), 5); diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 64218061d4930..b465301cd963a 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -117,15 +117,15 @@ mod v5 { } #[storage_alias] - type ContractInfoOf = Map< - Pallet, + type ContractInfoOf = Map< + Pallet, Twox64Concat, ::AccountId, ContractInfo, >; #[storage_alias] - type DeletionQueue = Value, Vec>; + type DeletionQueue = Value, Vec>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -203,18 +203,18 @@ mod v6 { type ContractInfo = RawContractInfo, BalanceOf>; #[storage_alias] - type ContractInfoOf = Map< - Pallet, + type ContractInfoOf = Map< + Pallet, Twox64Concat, ::AccountId, ContractInfo, >; #[storage_alias] - type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; + type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; #[storage_alias] - type OwnerInfoOf = Map, Identity, CodeHash, OwnerInfo>; + type OwnerInfoOf = Map, Identity, CodeHash, OwnerInfo>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -259,9 +259,9 @@ mod v7 { pub fn migrate() -> Weight { #[storage_alias] - type AccountCounter = Value, u64, ValueQuery>; + type AccountCounter = Value, u64, ValueQuery>; #[storage_alias] - type Nonce = Value, u64, ValueQuery>; + type Nonce = Value, u64, ValueQuery>; Nonce::::set(AccountCounter::::take()); T::DbWeight::get().reads_writes(1, 2) diff --git a/frame/elections-phragmen/src/migrations/v3.rs b/frame/elections-phragmen/src/migrations/v3.rs index 34b8486183ff0..1889c5f60e3ed 100644 --- a/frame/elections-phragmen/src/migrations/v3.rs +++ b/frame/elections-phragmen/src/migrations/v3.rs @@ -48,26 +48,20 @@ pub trait V2ToV3 { } #[frame_support::storage_alias] -type Candidates = - Value, Vec<(::AccountId, ::Balance)>, ValueQuery>; +type Candidates = + Value, Vec<(::AccountId, ::Balance)>, ValueQuery>; #[frame_support::storage_alias] -type Members = Value< - Pallet, - Vec::AccountId, ::Balance>>, - ValueQuery, ->; +type Members = + Value, Vec::AccountId, ::Balance>>, ValueQuery>; #[frame_support::storage_alias] -type RunnersUp = Value< - Pallet, - Vec::AccountId, ::Balance>>, - ValueQuery, ->; +type RunnersUp = + Value, Vec::AccountId, ::Balance>>, ValueQuery>; #[frame_support::storage_alias] -type Voting = Map< - Pallet, +type Voting = Map< + Pallet, Twox64Concat, ::AccountId, Voter<::AccountId, ::Balance>, diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index 54989555343c8..5a7a470ce6cf7 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -30,7 +30,7 @@ type DeferredOffenceOf = ( // Deferred reports that have been rejected by the offence handler and need to be submitted // at a later time. #[storage_alias] -type DeferredOffences = Value, Vec>, ValueQuery>; +type DeferredOffences = Value, Vec>, ValueQuery>; pub fn remove_deferred_storage() -> Weight { let mut weight = T::DbWeight::get().reads_writes(1, 1); diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 66bb7e959b483..5d3e93a0de814 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -142,9 +142,9 @@ pub mod v7 { use frame_support::storage_alias; #[storage_alias] - type CounterForValidators = Value, u32>; + type CounterForValidators = Value, u32>; #[storage_alias] - type CounterForNominators = Value, u32>; + type CounterForNominators = Value, u32>; pub fn pre_migrate() -> Result<(), &'static str> { assert!( @@ -182,17 +182,17 @@ pub mod v6 { // NOTE: value type doesn't matter, we just set it to () here. #[storage_alias] - type SnapshotValidators = Value, ()>; + type SnapshotValidators = Value, ()>; #[storage_alias] - type SnapshotNominators = Value, ()>; + type SnapshotNominators = Value, ()>; #[storage_alias] - type QueuedElected = Value, ()>; + type QueuedElected = Value, ()>; #[storage_alias] - type QueuedScore = Value, ()>; + type QueuedScore = Value, ()>; #[storage_alias] - type EraElectionStatus = Value, ()>; + type EraElectionStatus = Value, ()>; #[storage_alias] - type IsCurrentSessionFinal = Value, ()>; + type IsCurrentSessionFinal = Value, ()>; /// check to execute prior to migration. pub fn pre_migrate() -> Result<(), &'static str> { diff --git a/frame/support/procedural/src/storage_alias.rs b/frame/support/procedural/src/storage_alias.rs index 6fe98700385de..01c04d1e85e91 100644 --- a/frame/support/procedural/src/storage_alias.rs +++ b/frame/support/procedural/src/storage_alias.rs @@ -25,7 +25,7 @@ use syn::{ parenthesized, parse::{Parse, ParseStream}, punctuated::Punctuated, - token, Attribute, Error, Ident, Result, Token, Type, TypeParam, Visibility, + token, Attribute, Error, Ident, Result, Token, Type, TypeParam, Visibility, WhereClause, }; /// Represents a path that only consists of [`Ident`] separated by `::`. @@ -63,6 +63,39 @@ impl ToTokens for SimplePath { } } +/// Represents generics which only support [`Ident`] separated by commas as you would pass it to a +/// type. +struct TypeGenerics { + lt_token: Token![<], + params: Punctuated, + gt_token: Token![>], +} + +impl TypeGenerics { + /// Returns the generics for types declarations etc. + fn iter(&self) -> impl Iterator { + self.params.iter() + } +} + +impl Parse for TypeGenerics { + fn parse(input: ParseStream<'_>) -> Result { + Ok(Self { + lt_token: input.parse()?, + params: Punctuated::parse_separated_nonempty(input)?, + gt_token: input.parse()?, + }) + } +} + +impl ToTokens for TypeGenerics { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.lt_token.to_tokens(tokens); + self.params.to_tokens(tokens); + self.gt_token.to_tokens(tokens); + } +} + /// Represents generics which only support [`TypeParam`] separated by commas. struct SimpleGenerics { lt_token: Token![<], @@ -80,13 +113,6 @@ impl SimpleGenerics { fn impl_generics(&self) -> impl Iterator { self.params.iter() } - - /// Returns `true` if all parameters have at least one trait bound. - fn all_have_trait_bounds(&self) -> bool { - self.params - .iter() - .all(|p| p.bounds.iter().any(|b| matches!(b, syn::TypeParamBound::Trait(_)))) - } } impl Parse for SimpleGenerics { @@ -120,7 +146,7 @@ enum StorageType { _kw: storage_types::Value, _lt_token: Token![<], prefix: SimplePath, - prefix_generics: Option, + prefix_generics: Option, _value_comma: Token![,], value_ty: Type, query_type: Option<(Token![,], Type)>, @@ -131,7 +157,7 @@ enum StorageType { _kw: storage_types::Map, _lt_token: Token![<], prefix: SimplePath, - prefix_generics: Option, + prefix_generics: Option, _hasher_comma: Token![,], hasher_ty: Type, _key_comma: Token![,], @@ -146,7 +172,7 @@ enum StorageType { _kw: storage_types::DoubleMap, _lt_token: Token![<], prefix: SimplePath, - prefix_generics: Option, + prefix_generics: Option, _hasher1_comma: Token![,], hasher1_ty: Type, _key1_comma: Token![,], @@ -165,7 +191,7 @@ enum StorageType { _kw: storage_types::NMap, _lt_token: Token![<], prefix: SimplePath, - prefix_generics: Option, + prefix_generics: Option, _paren_comma: Token![,], _paren_token: token::Paren, key_types: Punctuated, @@ -189,35 +215,33 @@ impl StorageType { attributes: &[Attribute], ) -> TokenStream { let storage_instance = &storage_instance.name; - let type_generics = self - .prefix_generics() - .map(|g| { - let g = g.type_generics(); - quote! { <#( #g ),*> } - }) - .unwrap_or_default(); let attributes = attributes.iter(); + let storage_generics = storage_generics.map(|g| { + let generics = g.type_generics(); + + quote!( < #( #generics ),* > ) + }); match self { - Self::Value { value_ty, query_type, .. } => { + Self::Value { value_ty, query_type, prefix_generics, .. } => { let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); quote! { #( #attributes )* #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageValue< - #storage_instance #type_generics, + #storage_instance #prefix_generics, #value_ty #query_type >; } }, - Self::Map { value_ty, query_type, hasher_ty, key_ty, .. } => { + Self::Map { value_ty, query_type, hasher_ty, key_ty, prefix_generics, .. } => { let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); quote! { #( #attributes )* #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageMap< - #storage_instance #type_generics, + #storage_instance #prefix_generics, #hasher_ty, #key_ty, #value_ty @@ -232,6 +256,7 @@ impl StorageType { key1_ty, hasher2_ty, key2_ty, + prefix_generics, .. } => { let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); @@ -239,7 +264,7 @@ impl StorageType { quote! { #( #attributes )* #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageDoubleMap< - #storage_instance #type_generics, + #storage_instance #prefix_generics, #hasher1_ty, #key1_ty, #hasher2_ty, @@ -249,14 +274,14 @@ impl StorageType { >; } }, - Self::NMap { value_ty, query_type, key_types, .. } => { + Self::NMap { value_ty, query_type, key_types, prefix_generics, .. } => { let query_type = query_type.as_ref().map(|(c, t)| quote!(#c #t)); let key_types = key_types.iter(); quote! { #( #attributes )* #visibility type #storage_name #storage_generics = #crate_::storage::types::StorageNMap< - #storage_instance #type_generics, + #storage_instance #prefix_generics, ( #( #key_types ),* ), #value_ty #query_type @@ -277,7 +302,7 @@ impl StorageType { } /// The prefix generics for this storage type. - fn prefix_generics(&self) -> Option<&SimpleGenerics> { + fn prefix_generics(&self) -> Option<&TypeGenerics> { match self { Self::Value { prefix_generics, .. } | Self::Map { prefix_generics, .. } | @@ -299,20 +324,10 @@ impl Parse for StorageType { } }; - let parse_pallet_generics = |input: ParseStream<'_>| -> Result> { + let parse_pallet_generics = |input: ParseStream<'_>| -> Result> { let lookahead = input.lookahead1(); if lookahead.peek(Token![<]) { - let generics = input.parse::()?; - - if generics.all_have_trait_bounds() { - Ok(Some(generics)) - } else { - Err(Error::new_spanned( - generics, - "The pallet generics require to be bound by the \ - pallet `Config` trait and optional `Instance` trait.", - )) - } + Ok(Some(input.parse()?)) } else if lookahead.peek(Token![,]) { Ok(None) } else { @@ -399,6 +414,7 @@ struct Input { storage_generics: Option, _equal: Token![=], storage_type: StorageType, + where_clause: Option, _semicolon: Token![;], } @@ -420,6 +436,8 @@ impl Parse for Input { let storage_type = input.parse()?; + let where_clause = input.parse()?; + let _semicolon = input.parse()?; Ok(Self { @@ -430,6 +448,7 @@ impl Parse for Input { storage_generics, _equal, storage_type, + where_clause, _semicolon, }) } @@ -443,6 +462,8 @@ pub fn storage_alias(input: TokenStream) -> Result { let storage_instance = generate_storage_instance( &crate_, &input.storage_name, + input.storage_generics.as_ref(), + input.where_clause.as_ref(), input.storage_type.prefix(), input.storage_type.prefix_generics(), &input.visibility, @@ -476,15 +497,21 @@ struct StorageInstance { fn generate_storage_instance( crate_: &Ident, storage_name: &Ident, + storage_generics: Option<&SimpleGenerics>, + storage_where_clause: Option<&WhereClause>, prefix: &SimplePath, - prefix_generics: Option<&SimpleGenerics>, + prefix_generics: Option<&TypeGenerics>, visibility: &Visibility, ) -> Result { let (pallet_prefix, impl_generics, type_generics) = - if let Some(prefix_generics) = prefix_generics { - let type_generics = prefix_generics.type_generics(); - let type_generics2 = prefix_generics.type_generics(); - let impl_generics = prefix_generics.impl_generics(); + if let Some((prefix_generics, storage_generics)) = + prefix_generics.and_then(|p| storage_generics.map(|s| (p, s))) + { + let type_generics = prefix_generics.iter(); + let type_generics2 = prefix_generics.iter(); + let impl_generics = storage_generics + .impl_generics() + .filter(|g| prefix_generics.params.iter().any(|pg| *pg == g.ident)); ( quote! { @@ -504,14 +531,20 @@ fn generate_storage_instance( )) }; + let where_clause = storage_where_clause.map(|w| quote!(#w)).unwrap_or_default(); + let name = Ident::new(&format!("{}_Storage_Instance", storage_name), Span::call_site()); let storage_name_str = storage_name.to_string(); // Implement `StorageInstance` trait. let code = quote! { - #visibility struct #name< #impl_generics >(#crate_::sp_std::marker::PhantomData<(#type_generics)>); + #visibility struct #name< #impl_generics >( + #crate_::sp_std::marker::PhantomData<(#type_generics)> + ) #where_clause; - impl<#impl_generics> #crate_::traits::StorageInstance for #name< #type_generics > { + impl<#impl_generics> #crate_::traits::StorageInstance + for #name< #type_generics > #where_clause + { fn pallet_prefix() -> &'static str { #pallet_prefix } diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 0453c5339f80d..77a8ba0f41d72 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -215,8 +215,8 @@ macro_rules! bounded_btree_map { /// // The prefix will then be the pallet name as configured in the runtime through /// // `construct_runtime!`. /// -/// # struct Pallet(std::marker::PhantomData); -/// # impl frame_support::traits::PalletInfoAccess for Pallet { +/// # struct Pallet(std::marker::PhantomData<(T, I)>); +/// # impl frame_support::traits::PalletInfoAccess for Pallet { /// # fn index() -> usize { 0 } /// # fn name() -> &'static str { "pallet" } /// # fn module_name() -> &'static str { "module" } @@ -224,7 +224,12 @@ macro_rules! bounded_btree_map { /// # } /// /// #[storage_alias] -/// type SomeValue = Value, u64>; +/// type SomeValue = Value, u64>; +/// +/// // Pallet with instance +/// +/// #[storage_alias] +/// type SomeValue2 = Value, u64>; /// /// # fn main() {} /// ``` diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 83f6a722f93aa..eac7a271f044e 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -17,6 +17,7 @@ use frame_support::{ dispatch::{Parameter, UnfilteredDispatchable}, + pallet_prelude::ValueQuery, storage::unhashed, traits::{ ConstU32, GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize, @@ -1635,3 +1636,16 @@ fn assert_type_all_pallets_without_system_reversed_is_correct() { _a(t) } } + +#[test] +fn test_storage_alias() { + #[frame_support::storage_alias] + type Value = + Value, u32, ValueQuery> + where ::AccountId: From + SomeAssociation1; + + TestExternalities::default().execute_with(|| { + pallet::Value::::put(10); + assert_eq!(10, Value::::get()); + }) +} diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 118794e2fa20a..47793994c4c94 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -17,6 +17,7 @@ use frame_support::{ dispatch::UnfilteredDispatchable, + pallet_prelude::ValueQuery, storage::unhashed, traits::{ConstU32, GetCallName, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade}, weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}, @@ -821,3 +822,14 @@ fn test_pallet_info_access() { assert_eq!(::index(), 3); assert_eq!(::index(), 4); } + +#[test] +fn test_storage_alias() { + #[frame_support::storage_alias] + type Value, I: 'static> = Value, u32, ValueQuery>; + + TestExternalities::default().execute_with(|| { + pallet::Value::::put(10); + assert_eq!(10, Value::::get()); + }) +} diff --git a/frame/system/src/migrations/mod.rs b/frame/system/src/migrations/mod.rs index 7e1e2ab05ffcf..6d21faa1ea28f 100644 --- a/frame/system/src/migrations/mod.rs +++ b/frame/system/src/migrations/mod.rs @@ -54,14 +54,14 @@ pub trait V2ToV3 { } #[frame_support::storage_alias] -type UpgradedToU32RefCount = Value, bool, ValueQuery>; +type UpgradedToU32RefCount = Value, bool, ValueQuery>; #[frame_support::storage_alias] -type UpgradedToTripleRefCount = Value, bool, ValueQuery>; +type UpgradedToTripleRefCount = Value, bool, ValueQuery>; #[frame_support::storage_alias] -type Account = Map< - Pallet, +type Account = Map< + Pallet, Blake2_128Concat, ::AccountId, AccountInfo<::Index, ::AccountData>, From e11c001761acdd867226151396fc97a6578d4ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 11 May 2022 17:00:11 +0200 Subject: [PATCH 07/10] FMT --- frame/contracts/src/migration.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index b465301cd963a..846d3d1754602 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -117,12 +117,8 @@ mod v5 { } #[storage_alias] - type ContractInfoOf = Map< - Pallet, - Twox64Concat, - ::AccountId, - ContractInfo, - >; + type ContractInfoOf = + Map, Twox64Concat, ::AccountId, ContractInfo>; #[storage_alias] type DeletionQueue = Value, Vec>; @@ -203,12 +199,8 @@ mod v6 { type ContractInfo = RawContractInfo, BalanceOf>; #[storage_alias] - type ContractInfoOf = Map< - Pallet, - Twox64Concat, - ::AccountId, - ContractInfo, - >; + type ContractInfoOf = + Map, Twox64Concat, ::AccountId, ContractInfo>; #[storage_alias] type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; From 38bcf1613119789976938beed1ad242a7654ef2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 16 May 2022 12:08:08 +0200 Subject: [PATCH 08/10] Prefix variants with `Storage` --- frame/bags-list/src/list/tests.rs | 2 +- frame/bags-list/src/migrations.rs | 2 +- frame/contracts/src/migration.rs | 26 ++++++++++++------- frame/elections-phragmen/src/migrations/v3.rs | 18 ++++++++----- frame/offences/src/migration.rs | 3 ++- frame/staking/src/migrations.rs | 16 ++++++------ frame/support/procedural/src/storage_alias.rs | 24 ++++++++--------- frame/support/src/lib.rs | 26 +++++++++++-------- .../support/src/storage/bounded_btree_map.rs | 6 ++--- .../support/src/storage/bounded_btree_set.rs | 6 ++--- frame/support/src/storage/bounded_vec.rs | 7 ++--- .../src/storage/generator/double_map.rs | 2 +- frame/support/src/storage/generator/map.rs | 2 +- frame/support/src/storage/generator/nmap.rs | 12 ++++++--- frame/support/src/storage/mod.rs | 9 ++++--- frame/support/src/storage/types/nmap.rs | 2 +- frame/support/src/storage/weak_bounded_vec.rs | 6 ++--- frame/support/test/tests/pallet.rs | 2 +- frame/support/test/tests/pallet_instance.rs | 3 ++- frame/system/src/migrations/mod.rs | 6 ++--- 20 files changed, 104 insertions(+), 76 deletions(-) diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index 17d17459d1ff1..40a174b35a5d3 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -370,7 +370,7 @@ mod list { // not exposed as mutable in any sense. #[frame_support::storage_alias] type CounterForListNodes = - Value, u32, frame_support::pallet_prelude::ValueQuery>; + StorageValue, u32, frame_support::pallet_prelude::ValueQuery>; CounterForListNodes::::mutate(|counter| *counter += 1); assert_eq!(crate::ListNodes::::count(), 5); diff --git a/frame/bags-list/src/migrations.rs b/frame/bags-list/src/migrations.rs index 42606ff7e635d..68569c699aa68 100644 --- a/frame/bags-list/src/migrations.rs +++ b/frame/bags-list/src/migrations.rs @@ -31,7 +31,7 @@ impl OnRuntimeUpgrade for CheckCounterPrefix { use frame_support::ensure; // The old explicit storage item. #[frame_support::storage_alias] - type CounterForListNodes = Value, u32>; + type CounterForListNodes = StorageValue, u32>; // ensure that a value exists in the counter struct. ensure!( diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 846d3d1754602..3e2e2740b42aa 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -117,11 +117,15 @@ mod v5 { } #[storage_alias] - type ContractInfoOf = - Map, Twox64Concat, ::AccountId, ContractInfo>; + type ContractInfoOf = StorageMap< + Pallet, + Twox64Concat, + ::AccountId, + ContractInfo, + >; #[storage_alias] - type DeletionQueue = Value, Vec>; + type DeletionQueue = StorageValue, Vec>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -199,14 +203,18 @@ mod v6 { type ContractInfo = RawContractInfo, BalanceOf>; #[storage_alias] - type ContractInfoOf = - Map, Twox64Concat, ::AccountId, ContractInfo>; + type ContractInfoOf = StorageMap< + Pallet, + Twox64Concat, + ::AccountId, + ContractInfo, + >; #[storage_alias] - type CodeStorage = Map, Identity, CodeHash, PrefabWasmModule>; + type CodeStorage = StorageMap, Identity, CodeHash, PrefabWasmModule>; #[storage_alias] - type OwnerInfoOf = Map, Identity, CodeHash, OwnerInfo>; + type OwnerInfoOf = StorageMap, Identity, CodeHash, OwnerInfo>; pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -251,9 +259,9 @@ mod v7 { pub fn migrate() -> Weight { #[storage_alias] - type AccountCounter = Value, u64, ValueQuery>; + type AccountCounter = StorageValue, u64, ValueQuery>; #[storage_alias] - type Nonce = Value, u64, ValueQuery>; + type Nonce = StorageValue, u64, ValueQuery>; Nonce::::set(AccountCounter::::take()); T::DbWeight::get().reads_writes(1, 2) diff --git a/frame/elections-phragmen/src/migrations/v3.rs b/frame/elections-phragmen/src/migrations/v3.rs index 1889c5f60e3ed..b1cdd4be98541 100644 --- a/frame/elections-phragmen/src/migrations/v3.rs +++ b/frame/elections-phragmen/src/migrations/v3.rs @@ -49,18 +49,24 @@ pub trait V2ToV3 { #[frame_support::storage_alias] type Candidates = - Value, Vec<(::AccountId, ::Balance)>, ValueQuery>; + StorageValue, Vec<(::AccountId, ::Balance)>, ValueQuery>; #[frame_support::storage_alias] -type Members = - Value, Vec::AccountId, ::Balance>>, ValueQuery>; +type Members = StorageValue< + Pallet, + Vec::AccountId, ::Balance>>, + ValueQuery, +>; #[frame_support::storage_alias] -type RunnersUp = - Value, Vec::AccountId, ::Balance>>, ValueQuery>; +type RunnersUp = StorageValue< + Pallet, + Vec::AccountId, ::Balance>>, + ValueQuery, +>; #[frame_support::storage_alias] -type Voting = Map< +type Voting = StorageMap< Pallet, Twox64Concat, ::AccountId, diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index 5a7a470ce6cf7..e8fab1c0babc7 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -30,7 +30,8 @@ type DeferredOffenceOf = ( // Deferred reports that have been rejected by the offence handler and need to be submitted // at a later time. #[storage_alias] -type DeferredOffences = Value, Vec>, ValueQuery>; +type DeferredOffences = + StorageValue, Vec>, ValueQuery>; pub fn remove_deferred_storage() -> Weight { let mut weight = T::DbWeight::get().reads_writes(1, 1); diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 5d3e93a0de814..14846da8a5d54 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -142,9 +142,9 @@ pub mod v7 { use frame_support::storage_alias; #[storage_alias] - type CounterForValidators = Value, u32>; + type CounterForValidators = StorageValue, u32>; #[storage_alias] - type CounterForNominators = Value, u32>; + type CounterForNominators = StorageValue, u32>; pub fn pre_migrate() -> Result<(), &'static str> { assert!( @@ -182,17 +182,17 @@ pub mod v6 { // NOTE: value type doesn't matter, we just set it to () here. #[storage_alias] - type SnapshotValidators = Value, ()>; + type SnapshotValidators = StorageValue, ()>; #[storage_alias] - type SnapshotNominators = Value, ()>; + type SnapshotNominators = StorageValue, ()>; #[storage_alias] - type QueuedElected = Value, ()>; + type QueuedElected = StorageValue, ()>; #[storage_alias] - type QueuedScore = Value, ()>; + type QueuedScore = StorageValue, ()>; #[storage_alias] - type EraElectionStatus = Value, ()>; + type EraElectionStatus = StorageValue, ()>; #[storage_alias] - type IsCurrentSessionFinal = Value, ()>; + type IsCurrentSessionFinal = StorageValue, ()>; /// check to execute prior to migration. pub fn pre_migrate() -> Result<(), &'static str> { diff --git a/frame/support/procedural/src/storage_alias.rs b/frame/support/procedural/src/storage_alias.rs index 01c04d1e85e91..c44ca586eea94 100644 --- a/frame/support/procedural/src/storage_alias.rs +++ b/frame/support/procedural/src/storage_alias.rs @@ -134,16 +134,16 @@ impl ToTokens for SimpleGenerics { } mod storage_types { - syn::custom_keyword!(Value); - syn::custom_keyword!(Map); - syn::custom_keyword!(DoubleMap); - syn::custom_keyword!(NMap); + syn::custom_keyword!(StorageValue); + syn::custom_keyword!(StorageMap); + syn::custom_keyword!(StorageDoubleMap); + syn::custom_keyword!(StorageNMap); } /// The supported storage types enum StorageType { Value { - _kw: storage_types::Value, + _kw: storage_types::StorageValue, _lt_token: Token![<], prefix: SimplePath, prefix_generics: Option, @@ -154,7 +154,7 @@ enum StorageType { _gt_token: Token![>], }, Map { - _kw: storage_types::Map, + _kw: storage_types::StorageMap, _lt_token: Token![<], prefix: SimplePath, prefix_generics: Option, @@ -169,7 +169,7 @@ enum StorageType { _gt_token: Token![>], }, DoubleMap { - _kw: storage_types::DoubleMap, + _kw: storage_types::StorageDoubleMap, _lt_token: Token![<], prefix: SimplePath, prefix_generics: Option, @@ -188,7 +188,7 @@ enum StorageType { _gt_token: Token![>], }, NMap { - _kw: storage_types::NMap, + _kw: storage_types::StorageNMap, _lt_token: Token![<], prefix: SimplePath, prefix_generics: Option, @@ -335,7 +335,7 @@ impl Parse for StorageType { } }; - if lookahead.peek(storage_types::Value) { + if lookahead.peek(storage_types::StorageValue) { Ok(Self::Value { _kw: input.parse()?, _lt_token: input.parse()?, @@ -347,7 +347,7 @@ impl Parse for StorageType { _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, _gt_token: input.parse()?, }) - } else if lookahead.peek(storage_types::Map) { + } else if lookahead.peek(storage_types::StorageMap) { Ok(Self::Map { _kw: input.parse()?, _lt_token: input.parse()?, @@ -363,7 +363,7 @@ impl Parse for StorageType { _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, _gt_token: input.parse()?, }) - } else if lookahead.peek(storage_types::DoubleMap) { + } else if lookahead.peek(storage_types::StorageDoubleMap) { Ok(Self::DoubleMap { _kw: input.parse()?, _lt_token: input.parse()?, @@ -383,7 +383,7 @@ impl Parse for StorageType { _trailing_comma: input.peek(Token![,]).then(|| input.parse()).transpose()?, _gt_token: input.parse()?, }) - } else if lookahead.peek(storage_types::NMap) { + } else if lookahead.peek(storage_types::StorageNMap) { let content; Ok(Self::NMap { _kw: input.parse()?, diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 77a8ba0f41d72..583ed90f23cee 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -171,12 +171,12 @@ macro_rules! bounded_btree_map { /// use frame_support::Twox64Concat; /// // generate a storage value with type u32. /// #[storage_alias] -/// type StorageName = Value; +/// type StorageName = StorageValue; /// /// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key) /// // to `Vec` /// #[storage_alias] -/// type OtherStorageName = DoubleMap< +/// type OtherStorageName = StorageDoubleMap< /// OtherPrefix, /// Twox64Concat, /// u32, @@ -188,9 +188,9 @@ macro_rules! bounded_btree_map { /// // optionally specify the query type /// use frame_support::pallet_prelude::{ValueQuery, OptionQuery}; /// #[storage_alias] -/// type ValueName = Value; +/// type ValueName = StorageValue; /// #[storage_alias] -/// type SomeStorageName = Map< +/// type SomeStorageName = StorageMap< /// Prefix, /// Twox64Concat, /// u32, @@ -201,13 +201,13 @@ macro_rules! bounded_btree_map { /// // generate a map from `Config::AccountId` (with hasher `Twox64Concat`) to `Vec` /// trait Config { type AccountId: codec::FullCodec; } /// #[storage_alias] -/// type GenericStorage = Map::AccountId, Vec>; +/// type GenericStorage = StorageMap::AccountId, Vec>; /// /// // It also supports NMap /// use frame_support::storage::types::Key as NMapKey; /// /// #[storage_alias] -/// type SomeNMap = NMap, NMapKey), Vec>; +/// type SomeNMap = StorageNMap, NMapKey), Vec>; /// /// // Using pallet name as prefix. /// // @@ -224,12 +224,12 @@ macro_rules! bounded_btree_map { /// # } /// /// #[storage_alias] -/// type SomeValue = Value, u64>; +/// type SomeValue = StorageValue, u64>; /// /// // Pallet with instance /// /// #[storage_alias] -/// type SomeValue2 = Value, u64>; +/// type SomeValue2 = StorageValue, u64>; /// /// # fn main() {} /// ``` @@ -894,8 +894,12 @@ pub mod tests { fn storage_alias_works() { new_test_ext().execute_with(|| { #[crate::storage_alias] - type GenericData2 = - Map::BlockNumber, ::BlockNumber>; + type GenericData2 = StorageMap< + Test, + Blake2_128Concat, + ::BlockNumber, + ::BlockNumber, + >; assert_eq!(Module::::generic_data2(5), None); GenericData2::::insert(5, 5); @@ -903,7 +907,7 @@ pub mod tests { /// Some random docs that ensure that docs are accepted #[crate::storage_alias] - pub type GenericData = Map< + pub type GenericData = StorageMap< Test2, Blake2_128Concat, ::BlockNumber, diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 6afc786aeb987..390330457b9b9 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -349,14 +349,14 @@ pub mod test { use sp_io::TestExternalities; #[crate::storage_alias] - type Foo = Value>>; + type Foo = StorageValue>>; #[crate::storage_alias] - type FooMap = Map>>; + type FooMap = StorageMap>>; #[crate::storage_alias] type FooDoubleMap = - DoubleMap>>; + StorageDoubleMap>>; fn map_from_keys(keys: &[K]) -> BTreeMap where diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index f674c9b2c0bf3..275bb07c6275c 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -323,14 +323,14 @@ pub mod test { use sp_io::TestExternalities; #[crate::storage_alias] - type Foo = Value>>; + type Foo = StorageValue>>; #[crate::storage_alias] - type FooMap = Map>>; + type FooMap = StorageMap>>; #[crate::storage_alias] type FooDoubleMap = - DoubleMap>>; + StorageDoubleMap>>; fn set_from_keys(keys: &[T]) -> BTreeSet where diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 2024d99771b3d..0d54f464955e2 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -610,13 +610,14 @@ pub mod test { use sp_io::TestExternalities; #[crate::storage_alias] - type Foo = Value>>; + type Foo = StorageValue>>; #[crate::storage_alias] - type FooMap = Map>>; + type FooMap = StorageMap>>; #[crate::storage_alias] - type FooDoubleMap = DoubleMap>>; + type FooDoubleMap = + StorageDoubleMap>>; #[test] fn slide_works() { diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index 6264738265678..1c308bc351902 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -526,7 +526,7 @@ mod test_iterators { sp_io::TestExternalities::default().execute_with(|| { use crate::hash::Identity; #[crate::storage_alias] - type MyDoubleMap = DoubleMap; + type MyDoubleMap = StorageDoubleMap; MyDoubleMap::insert(1, 10, 100); MyDoubleMap::insert(1, 21, 201); diff --git a/frame/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs index f054c5c36b84a..bd24e14e9e0d8 100644 --- a/frame/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -385,7 +385,7 @@ mod test_iterators { sp_io::TestExternalities::default().execute_with(|| { use crate::hash::Identity; #[crate::storage_alias] - type MyMap = Map; + type MyMap = StorageMap; MyMap::insert(1, 10); MyMap::insert(2, 20); diff --git a/frame/support/src/storage/generator/nmap.rs b/frame/support/src/storage/generator/nmap.rs index ef243cead7580..18c912cf294ef 100755 --- a/frame/support/src/storage/generator/nmap.rs +++ b/frame/support/src/storage/generator/nmap.rs @@ -476,7 +476,7 @@ mod test_iterators { sp_io::TestExternalities::default().execute_with(|| { use crate::{hash::Identity, storage::Key as NMapKey}; #[crate::storage_alias] - type MyNMap = NMap< + type MyNMap = StorageNMap< MyModule, (NMapKey, NMapKey, NMapKey), u64, @@ -521,8 +521,14 @@ mod test_iterators { { #[crate::storage_alias] - type NMap = - DoubleMap; + type NMap = StorageDoubleMap< + Test, + crate::Blake2_128Concat, + u16, + crate::Twox64Concat, + u32, + u64, + >; let value = NMap::get(1, 2).unwrap(); assert_eq!(value, 50); diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index d181ba12ca869..7135ead850b6d 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1546,7 +1546,7 @@ mod test { TestExternalities::default().execute_with(|| { use crate::{hash::Identity, storage::generator::map::StorageMap}; #[crate::storage_alias] - type MyStorageMap = Map; + type MyStorageMap = StorageMap; MyStorageMap::insert(1, 10); MyStorageMap::insert(2, 20); @@ -1662,11 +1662,12 @@ mod test { } #[crate::storage_alias] - type Foo = Value>>; + type Foo = StorageValue>>; #[crate::storage_alias] - type FooMap = Map>>; + type FooMap = StorageMap>>; #[crate::storage_alias] - type FooDoubleMap = DoubleMap>>; + type FooDoubleMap = + StorageDoubleMap>>; #[test] fn try_append_works() { diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 349d9eea3bede..5faeb5d8cac28 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -590,7 +590,7 @@ mod test { { #[crate::storage_alias] - type Foo = NMap), u32>; + type Foo = StorageNMap), u32>; assert_eq!(Foo::contains_key((3,)), true); assert_eq!(Foo::get((3,)), Some(10)); diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index ddbde380147db..8d1d38374d8a7 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -322,12 +322,12 @@ pub mod test { use sp_io::TestExternalities; #[crate::storage_alias] - type Foo = Value>>; + type Foo = StorageValue>>; #[crate::storage_alias] - type FooMap = Map>>; + type FooMap = StorageMap>>; #[crate::storage_alias] type FooDoubleMap = - DoubleMap>>; + StorageDoubleMap>>; #[test] fn bound_returns_correct_value() { diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index eac7a271f044e..6463e4f9317c1 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -1641,7 +1641,7 @@ fn assert_type_all_pallets_without_system_reversed_is_correct() { fn test_storage_alias() { #[frame_support::storage_alias] type Value = - Value, u32, ValueQuery> + StorageValue, u32, ValueQuery> where ::AccountId: From + SomeAssociation1; TestExternalities::default().execute_with(|| { diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 47793994c4c94..29074843f4bbb 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -826,7 +826,8 @@ fn test_pallet_info_access() { #[test] fn test_storage_alias() { #[frame_support::storage_alias] - type Value, I: 'static> = Value, u32, ValueQuery>; + type Value, I: 'static> = + StorageValue, u32, ValueQuery>; TestExternalities::default().execute_with(|| { pallet::Value::::put(10); diff --git a/frame/system/src/migrations/mod.rs b/frame/system/src/migrations/mod.rs index 6d21faa1ea28f..f02af7a316fe1 100644 --- a/frame/system/src/migrations/mod.rs +++ b/frame/system/src/migrations/mod.rs @@ -54,13 +54,13 @@ pub trait V2ToV3 { } #[frame_support::storage_alias] -type UpgradedToU32RefCount = Value, bool, ValueQuery>; +type UpgradedToU32RefCount = StorageValue, bool, ValueQuery>; #[frame_support::storage_alias] -type UpgradedToTripleRefCount = Value, bool, ValueQuery>; +type UpgradedToTripleRefCount = StorageValue, bool, ValueQuery>; #[frame_support::storage_alias] -type Account = Map< +type Account = StorageMap< Pallet, Blake2_128Concat, ::AccountId, From 4448e20d20d276445453ca355fb12fcfa3fc81a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 16 May 2022 21:17:11 +0200 Subject: [PATCH 09/10] Make it compile --- frame/bags-list/src/migrations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/bags-list/src/migrations.rs b/frame/bags-list/src/migrations.rs index 68569c699aa68..f8041327f10be 100644 --- a/frame/bags-list/src/migrations.rs +++ b/frame/bags-list/src/migrations.rs @@ -31,7 +31,7 @@ impl OnRuntimeUpgrade for CheckCounterPrefix { use frame_support::ensure; // The old explicit storage item. #[frame_support::storage_alias] - type CounterForListNodes = StorageValue, u32>; + type CounterForListNodes = StorageValue, u32>; // ensure that a value exists in the counter struct. ensure!( From 608e98560e4a206c7e20968c76d6bbfbbe6225c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 16 May 2022 22:04:40 +0200 Subject: [PATCH 10/10] Fix where clause on rust stable --- frame/support/procedural/src/storage_alias.rs | 21 +++++++++++++------ frame/support/test/tests/pallet.rs | 7 ++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/frame/support/procedural/src/storage_alias.rs b/frame/support/procedural/src/storage_alias.rs index c44ca586eea94..adec995016653 100644 --- a/frame/support/procedural/src/storage_alias.rs +++ b/frame/support/procedural/src/storage_alias.rs @@ -412,9 +412,9 @@ struct Input { _type: Token![type], storage_name: Ident, storage_generics: Option, + where_clause: Option, _equal: Token![=], storage_type: StorageType, - where_clause: Option, _semicolon: Token![;], } @@ -426,17 +426,26 @@ impl Parse for Input { let storage_name = input.parse()?; let lookahead = input.lookahead1(); - let (storage_generics, _equal) = if lookahead.peek(Token![<]) { - (Some(input.parse()?), input.parse()?) + let storage_generics = if lookahead.peek(Token![<]) { + Some(input.parse()?) } else if lookahead.peek(Token![=]) { - (None, input.parse()?) + None } else { return Err(lookahead.error()) }; - let storage_type = input.parse()?; + let lookahead = input.lookahead1(); + let where_clause = if lookahead.peek(Token![where]) { + Some(input.parse()?) + } else if lookahead.peek(Token![=]) { + None + } else { + return Err(lookahead.error()) + }; + + let _equal = input.parse()?; - let where_clause = input.parse()?; + let storage_type = input.parse()?; let _semicolon = input.parse()?; diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 6463e4f9317c1..935dfd5ffeb33 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -1640,9 +1640,10 @@ fn assert_type_all_pallets_without_system_reversed_is_correct() { #[test] fn test_storage_alias() { #[frame_support::storage_alias] - type Value = - StorageValue, u32, ValueQuery> - where ::AccountId: From + SomeAssociation1; + type Value + where + ::AccountId: From + SomeAssociation1, + = StorageValue, u32, ValueQuery>; TestExternalities::default().execute_with(|| { pallet::Value::::put(10);