diff --git a/substrate/substrate/client/src/client.rs b/substrate/substrate/client/src/client.rs index fff747296b..963d165b1f 100644 --- a/substrate/substrate/client/src/client.rs +++ b/substrate/substrate/client/src/client.rs @@ -802,6 +802,9 @@ mod tests { client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - assert_eq!(client.json_metadata(&BlockId::Number(1)).unwrap(), r#"{ "events": "events" }"#); + assert_eq!( + client.json_metadata(&BlockId::Number(1)).unwrap(), + r#"{ "events": { "name": "Test", "events": { "event": hallo } } }"# + ); } } diff --git a/substrate/substrate/runtime-support/src/event.rs b/substrate/substrate/runtime-support/src/event.rs index 9249c7ed0e..a9767f51bf 100644 --- a/substrate/substrate/runtime-support/src/event.rs +++ b/substrate/substrate/runtime-support/src/event.rs @@ -14,6 +14,123 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +/// Implement an `Event`/`RawEvent` for a module. +#[macro_export] +macro_rules! decl_event { + ( + $(#[$attr:meta])* + pub enum Event<$( $evt_generic_param:ident )*> with RawEvent<$( $generic_param:ident ),*> + where $( <$generic:ident as $trait:path>::$trait_type:ident),* { + $( + $(#[doc = $doc_attr:tt])* + $event:ident( $( $param:path ),* ), + )* + } + ) => { + pub type Event<$( $evt_generic_param )*> = RawEvent<$( <$generic as $trait>::$trait_type ),*>; + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, PartialEq, Eq, Encode, Decode)] + #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] + $(#[$attr])* + pub enum RawEvent<$( $generic_param ),*> { + $( + $( #[doc = $doc_attr] )* + $event($( $param ),*), + )* + } + impl<$( $generic_param ),*> From> for () { + fn from(_: RawEvent<$( $generic_param ),*>) -> () { () } + } + impl<$( $generic_param ),*> RawEvent<$( $generic_param ),*> { + #[allow(dead_code)] + pub fn event_json_metadata() -> &'static str { + concat!( + "{", + __impl_event_json_metadata!(""; + $( + $event ( $( $param ),* ); + __function_doc_to_json!(""; $($doc_attr)*); + )* + ), + " }" + ) + } + } + }; + ( + $(#[$attr:meta])* + pub enum Event { + $( + $(#[doc = $doc_attr:tt])* + $event:ident, + )* + } + ) => { + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, PartialEq, Eq, Encode, Decode)] + #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] + $(#[$attr])* + pub enum Event { + $( + $( #[doc = $doc_attr] )* + $event, + )* + } + impl From for () { + fn from(_: Event) -> () { () } + } + impl Event { + #[allow(dead_code)] + pub fn event_json_metadata() -> &'static str { + concat!( + "{", + __impl_event_json_metadata!(""; + $( + $event; + __function_doc_to_json!(""; $($doc_attr)*); + )* + ), + " }" + ) + } + } + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_event_json_metadata { + ( + $prefix_str:expr; + $event:ident( $first_param:path $(, $param:path )* ); + $event_doc:expr; + $( $rest:tt )* + ) => { + concat!($prefix_str, " ", "\"", stringify!($event), r#"": { "params": [ ""#, + stringify!($first_param), "\"" + $(, concat!(", \"", stringify!($param), "\"") )*, r#" ], "description": ["#, + $event_doc, " ] }", + __impl_event_json_metadata!(","; $( $rest )*) + ) + }; + ( + $prefix_str:expr; + $event:ident; + $event_doc:expr; + $( $rest:tt )* + ) => { + concat!($prefix_str, " ", "\"", stringify!($event), + r#"": { "params": null, "description": ["#, $event_doc, " ] }", + __impl_event_json_metadata!(","; $( $rest )*) + ) + }; + ( + $prefix_str:expr; + ) => { + "" + } +} + #[macro_export] macro_rules! impl_outer_event { ($(#[$attr:meta])* pub enum $name:ident for $runtime:ident { $( $module:ident ),* }) => { @@ -54,39 +171,84 @@ macro_rules! __impl_outer_event_json_metadata { ) => { impl $runtime { #[allow(dead_code)] - pub fn outer_event_json_metadata() -> &'static str { - concat!(r#"{ "name": ""#, stringify!($event_name), r#"", "items": { "#, - r#""system": "system::Event""#, - $(concat!(", \"", stringify!($module), r#"": ""#, - stringify!($module), "::Event<", stringify!($runtime), r#">""#),)* - " } }") + pub fn outer_event_json_metadata() -> (&'static str, &'static [(&'static str, fn() -> &'static str)]) { + static METADATA: &[(&str, fn() -> &'static str)] = &[ + ("system", system::Event::event_json_metadata) + $( + , ( + stringify!($module), + $module::Event::<$runtime>::event_json_metadata + ) + )* + ]; + ( + stringify!($event_name), + METADATA + ) } } } } #[cfg(test)] +#[allow(dead_code)] mod tests { use serde; use serde_json; mod system { - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] - pub struct Event; + pub trait Trait { + type Origin; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + pub enum Event { + SystemEvent, + } + ); } mod event_module { - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] - pub struct Event { - t: T, + pub trait Trait { + type Origin; + type Balance; } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + pub enum Event with RawEvent + where ::Balance + { + /// Hi, I am a comment. + TestEvent(Balance), + } + ); } mod event_module2 { - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] - pub struct Event { - t: T, + pub trait Trait { + type Origin; + type Balance; } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + pub enum Event with RawEvent + where ::Balance + { + TestEvent(Balance), + } + ); } #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] @@ -98,19 +260,39 @@ mod tests { } } - const EXPECTED_METADATA: &str = concat!( - r#"{ "name": "TestEvent", "items": { "#, - r#""system": "system::Event", "#, - r#""event_module": "event_module::Event", "#, - r#""event_module2": "event_module2::Event" "#, - r#"} }"# + impl event_module::Trait for TestRuntime { + type Origin = u32; + type Balance = u32; + } + + impl event_module2::Trait for TestRuntime { + type Origin = u32; + type Balance = u32; + } + + impl system::Trait for TestRuntime { + type Origin = u32; + } + + const EXPECTED_METADATA: (&str, &[(&str, &str)]) = ( + "TestEvent", &[ + ("system", r#"{ "SystemEvent": { "params": null, "description": [ ] } }"#), + ("event_module", r#"{ "TestEvent": { "params": [ "Balance" ], "description": [ " Hi, I am a comment." ] } }"#), + ("event_module2", r#"{ "TestEvent": { "params": [ "Balance" ], "description": [ ] } }"#), + ] ); #[test] fn outer_event_json_metadata() { let metadata = TestRuntime::outer_event_json_metadata(); - assert_eq!(EXPECTED_METADATA, metadata); - let _: serde::de::IgnoredAny = - serde_json::from_str(metadata).expect("Is valid json syntax"); + assert_eq!(EXPECTED_METADATA.0, metadata.0); + assert_eq!(EXPECTED_METADATA.1.len(), metadata.1.len()); + + for (expected, got) in EXPECTED_METADATA.1.iter().zip(metadata.1.iter()) { + assert_eq!(expected.0, got.0); + assert_eq!(expected.1, got.1()); + let _: serde::de::IgnoredAny = + serde_json::from_str(got.1()).expect(&format!("Is valid json syntax: {}", got.1())); + } } } diff --git a/substrate/substrate/runtime-support/src/metadata.rs b/substrate/substrate/runtime-support/src/metadata.rs index 69c6383ace..12953871d3 100644 --- a/substrate/substrate/runtime-support/src/metadata.rs +++ b/substrate/substrate/runtime-support/src/metadata.rs @@ -40,9 +40,11 @@ macro_rules! impl_json_metadata { ) => { impl $runtime { pub fn json_metadata() -> $crate::metadata::Vec<$crate::metadata::JSONMetadata> { + let events = Self::outer_event_json_metadata(); __impl_json_metadata!($runtime; $crate::metadata::JSONMetadata::Events { - events: Self::outer_event_json_metadata() + name: events.0, + events: events.1, }; $( $rest )* ) @@ -52,10 +54,10 @@ macro_rules! impl_json_metadata { } /// The metadata of a runtime encoded as JSON. -#[derive(Eq, PartialEq)] +#[derive(Eq)] #[cfg_attr(feature = "std", derive(Debug))] pub enum JSONMetadata { - Events { events: &'static str }, + Events { name: &'static str, events: &'static [(&'static str, fn() -> &'static str)] }, Module { module: &'static str, prefix: &'static str }, ModuleWithStorage { module: &'static str, prefix: &'static str, storage: &'static str } } @@ -63,9 +65,14 @@ pub enum JSONMetadata { impl Encode for JSONMetadata { fn encode_to(&self, dest: &mut W) { match self { - JSONMetadata::Events { events } => { + JSONMetadata::Events { name, events } => { 0i8.encode_to(dest); - events.encode_to(dest); + name.encode_to(dest); + events.iter().fold(0u32, |count, _| count + 1).encode_to(dest); + events + .iter() + .map(|(module, data)| (module, data())) + .for_each(|val| val.encode_to(dest)); }, JSONMetadata::Module { module, prefix } => { 1i8.encode_to(dest); @@ -82,11 +89,39 @@ impl Encode for JSONMetadata { } } +impl PartialEq for JSONMetadata { + fn eq(&self, other: &JSONMetadata) -> bool { + match (self, other) { + ( + JSONMetadata::Events { name: lname, events: left }, + JSONMetadata::Events { name: rname, events: right } + ) => { + lname == rname && left.iter().zip(right.iter()).fold(true, |res, (l, r)| { + res && l.0 == r.0 && l.1() == r.1() + }) + }, + ( + JSONMetadata::Module { prefix: lpre, module: lmod }, + JSONMetadata::Module { prefix: rpre, module: rmod } + ) => { + lpre == rpre && lmod == rmod + }, + ( + JSONMetadata::ModuleWithStorage { prefix: lpre, module: lmod, storage: lstore }, + JSONMetadata::ModuleWithStorage { prefix: rpre, module: rmod, storage: rstore } + ) => { + lpre == rpre && lmod == rmod && lstore == rstore + }, + _ => false, + } + } +} + /// Utility struct for making `JSONMetadata` decodeable. #[derive(Eq, PartialEq, Debug)] #[cfg(feature = "std")] pub enum JSONMetadataDecodable { - Events { events: String }, + Events { name: String, events: Vec<(String, String)> }, Module { module: String, prefix: String }, ModuleWithStorage { module: String, prefix: String, storage: String } } @@ -97,15 +132,33 @@ impl JSONMetadataDecodable { /// The first value of the tuple is the name of the metadata type and the second in the JSON string. pub fn into_json_string(self) -> (&'static str, String) { match self { - JSONMetadataDecodable::Events { events } => { - ("events", events) + JSONMetadataDecodable::Events { name, events } => { + ( + "events", + format!( + r#"{{ "name": "{}", "events": {{ {} }} }}"#, name, + events.iter().enumerate() + .fold(String::from(""), |mut json, (i, (name, data))| { + if i > 0 { + json.push_str(", "); + } + json.push_str(&format!(r#""{}": {}"#, name, data)); + json + }) + ) + ) }, JSONMetadataDecodable::Module { prefix, module } => { ("module", format!(r#"{{ "prefix": "{}", "module": {} }}"#, prefix, module)) }, JSONMetadataDecodable::ModuleWithStorage { prefix, module, storage } => { - ("moduleWithStorage", - format!(r#"{{ "prefix": "{}", "module": {}, "storage": {} }}"#, prefix, module, storage)) + ( + "moduleWithStorage", + format!( + r#"{{ "prefix": "{}", "module": {}, "storage": {} }}"#, + prefix, module, storage + ) + ) } } } @@ -117,7 +170,8 @@ impl Decode for JSONMetadataDecodable { i8::decode(input).and_then(|variant| { match variant { 0 => String::decode(input) - .and_then(|events| Some(JSONMetadataDecodable::Events { events })), + .and_then(|name| Vec::<(String, String)>::decode(input).map(|events| (name, events))) + .and_then(|(name, events)| Some(JSONMetadataDecodable::Events { name, events })), 1 => String::decode(input) .and_then(|prefix| String::decode(input).map(|v| (prefix, v))) .and_then(|(prefix, module)| Some(JSONMetadataDecodable::Module { prefix, module })), @@ -136,10 +190,12 @@ impl PartialEq for JSONMetadataDecodable { fn eq(&self, other: &JSONMetadata) -> bool { match (self, other) { ( - JSONMetadataDecodable::Events { events: left }, - JSONMetadata::Events { events: right } + JSONMetadataDecodable::Events { name: lname, events: left }, + JSONMetadata::Events { name: rname, events: right } ) => { - left == right + lname == rname && left.iter().zip(right.iter()).fold(true, |res, (l, r)| { + res && l.0 == r.0 && l.1 == r.1() + }) }, ( JSONMetadataDecodable::Module { prefix: lpre, module: lmod }, @@ -228,21 +284,42 @@ macro_rules! __impl_json_metadata { #[allow(dead_code)] mod tests { use super::*; - use dispatch::Result; + use serde; + use serde_json; mod system { - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] - pub struct Event; + pub trait Trait { + type Origin; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + pub enum Event { + SystemEvent, + } + ); } mod event_module { - use super::*; + use dispatch::Result; - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] - pub struct Event { - t: T, + pub trait Trait { + type Origin; + type Balance; } + decl_event!( + pub enum Event with RawEvent + where ::Balance + { + /// Hi, I am a comment. + TestEvent(Balance), + } + ); + decl_module! { pub struct Module for enum Call where origin: T::Origin { fn aux_0(origin) -> Result; @@ -257,13 +334,19 @@ mod tests { } mod event_module2 { - use super::*; - - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)] - pub struct Event { - t: T, + pub trait Trait { + type Origin; + type Balance; } + decl_event!( + pub enum Event with RawEvent + where ::Balance + { + TestEvent(Balance), + } + ); + decl_module! { pub struct ModuleWithStorage for enum Call where origin: T::Origin {} } @@ -284,11 +367,17 @@ mod tests { } } - pub trait Trait { - type Origin; + impl event_module::Trait for TestRuntime { + type Origin = u32; + type Balance = u32; } - impl Trait for TestRuntime { + impl event_module2::Trait for TestRuntime { + type Origin = u32; + type Balance = u32; + } + + impl system::Trait for TestRuntime { type Origin = u32; } @@ -298,13 +387,26 @@ mod tests { event_module2::ModuleWithStorage with Storage ); + fn system_event_json() -> &'static str { + r#"{ "SystemEvent": { "params": null, "description": [ ] } }"# + } + + fn event_module_event_json() -> &'static str { + r#"{ "TestEvent": { "params": [ "Balance" ], "description": [ " Hi, I am a comment." ] } }"# + } + + fn event_module2_event_json() -> &'static str { + r#"{ "TestEvent": { "params": [ "Balance" ], "description": [ ] } }"# + } + const EXPECTED_METADATA: &[JSONMetadata] = &[ JSONMetadata::Events { - events: concat!( - r#"{ "name": "TestEvent", "items": "#, - r#"{ "system": "system::Event", "#, - r#""event_module": "event_module::Event", "#, - r#""event_module2": "event_module2::Event" } }"#) + name: "TestEvent", + events: &[ + ("system", system_event_json), + ("event_module", event_module_event_json), + ("event_module2", event_module2_event_json), + ] }, JSONMetadata::Module { module: concat!( @@ -341,4 +443,17 @@ mod tests { assert_eq!(&metadata_decoded.unwrap()[..], &metadata[..]); } + + #[test] + fn into_json_string_is_valid_json() { + let metadata = TestRuntime::json_metadata(); + let metadata_encoded = metadata.encode(); + let metadata_decoded = Vec::::decode(&mut &metadata_encoded[..]); + + for mdata in metadata_decoded.unwrap().into_iter() { + let json = mdata.into_json_string(); + let _: serde::de::IgnoredAny = + serde_json::from_str(&json.1).expect(&format!("Is valid json syntax: {}", json.1)); + } + } } diff --git a/substrate/substrate/runtime/balances/src/lib.rs b/substrate/substrate/runtime/balances/src/lib.rs index a35ec3227f..3451b55f6a 100644 --- a/substrate/substrate/runtime/balances/src/lib.rs +++ b/substrate/substrate/runtime/balances/src/lib.rs @@ -67,12 +67,6 @@ const RECLAIM_INDEX_MAGIC: usize = 0x69; pub type Address = RawAddress<::AccountId, ::AccountIndex>; -pub type Event = RawEvent< - ::AccountId, - ::AccountIndex, - ::Balance, ->; - /// The account with the given id was killed. pub trait OnFreeBalanceZero { /// The account was the given id was killed. @@ -130,7 +124,7 @@ pub trait Trait: system::Trait { /// A function that returns true iff a given account can transfer its funds to another account. type EnsureAccountLiquid: EnsureAccountLiquid; - /// The overarching event type. + /// The overarching event type. type Event: From> + Into<::Event>; } @@ -141,21 +135,17 @@ decl_module! { } } -/// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// A new account was created. - NewAccount(AccountId, AccountIndex, NewAccountOutcome), - /// An account was reaped. - ReapedAccount(AccountId), - /// Transfer succeeded (from, to, value, fees). - Transfer(AccountId, AccountId, Balance, Balance), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::AccountId, ::AccountIndex, ::Balance { + /// A new account was created. + NewAccount(AccountId, AccountIndex, NewAccountOutcome), + /// An account was reaped. + ReapedAccount(AccountId), + /// Transfer succeeded (from, to, value, fees). + Transfer(AccountId, AccountId, Balance, Balance), + } +); decl_storage! { trait Store for Module as Balances { @@ -313,7 +303,7 @@ impl Module { }; if transactor != dest { - Self::set_free_balance(&transactor, new_from_balance); + Self::set_free_balance(&transactor, new_from_balance); Self::decrease_total_stake_by(fee); Self::set_free_balance_creating(&dest, new_to_balance); Self::deposit_event(RawEvent::Transfer(transactor, dest, value, fee)); @@ -400,7 +390,7 @@ impl Module { }; Self::set_free_balance(who, credit); Self::increase_total_stake_by(credit - balance); - } else { + } else { Self::set_free_balance(who, balance); } diff --git a/substrate/substrate/runtime/council/src/motions.rs b/substrate/substrate/runtime/council/src/motions.rs index 47d85cbf58..b9b26df00f 100644 --- a/substrate/substrate/runtime/council/src/motions.rs +++ b/substrate/substrate/runtime/council/src/motions.rs @@ -39,7 +39,7 @@ pub trait Trait: CouncilTrait + MaybeSerializeDebug { type Event: From> + Into<::Event>; } -/// Origin for the council module. +/// Origin for the council module. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] pub enum Origin { @@ -47,29 +47,24 @@ pub enum Origin { Members(u32), } -/// Outwardly visible event. -pub type Event = RawEvent<::Hash, ::AccountId>; - /// Event for this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// A motion (given hash) has been proposed (by given account) with a threshold (given u32). - Proposed(AccountId, ProposalIndex, Hash, u32), - /// A motion (given hash) has been voted on by given account, leaving - /// a tally (yes votes and no votes given as u32s respectively). - Voted(AccountId, Hash, bool, u32, u32), - /// A motion was approved by the required threshold. - Approved(Hash), - /// A motion was not approved by the required threshold. - Disapproved(Hash), - /// A motion was executed; `bool` is true if returned without error. - Executed(Hash, bool), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::Hash, ::AccountId + { + /// A motion (given hash) has been proposed (by given account) with a threshold (given u32). + Proposed(AccountId, ProposalIndex, Hash, u32), + /// A motion (given hash) has been voted on by given account, leaving + /// a tally (yes votes and no votes given as u32s respectively). + Voted(AccountId, Hash, bool, u32, u32), + /// A motion was approved by the required threshold. + Approved(Hash), + /// A motion was not approved by the required threshold. + Disapproved(Hash), + /// A motion was executed; `bool` is true if returned without error. + Executed(Hash, bool), + } +); decl_module! { #[cfg_attr(feature = "std", serde(bound(deserialize = "::Proposal: ::serde::de::DeserializeOwned")))] diff --git a/substrate/substrate/runtime/council/src/seats.rs b/substrate/substrate/runtime/council/src/seats.rs index 6673427404..b98a655fbd 100644 --- a/substrate/substrate/runtime/council/src/seats.rs +++ b/substrate/substrate/runtime/council/src/seats.rs @@ -154,25 +154,21 @@ decl_storage! { } } -pub type Event = RawEvent<::AccountId>; - -/// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// reaped voter, reaper - VoterReaped(AccountId, AccountId), - /// slashed reaper - BadReaperSlashed(AccountId), - /// A tally (for approval votes of council seat(s)) has started. - TallyStarted(u32), - /// A tally (for approval votes of council seat(s)) has ended (with one or more new members). - TallyFinalised(Vec, Vec), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + /// An event in this module. + pub enum Event with RawEvent + where ::AccountId + { + /// reaped voter, reaper + VoterReaped(AccountId, AccountId), + /// slashed reaper + BadReaperSlashed(AccountId), + /// A tally (for approval votes of council seat(s)) has started. + TallyStarted(u32), + /// A tally (for approval votes of council seat(s)) has ended (with one or more new members). + TallyFinalised(Vec, Vec), + } +); impl Module { @@ -235,7 +231,7 @@ impl Module { /// are registered. fn set_approvals(origin: T::Origin, votes: Vec, index: VoteIndex) -> Result { let who = ensure_signed(origin)?; - + ensure!(!Self::presentation_active(), "no approval changes during presentation period"); ensure!(index == Self::vote_index(), "incorrect vote index"); if !>::exists(&who) { @@ -267,7 +263,7 @@ impl Module { assumed_vote_index: VoteIndex ) -> Result { let reporter = ensure_signed(origin)?; - + let who = >::lookup(who)?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_last_active(&reporter).is_some(), "reporter must be a voter"); @@ -310,7 +306,7 @@ impl Module { /// Remove a voter. All votes are cancelled and the voter deposit is returned. fn retract_voter(origin: T::Origin, index: u32) -> Result { let who = ensure_signed(origin)?; - + ensure!(!Self::presentation_active(), "cannot retract when presenting"); ensure!(>::exists(&who), "cannot retract non-voter"); let voters = Self::voters(); @@ -328,7 +324,7 @@ impl Module { /// Account must have enough transferrable funds in it to pay the bond. fn submit_candidacy(origin: T::Origin, slot: u32) -> Result { let who = ensure_signed(origin)?; - + ensure!(!Self::is_a_candidate(&who), "duplicate candidate submission"); let slot = slot as usize; let count = Self::candidate_count() as usize; @@ -1356,4 +1352,4 @@ mod tests { assert_eq!(Council::candidate_reg_info(4), Some((0, 3))); }); } -} \ No newline at end of file +} diff --git a/substrate/substrate/runtime/council/src/voting.rs b/substrate/substrate/runtime/council/src/voting.rs index a024413654..450eb034f1 100644 --- a/substrate/substrate/runtime/council/src/voting.rs +++ b/substrate/substrate/runtime/council/src/voting.rs @@ -53,21 +53,19 @@ decl_storage! { } } -pub type Event = RawEvent<::Hash>; - /// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// A voting tally has happened for a referendum cancelation vote. Last three are yes, no, abstain counts. - TallyCancelation(Hash, u32, u32, u32), - /// A voting tally has happened for a referendum vote. Last three are yes, no, abstain counts. - TallyReferendum(Hash, u32, u32, u32), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::Hash + { + /// A voting tally has happened for a referendum cancelation vote. + /// Last three are yes, no, abstain counts. + TallyCancelation(Hash, u32, u32, u32), + /// A voting tally has happened for a referendum vote. + /// Last three are yes, no, abstain counts. + TallyReferendum(Hash, u32, u32, u32), + } +); impl Module { diff --git a/substrate/substrate/runtime/democracy/src/lib.rs b/substrate/substrate/runtime/democracy/src/lib.rs index b9bb2f3802..cd540d5ed3 100644 --- a/substrate/substrate/runtime/democracy/src/lib.rs +++ b/substrate/substrate/runtime/democracy/src/lib.rs @@ -108,26 +108,19 @@ decl_storage! { } } -/// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - Tabled(PropIndex, Balance, Vec), - Started(ReferendumIndex, VoteThreshold), - Passed(ReferendumIndex), - NotPassed(ReferendumIndex), - Cancelled(ReferendumIndex), - Executed(ReferendumIndex, bool), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} - -pub type Event = RawEvent< - ::Balance, - ::AccountId, ->; +decl_event!( + /// An event in this module. + pub enum Event with RawEvent + where ::Balance, ::AccountId + { + Tabled(PropIndex, Balance, Vec), + Started(ReferendumIndex, VoteThreshold), + Passed(ReferendumIndex), + NotPassed(ReferendumIndex), + Cancelled(ReferendumIndex), + Executed(ReferendumIndex, bool), + } +); impl Module { diff --git a/substrate/substrate/runtime/example/src/lib.rs b/substrate/substrate/runtime/example/src/lib.rs index a195f8e2ea..fee47239ae 100644 --- a/substrate/substrate/runtime/example/src/lib.rs +++ b/substrate/substrate/runtime/example/src/lib.rs @@ -65,10 +65,10 @@ use system::{ensure_signed, ensure_root}; /// Our module's configuration trait. All our types and consts go in here. If the /// module is dependent on specific other modules, then their configuration traits /// should be added to our implied traits list. -/// +/// /// `system::Trait` should always be included in our implied traits. pub trait Trait: balances::Trait { - /// The overarching event type. + /// The overarching event type. type Event: From> + Into<::Event>; } @@ -87,12 +87,12 @@ pub trait Trait: balances::Trait { // // Information about where this dispatch initiated from is provided as the first argument // "origin". As such functions must always look like: -// +// // `fn foo(origin, bar: Bar, baz: Baz) -> Result = 0;` // // The `Result` is required as part of the syntax (and expands to the conventional dispatch // result of `Result<(), &'static str>`). -// +// // When you come to `impl` them later in the module, you must specify the full type for `origin`: // // `fn foo(origin: T::Origin, bar: Bar, baz: Baz) { ... }` @@ -101,7 +101,7 @@ pub trait Trait: balances::Trait { // to the above bullets: `::Signed(AccountId)`, `::Root` and `::Inherent`. You should always match // against them as the first thing you do in your function. There are three convenience calls // in system that do the matching for you and return a convenient result: `ensure_signed`, -// `ensure_root` and `ensure_inherent`. +// `ensure_root` and `ensure_inherent`. decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. pub struct Module for enum Call where origin: T::Origin { @@ -117,31 +117,18 @@ decl_module! { } } -/// Exported Event type that's generic over the configuration trait. -// NOTE: External macro-fu expects this type to exist and be generic over -// the configuration trait. -pub type Event = RawEvent< - ::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. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - // 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), -} - -// By convention we implement any trait for which a "null implementation" makes sense -// for `()`. This is the case for conversion of module `Event` types and hook traits. It -// is helpful for test code and production configurations where no eventing is necessary -// or the hook is unused. -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::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. @@ -205,15 +192,15 @@ impl Module { // // - MUST NOT PANIC: Under no circumstances (save, perhaps, storage getting into an // irreparably damaged state) must this function panic. - // - NO SIDE-EFFECTS ON ERROR: This function must either complete totally (and return + // - NO SIDE-EFFECTS ON ERROR: This function must either complete totally (and return // `Ok(())` or it must have no side-effects on storage and return `Err('Some reason')`. // // The first is relatively easy to audit for - just ensure all panickers are removed from - // logic that executes in production (which you do anyway, right?!). To ensure the second + // logic that executes in production (which you do anyway, right?!). To ensure the second // is followed, you should do all tests for validity at the top of your function. This // is stuff like checking the sender (`origin`) or that state is such that the operation // makes sense. - // + // // Once you've determined that it's all good, then enact the operation and change storage. // If you can't be certain that the operation will succeed without substantial computation // then you have a classic blockchain attack scenario. The normal way of managing this is @@ -322,10 +309,10 @@ impl Default for GenesisConfig { // This expresses the specific key/value pairs that must be placed in storage in order // to initialise the module and properly reflect the configuration. -// +// // Ideally this would re-use the `::put` logic in the storage item type for introducing // the values into the `StorageMap` (which is just a `HashMap, Vec>`). That -// is not yet in place, though, so for now we do everything "manually", using `hash`, +// is not yet in place, though, so for now we do everything "manually", using `hash`, // `::key()` and `.to_vec()` for the key and `.encode()` for the value. #[cfg(feature = "std")] impl runtime_primitives::BuildStorage for GenesisConfig diff --git a/substrate/substrate/runtime/session/src/lib.rs b/substrate/substrate/runtime/session/src/lib.rs index 5338b85272..ccbb9a9890 100644 --- a/substrate/substrate/runtime/session/src/lib.rs +++ b/substrate/substrate/runtime/session/src/lib.rs @@ -73,8 +73,6 @@ pub trait Trait: timestamp::Trait { type Event: From> + Into<::Event>; } -pub type Event = RawEvent<::BlockNumber>; - decl_module! { pub struct Module for enum Call where origin: T::Origin { fn set_key(origin, key: T::SessionKey) -> Result; @@ -85,17 +83,15 @@ decl_module! { } /// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// New session has happened. Note that the argument is the session index, not the block number - /// as the type might suggest. - NewSession(BlockNumber), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::BlockNumber + { + /// New session has happened. Note that the argument is the session index, not the block + /// number as the type might suggest. + NewSession(BlockNumber), + } +); decl_storage! { trait Store for Module as Session { diff --git a/substrate/substrate/runtime/staking/src/lib.rs b/substrate/substrate/runtime/staking/src/lib.rs index 6a0d19deef..f9737d6a3c 100644 --- a/substrate/substrate/runtime/staking/src/lib.rs +++ b/substrate/substrate/runtime/staking/src/lib.rs @@ -6,6 +6,8 @@ // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. + + // Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -64,11 +66,6 @@ pub use genesis_config::GenesisConfig; const DEFAULT_MINIMUM_VALIDATOR_COUNT: usize = 4; -pub type Event = RawEvent< - ::Balance, - ::AccountId ->; - #[derive(PartialEq, Clone)] #[cfg_attr(test, derive(Debug))] pub enum LockStatus { @@ -100,7 +97,7 @@ pub trait Trait: balances::Trait + session::Trait { /// Some tokens minted. type OnRewardMinted: OnDilution<::Balance>; - /// The overarching event type. + /// The overarching event type. type Event: From> + Into<::Event>; } @@ -122,20 +119,19 @@ decl_module! { } /// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// All validators have been rewarded by the given balance. - Reward(Balance), - /// One validator (and their nominators) has been given a offline-warning (they're still within - /// their grace). The accrued number of slashes is recorded, too. - OfflineWarning(AccountId, u32), - /// One validator (and their nominators) has been slashed by the given amount. - OfflineSlash(AccountId, Balance), -} -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::Balance, ::AccountId + { + /// All validators have been rewarded by the given balance. + Reward(Balance), + /// One validator (and their nominators) has been given a offline-warning (they're still + /// within their grace). The accrued number of slashes is recorded, too. + OfflineWarning(AccountId, u32), + /// One validator (and their nominators) has been slashed by the given amount. + OfflineSlash(AccountId, Balance), + } +); pub type PairOf = (T, T); @@ -307,8 +303,8 @@ impl Module { Ok(()) } - /// Set the given account's preference for slashing behaviour should they be a validator. - /// + /// Set the given account's preference for slashing behaviour should they be a validator. + /// /// An error (no-op) if `Self::intentions()[intentions_index] != origin`. fn register_preferences( origin: T::Origin, @@ -320,7 +316,7 @@ impl Module { if Self::intentions().get(intentions_index as usize) != Some(&who) { return Err("Invalid index") } - + >::insert(who, prefs); Ok(()) diff --git a/substrate/substrate/runtime/system/src/lib.rs b/substrate/substrate/runtime/system/src/lib.rs index 7053bfcdf2..1df27352bb 100644 --- a/substrate/substrate/runtime/system/src/lib.rs +++ b/substrate/substrate/runtime/system/src/lib.rs @@ -110,21 +110,17 @@ pub struct EventRecord { pub event: E, } -/// Event for the system module. -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub enum Event { - /// An extrinsic completed successfully. - ExtrinsicSuccess, - /// An extrinsic failed. - ExtrinsicFailed, -} +/// Event for the system module. +decl_event!( + pub enum Event { + /// An extrinsic completed successfully. + ExtrinsicSuccess, + /// An extrinsic failed. + ExtrinsicFailed, + } +); -impl From for () { - fn from(_: Event) -> () { () } -} - -/// Origin for the system module. +/// Origin for the system module. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] pub enum RawOrigin { @@ -388,7 +384,7 @@ mod tests { impl From for u16 { fn from(e: Event) -> u16 { - match e { + match e { Event::ExtrinsicSuccess => 100, Event::ExtrinsicFailed => 101, } diff --git a/substrate/substrate/runtime/treasury/src/lib.rs b/substrate/substrate/runtime/treasury/src/lib.rs index 6826782a54..0aac4c3f9d 100644 --- a/substrate/substrate/runtime/treasury/src/lib.rs +++ b/substrate/substrate/runtime/treasury/src/lib.rs @@ -51,7 +51,7 @@ use system::{ensure_signed, ensure_root}; /// Our module's configuration trait. All our types and consts go in here. If the /// module is dependent on specific other modules, then their configuration traits /// should be added to our implied traits list. -/// +/// /// `system::Trait` should always be included in our implied traits. pub trait Trait: balances::Trait { /// Origin from which approvals must come. @@ -60,7 +60,7 @@ pub trait Trait: balances::Trait { /// Origin from which rejections must come. type RejectOrigin: EnsureOrigin; - /// The overarching event type. + /// The overarching event type. type Event: From> + Into<::Event>; } @@ -108,7 +108,7 @@ decl_storage! { /// Proportion of funds that should be bonded in order to place a proposal. An accepted /// proposal gets these back. A rejected proposal doesn't. ProposalBond get(proposal_bond): required Permill; - + /// Minimum amount of funds that should be placed ina deposit for making a proposal. ProposalBondMinimum get(proposal_bond_minimum): required T::Balance; @@ -134,31 +134,23 @@ decl_storage! { } } -/// Exported Event type that's generic over the configuration trait. -pub type Event = RawEvent< - ::Balance, - ::AccountId, ->; - /// An event in this module. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { - /// New proposal. - Proposed(ProposalIndex), - /// We have ended a spend period and will now allocate funds. - Spending(Balance), - /// Some funds have been allocated. - Awarded(ProposalIndex, Balance, AccountId), - /// Some of our funds have been burnt. - Burnt(Balance), - /// Spending has finished; this is the amount that rolls over until next spend. - Rollover(Balance), -} - -impl From> for () { - fn from(_: RawEvent) -> () { () } -} +decl_event!( + pub enum Event with RawEvent + where ::Balance, ::AccountId + { + /// New proposal. + Proposed(ProposalIndex), + /// We have ended a spend period and will now allocate funds. + Spending(Balance), + /// Some funds have been allocated. + Awarded(ProposalIndex, Balance, AccountId), + /// Some of our funds have been burnt. + Burnt(Balance), + /// Spending has finished; this is the amount that rolls over until next spend. + Rollover(Balance), + } +); impl Module { /// Deposit one of this module's events. @@ -188,7 +180,7 @@ impl Module { T::RejectOrigin::ensure_origin(origin)?; let proposal = >::take(proposal_id).ok_or("No proposal at that index")?; - + let value = proposal.bond; let _ = >::slash_reserved(&proposal.proposer, value); @@ -215,7 +207,7 @@ impl Module { } fn configure( - origin: T::Origin, + origin: T::Origin, proposal_bond: Permill, proposal_bond_minimum: T::Balance, spend_period: T::BlockNumber, @@ -260,7 +252,7 @@ impl Module { true } } else { - false + false } }).collect(); >::put(remaining_approvals); diff --git a/substrate/substrate/test-runtime/src/lib.rs b/substrate/substrate/test-runtime/src/lib.rs index 55b41c7199..5f9712aa71 100644 --- a/substrate/substrate/test-runtime/src/lib.rs +++ b/substrate/substrate/test-runtime/src/lib.rs @@ -134,13 +134,19 @@ pub fn run_tests(mut input: &[u8]) -> Vec { [stxs.len() as u8].encode() } +fn test_event_json() -> &'static str { + "hallo" +} + pub mod api { use system; impl_stubs!( version => |()| super::version(), json_metadata => |()| { let mut vec = ::runtime_support::metadata::Vec::new(); - vec.push(::runtime_support::metadata::JSONMetadata::Events { events: r#""events""# }); + vec.push(::runtime_support::metadata::JSONMetadata::Events { + name: "Test", events: &[ ("event", super::test_event_json) ] + }); vec }, authorities => |()| system::authorities(),