diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index e6e74460b3..3c9aaab1be 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -251,6 +251,15 @@ pub trait OnFinalise { impl OnFinalise for () {} +/// The block initialisation trait. Implementing this lets you express what should happen +/// for your module when the block is beginning (right before the first extrinsic is executed). +pub trait OnInitialise { + /// The block is being initialised. Implement to have something happen. + fn on_initialise(_n: BlockNumber) {} +} + +impl OnInitialise for () {} + macro_rules! tuple_impl { ($one:ident,) => { impl> OnFinalise for ($one,) { @@ -258,6 +267,11 @@ macro_rules! tuple_impl { $one::on_finalise(n); } } + impl> OnInitialise for ($one,) { + fn on_initialise(n: Number) { + $one::on_initialise(n); + } + } }; ($first:ident, $($rest:ident,)+) => { impl< @@ -270,6 +284,16 @@ macro_rules! tuple_impl { $($rest::on_finalise(n);)+ } } + impl< + Number: Copy, + $first: OnInitialise, + $($rest: OnInitialise),+ + > OnInitialise for ($first, $($rest),+) { + fn on_initialise(n: Number) { + $first::on_initialise(n); + $($rest::on_initialise(n);)+ + } + } tuple_impl!($($rest,)+); } } diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index c5cdf3c62d..3e8e1dc395 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -66,8 +66,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 19, - impl_version: 19, + spec_version: 20, + impl_version: 20, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index fab64a8aab..60132cd0ea 100644 Binary files a/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ diff --git a/substrate/srml/example/src/lib.rs b/substrate/srml/example/src/lib.rs index 45c33c993f..cfad2f4997 100644 --- a/substrate/srml/example/src/lib.rs +++ b/substrate/srml/example/src/lib.rs @@ -31,7 +31,8 @@ extern crate sr_io; #[cfg(test)] extern crate substrate_primitives; -// Needed for various traits. In our case, `OnFinalise`. +// Needed for various traits. In our case, `OnInitialise` and `OnFinalise` in our +// tests. extern crate sr_primitives; // Needed for deriving `Encode` and `Decode` for `RawEvent`. @@ -63,6 +64,52 @@ pub trait Trait: balances::Trait { type Event: From> + Into<::Event>; } +decl_storage! { + // A macro for the Storage trait, and its implementation, for this module. + // This allows for type-safe usage of the Substrate storage database, so you can + // keep things around between blocks. + trait Store for Module as Example { + // Any storage declarations of the form: + // `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : (= )?;` + // where `` is either: + // - `Type` (a basic value item); or + // - `map KeyType => ValueType` (a map item). + // + // Note that there are two optional modifiers for the storage type declaration. + // - `Foo: Option`: + // - `Foo::put(1); Foo::get()` returns `Some(1)`; + // - `Foo::kill(); Foo::get()` returns `None`. + // - `Foo: u32`: + // - `Foo::put(1); Foo::get()` returns `1`; + // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). + // e.g. Foo: u32; + // e.g. pub Bar get(bar): map T::AccountId => Vec<(T::Balance, u64)>; + // + // For basic value items, you'll get a type which implements + // `support::StorageValue`. For map items, you'll get a type which + // implements `support::StorageMap`. + // + // If they have a getter (`get(getter_name)`), then your module will come + // equipped with `fn getter_name() -> Type` for basic value items or + // `fn getter_name(key: KeyType) -> ValueType` for map items. + Dummy get(dummy) config(): Option; + + // this one uses the default, we'll demonstrate the usage of 'mutate' API. + Foo get(foo) config(): T::Balance; + } +} + +/// An event in this module. Events are simple means of reporting specific conditions and +/// circumstances that have happened that users, Dapps and/or chain explorers would find +/// interesting and otherwise difficult to detect. +decl_event!( + pub enum Event where B = ::Balance { + // Just a normal `enum`, here's a dummy event to ensure it compiles. + /// Dummy event, just here so there's a generic type that's used. + Dummy(B), + } +); + // The module declaration. This states the entry points that we handle. The // macro takes care of the marshalling of arguments and dispatch. // @@ -182,6 +229,12 @@ decl_module! { >::put(new_value); } + // The signature could also look like: `fn on_initialise()` + fn on_initialise(_n: T::BlockNumber) { + // Anything that needs to be done at the start of the block. + // We don't do anything here. + } + // The signature could also look like: `fn on_finalise()` fn on_finalise(_n: T::BlockNumber) { // Anything that needs to be done at the end of the block. @@ -191,52 +244,6 @@ decl_module! { } } -/// An event in this module. Events are simple means of reporting specific conditions and -/// circumstances that have happened that users, Dapps and/or chain explorers would find -/// interesting and otherwise difficult to detect. -decl_event!( - pub enum Event where B = ::Balance { - // Just a normal `enum`, here's a dummy event to ensure it compiles. - /// Dummy event, just here so there's a generic type that's used. - Dummy(B), - } -); - -decl_storage! { - // A macro for the Storage trait, and its implementation, for this module. - // This allows for type-safe usage of the Substrate storage database, so you can - // keep things around between blocks. - trait Store for Module as Example { - // Any storage declarations of the form: - // `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : (= )?;` - // where `` is either: - // - `Type` (a basic value item); or - // - `map KeyType => ValueType` (a map item). - // - // Note that there are two optional modifiers for the storage type declaration. - // - `Foo: Option`: - // - `Foo::put(1); Foo::get()` returns `Some(1)`; - // - `Foo::kill(); Foo::get()` returns `None`. - // - `Foo: u32`: - // - `Foo::put(1); Foo::get()` returns `1`; - // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). - // e.g. Foo: u32; - // e.g. pub Bar get(bar): map T::AccountId => Vec<(T::Balance, u64)>; - // - // For basic value items, you'll get a type which implements - // `support::StorageValue`. For map items, you'll get a type which - // implements `support::StorageMap`. - // - // If they have a getter (`get(getter_name)`), then your module will come - // equipped with `fn getter_name() -> Type` for basic value items or - // `fn getter_name(key: KeyType) -> ValueType` for map items. - Dummy get(dummy) config(): Option; - - // this one uses the default, we'll demonstrate the usage of 'mutate' API. - Foo get(foo) config(): T::Balance; - } -} - // The main implementation block for the module. Functions here fall into three broad // categories: // - Public interface. These are functions that are `pub` and generally fall into inspector @@ -269,7 +276,8 @@ mod tests { // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. use sr_primitives::{ - BuildStorage, traits::{BlakeTwo256, OnFinalise, IdentityLookup}, testing::{Digest, DigestItem, Header} + BuildStorage, traits::{BlakeTwo256, OnInitialise, OnFinalise, IdentityLookup}, + testing::{Digest, DigestItem, Header} }; impl_outer_origin! { @@ -334,6 +342,7 @@ mod tests { assert_eq!(Example::dummy(), None); // Check that accumulate works when we Dummy has None in it. + >::on_initialise(2); assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); assert_eq!(Example::dummy(), Some(42)); }); diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index 27595404ac..6646b229b8 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -45,7 +45,7 @@ use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::result; use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise, - MakePayment, Hash, As, Digest}; + OnInitialise, MakePayment, Hash, As, Digest}; use runtime_support::Dispatchable; use codec::{Codec, Encode}; use system::extrinsics_root; @@ -74,16 +74,16 @@ pub struct Executive< Block, Context, Payment, - Finalisation, ->(PhantomData<(System, Block, Context, Payment, Finalisation)>); + AllModules, +>(PhantomData<(System, Block, Context, Payment, AllModules)>); impl< Context: Default, System: system::Trait, Block: traits::Block, Payment: MakePayment, - Finalisation: OnFinalise, -> Executive where + AllModules: OnInitialise + OnFinalise, +> Executive where Block::Extrinsic: Checkable + Codec, >::Checked: Applyable, <>::Checked as Applyable>::Call: Dispatchable, @@ -92,6 +92,7 @@ impl< /// Start the execution of a particular block. pub fn initialise_block(header: &System::Header) { >::initialise(header.number(), header.parent_hash(), header.extrinsics_root()); + >::on_initialise(*header.number()); } fn initial_checks(block: &Block) { @@ -123,7 +124,7 @@ impl< // post-transactional book-keeping. >::note_finished_extrinsics(); - Finalisation::on_finalise(*header.number()); + >::on_finalise(*header.number()); // any final checks Self::final_checks(&header); @@ -133,7 +134,7 @@ impl< /// except state-root. pub fn finalise_block() -> System::Header { >::note_finished_extrinsics(); - Finalisation::on_finalise(>::block_number()); + >::on_finalise(>::block_number()); // setup extrinsics >::derive_extrinsics(); diff --git a/substrate/srml/support/src/dispatch.rs b/substrate/srml/support/src/dispatch.rs index e3a8e6c8e3..d7f57e1b49 100644 --- a/substrate/srml/support/src/dispatch.rs +++ b/substrate/srml/support/src/dispatch.rs @@ -86,8 +86,8 @@ impl Parameter for T where T: Codec + Clone + Eq {} /// 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_finalise` function is special, since it can either take no parameters, -/// or one parameter, which has the runtime's block number type. +/// The `on_initialise` and `on_finalise` functions are special, since it can either take no +/// parameters, or one parameter, which has the runtime's block number type. #[macro_export] macro_rules! decl_module { // Macro transformations (to convert invocations with incomplete parameters to the canonical @@ -105,6 +105,7 @@ macro_rules! decl_module { for enum $call_type where origin: $origin_type, system = system {} {} + {} [] $($t)* ); @@ -122,6 +123,7 @@ macro_rules! decl_module { for enum $call_type where origin: $origin_type, system = $system {} {} + {} [] $($t)* ); @@ -132,6 +134,7 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {} + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -143,6 +146,7 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name> for enum $call_type where origin: $origin_type, system = $system { $vis fn deposit_event $(<$dpeg>)* () = default; } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* ] $($rest)* @@ -153,6 +157,7 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {} + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -166,6 +171,7 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name> for enum $call_type where origin: $origin_type, system = $system { $vis fn deposit_event $(<$dpeg>)* ($( $param_name: $param ),* ) { $( $impl )* } } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* ] $($rest)* @@ -175,7 +181,8 @@ macro_rules! decl_module { $(#[$attr:meta])* pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident - { $( $deposit_event:tt )* } + { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } {} [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -187,6 +194,7 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } + { $( $on_initialise )* } { fn on_finalise( $( $param_name : $param ),* ) { $( $impl )* } } [ $($t)* ] $($rest)* @@ -197,6 +205,30 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + {} + { $( $on_finalise:tt )* } + [ $($t:tt)* ] + $(#[doc = $doc_attr:tt])* + fn on_initialise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name> + for enum $call_type where origin: $origin_type, system = $system + { $( $deposit_event )* } + { fn on_initialise( $( $param_name : $param ),* ) { $( $impl )* } } + { $( $on_finalise )* } + [ $($t)* ] + $($rest)* + ); + }; + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -210,6 +242,7 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* @@ -226,6 +259,7 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -245,6 +279,7 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -264,6 +299,7 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -277,6 +313,7 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* @@ -293,6 +330,7 @@ macro_rules! decl_module { pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] ) => { @@ -303,6 +341,7 @@ macro_rules! decl_module { $($t)* } { $( $deposit_event )* } + { $( $on_initialise )* } { $( $on_finalise )* } ); }; @@ -374,13 +413,47 @@ macro_rules! decl_module { } }; + (@impl_on_initialise + $module:ident<$trait_instance:ident: $trait_name:ident>; + fn on_initialise() { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name> + $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> + for $module<$trait_instance> + { + fn on_initialise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + } + }; + + (@impl_on_initialise + $module:ident<$trait_instance:ident: $trait_name:ident>; + fn on_initialise($param:ident : $param_ty:ty) { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name> + $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> + for $module<$trait_instance> + { + fn on_initialise($param: $param_ty) { $( $impl )* } + } + }; + + (@impl_on_initialise + $module:ident<$trait_instance:ident: $trait_name:ident>; + ) => { + impl<$trait_instance: $trait_name> + $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> + for $module<$trait_instance> + {} + }; + (@impl_on_finalise $module:ident<$trait_instance:ident: $trait_name:ident>; fn on_finalise() { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name> $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> { + for $module<$trait_instance> + { fn on_finalise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } } }; @@ -391,7 +464,8 @@ macro_rules! decl_module { ) => { impl<$trait_instance: $trait_name> $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> { + for $module<$trait_instance> + { fn on_finalise($param: $param_ty) { $( $impl )* } } }; @@ -401,7 +475,9 @@ macro_rules! decl_module { ) => { impl<$trait_instance: $trait_name> $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> {} + for $module<$trait_instance> + { + } }; (@impl_function @@ -480,6 +556,7 @@ macro_rules! decl_module { )* } { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -497,6 +574,12 @@ macro_rules! decl_module { #[cfg(not(feature = "std"))] pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>); + decl_module! { + @impl_on_initialise + $mod_type<$trait_instance: $trait_name>; + $( $on_initialise )* + } + decl_module! { @impl_on_finalise $mod_type<$trait_instance: $trait_name>; @@ -972,10 +1055,11 @@ macro_rules! __function_to_metadata { #[allow(dead_code)] mod tests { use super::*; + use crate::runtime_primitives::traits::{OnInitialise, OnFinalise}; pub trait Trait { type Origin; - type BlockNumber; + type BlockNumber: Into; } pub mod system { @@ -994,6 +1078,9 @@ mod tests { fn aux_2(_origin, _data: i32, _data2: String) -> Result { unreachable!() } fn aux_3() -> Result { unreachable!() } fn aux_4(_data: i32) -> Result { unreachable!() } + + fn on_initialise(n: T::BlockNumber) { if n.into() == 42 { panic!("on_initialise") } } + fn on_finalise(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalise") } } } } @@ -1065,4 +1152,16 @@ mod tests { let encoded = call.encode(); assert_eq!(encoded.len(), 2); } + + #[test] + #[should_panic(expected = "on_initialise")] + fn on_initialise_should_work() { + as OnInitialise>::on_initialise(42); + } + + #[test] + #[should_panic(expected = "on_finalise")] + fn on_finalise_should_work() { + as OnFinalise>::on_finalise(42); + } }