Add OnInitialise handler. (#1690)

* Add OnInitialise handler.

Closes #1686

* Fix typo

* Fix wasm build

* Add tests for initialise and finalise.
This commit is contained in:
Gav Wood
2019-02-06 10:01:28 +01:00
committed by Bastian Köcher
parent 0eeef28382
commit fa2e323478
6 changed files with 197 additions and 64 deletions
+57 -48
View File
@@ -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<Event<Self>> + Into<<Self as system::Trait>::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<T: Trait> as Example {
// Any storage declarations of the form:
// `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : <type> (= <new_default_value>)?;`
// where `<type>` 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<u32>`:
// - `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<T::Balance>;
// 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<T> where B = <T as balances::Trait>::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! {
<Dummy<T>>::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<T> where B = <T as balances::Trait>::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<T: Trait> as Example {
// Any storage declarations of the form:
// `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : <type> (= <new_default_value>)?;`
// where `<type>` 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<u32>`:
// - `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<T::Balance>;
// 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.
<Example as OnInitialise<u64>>::on_initialise(2);
assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42));
assert_eq!(Example::dummy(), Some(42));
});