Documentation: decl_module! macro (#2147)

* Add: initial draft of decl_module!, before fact-check

* Add: edits after content review by Guillaume

* style

* add link to event doc

* Changed `nocompile` to `rust,ignore` for docs

* Update srml/support/src/dispatch.rs

Co-Authored-By: nczhu <nicole@parity.io>

* Update dispatch.rs

* Changed examples layout of decl_module macro docs

* style and links

* decl_module doc tests passing

* All doc tests passing for decl_module

* Minor cleanup, comment out doc test imports

* some cleanup

* Update srml/support/src/dispatch.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Bump `impl_version` for CI

* Fix indentation

* Update description of Multiple Module Instances

* function definition updates

* restructure example and spelling fixes

* update after review

* `ensure_root` is not a macro

* remove ! from ensure_root in text

* public vs private
This commit is contained in:
Nicole Zhu
2019-04-23 19:52:10 +02:00
committed by Gavin Wood
parent 116e99b6f3
commit 25c529095c
4 changed files with 137 additions and 33 deletions
+133 -31
View File
@@ -27,17 +27,17 @@ pub use srml_metadata::{
FunctionArgumentMetadata, OuterDispatchMetadata, OuterDispatchCall
};
/// A type that can not be instantiated.
/// A type that cannot be instantiated.
pub enum Never {}
/// Result of a module function call; either nothing (functions are only called for "side effects")
/// or an error message.
pub type Result = result::Result<(), &'static str>;
/// A lazy call (module function and argument values) that can be executed via its dispatch()
/// A lazy call (module function and argument values) that can be executed via its `dispatch`
/// method.
pub trait Dispatchable {
/// Every function call to your runtime has an origin which specifies where the extrinsic was
/// Every function call from your runtime has an origin, which specifies where the extrinsic was
/// generated from. In the case of a signed extrinsic (transaction), the origin contains an
/// identifier for the caller. The origin can be empty in the case of an inherent extrinsic.
type Origin;
@@ -67,38 +67,140 @@ pub trait Parameter: Codec + Clone + Eq {}
#[cfg(not(feature = "std"))]
impl<T> Parameter for T where T: Codec + Clone + Eq {}
/// Declare a module struct and implement the dispatch logic.
/// Declares a `Module` struct and a `Call` enum, which implements the dispatch logic.
///
/// Usually used as follows:
/// ## Declaration
///
/// ```
/// # #[macro_use]
/// # extern crate srml_support;
/// # use srml_support::dispatch::Result;
/// # use srml_system::{self as system, Trait, ensure_signed};
/// decl_module! {
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
///
/// // Private functions are dispatchable, but not available to other
/// // SRML modules.
/// fn my_function(origin, var: u64) -> Result {
/// // Your implementation
/// Ok(())
/// }
///
/// // Public functions are both dispatchable and available to other
/// // SRML modules.
/// pub fn my_public_function(origin) -> Result {
/// // Your implementation
/// Ok(())
/// }
/// }
/// }
/// # fn main() {}
/// ```
///
/// The declaration is set with the header where:
///
/// * `Module`: The struct generated by the macro, with type `Trait`.
/// * `Call`: The enum generated for every module, which implements [`Callable`](./dispatch/trait.Callable.html).
/// * `origin`: Alias of `T::Origin`, declared by the [`impl_outer_origin!`](./macro.impl_outer_origin.html) macro.
/// * `Result`: The expected return type from module functions.
///
/// ### Shorthand Example
///
/// The macro automatically expands a shorthand function declaration to return the `Result` type.
/// These functions are the same:
///
/// ```
/// # #[macro_use]
/// # extern crate srml_support;
/// # use srml_support::dispatch::Result;
/// # use srml_system::{self as system, Trait, ensure_signed};
/// decl_module! {
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
///
/// fn my_long_function(origin) -> Result {
/// // Your implementation
/// Ok(())
/// }
///
/// fn my_short_function(origin) {
/// // Your implementation
/// }
/// }
/// }
/// # fn main() {}
/// ```
///
/// ### Privileged Function Example
///
/// If the `origin` param is omitted, the macro adds it as the first parameter and adds `ensure_root(origin)`
/// as the first line of the function. These functions are the same:
///
/// ```
/// # #[macro_use]
/// # extern crate srml_support;
/// # use srml_support::dispatch::Result;
/// # use srml_system::{self as system, Trait, ensure_signed, ensure_root};
/// decl_module! {
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
///
/// fn my_privileged_function() -> Result {
/// // Your implementation
/// Ok(())
/// }
///
/// fn my_function(origin) -> Result {
/// ensure_root(origin);
/// // Your implementation
/// Ok(())
/// }
/// }
/// }
/// # fn main() {}
/// ```
///
/// ## Multiple Module Instances Example
///
/// A Substrate module can be built such that multiple instances of the same module can be used within a single
/// runtime. For example, the [Balances module](../srml_balances/index.html) can be added multiple times to your
/// runtime in order to support multiple, independent currencies for your blockchain. Here is an example of how
/// you would declare such a module using the `decl_module!` macro:
///
/// ```
/// # #[macro_use]
/// # extern crate srml_support;
/// # use srml_support::dispatch::Result;
/// # use srml_system::{self as system, ensure_signed};
/// # pub struct DefaultInstance;
/// # pub trait Instance {}
/// # impl Instance for DefaultInstance {}
/// pub trait Trait<I: Instance=DefaultInstance>: system::Trait {}
///
/// decl_module! {
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin
///{}
/// }
///
/// where "Trait" is a trait describing this module's requirements for the Runtime type.
/// T::Origin is declared using a impl_outer_origin! per-module macro (which is generated by the
/// construct_runtime! macro) and automatically includes all the modules that are used by the
/// runtime (alongside with a variant called "system").
///
/// A runtime module is a collection of functions unified by a common problem domain and certain
/// shared types. The "functions" do not actually return values (see Dispatchable) and are only
/// used for side effects.
///
/// For every module an associated enum (usually "Call") is generated with every variant
/// corresponding to a function of the module. This enum implements Callable and thus its values
/// can be used as an extrinsic's payload.
///
/// The `on_initialize` and `on_finalize` functions are special, since it can either take no
/// parameters, or one parameter, which has the runtime's block number type.
///
/// ### Module with instances
///
/// decl_module! support modules with instances with the following syntax: (DefaultInstance type is
/// optionnal)
/// ```nocompile
/// pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {}
/// pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
/// // Your implementation
/// }
/// }
/// # fn main() {}
/// ```
///
/// ## Reserved Functions
///
/// The following are reserved function signatures:
///
/// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.dev/docs/event-enum).
/// The default behavior is to call `deposit_event` from the [System module](../srml_system/index.html).
/// However, you can write your own implementation for events in your runtime. To use the default behavior,
/// add `fn deposit_event<T>() = default;` to your `Module`.
///
/// The following reserved functions also take the block number (with type `T::BlockNumber`) as an optional input:
///
/// * `on_initialize`: Executes at the beginning of a block. Using this function will
/// implement the [`OnInitialize`](../sr_primitives/traits/trait.OnInitialize.html) trait.
/// * `on_finalize`: Executes at the end of a block. Using this function will
/// implement the [`OnFinalize`](../sr_primitives/traits/trait.OnFinalize.html) trait.
/// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future block
/// upon completion. Using this function will implement the
/// [`OffchainWorker`](../sr_primitives/traits/trait.OffchainWorker.html) trait.
#[macro_export]
macro_rules! decl_module {
// Macro transformations (to convert invocations with incomplete parameters to the canonical