Newer
Older
Guanqun Lu
committed
// This file is part of Substrate.
// 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.
//!
//! ## Note on Tuple Traits
//!
//! Many of the traits defined in [`traits`] have auto-implementations on tuples as well. Usually,
//! the tuple is a function of number of pallets in the runtime. By default, the traits are
//! implemented for tuples of up to 64 items.
//
// If you have more pallets in your runtime, or for any other reason need more, enabled `tuples-96`
// or the `tuples-128` complication flag. Note that these features *will increase* the compilation
// of this crate.
#![cfg_attr(not(feature = "std"), no_std)]
/// Export ourself as `frame_support` to make tests happy.
extern crate self as frame_support;
#[doc(hidden)]
pub use frame_metadata as metadata;
#[doc(hidden)]
pub use log;
#[cfg(feature = "std")]
#[doc(hidden)]
pub use once_cell;
#[doc(hidden)]
pub use paste;
#[doc(hidden)]
pub use scale_info;
pub use sp_api::metadata_ir;
pub use sp_core::{OpaqueMetadata, Void};
pub use sp_core_hashing_proc_macro;
#[doc(hidden)]
pub use sp_io::{self, storage::root as storage_root};
#[cfg(feature = "std")]
#[doc(hidden)]
pub use sp_runtime::{bounded_btree_map, bounded_vec};
pub use sp_runtime::{RuntimeDebug, StateVersion};
#[doc(hidden)]
pub use sp_state_machine::BasicExternalities;
#[doc(hidden)]
pub use tt_call::*;
pub mod event;
Sasha Gryaznov
committed
pub mod crypto;
Bastian Köcher
committed
pub mod dispatch_context;
pub mod migrations;
pub mod weights;
#[doc(hidden)]
pub mod unsigned {
#[doc(hidden)]
pub use crate::sp_runtime::traits::ValidateUnsigned;
#[doc(hidden)]
pub use crate::sp_runtime::transaction_validity::{
TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
#[cfg(any(feature = "std", feature = "runtime-benchmarks", feature = "try-runtime", test))]
pub use self::storage::storage_noop_guard::StorageNoopGuard;
pub use self::{
dispatch::{Callable, Parameter},
hash::{
Blake2_128, Blake2_128Concat, Blake2_256, Hashable, Identity, ReversibleStorageHasher,
StorageHasher, Twox128, Twox256, Twox64Concat,
},
storage::{
bounded_btree_map::BoundedBTreeMap,
bounded_btree_set::BoundedBTreeSet,
bounded_vec::{BoundedSlice, BoundedVec},
migration,
weak_bounded_vec::WeakBoundedVec,
IterableStorageDoubleMap, IterableStorageMap, IterableStorageNMap, StorageDoubleMap,
StorageMap, StorageNMap, StoragePrefixedMap, StorageValue,
},
pub use sp_runtime::{
self, print, traits::Printable, ConsensusEngineId, MAX_MODULE_ERROR_ENCODED_SIZE,
};
use codec::{Decode, Encode};
use sp_runtime::TypeId;
/// A unified log target for support operations.
pub const LOG_TARGET: &str = "runtime::frame-support";
/// A type that cannot be instantiated.
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub enum Never {}
/// A pallet identifier. These are per pallet and should be stored in a registry somewhere.
#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode, TypeInfo)]
pub struct PalletId(pub [u8; 8]);
impl TypeId for PalletId {
const TYPE_ID: [u8; 4] = *b"modl";
}
/// Generate a new type alias for [`storage::types::StorageValue`],
/// [`storage::types::StorageMap`], [`storage::types::StorageDoubleMap`]
/// and [`storage::types::StorageNMap`].
///
/// Useful for creating a *storage-like* struct for test and migrations.
///
/// # use frame_support::storage_alias;
/// use frame_support::codec;
/// use frame_support::Twox64Concat;
/// // generate a storage value with type u32.
/// #[storage_alias]
/// type StorageName = StorageValue<Prefix, u32>;
/// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key)
/// #[storage_alias]
/// type OtherStorageName = StorageDoubleMap<
/// OtherPrefix,
/// Twox64Concat,
/// u32,
/// Twox64Concat,
/// u32,
/// Vec<u8>,
/// >;
/// // optionally specify the query type
/// use frame_support::pallet_prelude::{ValueQuery, OptionQuery};
/// #[storage_alias]
/// type ValueName = StorageValue<Prefix, u32, OptionQuery>;
/// #[storage_alias]
/// type SomeStorageName = StorageMap<
/// Prefix,
/// Twox64Concat,
/// u32,
/// Vec<u8>,
/// ValueQuery,
/// >;
/// // generate a map from `Config::AccountId` (with hasher `Twox64Concat`) to `Vec<u8>`
/// trait Config { type AccountId: codec::FullCodec; }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/// #[storage_alias]
/// type GenericStorage<T> = StorageMap<Prefix, Twox64Concat, <T as Config>::AccountId, Vec<u8>>;
///
/// // It also supports NMap
/// use frame_support::storage::types::Key as NMapKey;
///
/// #[storage_alias]
/// type SomeNMap = StorageNMap<Prefix, (NMapKey<Twox64Concat, u32>, NMapKey<Twox64Concat, u64>), Vec<u8>>;
///
/// // 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<T: Config, I = ()>(std::marker::PhantomData<(T, I)>);
/// # impl<T: Config, I: 'static> frame_support::traits::PalletInfoAccess for Pallet<T, I> {
/// # 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<T: Config> = StorageValue<Pallet<T>, u64>;
///
/// // Pallet with instance
///
/// #[storage_alias]
/// type SomeValue2<T: Config, I: 'static> = StorageValue<Pallet<T, I>, u64>;
///
/// # fn main() {}
pub use frame_support_procedural::storage_alias;
/// Create new implementations of the [`Get`](crate::traits::Get) trait.
///
/// The so-called parameter type can be created in four different ways:
/// - Using `const` to create a parameter type that provides a `const` getter. It is required that
/// the `value` is const.
///
/// - Declare the parameter type without `const` to have more freedom when creating the value.
///
/// - Using `storage` to create a storage parameter type. This type is special as it tries to load
/// the value from the storage under a fixed key. If the value could not be found in the storage,
/// the given default value will be returned. It is required that the value implements
/// [`Encode`](codec::Encode) and [`Decode`](codec::Decode). The key for looking up the value in
/// the storage is built using the following formula:
///
/// `twox_128(":" ++ NAME ++ ":")` where `NAME` is the name that is passed as type name.
///
/// - Using `static` to create a static parameter type. Its value is being provided by a static
/// variable with the equivalent name in `UPPER_SNAKE_CASE`. An additional `set` function is
/// provided in this case to alter the static variable. **This is intended for testing ONLY and is
/// ONLY available when `std` is enabled.**
/// ```
/// # use frame_support::traits::Get;
/// # use frame_support::parameter_types;
/// // This function cannot be used in a const context.
/// fn non_const_expression() -> u64 { 99 }
///
/// const FIXED_VALUE: u64 = 10;
/// pub const Argument: u64 = 42 + FIXED_VALUE;
/// /// Visibility of the type is optional
/// OtherArgument: u64 = non_const_expression();
/// pub storage StorageArgument: u64 = 5;
/// pub static StaticArgument: u32 = 7;
/// type Parameter: Get<u64>;
/// type OtherParameter: Get<u64>;
/// type StorageParameter: Get<u64>;
/// type StaticParameter: Get<u32>;
/// struct Runtime;
/// impl Config for Runtime {
/// type Parameter = Argument;
/// type OtherParameter = OtherArgument;
/// type StorageParameter = StorageArgument;
/// type StaticParameter = StaticArgument;
/// }
///
/// // In testing, `StaticArgument` can be altered later: `StaticArgument::set(8)`.
/// ```
///
/// # Invalid example:
///
/// ```compile_fail
/// # use frame_support::traits::Get;
/// # use frame_support::parameter_types;
/// // This function cannot be used in a const context.
/// fn non_const_expression() -> u64 { 99 }
///
/// parameter_types! {
/// pub const Argument: u64 = non_const_expression();
/// }
/// ```
#[macro_export]
macro_rules! parameter_types {
(
$( #[ $attr:meta ] )*
$vis:vis const $name:ident $(< $($ty_params:ident),* >)?: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$( #[ $attr ] )*
$vis struct $name $(
< $($ty_params),* >( $($crate::sp_std::marker::PhantomData<$ty_params>),* )
)?;
$crate::parameter_types!(IMPL_CONST $name , $type , $value $( $(, $ty_params)* )?);
$crate::parameter_types!( $( $rest )* );
);
(
$( #[ $attr:meta ] )*
$vis:vis $name:ident $(< $($ty_params:ident),* >)?: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$( #[ $attr ] )*
$vis struct $name $(
< $($ty_params),* >( $($crate::sp_std::marker::PhantomData<$ty_params>),* )
)?;
$crate::parameter_types!(IMPL $name, $type, $value $( $(, $ty_params)* )?);
$crate::parameter_types!( $( $rest )* );
);
(
$( #[ $attr:meta ] )*
$vis:vis storage $name:ident $(< $($ty_params:ident),* >)?: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$( #[ $attr ] )*
$vis struct $name $(
< $($ty_params),* >( $($crate::sp_std::marker::PhantomData<$ty_params>),* )
)?;
$crate::parameter_types!(IMPL_STORAGE $name, $type, $value $( $(, $ty_params)* )?);
$crate::parameter_types!( $( $rest )* );
(IMPL_CONST $name:ident, $type:ty, $value:expr $(, $ty_params:ident)*) => {
impl< $($ty_params),* > $name< $($ty_params),* > {
/// Returns the value of this parameter type.
pub const fn get() -> $type {
$value
}
}
impl<_I: From<$type> $(, $ty_params)*> $crate::traits::Get<_I> for $name< $($ty_params),* > {
fn get() -> _I {
_I::from(Self::get())
}
}
impl< $($ty_params),* > $crate::traits::TypedGet for $name< $($ty_params),* > {
type Type = $type;
fn get() -> $type {
Self::get()
}
}
(IMPL $name:ident, $type:ty, $value:expr $(, $ty_params:ident)*) => {
impl< $($ty_params),* > $name< $($ty_params),* > {
/// Returns the value of this parameter type.
pub fn get() -> $type {
$value
}
}
impl<_I: From<$type>, $(, $ty_params)*> $crate::traits::Get<_I> for $name< $($ty_params),* > {
fn get() -> _I {
_I::from(Self::get())
impl< $($ty_params),* > $crate::traits::TypedGet for $name< $($ty_params),* > {
type Type = $type;
fn get() -> $type {
Self::get()
}
}
(IMPL_STORAGE $name:ident, $type:ty, $value:expr $(, $ty_params:ident)*) => {
impl< $($ty_params),* > $name< $($ty_params),* > {
/// Returns the key for this parameter type.
pub fn key() -> [u8; 16] {
$crate::sp_core_hashing_proc_macro::twox_128!(b":", $name, b":")
}
/// Set the value of this parameter type in the storage.
///
Liam Aharon
committed
/// This needs to be executed in an externalities provided environment.
pub fn set(value: &$type) {
$crate::storage::unhashed::put(&Self::key(), value);
}
/// Returns the value of this parameter type.
///
Liam Aharon
committed
/// This needs to be executed in an externalities provided environment.
#[allow(unused)]
pub fn get() -> $type {
$crate::storage::unhashed::get(&Self::key()).unwrap_or_else(|| $value)
}
}
impl<_I: From<$type> $(, $ty_params)*> $crate::traits::Get<_I> for $name< $($ty_params),* > {
fn get() -> _I {
_I::from(Self::get())
impl< $($ty_params),* > $crate::traits::TypedGet for $name< $($ty_params),* > {
type Type = $type;
fn get() -> $type {
Self::get()
}
}
$( #[ $attr:meta ] )*
$vis:vis static $name:ident: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$crate::parameter_types_impl_thread_local!(
$( #[ $attr ] )*
$vis static $name: $type = $value;
$crate::parameter_types!( $( $rest )* );
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
);
}
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! parameter_types_impl_thread_local {
( $( $any:tt )* ) => {
compile_error!("static parameter types is only available in std and for testing.");
};
}
#[cfg(feature = "std")]
#[macro_export]
macro_rules! parameter_types_impl_thread_local {
(
$(
$( #[ $attr:meta ] )*
$vis:vis static $name:ident: $type:ty = $value:expr;
)*
) => {
$crate::parameter_types_impl_thread_local!(
IMPL_THREAD_LOCAL $( $vis, $name, $type, $value, )*
);
$crate::paste::item! {
$crate::parameter_types!(
$(
$( #[ $attr ] )*
$vis $name: $type = [<$name:snake:upper>].with(|v| v.borrow().clone());
)*
);
$(
impl $name {
/// Set the internal value.
pub fn set(t: $type) {
[<$name:snake:upper>].with(|v| *v.borrow_mut() = t);
}
/// Mutate the internal value in place.
pub fn mutate<R, F: FnOnce(&mut $type) -> R>(mutate: F) -> R{
let mut current = Self::get();
let result = mutate(&mut current);
Self::set(current);
result
}
/// Get current value and replace with initial value of the parameter type.
pub fn take() -> $type {
let current = Self::get();
Self::set($value);
current
}
}
)*
}
};
(IMPL_THREAD_LOCAL $( $vis:vis, $name:ident, $type:ty, $value:expr, )* ) => {
$crate::paste::item! {
thread_local! {
$(
pub static [<$name:snake:upper>]: std::cell::RefCell<$type> =
std::cell::RefCell::new($value);
)*
}
}
};
/// Macro for easily creating a new implementation of both the `Get` and `Contains` traits. Use
/// exactly as with `parameter_types`, only the type must be `Ord`.
#[macro_export]
macro_rules! ord_parameter_types {
(
$( #[ $attr:meta ] )*
$vis:vis const $name:ident: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$( #[ $attr ] )*
$vis struct $name;
$crate::parameter_types!{IMPL $name , $type , $value}
$crate::ord_parameter_types!{IMPL $name , $type , $value}
$crate::ord_parameter_types!{ $( $rest )* }
);
() => ();
(IMPL $name:ident , $type:ty , $value:expr) => {
impl $crate::traits::SortedMembers<$type> for $name {
fn contains(t: &$type) -> bool { &$value == t }
fn sorted_members() -> $crate::sp_std::prelude::Vec<$type> { vec![$value] }
fn count() -> usize { 1 }
#[cfg(feature = "runtime-benchmarks")]
fn add(_: &$type) {}
impl $crate::traits::Contains<$type> for $name {
fn contains(t: &$type) -> bool { &$value == t }
}
/// Print out a formatted message.
///
/// # Example
///
/// ```
/// frame_support::runtime_print!("my value is {}", 3);
/// ```
#[macro_export]
macro_rules! runtime_print {
($($arg:tt)+) => {
{
use core::fmt::Write;
let mut w = $crate::sp_std::Writer::default();
let _ = core::write!(&mut w, $($arg)+);
$crate::sp_io::misc::print_utf8(&w.inner())
}
}
}
/// Print out the debuggable type.
pub fn debug(data: &impl sp_std::fmt::Debug) {
runtime_print!("{:?}", data);
}
pub use frame_support_procedural::{
construct_runtime, decl_storage, match_and_insert, transactional, PalletError,
RuntimeDebugNoBound,
#[doc(hidden)]
pub use frame_support_procedural::{__create_tt_macro, __generate_dummy_part_checker};
/// Derive [`Clone`] but do not bound any generic.
///
/// This is useful for type generic over runtime:
/// ```
/// # use frame_support::CloneNoBound;
/// }
///
/// // Foo implements [`Clone`] because `C` bounds [`Clone`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Clone`].
/// #[derive(CloneNoBound)]
/// struct Foo<T: Config> {
/// }
/// ```
pub use frame_support_procedural::CloneNoBound;
/// Derive [`Eq`] but do not bound any generic.
///
/// This is useful for type generic over runtime:
/// ```
/// # use frame_support::{EqNoBound, PartialEqNoBound};
/// }
///
/// // Foo implements [`Eq`] because `C` bounds [`Eq`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Eq`].
/// #[derive(PartialEqNoBound, EqNoBound)]
/// struct Foo<T: Config> {
/// }
/// ```
pub use frame_support_procedural::EqNoBound;
/// Derive [`PartialEq`] but do not bound any generic.
///
/// This is useful for type generic over runtime:
/// ```
/// # use frame_support::PartialEqNoBound;
/// }
///
/// // Foo implements [`PartialEq`] because `C` bounds [`PartialEq`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`PartialEq`].
/// #[derive(PartialEqNoBound)]
/// struct Foo<T: Config> {
/// }
/// ```
pub use frame_support_procedural::PartialEqNoBound;
/// Derive [`Debug`] but do not bound any generic.
///
/// This is useful for type generic over runtime:
/// ```
/// # use frame_support::DebugNoBound;
/// # use core::fmt::Debug;
/// }
///
/// // Foo implements [`Debug`] because `C` bounds [`Debug`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Debug`].
/// #[derive(DebugNoBound)]
/// struct Foo<T: Config> {
/// }
/// ```
pub use frame_support_procedural::DebugNoBound;
/// Derive [`Default`] but do not bound any generic.
///
/// This is useful for type generic over runtime:
/// ```
/// # use frame_support::DefaultNoBound;
/// # use core::default::Default;
/// trait Config {
/// }
///
/// // Foo implements [`Default`] because `C` bounds [`Default`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Default`].
/// #[derive(DefaultNoBound)]
/// struct Foo<T: Config> {
/// c: T::C,
/// }
///
/// // Also works with enums, by specifying the default with #[default]:
/// #[derive(DefaultNoBound)]
/// enum Bar<T: Config> {
/// // Bar will implement Default as long as all of the types within Baz also implement default.
/// #[default]
/// Baz(T::C),
/// Quxx,
/// }
/// ```
pub use frame_support_procedural::DefaultNoBound;
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
/// Assert the annotated function is executed within a storage transaction.
///
/// The assertion is enabled for native execution and when `debug_assertions` are enabled.
///
/// # Example
///
/// ```
/// # use frame_support::{
/// # require_transactional, transactional, dispatch::DispatchResult
/// # };
///
/// #[require_transactional]
/// fn update_all(value: u32) -> DispatchResult {
/// // Update multiple storages.
/// // Return `Err` to indicate should revert.
/// Ok(())
/// }
///
/// #[transactional]
/// fn safe_update(value: u32) -> DispatchResult {
/// // This is safe
/// update_all(value)
/// }
///
/// fn unsafe_update(value: u32) -> DispatchResult {
/// // this may panic if unsafe_update is not called within a storage transaction
/// update_all(value)
/// }
/// ```
pub use frame_support_procedural::require_transactional;
/// Convert the current crate version into a [`CrateVersion`](crate::traits::CrateVersion).
///
/// It uses the `CARGO_PKG_VERSION_MAJOR`, `CARGO_PKG_VERSION_MINOR` and
/// `CARGO_PKG_VERSION_PATCH` environment variables to fetch the crate version.
/// This means that the [`CrateVersion`](crate::traits::CrateVersion)
/// object will correspond to the version of the crate the macro is called in!
///
/// # Example
///
/// ```
/// # use frame_support::{traits::CrateVersion, crate_to_crate_version};
/// const Version: CrateVersion = crate_to_crate_version!();
/// ```
pub use frame_support_procedural::crate_to_crate_version;
/// Return Err of the expression: `return Err($expression);`.
///
/// Used as `fail!(expression)`.
#[macro_export]
macro_rules! fail {
( $y:expr ) => {{
return Err($y.into())
}};
/// Evaluate `$x:expr` and if not true return `Err($y:expr)`.
///
/// Used as `ensure!(expression_to_ensure, expression_to_return_on_false)`.
#[macro_export]
macro_rules! ensure {
$crate::fail!($y);
/// Evaluate an expression, assert it returns an expected `Err` value and that
/// runtime storage has not been mutated (i.e. expression is a no-operation).
///
/// Used as `assert_noop(expression_to_assert, expected_error_expression)`.
(
$x:expr,
$y:expr $(,)?
) => {
let h = $crate::storage_root($crate::StateVersion::V1);
$crate::assert_err!($x, $y);
assert_eq!(h, $crate::storage_root($crate::StateVersion::V1), "storage has been mutated");
/// Evaluate any expression and assert that runtime storage has not been mutated
/// (i.e. expression is a storage no-operation).
///
/// Used as `assert_storage_noop(expression_to_assert)`.
#[macro_export]
macro_rules! assert_storage_noop {
(
$x:expr
) => {
let h = $crate::storage_root($crate::StateVersion::V1);
assert_eq!(h, $crate::storage_root($crate::StateVersion::V1));
/// Assert an expression returns an error specified.
///
/// Used as `assert_err!(expression_to_assert, expected_error_expression)`
assert_eq!($x, Err($y.into()));
/// Assert an expression returns an error specified.
///
Sam Johnson
committed
/// This can be used on `DispatchResultWithPostInfo` when the post info should
/// be ignored.
#[macro_export]
macro_rules! assert_err_ignore_postinfo {
( $x:expr , $y:expr $(,)? ) => {
$crate::assert_err!($x.map(|_| ()).map_err(|e| e.error), $y);
/// Assert an expression returns error with the given weight.
#[macro_export]
macro_rules! assert_err_with_weight {
($call:expr, $err:expr, $weight:expr $(,)? ) => {
if let Err(dispatch_err_with_post) = $call {
$crate::assert_err!($call.map(|_| ()).map_err(|e| e.error), $err);
assert_eq!(dispatch_err_with_post.post_info.actual_weight, $weight);
} else {
panic!("expected Err(_), got Ok(_).")
}
/// Panic if an expression doesn't evaluate to `Ok`.
///
/// Used as `assert_ok!(expression_to_assert, expected_ok_expression)`,
/// or `assert_ok!(expression_to_assert)` which would assert against `Ok(())`.
( $x:expr $(,)? ) => {
let is = $x;
match is {
Ok(_) => (),
_ => assert!(false, "Expected Ok(_). Got {:#?}", is),
}
( $x:expr, $y:expr $(,)? ) => {
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
/// Assert that the maximum encoding size does not exceed the value defined in
/// [`MAX_MODULE_ERROR_ENCODED_SIZE`] during compilation.
///
/// This macro is intended to be used in conjunction with `tt_call!`.
#[macro_export]
macro_rules! assert_error_encoded_size {
{
path = [{ $($path:ident)::+ }]
runtime = [{ $runtime:ident }]
assert_message = [{ $assert_message:literal }]
error = [{ $error:ident }]
} => {
const _: () = assert!(
<
$($path::)+$error<$runtime> as $crate::traits::PalletError
>::MAX_ENCODED_SIZE <= $crate::MAX_MODULE_ERROR_ENCODED_SIZE,
$assert_message
);
};
{
path = [{ $($path:ident)::+ }]
runtime = [{ $runtime:ident }]
assert_message = [{ $assert_message:literal }]
} => {};
}
Bastian Köcher
committed
#[doc(hidden)]
pub use serde::{Deserialize, Serialize};
Drew Stone
committed
pub mod tests {
use crate::metadata_ir::{
PalletStorageMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR,
StorageEntryTypeIR, StorageHasherIR,
use sp_io::{MultiRemovalResults, TestExternalities};
Qinxuan Chen
committed
use sp_runtime::{generic, traits::BlakeTwo256, BuildStorage};
Qinxuan Chen
committed
pub use self::frame_system::{Config, Pallet};
Qinxuan Chen
committed
#[pallet]
pub mod frame_system {
#[allow(unused)]
use super::{frame_system, frame_system::pallet_prelude::*};
pub use crate::dispatch::RawOrigin;
use crate::pallet_prelude::*;
#[pallet::pallet]
pub struct Pallet<T>(PhantomData<T>);
#[pallet::config]
#[pallet::disable_frame_system_supertrait_check]
pub trait Config: 'static {
type BlockNumber: Parameter + Default + MaxEncodedLen;
type AccountId;
type BaseCallFilter: crate::traits::Contains<Self::RuntimeCall>;
type RuntimeOrigin;
type RuntimeCall;
type PalletInfo: crate::traits::PalletInfo;
type DbWeight: Get<crate::weights::RuntimeDbWeight>;
}
Qinxuan Chen
committed
#[pallet::error]
pub enum Error<T> {
/// Required by construct_runtime
CallFiltered,
}
Qinxuan Chen
committed
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
#[pallet::origin]
pub type Origin<T> = RawOrigin<<T as Config>::AccountId>;
#[pallet::call]
impl<T: Config> Pallet<T> {}
#[pallet::storage]
pub type Data<T> = StorageMap<_, Twox64Concat, u32, u64, ValueQuery>;
#[pallet::storage]
pub type OptionLinkedMap<T> = StorageMap<_, Blake2_128Concat, u32, u32, OptionQuery>;
#[pallet::storage]
#[pallet::getter(fn generic_data)]
pub type GenericData<T: Config> =
StorageMap<_, Identity, T::BlockNumber, T::BlockNumber, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn generic_data2)]
pub type GenericData2<T: Config> =
StorageMap<_, Blake2_128Concat, T::BlockNumber, T::BlockNumber, OptionQuery>;
#[pallet::storage]
pub type DataDM<T> =
StorageDoubleMap<_, Twox64Concat, u32, Blake2_128Concat, u32, u64, ValueQuery>;
#[pallet::storage]
pub type GenericDataDM<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::BlockNumber,
Identity,
T::BlockNumber,
T::BlockNumber,
ValueQuery,
>;
#[pallet::storage]
pub type GenericData2DM<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::BlockNumber,
Twox64Concat,
T::BlockNumber,
T::BlockNumber,
OptionQuery,
>;
#[pallet::storage]
#[pallet::unbounded]
pub type AppendableDM<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
u32,
Blake2_128Concat,
T::BlockNumber,
Vec<u32>,
ValueQuery,
>;
#[pallet::genesis_config]
pub struct GenesisConfig {
pub data: Vec<(u32, u64)>,
pub test_config: Vec<(u32, u32, u64)>,
}
Qinxuan Chen
committed
impl Default for GenesisConfig {
fn default() -> Self {
Self { data: vec![(15u32, 42u64)], test_config: vec![(15u32, 16u32, 42u64)] }
}
}
Qinxuan Chen
committed
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
for (k, v) in &self.data {
<Data<T>>::insert(k, v);
}
for (k1, k2, v) in &self.test_config {
<DataDM<T>>::insert(k1, k2, v);
}
}
Qinxuan Chen
committed
pub mod pallet_prelude {
pub type OriginFor<T> = <T as super::Config>::RuntimeOrigin;
Qinxuan Chen
committed
type BlockNumber = u32;
type AccountId = u32;
type Header = generic::Header<BlockNumber, BlakeTwo256>;
type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, RuntimeCall, (), ()>;
type Block = generic::Block<Header, UncheckedExtrinsic>;
crate::construct_runtime!(
pub enum Runtime
where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: self::frame_system,
}
);
Qinxuan Chen
committed
impl Config for Runtime {
type BlockNumber = BlockNumber;
type AccountId = AccountId;
type BaseCallFilter = crate::traits::Everything;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type PalletInfo = PalletInfo;
fn new_test_ext() -> TestExternalities {
GenesisConfig::default().build_storage().unwrap().into()
trait Sorted {
fn sorted(self) -> Self;
}
impl<T: Ord> Sorted for Vec<T> {
fn sorted(mut self) -> Self {
self.sort();
self
}
}
fn storage_alias_works() {
#[crate::storage_alias]