From 25c529095cf896f07b2b497c783be2ef14cef373 Mon Sep 17 00:00:00 2001 From: Nicole Zhu Date: Tue, 23 Apr 2019 19:52:10 +0200 Subject: [PATCH] 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 * 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 --- substrate/Cargo.lock | 1 + substrate/core/sr-primitives/src/traits.rs | 4 +- substrate/srml/support/Cargo.toml | 1 + substrate/srml/support/src/dispatch.rs | 164 +++++++++++++++++---- 4 files changed, 137 insertions(+), 33 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index d2b0eb4f72..62880e324e 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -3511,6 +3511,7 @@ dependencies = [ "sr-std 1.0.0", "srml-metadata 1.0.0", "srml-support-procedural 1.0.0", + "srml-system 1.0.0", "substrate-inherents 1.0.0", ] diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index 4c9bf9f95e..3004a5e069 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -299,9 +299,9 @@ impl OnInitialize for () {} /// Off-chain computation trait. /// -/// Implementing this trait on a module allows you to perform a long-running tasks +/// Implementing this trait on a module allows you to perform long-running tasks /// that make validators generate extrinsics (either transactions or inherents) -/// with results of those long-running computations. +/// with the results of those long-running computations. /// /// NOTE: This function runs off-chain, so it can access the block state, /// but cannot preform any alterations. diff --git a/substrate/srml/support/Cargo.toml b/substrate/srml/support/Cargo.toml index 3cb358a4e1..5a6dc3d9eb 100644 --- a/substrate/srml/support/Cargo.toml +++ b/substrate/srml/support/Cargo.toml @@ -20,6 +20,7 @@ bitmask = { version = "0.5", default-features = false } [dev-dependencies] pretty_assertions = "0.6.1" +srml-system = { path = "../system", default-features = false } [features] default = ["std"] diff --git a/substrate/srml/support/src/dispatch.rs b/substrate/srml/support/src/dispatch.rs index f249d3f2bc..48db2e748e 100644 --- a/substrate/srml/support/src/dispatch.rs +++ b/substrate/srml/support/src/dispatch.rs @@ -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 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 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 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 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: system::Trait {} /// /// decl_module! { -/// pub struct Module 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, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {} +/// pub struct Module, 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() = 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