// This file is part of Bizinikiwi. // Copyright (C) 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. //! Proc macro of Support code for the runtime. #![recursion_limit = "512"] #![deny(rustdoc::broken_intra_doc_links)] mod benchmark; mod construct_runtime; mod crate_version; mod deprecation; mod derive_impl; mod dummy_part_checker; mod dynamic_params; mod key_prefix; mod match_and_insert; mod no_bound; mod pezpallet; mod pezpallet_error; mod runtime; mod storage_alias; mod transactional; mod tt_macro; use macro_magic::{import_tokens_attr, import_tokens_attr_verbatim}; use pezframe_support_procedural_tools::generate_access_from_frame_or_crate; use proc_macro::TokenStream; use quote::{quote, ToTokens}; use std::{cell::RefCell, str::FromStr}; use syn::{parse_macro_input, Error, ItemImpl, ItemMod, TraitItemType}; pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; thread_local! { /// A global counter, can be used to generate a relatively unique identifier. static COUNTER: RefCell = RefCell::new(Counter(0)); } /// Counter to generate a relatively unique identifier for macros. This is necessary because /// declarative macros gets hoisted to the crate root, which shares the namespace with other pallets /// containing the very same macros. struct Counter(u64); impl Counter { fn inc(&mut self) -> u64 { let ret = self.0; self.0 += 1; ret } } /// Get the value from the given environment variable set by cargo. /// /// The value is parsed into the requested destination type. fn get_cargo_env_var(version_env: &str) -> std::result::Result { let version = std::env::var(version_env) .unwrap_or_else(|_| panic!("`{}` is always set by cargo; qed", version_env)); T::from_str(&version).map_err(drop) } /// Generate the counter_prefix related to the storage. /// counter_prefix is used by counted storage map. fn counter_prefix(prefix: &str) -> String { format!("CounterFor{}", prefix) } /// Construct a runtime, with the given name and the given pallets. /// /// NOTE: A new version of this macro is available at `pezframe_support::runtime`. This macro will /// soon be deprecated. Please use the new macro instead. /// /// The parameters here are specific types for `Block`, `NodeBlock`, and `UncheckedExtrinsic` /// and the pallets that are used by the runtime. /// `Block` is the block type that is used in the runtime and `NodeBlock` is the block type /// that is used in the node. For instance they can differ in the extrinsics type. /// /// # Example: /// /// ```ignore /// construct_runtime!( /// pub enum Runtime where /// Block = Block, /// NodeBlock = node::Block, /// UncheckedExtrinsic = UncheckedExtrinsic /// { /// System: pezframe_system::{Pezpallet, Call, Event, Config} = 0, /// Test: path::to::test::{Pezpallet, Call} = 1, /// /// // Pallets with instances. /// Test2_Instance1: test2::::{Pezpallet, Call, Storage, Event, Config, Origin}, /// Test2_DefaultInstance: test2::{Pezpallet, Call, Storage, Event, Config, Origin} = 4, /// /// // Pallets declared with `pezpallet` attribute macro: no need to define the parts /// Test3_Instance1: test3::, /// Test3_DefaultInstance: test3, /// /// // with `exclude_parts` keyword some part can be excluded. /// Test4_Instance1: test4:: exclude_parts { Call, Origin }, /// Test4_DefaultInstance: test4 exclude_parts { Storage }, /// /// // with `use_parts` keyword, a subset of the pezpallet parts can be specified. /// Test4_Instance1: test4:: use_parts { Pezpallet, Call}, /// Test4_DefaultInstance: test4 use_parts { Pezpallet }, /// } /// ) /// ``` /// /// Each pezpallet is declared as such: /// * `Identifier`: name given to the pezpallet that uniquely identifies it. /// /// * `:`: colon separator /// /// * `path::to::pezpallet`: identifiers separated by colons which declare the path to a pezpallet /// definition. /// /// * `::` optional: specify the instance of the pezpallet to use. If not specified it /// will use the default instance (or the only instance in case of non-instantiable pallets). /// /// * `::{ Part1, Part2, .. }` optional if pezpallet declared with `pezframe_support::pezpallet`: /// Comma separated parts declared with their generic. If a pezpallet is declared with /// `pezframe_support::pezpallet` macro then the parts can be automatically derived if not /// explicitly provided. We provide support for the following module parts in a pezpallet: /// /// - `Pezpallet` - Required for all pallets /// - `Call` - If the pezpallet has callable functions /// - `Storage` - If the pezpallet uses storage /// - `Event` or `Event` (if the event is generic) - If the pezpallet emits events /// - `Origin` or `Origin` (if the origin is generic) - If the pezpallet has instantiable /// origins /// - `Config` or `Config` (if the config is generic) - If the pezpallet builds the genesis /// storage with `GenesisConfig` /// - `Inherent` - If the pezpallet provides/can check inherents. /// - `ValidateUnsigned` - If the pezpallet validates unsigned extrinsics. /// /// It is important to list these parts here to export them correctly in the metadata or to make /// the pezpallet usable in the runtime. /// /// * `exclude_parts { Part1, Part2 }` optional: comma separated parts without generics. I.e. one of /// `Pezpallet`, `Call`, `Storage`, `Event`, `Origin`, `Config`, `Inherent`, `ValidateUnsigned`. /// It is incompatible with `use_parts`. This specifies the part to exclude. In order to select /// subset of the pezpallet parts. /// /// For example excluding the part `Call` can be useful if the runtime doesn't want to make the /// pezpallet calls available. /// /// * `use_parts { Part1, Part2 }` optional: comma separated parts without generics. I.e. one of /// `Pezpallet`, `Call`, `Storage`, `Event`, `Origin`, `Config`, `Inherent`, `ValidateUnsigned`. /// It is incompatible with `exclude_parts`. This specifies the part to use. In order to select a /// subset of the pezpallet parts. /// /// For example not using the part `Call` can be useful if the runtime doesn't want to make the /// pezpallet calls available. /// /// * `= $n` optional: number to define at which index the pezpallet variants in `OriginCaller`, /// `Call` and `Event` are encoded, and to define the ModuleToIndex value. /// /// if `= $n` is not given, then index is resolved in the same way as fieldless enum in Rust /// (i.e. incrementally from previous index): /// ```nocompile /// pallet1 .. = 2, /// pallet2 .., // Here pallet2 is given index 3 /// pallet3 .. = 0, /// pallet4 .., // Here pallet4 is given index 1 /// ``` /// /// # Note /// /// The population of the genesis storage depends on the order of pallets. So, if one of your /// pallets depends on another pezpallet, the pezpallet that is depended upon needs to come before /// the pezpallet depending on it. /// /// # Type definitions /// /// * The macro generates a type alias for each pezpallet to their `Pezpallet`. E.g. `type System = /// pezframe_system::Pezpallet` #[proc_macro] pub fn construct_runtime(input: TokenStream) -> TokenStream { construct_runtime::construct_runtime(input) } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet`. #[proc_macro_attribute] pub fn pezpallet(attr: TokenStream, item: TokenStream) -> TokenStream { pezpallet::pezpallet(attr, item) } /// An attribute macro that can be attached to a (non-empty) module declaration. Doing so will /// designate that module as a benchmarking module. /// /// See `pezframe_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn benchmarks(attr: TokenStream, tokens: TokenStream) -> TokenStream { match benchmark::benchmarks(attr, tokens, false) { Ok(tokens) => tokens, Err(err) => err.to_compile_error().into(), } } /// An attribute macro that can be attached to a (non-empty) module declaration. Doing so will /// designate that module as an instance benchmarking module. /// /// See `pezframe_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn instance_benchmarks(attr: TokenStream, tokens: TokenStream) -> TokenStream { match benchmark::benchmarks(attr, tokens, true) { Ok(tokens) => tokens, Err(err) => err.to_compile_error().into(), } } /// An attribute macro used to declare a benchmark within a benchmarking module. Must be /// attached to a function definition containing an `#[extrinsic_call]` or `#[block]` /// attribute. /// /// See `pezframe_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn benchmark(_attrs: TokenStream, _tokens: TokenStream) -> TokenStream { quote!(compile_error!( "`#[benchmark]` must be in a module labeled with #[benchmarks] or #[instance_benchmarks]." )) .into() } /// An attribute macro used to specify the extrinsic call inside a benchmark function, and also /// used as a boundary designating where the benchmark setup code ends, and the benchmark /// verification code begins. /// /// See `pezframe_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn extrinsic_call(_attrs: TokenStream, _tokens: TokenStream) -> TokenStream { quote!(compile_error!( "`#[extrinsic_call]` must be in a benchmark function definition labeled with `#[benchmark]`." );) .into() } /// An attribute macro used to specify that a block should be the measured portion of the /// enclosing benchmark function, This attribute is also used as a boundary designating where /// the benchmark setup code ends, and the benchmark verification code begins. /// /// See `pezframe_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn block(_attrs: TokenStream, _tokens: TokenStream) -> TokenStream { quote!(compile_error!( "`#[block]` must be in a benchmark function definition labeled with `#[benchmark]`." )) .into() } /// Execute the annotated function in a new storage transaction. /// /// The return type of the annotated function must be `Result`. All changes to storage performed /// by the annotated function are discarded if it returns `Err`, or committed if `Ok`. /// /// # Example /// /// ```nocompile /// #[transactional] /// fn value_commits(v: u32) -> result::Result { /// Value::set(v); /// Ok(v) /// } /// /// #[transactional] /// fn value_rollbacks(v: u32) -> result::Result { /// Value::set(v); /// Err("nah") /// } /// ``` #[proc_macro_attribute] pub fn transactional(attr: TokenStream, input: TokenStream) -> TokenStream { transactional::transactional(attr, input).unwrap_or_else(|e| e.to_compile_error().into()) } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::require_transactional`. #[proc_macro_attribute] pub fn require_transactional(attr: TokenStream, input: TokenStream) -> TokenStream { transactional::require_transactional(attr, input) .unwrap_or_else(|e| e.to_compile_error().into()) } /// Derive [`Clone`] but do not bound any generic. /// /// Docs at `pezframe_support::CloneNoBound`. #[proc_macro_derive(CloneNoBound)] pub fn derive_clone_no_bound(input: TokenStream) -> TokenStream { no_bound::clone::derive_clone_no_bound(input) } /// Derive [`Debug`] but do not bound any generics. /// /// Docs at `pezframe_support::DebugNoBound`. #[proc_macro_derive(DebugNoBound)] pub fn derive_debug_no_bound(input: TokenStream) -> TokenStream { no_bound::debug::derive_debug_no_bound(input) } /// Derive [`Debug`], if `std` is enabled it uses `pezframe_support::DebugNoBound`, if `std` is not /// enabled it just returns `""`. /// This behaviour is useful to prevent bloating the runtime WASM blob from unneeded code. #[proc_macro_derive(RuntimeDebugNoBound)] pub fn derive_runtime_debug_no_bound(input: TokenStream) -> TokenStream { let try_runtime_or_std_impl: proc_macro2::TokenStream = no_bound::debug::derive_debug_no_bound(input.clone()).into(); let stripped_impl = { let input = syn::parse_macro_input!(input as syn::DeriveInput); let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); quote::quote!( const _: () = { impl #impl_generics ::core::fmt::Debug for #name #ty_generics #where_clause { fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> core::fmt::Result { fmt.write_str("") } } }; ) }; let pezframe_support = match generate_access_from_frame_or_crate("pezframe-support") { Ok(pezframe_support) => pezframe_support, Err(e) => return e.to_compile_error().into(), }; quote::quote!( #pezframe_support::try_runtime_or_std_enabled! { #try_runtime_or_std_impl } #pezframe_support::try_runtime_and_std_not_enabled! { #stripped_impl } ) .into() } /// Derive [`PartialEq`] but do not bound any generic. /// /// Docs at `pezframe_support::PartialEqNoBound`. #[proc_macro_derive(PartialEqNoBound)] pub fn derive_partial_eq_no_bound(input: TokenStream) -> TokenStream { no_bound::partial_eq::derive_partial_eq_no_bound(input) } /// DeriveEq but do no bound any generic. /// /// Docs at `pezframe_support::EqNoBound`. #[proc_macro_derive(EqNoBound)] pub fn derive_eq_no_bound(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); quote::quote_spanned!(name.span() => #[allow(deprecated)] const _: () = { impl #impl_generics ::core::cmp::Eq for #name #ty_generics #where_clause {} }; ) .into() } /// Derive [`PartialOrd`] but do not bound any generic. Docs are at /// `pezframe_support::PartialOrdNoBound`. #[proc_macro_derive(PartialOrdNoBound)] pub fn derive_partial_ord_no_bound(input: TokenStream) -> TokenStream { no_bound::partial_ord::derive_partial_ord_no_bound(input) } /// Derive [`Ord`] but do no bound any generic. Docs are at `pezframe_support::OrdNoBound`. #[proc_macro_derive(OrdNoBound)] pub fn derive_ord_no_bound(input: TokenStream) -> TokenStream { no_bound::ord::derive_ord_no_bound(input) } /// derive `Default` but do no bound any generic. Docs are at `pezframe_support::DefaultNoBound`. #[proc_macro_derive(DefaultNoBound, attributes(default))] pub fn derive_default_no_bound(input: TokenStream) -> TokenStream { no_bound::default::derive_default_no_bound(input) } /// Macro used internally in FRAME to generate the crate version for a pezpallet. #[proc_macro] pub fn crate_to_crate_version(input: TokenStream) -> TokenStream { crate_version::crate_to_crate_version(input) .unwrap_or_else(|e| e.to_compile_error()) .into() } /// The number of module instances supported by the runtime, starting at index 1, /// and up to `NUMBER_OF_INSTANCE`. pub(crate) const NUMBER_OF_INSTANCE: u8 = 16; /// This macro is meant to be used by pezframe-support only. /// It implements the trait `HasKeyPrefix` and `HasReversibleKeyPrefix` for tuple of `Key`. #[proc_macro] pub fn impl_key_prefix_for_tuples(input: TokenStream) -> TokenStream { key_prefix::impl_key_prefix_for_tuples(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } /// Internal macro use by pezframe_support to generate dummy part checker for old pezpallet /// declaration #[proc_macro] pub fn __generate_dummy_part_checker(input: TokenStream) -> TokenStream { dummy_part_checker::generate_dummy_part_checker(input) } /// Macro that inserts some tokens after the first match of some pattern. /// /// # Example: /// /// ```nocompile /// match_and_insert!( /// target = [{ Some content with { at some point match pattern } other match pattern are ignored }] /// pattern = [{ match pattern }] // the match pattern cannot contain any group: `[]`, `()`, `{}` /// // can relax this constraint, but will require modifying the match logic in code /// tokens = [{ expansion tokens }] // content inside braces can be anything including groups /// ); /// ``` /// /// will generate: /// /// ```nocompile /// Some content with { at some point match pattern expansion tokens } other match patterns are /// ignored /// ``` #[proc_macro] pub fn match_and_insert(input: TokenStream) -> TokenStream { match_and_insert::match_and_insert(input) } #[proc_macro_derive(PalletError, attributes(codec))] pub fn derive_pallet_error(input: TokenStream) -> TokenStream { pezpallet_error::derive_pallet_error(input) } /// Internal macro used by `pezframe_support` to create tt-call-compliant macros #[proc_macro] pub fn __create_tt_macro(input: TokenStream) -> TokenStream { tt_macro::create_tt_return_macro(input) } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::storage_alias`. #[proc_macro_attribute] pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream { storage_alias::storage_alias(attributes.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// This attribute can be used to derive a full implementation of a trait based on a local partial /// impl and an external impl containing defaults that can be overridden in the local impl. /// /// For a full end-to-end example, see [below](#use-case-auto-derive-test-pezpallet-config-traits). /// /// # Usage /// /// The attribute should be attached to an impl block (strictly speaking a `syn::ItemImpl`) for /// which we want to inject defaults in the event of missing trait items in the block. /// /// The attribute minimally takes a single `default_impl_path` argument, which should be the module /// path to an impl registered via [`#[register_default_impl]`](`macro@register_default_impl`) that /// contains the default trait items we want to potentially inject, with the general form: /// /// ```ignore /// #[derive_impl(default_impl_path)] /// impl SomeTrait for SomeStruct { /// ... /// } /// ``` /// /// Optionally, a `disambiguation_path` can be specified as follows by providing `as path::here` /// after the `default_impl_path`: /// /// ```ignore /// #[derive_impl(default_impl_path as disambiguation_path)] /// impl SomeTrait for SomeStruct { /// ... /// } /// ``` /// /// The `disambiguation_path`, if specified, should be the path to a trait that will be used to /// qualify all default entries that are injected into the local impl. For example if your /// `default_impl_path` is `some::path::TestTraitImpl` and your `disambiguation_path` is /// `another::path::DefaultTrait`, any items injected into the local impl will be qualified as /// `::specific_trait_item`. /// /// If you omit the `as disambiguation_path` portion, the `disambiguation_path` will internally /// default to `A` from the `impl A for B` part of the default impl. This is useful for scenarios /// where all of the relevant types are already in scope via `use` statements. /// /// In case the `default_impl_path` is scoped to a different module such as /// `some::path::TestTraitImpl`, the same scope is assumed for the `disambiguation_path`, i.e. /// `some::A`. This enables the use of `derive_impl` attribute without having to specify the /// `disambiguation_path` in most (if not all) uses within FRAME's context. /// /// Conversely, the `default_impl_path` argument is required and cannot be omitted. /// /// Optionally, `no_aggregated_types` can be specified as follows: /// /// ```ignore /// #[derive_impl(default_impl_path as disambiguation_path, no_aggregated_types)] /// impl SomeTrait for SomeStruct { /// ... /// } /// ``` /// /// If specified, this indicates that the aggregated types (as denoted by impl items /// attached with [`#[inject_runtime_type]`]) should not be injected with the respective concrete /// types. By default, all such types are injected. /// /// You can also make use of `#[pezpallet::no_default]` on specific items in your default impl that /// you want to ensure will not be copied over but that you nonetheless want to use locally in the /// context of the foreign impl and the pezpallet (or context) in which it is defined. /// /// ## Use-Case Example: Auto-Derive Test Pezpallet Config Traits /// /// The `#[derive_imp(..)]` attribute can be used to derive a test pezpallet `Config` based on an /// existing pezpallet `Config` that has been marked with /// [`#[pezpallet::config(with_default)]`](`macro@config`) (which under the hood, generates a /// `DefaultConfig` trait in the pezpallet in which the macro was invoked). /// /// In this case, the `#[derive_impl(..)]` attribute should be attached to an `impl` block that /// implements a compatible `Config` such as `pezframe_system::Config` for a test/mock runtime, and /// should receive as its first argument the path to a `DefaultConfig` impl that has been registered /// via [`#[register_default_impl]`](`macro@register_default_impl`), and as its second argument, the /// path to the auto-generated `DefaultConfig` for the existing pezpallet `Config` we want to base /// our test config off of. /// /// The following is what the `basic` example pezpallet would look like with a default testing /// config: /// /// ```ignore /// #[derive_impl(pezframe_system::config_preludes::TestDefaultConfig as pezframe_system::pezpallet::DefaultConfig)] /// impl pezframe_system::Config for Test { /// // These are all defined by system as mandatory. /// type BaseCallFilter = pezframe_support::traits::Everything; /// type RuntimeEvent = RuntimeEvent; /// type RuntimeCall = RuntimeCall; /// type RuntimeOrigin = RuntimeOrigin; /// type OnSetCode = (); /// type PalletInfo = PalletInfo; /// type Block = Block; /// // We decide to override this one. /// type AccountData = pezpallet_balances::AccountData; /// } /// ``` /// /// where `TestDefaultConfig` was defined and registered as follows: /// ```ignore /// pub struct TestDefaultConfig; /// /// #[register_default_impl(TestDefaultConfig)] /// impl DefaultConfig for TestDefaultConfig { /// type Version = (); /// type BlockWeights = (); /// type BlockLength = (); /// type DbWeight = (); /// type Nonce = u64; /// type BlockNumber = u64; /// type Hash = pezsp_core::hash::H256; /// type Hashing = pezsp_runtime::traits::BlakeTwo256; /// type AccountId = AccountId; /// type Lookup = IdentityLookup; /// type BlockHashCount = pezframe_support::traits::ConstU64<10>; /// type AccountData = u32; /// type OnNewAccount = (); /// type OnKilledAccount = (); /// type SystemWeightInfo = (); /// type SS58Prefix = (); /// type MaxConsumers = pezframe_support::traits::ConstU32<16>; /// } /// ``` /// /// The above call to `derive_impl` would expand to roughly the following: /// ```ignore /// impl pezframe_system::Config for Test { /// use pezframe_system::config_preludes::TestDefaultConfig; /// use pezframe_system::pezpallet::DefaultConfig; /// /// type BaseCallFilter = pezframe_support::traits::Everything; /// type RuntimeEvent = RuntimeEvent; /// type RuntimeCall = RuntimeCall; /// type RuntimeOrigin = RuntimeOrigin; /// type OnSetCode = (); /// type PalletInfo = PalletInfo; /// type Block = Block; /// type AccountData = pezpallet_balances::AccountData; /// type Version = ::Version; /// type BlockWeights = ::BlockWeights; /// type BlockLength = ::BlockLength; /// type DbWeight = ::DbWeight; /// type Nonce = ::Nonce; /// type BlockNumber = ::BlockNumber; /// type Hash = ::Hash; /// type Hashing = ::Hashing; /// type AccountId = ::AccountId; /// type Lookup = ::Lookup; /// type BlockHashCount = ::BlockHashCount; /// type OnNewAccount = ::OnNewAccount; /// type OnKilledAccount = ::OnKilledAccount; /// type SystemWeightInfo = ::SystemWeightInfo; /// type SS58Prefix = ::SS58Prefix; /// type MaxConsumers = ::MaxConsumers; /// } /// ``` /// /// You can then use the resulting `Test` config in test scenarios. /// /// Note that items that are _not_ present in our local `DefaultConfig` are automatically copied /// from the foreign trait (in this case `TestDefaultConfig`) into the local trait impl (in this /// case `Test`), unless the trait item in the local trait impl is marked with /// [`#[pezpallet::no_default]`](`macro@no_default`), in which case it cannot be overridden, and any /// attempts to do so will result in a compiler error. /// /// See `frame/examples/default-config/tests.rs` for a runnable end-to-end example pezpallet that /// makes use of `derive_impl` to derive its testing config. /// /// See [here](`macro@config`) for more information and caveats about the auto-generated /// `DefaultConfig` trait. /// /// ## Optional Conventions /// /// Note that as an optional convention, we encourage creating a `config_preludes` module inside of /// your pezpallet. This is the convention we follow for `pezframe_system`'s `TestDefaultConfig` /// which, as shown above, is located at `pezframe_system::config_preludes::TestDefaultConfig`. This /// is just a suggested convention -- there is nothing in the code that expects modules with these /// names to be in place, so there is no imperative to follow this pattern unless desired. /// /// In `config_preludes`, you can place types named like: /// /// * `TestDefaultConfig` /// * `TeyrchainDefaultConfig` /// * `SolochainDefaultConfig` /// /// Signifying in which context they can be used. /// /// # Advanced Usage /// /// ## Expansion /// /// The `#[derive_impl(default_impl_path as disambiguation_path)]` attribute will expand to the /// local impl, with any extra items from the foreign impl that aren't present in the local impl /// also included. In the case of a colliding trait item, the version of the item that exists in the /// local impl will be retained. All imported items are qualified by the `disambiguation_path`, as /// discussed above. /// /// ## Handling of Unnamed Trait Items /// /// Items that lack a `syn::Ident` for whatever reason are first checked to see if they exist, /// verbatim, in the local/destination trait before they are copied over, so you should not need to /// worry about collisions between identical unnamed items. #[import_tokens_attr_verbatim { format!( "{}::macro_magic", match generate_access_from_frame_or_crate("pezframe-support") { Ok(path) => Ok(path), Err(_) => generate_access_from_frame_or_crate("pezkuwi-sdk-frame"), } .expect("Failed to find either `pezframe-support` or `pezkuwi-sdk-frame` in `Cargo.toml` dependencies.") .to_token_stream() .to_string() ) }] #[with_custom_parsing(derive_impl::DeriveImplAttrArgs)] #[proc_macro_attribute] pub fn derive_impl(attrs: TokenStream, input: TokenStream) -> TokenStream { let custom_attrs = parse_macro_input!(__custom_tokens as derive_impl::DeriveImplAttrArgs); derive_impl::derive_impl( __source_path.into(), attrs.into(), input.into(), custom_attrs.disambiguation_path, custom_attrs.no_aggregated_types, custom_attrs.generics, ) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::no_default`. #[proc_macro_attribute] pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::no_default_bounds`. #[proc_macro_attribute] pub fn no_default_bounds(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Attach this attribute to an impl statement that you want to use with /// [`#[derive_impl(..)]`](`macro@derive_impl`). /// /// You must also provide an identifier/name as the attribute's argument. This is the name you /// must provide to [`#[derive_impl(..)]`](`macro@derive_impl`) when you import this impl via /// the `default_impl_path` argument. This name should be unique at the crate-level. /// /// ## Example /// /// ```ignore /// pub struct ExampleTestDefaultConfig; /// /// #[register_default_impl(ExampleTestDefaultConfig)] /// impl DefaultConfig for ExampleTestDefaultConfig { /// type Version = (); /// type BlockWeights = (); /// type BlockLength = (); /// ... /// type SS58Prefix = (); /// type MaxConsumers = pezframe_support::traits::ConstU32<16>; /// } /// ``` /// /// ## Advanced Usage /// /// This macro acts as a thin wrapper around macro_magic's `#[export_tokens]`. See the docs /// [here](https://docs.rs/macro_magic/latest/macro_magic/attr.export_tokens.html) for more /// info. /// /// There are some caveats when applying a `use` statement to bring a /// `#[register_default_impl]` item into scope. If you have a `#[register_default_impl]` /// defined in `my_crate::submodule::MyItem`, it is currently not sufficient to do something /// like: /// /// ```ignore /// use my_crate::submodule::MyItem; /// #[derive_impl(MyItem as Whatever)] /// ``` /// /// This will fail with a mysterious message about `__export_tokens_tt_my_item` not being /// defined. /// /// You can, however, do any of the following: /// ```ignore /// // partial path works /// use my_crate::submodule; /// #[derive_impl(submodule::MyItem as Whatever)] /// ``` /// ```ignore /// // full path works /// #[derive_impl(my_crate::submodule::MyItem as Whatever)] /// ``` /// ```ignore /// // wild-cards work /// use my_crate::submodule::*; /// #[derive_impl(MyItem as Whatever)] /// ``` #[proc_macro_attribute] pub fn register_default_impl(attrs: TokenStream, tokens: TokenStream) -> TokenStream { // ensure this is a impl statement let item_impl = syn::parse_macro_input!(tokens as ItemImpl); // internally wrap macro_magic's `#[export_tokens]` macro match macro_magic::mm_core::export_tokens_internal( attrs, item_impl.to_token_stream(), true, false, ) { Ok(tokens) => tokens.into(), Err(err) => err.to_compile_error().into(), } } /// The optional attribute `#[inject_runtime_type]` can be attached to `RuntimeCall`, /// `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo` in an impl statement that has /// `#[register_default_impl]` attached to indicate that this item is generated by /// `construct_runtime`. /// /// Attaching this attribute to such an item ensures that the combined impl generated via /// [`#[derive_impl(..)]`](macro@derive_impl) will use the correct type auto-generated by /// `construct_runtime!`. #[doc = docify::embed!("examples/proc_main/inject_runtime_type.rs", derive_impl_works_with_runtime_type_injection)] /// /// However, if `no_aggregated_types` is specified while using /// [`#[derive_impl(..)]`](macro@derive_impl), then these items are attached verbatim to the /// combined impl. #[doc = docify::embed!("examples/proc_main/inject_runtime_type.rs", derive_impl_works_with_no_aggregated_types)] #[proc_macro_attribute] pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { let item = tokens.clone(); let item = syn::parse_macro_input!(item as TraitItemType); if item.ident != "RuntimeCall" && item.ident != "RuntimeEvent" && item.ident != "RuntimeTask" && item.ident != "RuntimeViewFunction" && item.ident != "RuntimeOrigin" && item.ident != "RuntimeHoldReason" && item.ident != "RuntimeFreezeReason" && item.ident != "RuntimeParameters" && item.ident != "PalletInfo" { return syn::Error::new_spanned( item, "`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, \ `RuntimeTask`, `RuntimeViewFunction`, `RuntimeOrigin`, `RuntimeParameters` or `PalletInfo`", ) .to_compile_error() .into(); } tokens } /// Used internally to decorate pezpallet attribute macro stubs when they are erroneously used /// outside of a pezpallet module fn pezpallet_macro_stub() -> TokenStream { quote!(compile_error!( "This attribute can only be used from within a pezpallet module marked with `#[pezframe_support::pezpallet]`" )) .into() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::config`. #[proc_macro_attribute] pub fn config(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::constant`. #[proc_macro_attribute] pub fn constant(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::constant_name`. #[proc_macro_attribute] pub fn constant_name(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::disable_pezframe_system_supertrait_check`. #[proc_macro_attribute] pub fn disable_pezframe_system_supertrait_check(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::storage_version`. #[proc_macro_attribute] pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::hooks`. #[proc_macro_attribute] pub fn hooks(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::weight`. #[proc_macro_attribute] pub fn weight(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::compact`. #[proc_macro_attribute] pub fn compact(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::call`. #[proc_macro_attribute] pub fn call(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Each dispatchable may also be annotated with the `#[pezpallet::call_index($idx)]` attribute, /// which explicitly defines the codec index for the dispatchable function in the `Call` enum. /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::call_index`. #[proc_macro_attribute] pub fn call_index(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::feeless_if`. #[proc_macro_attribute] pub fn feeless_if(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::extra_constants`. #[proc_macro_attribute] pub fn extra_constants(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::error`. #[proc_macro_attribute] pub fn error(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::event`. #[proc_macro_attribute] pub fn event(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::include_metadata`. #[proc_macro_attribute] pub fn include_metadata(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::generate_deposit`. #[proc_macro_attribute] pub fn generate_deposit(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::storage`. #[proc_macro_attribute] pub fn storage(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::getter`. #[proc_macro_attribute] pub fn getter(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::storage_prefix`. #[proc_macro_attribute] pub fn storage_prefix(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::unbounded`. #[proc_macro_attribute] pub fn unbounded(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::whitelist_storage`. #[proc_macro_attribute] pub fn whitelist_storage(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::disable_try_decode_storage`. #[proc_macro_attribute] pub fn disable_try_decode_storage(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::type_value`. #[proc_macro_attribute] pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::genesis_config`. #[proc_macro_attribute] pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::genesis_build`. #[proc_macro_attribute] pub fn genesis_build(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::inherent`. #[proc_macro_attribute] pub fn inherent(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::validate_unsigned`. #[proc_macro_attribute] pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::view_functions`. #[proc_macro_attribute] pub fn view_functions(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `pezframe_support::pezpallet_macros::origin`. #[proc_macro_attribute] pub fn origin(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `pezframe_support::pezpallet_macros::composite_enum`. #[proc_macro_attribute] pub fn composite_enum(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Allows you to define some service work that can be recognized by the off-chain worker. /// /// The off-chain worker can then create and submit all such work items at any given time. /// /// These work items are defined as instances of the `Task` trait (found at /// `pezframe_support::traits::Task`). [`pezpallet:tasks_experimental`](macro@tasks_experimental) /// when attached to an `impl` block inside a pezpallet, will generate an enum `Task` whose /// variants are mapped to functions inside this `impl` block. /// /// Each such function must have the following set of attributes: /// /// * [`pezpallet::task_list`](macro@task_list) /// * [`pezpallet::task_condition`](macro@task_condition) /// * [`pezpallet::task_weight`](macro@task_weight) /// * [`pezpallet::task_index`](macro@task_index) /// /// All of such Tasks are then aggregated into a `RuntimeTask` by /// [`construct_runtime`](macro@construct_runtime). /// /// Finally, the `RuntimeTask` can then be used by the off-chain worker to create and /// submit such tasks via an extrinsic defined in `pezframe_system` called `do_task` which accepts /// unsigned transaction from local source. /// /// When submitted as unsigned transactions, note that the tasks will be executed in a random order. /// /// ## Example #[doc = docify::embed!("examples/proc_main/tasks.rs", tasks_example)] /// Now, this can be executed as follows: #[doc = docify::embed!("examples/proc_main/tasks.rs", tasks_work)] #[proc_macro_attribute] pub fn tasks_experimental(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Allows defining an iterator over available work items for a task. /// /// This attribute is attached to a function inside an `impl` block annotated with /// [`pezpallet::tasks_experimental`](macro@tasks_experimental). /// /// It takes an iterator as input that yields a tuple with same types as the function /// arguments. #[proc_macro_attribute] pub fn task_list(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Allows defining conditions for a task to run. /// /// This attribute is attached to a function inside an `impl` block annotated with /// [`pezpallet::tasks_experimental`](macro@tasks_experimental) to define the conditions for a /// given work item to be valid. /// /// It takes a closure as input, which is then used to define the condition. The closure /// should have the same signature as the function it is attached to, except that it should /// return a `bool` instead. #[proc_macro_attribute] pub fn task_condition(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Allows defining the weight of a task. /// /// This attribute is attached to a function inside an `impl` block annotated with /// [`pezpallet::tasks_experimental`](macro@tasks_experimental) define the weight of a given work /// item. /// /// It takes a closure as input, which should return a `Weight` value. #[proc_macro_attribute] pub fn task_weight(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Allows defining an index for a task. /// /// This attribute is attached to a function inside an `impl` block annotated with /// [`pezpallet::tasks_experimental`](macro@tasks_experimental) to define the index of a given /// work item. /// /// It takes an integer literal as input, which is then used to define the index. This /// index should be unique for each function in the `impl` block. #[proc_macro_attribute] pub fn task_index(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `pezframe_support::pezpallet_macros::pezpallet_section`. #[proc_macro_attribute] pub fn pezpallet_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { let tokens_clone = tokens.clone(); // ensure this can only be attached to a module let _mod = parse_macro_input!(tokens_clone as ItemMod); // use macro_magic's export_tokens as the internal implementation otherwise match macro_magic::mm_core::export_tokens_internal(attr, tokens, false, true) { Ok(tokens) => tokens.into(), Err(err) => err.to_compile_error().into(), } } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `pezframe_support::pezpallet_macros::import_section`. #[import_tokens_attr { format!( "{}::macro_magic", match generate_access_from_frame_or_crate("pezframe-support") { Ok(path) => Ok(path), Err(_) => generate_access_from_frame_or_crate("pezkuwi-sdk-frame"), } .expect("Failed to find either `pezframe-support` or `pezkuwi-sdk-frame` in `Cargo.toml` dependencies.") .to_token_stream() .to_string() ) }] #[proc_macro_attribute] pub fn import_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { let foreign_mod = parse_macro_input!(attr as ItemMod); let mut internal_mod = parse_macro_input!(tokens as ItemMod); // check that internal_mod is a pezpallet module if !internal_mod.attrs.iter().any(|attr| { if let Some(last_seg) = attr.path().segments.last() { last_seg.ident == "pezpallet" } else { false } }) { return Error::new( internal_mod.ident.span(), "`#[import_section]` can only be applied to a valid pezpallet module", ) .to_compile_error() .into(); } if let Some(ref mut content) = internal_mod.content { if let Some(foreign_content) = foreign_mod.content { content.1.extend(foreign_content.1); } } quote! { #internal_mod } .into() } /// Construct a runtime, with the given name and the given pallets. /// /// # Example: #[doc = docify::embed!("examples/proc_main/runtime.rs", runtime_macro)] /// /// # Supported Attributes: /// /// ## Legacy Ordering /// /// An optional attribute can be defined as #[pezframe_support::runtime(legacy_ordering)] to /// ensure that the order of hooks is same as the order of pallets (and not based on the /// pezpallet_index). This is to support legacy runtimes and should be avoided for new ones. /// /// # Note /// /// The population of the genesis storage depends on the order of pallets. So, if one of your /// pallets depends on another pezpallet, the pezpallet that is depended upon needs to come before /// the pezpallet depending on it. /// /// # Type definitions /// /// * The macro generates a type alias for each pezpallet to their `Pezpallet`. E.g. `type System = /// pezframe_system::Pezpallet` #[proc_macro_attribute] pub fn runtime(attr: TokenStream, item: TokenStream) -> TokenStream { runtime::runtime(attr, item) } /// Mark a module that contains dynamic parameters. /// /// See the `pezpallet_parameters` for a full example. /// /// # Arguments /// /// The macro accepts two positional arguments, of which the second is optional. /// /// ## Aggregated Enum Name /// /// This sets the name that the aggregated Key-Value enum will be named after. Common names would be /// `RuntimeParameters`, akin to `RuntimeCall`, `RuntimeOrigin` etc. There is no default value for /// this argument. /// /// ## Parameter Storage Backend /// /// The second argument provides access to the storage of the parameters. It can either be set on /// on this attribute, or on the inner ones. If set on both, the inner one takes precedence. #[proc_macro_attribute] pub fn dynamic_params(attrs: TokenStream, input: TokenStream) -> TokenStream { dynamic_params::dynamic_params(attrs.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// Define a module inside a [`macro@dynamic_params`] module that contains dynamic parameters. /// /// See the `pezpallet_parameters` for a full example. /// /// # Argument /// /// This attribute takes one optional argument. The argument can either be put here or on the /// surrounding `#[dynamic_params]` attribute. If set on both, the inner one takes precedence. #[proc_macro_attribute] pub fn dynamic_pallet_params(attrs: TokenStream, input: TokenStream) -> TokenStream { dynamic_params::dynamic_pallet_params(attrs.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// Used internally by [`dynamic_params`]. #[doc(hidden)] #[proc_macro_attribute] pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream) -> TokenStream { dynamic_params::dynamic_aggregated_params_internal(attrs.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// Allows to authorize some general transactions with specific dispatchable functions /// (dispatchable functions a.k.a. calls). /// /// This attribute allows to specify a special validation logic for a specific call. /// A general transaction with this specific call can then be validated by the given function, /// and if valid then dispatched with the origin `pezframe_system::Origin::Authorized`. /// /// To ensure the origin of the call is the authorization process, the call must check the origin /// with `pezframe_system::ensure_authorized` function. /// /// To enable the authorization process on the extrinsic, the runtime must use /// `pezframe_system::AuthorizeCall` transaction extension in the transaction extension pipeline. /// /// To enable the creation of authorized call from offchain worker. The runtime should implement /// `pezframe_system::CreateAuthorizedTransaction`. This trait allows to specify which transaction /// extension to use when creating a transaction for an authorized call. /// /// # Usage in the pezpallet /// /// ## Example/Overview: /// /// ``` /// # #[allow(unused)] /// #[pezframe_support::pezpallet] /// pub mod pezpallet { /// use pezframe_support::pezpallet_prelude::*; /// use pezframe_system::pezpallet_prelude::*; /// /// #[pezpallet::pezpallet] /// pub struct Pezpallet(_); /// /// #[pezpallet::config] /// pub trait Config: pezframe_system::Config {} /// /// #[pezpallet::call] /// impl Pezpallet { /// #[pezpallet::weight(Weight::zero())] /// #[pezpallet::authorize(|_source, foo| if *foo == 42 { /// // The amount to refund, here we refund nothing /// let refund = Weight::zero(); /// // The validity, here we accept the call and it provides itself. /// // See `ValidTransaction` for more information. /// let validity = ValidTransaction::with_tag_prefix("my-pezpallet") /// .and_provides("some_call") /// .into(); /// Ok((validity, refund)) /// } else { /// Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) /// })] /// #[pezpallet::weight_of_authorize(Weight::zero())] /// #[pezpallet::call_index(0)] /// pub fn some_call(origin: OriginFor, arg: u32) -> DispatchResult { /// ensure_authorized(origin)?; /// /// Ok(()) /// } /// /// #[pezpallet::weight(Weight::zero())] /// // We can also give the callback as a function /// #[pezpallet::authorize(Self::authorize_some_other_call)] /// #[pezpallet::weight_of_authorize(Weight::zero())] /// #[pezpallet::call_index(1)] /// pub fn some_other_call(origin: OriginFor, arg: u32) -> DispatchResult { /// ensure_authorized(origin)?; /// /// Ok(()) /// } /// } /// /// impl Pezpallet { /// fn authorize_some_other_call( /// source: TransactionSource, /// foo: &u32 /// ) -> TransactionValidityWithRefund { /// if *foo == 42 { /// let refund = Weight::zero(); /// let validity = ValidTransaction::default(); /// Ok((validity, refund)) /// } else { /// Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) /// } /// } /// } /// /// #[pezframe_benchmarking::v2::benchmarks] /// mod benchmarks { /// use super::*; /// use pezframe_benchmarking::v2::BenchmarkError; /// /// #[benchmark] /// fn authorize_some_call() -> Result<(), BenchmarkError> { /// let call = Call::::some_call { arg: 42 }; /// /// #[block] /// { /// use pezframe_support::pezpallet_prelude::Authorize; /// call.authorize(TransactionSource::External) /// .ok_or("Call must give some authorization")??; /// } /// /// Ok(()) /// } /// } /// } /// ``` /// /// ## Specification: /// /// Authorize process comes with 2 attributes macro on top of the authorized call: /// /// * `#[pezpallet::authorize($authorized_function)]` - defines the function that authorizes the /// call. First argument is the transaction source `TransactionSource` then followed by the same /// as call arguments but by reference `&`. Return type is `TransactionValidityWithRefund`. /// * `#[pezpallet::weight_of_authorize($weight)]` - defines the value of the weight of the /// authorize function. This attribute is similar to `#[pezpallet::weight]`: /// * it can be ignore in `dev_mode` /// * it can be automatically infered from weight info. For the call `foo` the function /// `authorize_foo` in the weight info will be used. (weight info needs to be provided in the /// call attribute: `#[pezpallet::call(weight = T::WeightInfo)]`). /// * it can be a fixed value like `Weight::from_all(0)` (not recommended in production). /// /// The weight must be small enough so that nodes don't get DDOS by validating transactions. /// /// Then in the call it must be ensured that the origin is the authorization process. This can /// be done using `pezframe_system::ensure_authorized` function. /// /// # The macro expansion /// /// From the given "authorize" function and weight, the macro will implement the trait /// `Authorize` on the call. /// /// # How to benchmark /// /// The authorize function is used as the implementation of the trait /// `Authorize` for the call. /// To benchmark a call variant, use the function /// `Authorize::authorize` on a call value. /// See the example in the first section. #[proc_macro_attribute] pub fn authorize(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() } /// Allows to define the weight of the authorize function. /// /// See [`authorize`](macro@authorize) for more information on how authorization works. /// /// Defines the value of the weight of the authorize function. This attribute is similar to /// `#[pezpallet::weight]`: /// * it can be ignore in `dev_mode` /// * it can be automatically infered from weight info. For the call `foo` the function /// `authorize_foo` in the weight info will be used. /// * it can be a fixed value like `Weight::from_all(0)` (not recommended in production). #[proc_macro_attribute] pub fn weight_of_authorize(_: TokenStream, _: TokenStream) -> TokenStream { pezpallet_macro_stub() }