lib.rs 80.9 KiB
Newer Older
///
/// Item must be either a type alias or an enum or a struct. It needs to be public.
///
/// E.g.:
/// ```ignore
/// #[pallet::origin]
/// pub struct Origin<T>(PhantomData<(T)>);
/// ```
///
/// **WARNING**: modifying origin changes the outer runtime origin. This outer runtime origin
/// can be stored on-chain (e.g. in pallet-scheduler), thus any change must be done with care
/// as it might require some migration.
///
/// NOTE: for instantiable pallet, origin must be generic over T and I.
///
/// # General notes on instantiable pallet
///
/// An instantiable pallet is one where Config is generic, i.e. `Config<I>`. This allow runtime
/// to implement multiple instance of the pallet, by using different type for the generic.
/// This is the sole purpose of the generic `I`.
/// But because `PalletInfo` requires `Pallet` placeholder to be static it is important to
/// bound `'static` whenever `PalletInfo` can be used.
/// And in order to have instantiable pallet usable as a regular pallet without instance, it is
/// important to bound `= ()` on every types.
///
/// Thus impl bound look like `impl<T: Config<I>, I: 'static>`, and types look like
/// `SomeType<T, I=()>` or `SomeType<T: Config<I>, I: 'static = ()>`.
///
/// # Example for pallet without instance.
///
/// ```
/// pub use pallet::*; // reexport in crate namespace for `construct_runtime!`
///
/// #[frame_support::pallet]
/// // NOTE: The name of the pallet is provided by `construct_runtime` and is used as
/// // the unique identifier for the pallet's storage. It is not defined in the pallet itself.
/// 	use frame_support::pallet_prelude::*; // Import various types used in the pallet definition
/// 	use frame_system::pallet_prelude::*; // Import some system helper types.
///
/// 	type BalanceOf<T> = <T as Config>::Balance;
///
/// 	// Define the generic parameter of the pallet
/// 	// The macro parses `#[pallet::constant]` attributes and uses them to generate metadata
/// 	// for the pallet's constants.
/// 	#[pallet::config]
/// 	pub trait Config: frame_system::Config {
/// 		#[pallet::constant] // put the constant in metadata
/// 		type MyGetParam: Get<u32>;
/// 		type Balance: Parameter + MaxEncodedLen + From<u8>;
/// 		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
/// 	}
///
/// 	// Define some additional constant to put into the constant metadata.
/// 	#[pallet::extra_constants]
/// 	impl<T: Config> Pallet<T> {
/// 		/// Some description
/// 		fn exra_constant_name() -> u128 { 4u128 }
/// 	}
///
/// 	// Define the pallet struct placeholder, various pallet function are implemented on it.
/// 	#[pallet::pallet]
/// 	#[pallet::generate_store(pub(super) trait Store)]
/// 	// Implement the pallet hooks.
/// 	#[pallet::hooks]
/// 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
/// 		fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
/// 			unimplemented!();
/// 		}
///
/// 		// can implement also: on_finalize, on_runtime_upgrade, offchain_worker, ...
/// 		// see `Hooks` trait
/// 	}
///
/// 	// Declare Call struct and implement dispatchables.
/// 	//
/// 	// WARNING: Each parameter used in functions must implement: Clone, Debug, Eq, PartialEq,
/// 	// Codec.
/// 	//
/// 	// The macro parses `#[pallet::compact]` attributes on function arguments and implements
/// 	// the `Call` encoding/decoding accordingly.
/// 	#[pallet::call]
/// 	impl<T: Config> Pallet<T> {
/// 		/// Doc comment put in metadata
/// 		#[pallet::weight(0)] // Defines weight for call (function parameters are in scope)
/// 		pub fn toto(
/// 			origin: OriginFor<T>,
/// 			#[pallet::compact] _foo: u32,
/// 		) -> DispatchResultWithPostInfo {
/// 			let _ = origin;
/// 			unimplemented!();
/// 		}
/// 	}
///
/// 	// Declare the pallet `Error` enum (this is optional).
/// 	// The macro generates error metadata using the doc comment on each variant.
/// 	#[pallet::error]
/// 	pub enum Error<T> {
/// 		/// doc comment put into metadata
/// 		InsufficientProposersBalance,
/// 	}
///
/// 	// Declare pallet Event enum (this is optional).
/// 	//
/// 	// WARNING: Each type used in variants must implement: Clone, Debug, Eq, PartialEq, Codec.
/// 	//
/// 	// The macro generates event metadata, and derive Clone, Debug, Eq, PartialEq and Codec
/// 	#[pallet::event]
/// 	// Generate a funciton on Pallet to deposit an event.
/// 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
/// 	pub enum Event<T: Config> {
/// 		/// doc comment put in metadata
/// 		// `<T as frame_system::Config>::AccountId` is not defined in metadata list, the last
/// 		// Thus the metadata is `<T as frame_system::Config>::AccountId`.
/// 		Proposed(<T as frame_system::Config>::AccountId),
/// 		/// doc
/// 		// here metadata will be `Balance` as define in metadata list
/// 		Spending(BalanceOf<T>),
/// 		// here metadata will be `Other` as define in metadata list
/// 		Something(u32),
/// 	}
///
/// 	// Define a struct which implements `frame_support::traits::Get<T::Balance>` (optional).
/// 	#[pallet::type_value]
/// 	pub(super) fn MyDefault<T: Config>() -> T::Balance { 3.into() }
///
/// 	// Declare a storage item. Any amount of storage items can be declared (optional).
/// 	//
/// 	// Is expected either `StorageValue`, `StorageMap` or `StorageDoubleMap`.
/// 	// The macro generates the prefix type and replaces the first generic `_`.
/// 	//
/// 	// The macro expands the metadata for the storage item with the type used:
/// 	// * for a storage value the type of the value is copied into the metadata
/// 	// * for a storage map the type of the values and the type of the key is copied into the metadata
/// 	// * for a storage double map the types of the values and keys are copied into the
/// 	// NOTE: The generic `Hasher` must implement the `StorageHasher` trait (or the type is not
/// 	// usable at all). We use [`StorageHasher::METADATA`] for the metadata of the hasher of the
/// 	// storage item. Thus generic hasher is supported.
/// 	#[pallet::storage]
/// 	pub(super) type MyStorageValue<T: Config> =
/// 		StorageValue<Value = T::Balance, QueryKind = ValueQuery, OnEmpty = MyDefault<T>>;
/// 	// Another storage declaration
/// 	#[pallet::storage]
/// 	#[pallet::getter(fn my_storage)]
/// 	#[pallet::storage_prefix = "SomeOtherName"]
/// 	pub(super) type MyStorage<T> =
/// 		StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
/// 	// Declare the genesis config (optional).
/// 	// The macro accepts either a struct or an enum; it checks that generics are consistent.
/// 	// Type must implement the `Default` trait.
/// 	#[pallet::genesis_config]
/// 	#[derive(Default)]
/// 	pub struct GenesisConfig {
/// 		_myfield: u32,
/// 	}
///
/// 	// Declare genesis builder. (This is need only if GenesisConfig is declared)
/// 	#[pallet::genesis_build]
/// 	impl<T: Config> GenesisBuild<T> for GenesisConfig {
/// 		fn build(&self) {}
/// 	}
///
/// 	// Declare a pallet origin (this is optional).
/// 	//
/// 	// The macro accept type alias or struct or enum, it checks generics are consistent.
/// 	#[pallet::origin]
/// 	pub struct Origin<T>(PhantomData<T>);
///
/// 	// Declare validate_unsigned implementation (this is optional).
/// 	#[pallet::validate_unsigned]
/// 	impl<T: Config> ValidateUnsigned for Pallet<T> {
/// 		type Call = Call<T>;
/// 		fn validate_unsigned(
/// 			source: TransactionSource,
/// 			call: &Self::Call
/// 		) -> TransactionValidity {
/// 			Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
/// 		}
/// 	}
///
/// 	// Declare inherent provider for pallet (this is optional).
/// 	#[pallet::inherent]
/// 	impl<T: Config> ProvideInherent for Pallet<T> {
/// 		type Call = Call<T>;
/// 		type Error = InherentError;
///
/// 		const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
///
/// 		fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
/// 			unimplemented!();
/// 		}
///
/// 		fn is_inherent(_call: &Self::Call) -> bool {
/// 			unimplemented!();
/// 		}
/// 	}
///
/// 	// Regular rust code needed for implementing ProvideInherent trait
///
/// 	#[derive(codec::Encode, sp_runtime::RuntimeDebug)]
/// 	#[cfg_attr(feature = "std", derive(codec::Decode))]
/// 	pub enum InherentError {
/// 	}
///
/// 	impl sp_inherents::IsFatalError for InherentError {
/// 		fn is_fatal_error(&self) -> bool {
/// 			unimplemented!();
/// 		}
/// 	}
///
/// 	pub const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"testpall";
/// }
/// ```
///
/// # Example for pallet with instance.
///
/// ```
/// pub use pallet::*;
///
/// #[frame_support::pallet]
/// pub mod pallet {
/// 	use frame_support::pallet_prelude::*;
/// 	use frame_system::pallet_prelude::*;
///
/// 	type BalanceOf<T, I = ()> = <T as Config<I>>::Balance;
///
/// 	#[pallet::config]
/// 	pub trait Config<I: 'static = ()>: frame_system::Config {
/// 		#[pallet::constant]
/// 		type MyGetParam: Get<u32>;
/// 		type Balance: Parameter + MaxEncodedLen + From<u8>;
/// 		type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
/// 	}
///
/// 	#[pallet::extra_constants]
/// 	impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// 		/// Some description
/// 		fn exra_constant_name() -> u128 { 4u128 }
/// 	}
///
/// 	#[pallet::pallet]
/// 	#[pallet::generate_store(pub(super) trait Store)]
/// 	pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
///
/// 	#[pallet::hooks]
/// 	impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
/// 	}
///
/// 	#[pallet::call]
/// 	impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// 		/// Doc comment put in metadata
/// 		#[pallet::weight(0)]
/// 		pub fn toto(origin: OriginFor<T>, #[pallet::compact] _foo: u32) -> DispatchResultWithPostInfo {
/// 			let _ = origin;
/// 			unimplemented!();
/// 		}
/// 	}
///
/// 	#[pallet::error]
/// 	pub enum Error<T, I = ()> {
/// 		/// doc comment put into metadata
/// 		InsufficientProposersBalance,
/// 	}
///
/// 	#[pallet::event]
/// 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
/// 	pub enum Event<T: Config<I>, I: 'static = ()> {
/// 		/// doc comment put in metadata
/// 		Proposed(<T as frame_system::Config>::AccountId),
/// 		/// doc
/// 		Spending(BalanceOf<T, I>),
/// 		Something(u32),
/// 	}
///
/// 	#[pallet::type_value]
/// 	pub(super) fn MyDefault<T: Config<I>, I: 'static>() -> T::Balance { 3.into() }
///
/// 	#[pallet::storage]
/// 	pub(super) type MyStorageValue<T: Config<I>, I: 'static = ()> =
/// 		StorageValue<Value = T::Balance, QueryKind = ValueQuery, OnEmpty = MyDefault<T, I>>;
///
/// 	#[pallet::storage]
/// 	#[pallet::getter(fn my_storage)]
/// 	#[pallet::storage_prefix = "SomeOtherName"]
/// 	pub(super) type MyStorage<T, I = ()> =
/// 		StorageMap<Hasher = Blake2_128Concat, Key = u32, Value = u32>;
///
/// 	#[pallet::genesis_config]
/// 	#[derive(Default)]
/// 	pub struct GenesisConfig {
/// 		_myfield: u32,
/// 	}
///
/// 	#[pallet::genesis_build]
/// 	impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig {
/// 		fn build(&self) {}
/// 	}
///
/// 	#[pallet::origin]
/// 	pub struct Origin<T, I = ()>(PhantomData<(T, I)>);
///
/// 	#[pallet::validate_unsigned]
/// 	impl<T: Config<I>, I: 'static> ValidateUnsigned for Pallet<T, I> {
/// 		type Call = Call<T, I>;
/// 		fn validate_unsigned(
/// 			source: TransactionSource,
/// 			call: &Self::Call
/// 		) -> TransactionValidity {
/// 			Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
/// 		}
/// 	}
///
/// 	#[pallet::inherent]
/// 	impl<T: Config<I>, I: 'static> ProvideInherent for Pallet<T, I> {
/// 		type Call = Call<T, I>;
/// 		type Error = InherentError;
///
/// 		const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
///
/// 		fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
/// 			unimplemented!();
/// 		}
///
/// 		fn is_inherent(_call: &Self::Call) -> bool {
/// 			unimplemented!();
/// 		}
/// 	}
///
/// 	// Regular rust code needed for implementing ProvideInherent trait
///
/// 	#[derive(codec::Encode, sp_runtime::RuntimeDebug)]
/// 	#[cfg_attr(feature = "std", derive(codec::Decode))]
/// 	pub enum InherentError {
/// 	}
///
/// 	impl sp_inherents::IsFatalError for InherentError {
/// 		fn is_fatal_error(&self) -> bool {
/// 			unimplemented!();
/// 		}
/// 	}
///
/// 	pub const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"testpall";
/// }
/// ```
///
/// ## Upgrade guidelines:
///
/// 1. Export the metadata of the pallet for later checks
///     - run your node with the pallet active
///     - query the metadata using the `state_getMetadata` RPC and curl, or use `subsee -p
///       <PALLET_NAME> > meta.json`
/// 2. generate the template upgrade for the pallet provided by decl_storage
///     with environment variable `PRINT_PALLET_UPGRADE`:
///     `PRINT_PALLET_UPGRADE=1 cargo check -p my_pallet` This template can be
///     used as information it contains all information for storages, genesis
///     config and genesis build.
/// 3. reorganize pallet to have trait `Config`, `decl_*` macros, `ValidateUnsigned`,
/// 	`ProvideInherent`, `Origin` all together in one file. Suggested order:
/// 	* Config,
/// 	* decl_module,
/// 	* decl_event,
/// 	* decl_error,
/// 	* decl_storage,
/// 	* origin,
/// 	* validate_unsigned,
/// 	* provide_inherent,
/// 	so far it should compile and all be correct.
/// 4. start writing the new pallet module
/// 	```ignore
/// 	pub use pallet::*;
///
/// 	#[frame_support::pallet]
/// 	pub mod pallet {
/// 		use frame_support::pallet_prelude::*;
/// 		use frame_system::pallet_prelude::*;
/// 		use super::*;
///
/// 		#[pallet::pallet]
/// 		#[pallet::generate_store($visibility_of_trait_store trait Store)]
/// 		// NOTE: if the visibility of trait store is private but you want to make it available
/// 		// in super, then use `pub(super)` or `pub(crate)` to make it available in crate.
/// 		// pub struct Pallet<T, I = ()>(PhantomData<T>); // for instantiable pallet
/// 	}
/// 	```
/// 5. **migrate Config**: move trait into the module with
/// 	* all const in decl_module to `#[pallet::constant]`
/// 	* add bound `IsType<<Self as frame_system::Config>::Event>` to `type Event`
/// 7. **migrate decl_module**: write:
/// 	```ignore
/// 	#[pallet::hooks]
/// 	impl<T: Config> Hooks for Pallet<T> {
/// 	and write inside
/// 	`on_initialize`, `on_finalize`, `on_runtime_upgrade`, `offchain_worker`, `integrity_test`.
///
/// 	then write:
/// 	```ignore
/// 	#[pallet::call]
/// 	impl<T: Config> Pallet<T> {
/// 	and write inside all the calls in decl_module with a few changes in the signature:
/// 	- origin must now be written completely, e.g. `origin: OriginFor<T>`
/// 	- result type must be `DispatchResultWithPostInfo`, you need to write it and also you
///    might
/// 	need to put `Ok(().into())` at the end or the function.
/// 	- `#[compact]` must now be written `#[pallet::compact]`
/// 	- `#[weight = ..]` must now be written `#[pallet::weight(..)]`
///
/// 7. **migrate event**:
/// 	rewrite as a simple enum under with the attribute `#[pallet::event]`,
/// 	use `#[pallet::generate_deposit($vis fn deposit_event)]` to generate deposit_event,
/// 8. **migrate error**: rewrite it with attribute `#[pallet::error]`.
/// 9. **migrate storage**:
/// 	decl_storage provide an upgrade template (see 3.). All storages, genesis config, genesis
/// 	build and default implementation of genesis config can be taken from it directly.
///
/// 	Otherwise here is the manual process:
///
/// 	first migrate the genesis logic. write:
/// 	```ignore
/// 	#[pallet::genesis_config]
/// 	struct GenesisConfig {
/// 		// fields of add_extra_genesis
/// 	}
/// 	impl Default for GenesisConfig {
/// 		// type default or default provided for fields
/// 	}
/// 	#[pallet::genesis_build]
/// 	impl<T: Config> GenesisBuild<T> for GenesisConfig {
/// 	// for instantiable pallet:
/// 	// `impl<T: Config, I: 'static> GenesisBuild<T, I> for GenesisConfig {
/// 		fn build() {
/// 			// The add_extra_genesis build logic
/// 		}
/// 	}
/// 	```
/// 	for each storages, if it contains config(..) then add a fields, and make its default to the
/// 	value in `= ..;` or the type default if none, if it contains no build then also add the
/// 	logic to build the value.
/// 	for each storages if it contains build(..) then add the logic to genesis_build.
///
/// 	NOTE: in decl_storage: is executed first the individual config and build and at the end the
/// 	add_extra_genesis build
///
/// 	Once this is done you can migrate storage individually, a few notes:
/// 	- for private storage use `pub(crate) type ` or `pub(super) type` or nothing,
/// 	- for storage with `get(fn ..)` use `#[pallet::getter(fn ...)]`
/// 	- for storage with value being `Option<$something>` make generic `Value` being
///    `$something`
/// 		and generic `QueryKind` being `OptionQuery` (note: this is default). Otherwise make
/// 		`Value` the complete value type and `QueryKind` being `ValueQuery`.
/// 	- for storage with default value: `= $expr;` provide some specific OnEmpty generic. To do
///    so
/// 		use of `#[pallet::type_value]` to generate the wanted struct to put.
/// 		example: `MyStorage: u32 = 3u32` would be written:
/// 		```ignore
/// 		#[pallet::type_value] fn MyStorageOnEmpty() -> u32 { 3u32 }
/// 		#[pallet::storage]
/// 		pub(super) type MyStorage<T> = StorageValue<_, u32, ValueQuery, MyStorageOnEmpty>;
/// 	NOTE: `decl_storage` also generates functions `assimilate_storage` and `build_storage`
/// 	directly on GenesisConfig, those are sometimes used in tests. In order not to break they
/// 	can be implemented manually, one can implement those functions by calling `GenesisBuild`
/// 10. **migrate origin**: move the origin to the pallet module under `#[pallet::origin]`
/// 11. **migrate validate_unsigned**: move the `ValidateUnsigned` implementation to the pallet
/// 	module under `#[pallet::validate_unsigned]`
/// 12. **migrate provide_inherent**: move the `ProvideInherent` implementation to the pallet
/// 	module under `#[pallet::inherent]`
/// 13. rename the usage of `Module` to `Pallet` inside the crate.
/// 14. migration is done, now double check migration with the checking migration guidelines.
///
/// ## Checking upgrade guidelines:
///
/// * compare metadata. Use [subsee](https://github.com/ascjones/subsee) to fetch the metadata
/// and do a diff of the resulting json before and after migration. This checks for:
/// 	* call, names, signature, docs
/// 	* event names, docs
/// 	* error names, docs
/// 	* storage names, hasher, prefixes, default value
/// 	* error , error, constant,
/// * manually check that:
/// 	* `Origin` is moved inside the macro under `#[pallet::origin]` if it exists
/// 	* `ValidateUnsigned` is moved inside the macro under `#[pallet::validate_unsigned)]` if it
///    exists
/// 	* `ProvideInherent` is moved inside macro under `#[pallet::inherent)]` if it exists
/// 	* `on_initialize`/`on_finalize`/`on_runtime_upgrade`/`offchain_worker` are moved to
///    `Hooks`
/// 	* storages with `config(..)` are converted to `GenesisConfig` field, and their default is
/// 		`= $expr;` if the storage have default value
/// 	* storages with `build($expr)` or `config(..)` are built in `GenesisBuild::build`
/// 	* `add_extra_genesis` fields are converted to `GenesisConfig` field with their correct
/// 		default if specified
/// 	* `add_extra_genesis` build is written into `GenesisBuild::build`
/// * storage items defined with [`pallet`] use the name of the pallet provided by
/// 	[`traits::PalletInfo::name`] as `pallet_prefix` (in `decl_storage`, storage items used the
/// 	`pallet_prefix` given as input of `decl_storage` with the syntax `as Example`).
/// 	Thus a runtime using the pallet must be careful with this change.
/// 	To handle this change:
/// 	* either ensure that the name of the pallet given to `construct_runtime!` is the same
/// 		as the name the pallet was giving to `decl_storage`,
/// 	* or do a storage migration from the old prefix used to the new prefix used.
///
/// 	NOTE: The prefixes used by storage items are in the metadata. Thus, ensuring the metadata
/// hasn't 	changed does ensure that the `pallet_prefix`s used by the storage items haven't
/// changed.
///
/// # Notes when macro fails to show proper error message spans:
///
/// Rustc loses span for some macro input. Some tips to fix it:
/// * do not use inner attribute:
/// 	```ignore
/// 	#[pallet]
/// 	pub mod pallet {
/// 		//! This inner attribute will make span fail
/// 		..
/// 	}
/// 	```
/// * use the newest nightly possible.
pub use frame_support_procedural::pallet;