diff --git a/Cargo.lock b/Cargo.lock index 6cfbd9915e0bc..eafcb9aa92e99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2769,15 +2769,11 @@ dependencies = [ "substrate-codec-derive 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-balances 0.1.0", - "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-session 0.1.0", - "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "substrate-runtime-timestamp 0.1.0", ] [[package]] diff --git a/demo/executor/src/lib.rs b/demo/executor/src/lib.rs index 084249cbcaccc..f0cb26cce3292 100644 --- a/demo/executor/src/lib.rs +++ b/demo/executor/src/lib.rs @@ -52,11 +52,11 @@ mod tests { use primitives::{twox_128, KeccakHasher}; use demo_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::Header as HeaderT; - use runtime_primitives::{ApplyOutcome, ApplyError, ApplyResult, MaybeUnsigned}; + use runtime_primitives::{ApplyOutcome, ApplyError, ApplyResult}; use {balances, staking, session, system, consensus}; use system::{EventRecord, Phase}; - use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Runtime, Balances, - BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, BareExtrinsic, System, Event}; + use demo_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, + BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, Event}; use ed25519::{Public, Pair}; const BLOATY_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm"); @@ -77,20 +77,32 @@ mod tests { AccountId::from(Keyring::Bob.to_raw_public()) } + fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { + match xt.signed { + Some(signed) => { + let payload = (xt.index, xt.function); + let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap()); + let signature = pair.sign(&payload.encode()).into(); + UncheckedExtrinsic { + signature: Some((balances::address::Address::Id(signed), signature)), + index: payload.0, + function: payload.1, + } + } + None => UncheckedExtrinsic { + signature: None, + index: xt.index, + function: xt.function, + }, + } + } + fn xt() -> UncheckedExtrinsic { - let extrinsic = BareExtrinsic { - signed: alice(), + sign(CheckedExtrinsic { + signed: Some(alice()), index: 0, function: Call::Balances(balances::Call::transfer::(bob().into(), 69)), - }; - let signature = MaybeUnsigned(Keyring::from_raw_public(extrinsic.signed.0.clone()).unwrap() - .sign(&extrinsic.encode()).into()); - let extrinsic = Extrinsic { - signed: extrinsic.signed.into(), - index: extrinsic.index, - function: extrinsic.function, - }; - UncheckedExtrinsic::new(extrinsic, signature) + }) } fn from_block_number(n: u64) -> Header { @@ -225,19 +237,10 @@ mod tests { }.build_storage().unwrap().into() } - fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, extrinsics: Vec) -> (Vec, Hash) { + fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, extrinsics: Vec) -> (Vec, Hash) { use triehash::ordered_trie_root; - let extrinsics = extrinsics.into_iter().map(|extrinsic| { - let signature = MaybeUnsigned(Pair::from(Keyring::from_public(Public::from_raw(extrinsic.signed.0.clone())).unwrap()) - .sign(&extrinsic.encode()).into()); - let extrinsic = Extrinsic { - signed: extrinsic.signed.into(), - index: extrinsic.index, - function: extrinsic.function, - }; - UncheckedExtrinsic::new(extrinsic, signature) - }).collect::>(); + let extrinsics = extrinsics.into_iter().map(sign).collect::>(); let extrinsics_root = ordered_trie_root::(extrinsics.iter().map(Encode::encode)).0.into(); @@ -261,8 +264,8 @@ mod tests { // hex!("3437bf4b182ab17bb322af5c67e55f6be487a77084ad2b4e27ddac7242e4ad21").into(), // Keccak hex!("508a68a0918f614b86b2ccfd0975754f6d2abe1026a34e42d6d8d5abdf4db010").into(), - vec![BareExtrinsic { - signed: alice(), + vec![CheckedExtrinsic { + signed: Some(alice()), index: 0, function: Call::Balances(balances::Call::transfer(bob().into(), 69)), }] @@ -276,15 +279,15 @@ mod tests { // Blake // hex!("741fcb660e6fa9f625fbcd993b49f6c1cc4040f5e0cc8727afdedf11fd3c464b").into(), // Keccak - hex!("171f1b2c01c9c616e40ee2d842a699286b50a5a74874b56d826094dadedffb27").into(), + hex!("a72ec570c7642d9ad06ef0e5dd37be65fb04b71e0ab52b3927d760ed6c777a1f").into(), vec![ - BareExtrinsic { - signed: bob(), + CheckedExtrinsic { + signed: Some(bob()), index: 0, function: Call::Balances(balances::Call::transfer(alice().into(), 5)), }, - BareExtrinsic { - signed: alice(), + CheckedExtrinsic { + signed: Some(alice()), index: 1, function: Call::Balances(balances::Call::transfer(bob().into(), 15)), } @@ -300,10 +303,10 @@ mod tests { // hex!("2c7231a9c210a7aa4bea169d944bc4aaacd517862b244b8021236ffa7f697991").into(), // Keccak hex!("e45221804da3a3609454d4e09debe6364cc6af63c2ff067d802d1af62fea32ae").into(), - vec![BareExtrinsic { - signed: alice(), + vec![CheckedExtrinsic { + signed: Some(alice()), index: 0, - function: Call::Consensus(consensus::Call::remark(vec![0; 60000])), + function: Call::Consensus(consensus::Call::remark(vec![0; 60000000])), }] ) } diff --git a/demo/primitives/src/lib.rs b/demo/primitives/src/lib.rs index a435edd3696e2..858002bb98872 100644 --- a/demo/primitives/src/lib.rs +++ b/demo/primitives/src/lib.rs @@ -53,4 +53,4 @@ pub type Index = u64; pub type Hash = primitives::H256; /// Alias to 512-bit hash when used in the context of a signature on the relay chain. -pub type Signature = runtime_primitives::MaybeUnsigned; +pub type Signature = runtime_primitives::Ed25519Signature; diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index 1cf3e460adb80..9429c1a04e6cb 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -64,7 +64,7 @@ pub use runtime_primitives::BuildStorage; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -/// Runtime runtime type used to parameterize the various modules. +/// Runtime type used to collate and parameterize the various modules. pub struct Runtime; /// Runtime version. @@ -76,15 +76,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, }; -/// Version module for this concrete runtime. -pub type Version = version::Module; - -impl version::Trait for Runtime { - const VERSION: RuntimeVersion = VERSION; -} - impl system::Trait for Runtime { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = Index; type BlockNumber = BlockNumber; type Hash = Hash; @@ -154,7 +147,7 @@ impl staking::Trait for Runtime { pub type Staking = staking::Module; impl democracy::Trait for Runtime { - type Proposal = PrivCall; + type Proposal = Call; } /// Democracy module for this concrete runtime. @@ -179,20 +172,13 @@ impl_outer_log! { } } -impl DigestItem for Log { - type AuthoritiesChange = consensus::AuthoritiesChange; - - fn as_authorities_change(&self) -> Option<&Self::AuthoritiesChange> { - match *self { - Log::consensus(ref item) => item.as_authorities_change(), - } +impl_outer_origin! { + pub enum Origin for Runtime { } } impl_outer_dispatch! { - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] - pub enum Call where aux: ::PublicAux { + pub enum Call where origin: Origin { Consensus, Balances, Session, @@ -202,17 +188,28 @@ impl_outer_dispatch! { Council, CouncilVoting, } +} - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] - pub enum PrivCall { - Consensus, - Balances, - Session, - Staking, - Democracy, - Council, - CouncilVoting, +impl_outer_config! { + pub struct GenesisConfig for Runtime { + ConsensusConfig => consensus, + SystemConfig => system, + BalancesConfig => balances, + SessionConfig => session, + StakingConfig => staking, + DemocracyConfig => democracy, + CouncilConfig => council, + TimestampConfig => timestamp, + } +} + +impl DigestItem for Log { + type AuthoritiesChange = consensus::AuthoritiesChange; + + fn as_authorities_change(&self) -> Option<&Self::AuthoritiesChange> { + match *self { + Log::consensus(ref item) => item.as_authorities_change(), + } } } @@ -226,30 +223,15 @@ pub type Block = generic::Block; pub type BlockId = generic::BlockId; /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -/// Extrinsic type as expected by this runtime. This is not the type that is signed. -pub type Extrinsic = generic::Extrinsic; -/// Extrinsic type that is signed. -pub type BareExtrinsic = generic::Extrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = executive::Executive; -impl_outer_config! { - pub struct GenesisConfig for Runtime { - ConsensusConfig => consensus, - SystemConfig => system, - BalancesConfig => balances, - SessionConfig => session, - StakingConfig => staking, - DemocracyConfig => democracy, - CouncilConfig => council, - TimestampConfig => timestamp, - } -} - pub mod api { impl_stubs!( - version => |()| super::Version::version(), + version => |()| super::VERSION, authorities => |()| super::Consensus::authorities(), events => |()| super::System::events(), initialise_block => |header| super::Executive::initialise_block(&header), diff --git a/demo/runtime/wasm/Cargo.lock b/demo/runtime/wasm/Cargo.lock index 5a7006c298ada..42e7bfd91dcfb 100644 --- a/demo/runtime/wasm/Cargo.lock +++ b/demo/runtime/wasm/Cargo.lock @@ -688,7 +688,6 @@ dependencies = [ "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", - "substrate-codec-derive 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index 1e64ab9760537..f929ca9e6968d 100644 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm differ diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm index a7ed5f219890e..ed78742ddea36 100755 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm differ diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 75c6ebda9e7f2..4e4867d71e8c4 100644 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index 34d64bb11aca2..168f9e7989f2d 100755 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/runtime-support/src/dispatch.rs b/substrate/runtime-support/src/dispatch.rs index d15673b583ece..203e3a1347ffe 100644 --- a/substrate/runtime-support/src/dispatch.rs +++ b/substrate/runtime-support/src/dispatch.rs @@ -27,29 +27,11 @@ pub use codec::{Codec, Decode, Encode, Input, Output}; pub type Result = result::Result<(), &'static str>; pub trait Dispatchable { + type Origin; type Trait; - fn dispatch(self) -> Result; + fn dispatch(self, origin: Self::Origin) -> Result; } -pub trait AuxDispatchable { - type Aux; - type Trait; - fn dispatch(self, aux: &Self::Aux) -> Result; -} - -#[cfg(feature = "std")] -pub trait AuxCallable { - type Call: AuxDispatchable + Codec + ::serde::Serialize + Clone + PartialEq + Eq; -} -#[cfg(not(feature = "std"))] -pub trait AuxCallable { - type Call: AuxDispatchable + Codec + Clone + PartialEq + Eq; -} - -// dirty hack to work around serde_derive issue -// https://github.com/rust-lang/rust/issues/51331 -pub type AuxCallableCallFor = ::Call; - #[cfg(feature = "std")] pub trait Callable { type Call: Dispatchable + Codec + ::serde::Serialize + Clone + PartialEq + Eq; @@ -59,9 +41,9 @@ pub trait Callable { type Call: Dispatchable + Codec + Clone + PartialEq + Eq; } -// dirty hack to work around serde_derive issue. +// dirty hack to work around serde_derive issue // https://github.com/rust-lang/rust/issues/51331 -pub type CallableCallFor = ::Call; +pub type CallableCallFor = ::Call; #[cfg(feature = "std")] pub trait Parameter: Codec + serde::Serialize + Clone + Eq + fmt::Debug {} @@ -81,8 +63,15 @@ impl Parameter for T where T: Codec + Clone + Eq {} macro_rules! decl_module { ( $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $($rest:tt)* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + for enum $call_type:ident where origin: $origin_type:ty {$( + $(#[doc = $doc_attr:tt])* + fn $fn_name:ident(origin + $( + , $param_name:ident : $param:ty + )* + ) -> $result:ty; + )*} ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] @@ -91,244 +80,20 @@ macro_rules! decl_module { // serde-derive for when we attempt to derive `Deserialize` on these types, // in a situation where we've imported `substrate_runtime_support` as another name. #[cfg(feature = "std")] - $(#[$attr])* pub struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>); // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg(not(feature = "std"))] - $(#[$attr])* pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>); - decl_dispatch! { - impl for $mod_type<$trait_instance: $trait_name>; - $($rest)* - } - - __impl_json_metadata! { - impl for $mod_type<$trait_instance: $trait_name>; - $($rest)* - } - }; - ( - $(#[$attr:meta])* - struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $($rest:tt)* - ) => { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, Copy, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] - #[cfg(feature = "std")] - $(#[$attr])* - struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>); - - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, Copy, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] - #[cfg(not(feature = "std"))] - $(#[$attr])* - struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>); - decl_dispatch! { - impl for $mod_type<$trait_instance: $trait_name>; - $($rest)* - } - - __impl_json_metadata! { - impl for $mod_type<$trait_instance: $trait_name>; - $($rest)* - } - } -} - -/// Implement several dispatch modules to create a pairing of a dispatch trait and enum. -#[macro_export] -macro_rules! decl_dispatch { - // WITHOUT AUX - ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $(#[$attr:meta])* - pub enum $call_type:ident { - $( - $(#[$fn_attr:meta])* - fn $fn_name:ident( - $( - $param_name:ident : $param:ty - ),* - ) -> $result:ty; - )* - } - $($rest:tt)* - ) => { - __decl_dispatch_module_without_aux! { - impl for $mod_type<$trait_instance: $trait_name>; - $(#[$attr])* - pub enum $call_type; - $( - fn $fn_name( $( $param_name: $param ),* ) -> $result; - )* - } - decl_dispatch! { - impl for $mod_type<$trait_instance: $trait_name>; - $($rest)* - } - }; - // WITH AUX - ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $(#[$attr:meta])* - pub enum $call_type:ident where aux: $aux_type:ty { - $( - $(#[$fn_attr:meta])* - fn $fn_name:ident(aux - $( - , $param_name:ident : $param:ty - )* - ) -> $result:ty; - )* - } - $($rest:tt)* - ) => { - __decl_dispatch_module_with_aux! { - impl for $mod_type<$trait_instance: $trait_name>; - $(#[$attr])* - pub enum $call_type where aux: $aux_type; - $( - fn $fn_name(aux $(, $param_name: $param )*) -> $result; - )* - } - decl_dispatch! { - impl for $mod_type<$trait_instance: $trait_name>; - $($rest)* - } - }; - // BASE CASE - ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - ) => { - impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { - pub fn aux_dispatch>(d: D, aux: &D::Aux) -> $crate::dispatch::Result { - d.dispatch(aux) - } - pub fn dispatch>(d: D) -> $crate::dispatch::Result { - d.dispatch() - } - } - } -} - -#[macro_export] -#[doc(hidden)] -/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum. -macro_rules! __decl_dispatch_module_without_aux { - ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $(#[$attr:meta])* - pub enum $call_type:ident; - $( - fn $fn_name:ident( - $( - $param_name:ident : $param:ty - ),* - ) - -> $result:ty; - )* - ) => { - __decl_dispatch_module_common! { - impl for $mod_type<$trait_instance: $trait_name>; - $(#[$attr])* - pub enum $call_type; - $( fn $fn_name( $( $param_name : $param ),* ) -> $result; )* - } - impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable - for $call_type<$trait_instance> - { - type Trait = $trait_instance; - fn dispatch(self) -> $crate::dispatch::Result { - match self { - $( - $call_type::$fn_name( $( $param_name ),* ) => - <$mod_type<$trait_instance>>::$fn_name( $( $param_name ),* ), - )* - $call_type::__PhantomItem(_) => { panic!("__PhantomItem should never be used.") }, - } - } - } - impl<$trait_instance: $trait_name> $crate::dispatch::Callable - for $mod_type<$trait_instance> - { - type Call = $call_type<$trait_instance>; - } - } -} - -#[macro_export] -#[doc(hidden)] -/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum. -macro_rules! __decl_dispatch_module_with_aux { - ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $(#[$attr:meta])* - pub enum $call_type:ident where aux: $aux_type:ty; - $( - fn $fn_name:ident(aux - $( - , $param_name:ident : $param:ty - )* - ) - -> $result:ty; - )* - ) => { - __decl_dispatch_module_common! { - impl for $mod_type<$trait_instance: $trait_name>; - $(#[$attr])* - pub enum $call_type; - $( fn $fn_name( $( $param_name : $param ),* ) -> $result; )* - } - impl<$trait_instance: $trait_name> $crate::dispatch::AuxDispatchable - for $call_type<$trait_instance> - { - type Trait = $trait_instance; - type Aux = $aux_type; - fn dispatch(self, aux: &Self::Aux) -> $crate::dispatch::Result { - match self { - $( - $call_type::$fn_name( $( $param_name ),* ) => - <$mod_type<$trait_instance>>::$fn_name( aux $(, $param_name )* ), - )* - $call_type::__PhantomItem(_) => { panic!("__PhantomItem should never be used.") }, - } - } - } - impl<$trait_instance: $trait_name> $crate::dispatch::AuxCallable - for $mod_type<$trait_instance> - { - type Call = $call_type<$trait_instance>; - } - }; -} - -/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum. -#[macro_export] -#[doc(hidden)] -macro_rules! __decl_dispatch_module_common { - ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; - $(#[$attr:meta])* - pub enum $call_type:ident; - $( - fn $fn_name:ident( - $( - $param_name:ident : $param:ty - ),* - ) - -> $result:ty; - )* - ) => { #[cfg(feature = "std")] $(#[$attr])* + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum $call_type<$trait_instance: $trait_name> { __PhantomItem(::std::marker::PhantomData<$trait_instance>), + __OtherPhantomItem(::std::marker::PhantomData<$trait_instance>), $( #[allow(non_camel_case_types)] $fn_name ( $( $param ),* ), @@ -337,8 +102,10 @@ macro_rules! __decl_dispatch_module_common { #[cfg(not(feature = "std"))] $(#[$attr])* + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum $call_type<$trait_instance: $trait_name> { __PhantomItem(::core::marker::PhantomData<$trait_instance>), + __OtherPhantomItem(::core::marker::PhantomData<$trait_instance>), $( #[allow(non_camel_case_types)] $fn_name ( $( $param ),* ), @@ -356,30 +123,30 @@ macro_rules! __decl_dispatch_module_common { $call_type::$fn_name( $( ref $param_name ),* ) => $call_type::$fn_name( $( $param_name.clone() ),* ) ,)* - $call_type::__PhantomItem(_) => unreachable!(), + _ => unreachable!(), } } } impl<$trait_instance: $trait_name> $crate::dispatch::PartialEq for $call_type<$trait_instance> { - fn eq(&self, other: &Self) -> bool { + fn eq(&self, _other: &Self) -> bool { match *self { $( $call_type::$fn_name( $( ref $param_name ),* ) => { let self_params = ( $( $param_name, )* ); - if let $call_type::$fn_name( $( ref $param_name ),* ) = *other { + if let $call_type::$fn_name( $( ref $param_name ),* ) = *_other { self_params == ( $( $param_name, )* ) } else { - if let $call_type::__PhantomItem(_) = *other { - unreachable!() - } else { - false + match *_other { + $call_type::__PhantomItem(_) => unreachable!(), + $call_type::__OtherPhantomItem(_) => unreachable!(), + _ => false, } } } )* - $call_type::__PhantomItem(_) => unreachable!(), + _ => unreachable!(), } } } @@ -391,33 +158,65 @@ macro_rules! __decl_dispatch_module_common { impl<$trait_instance: $trait_name> $crate::dispatch::fmt::Debug for $call_type<$trait_instance> { - fn fmt(&self, f: &mut $crate::dispatch::fmt::Formatter) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> { + fn fmt(&self, _f: &mut $crate::dispatch::fmt::Formatter) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> { match *self { $( $call_type::$fn_name( $( ref $param_name ),* ) => - write!(f, "{}{:?}", + write!(_f, "{}{:?}", stringify!($fn_name), ( $( $param_name.clone(), )* ) ) ,)* - $call_type::__PhantomItem(_) => unreachable!(), + _ => unreachable!(), } } } impl<$trait_instance: $trait_name> $crate::dispatch::Decode for $call_type<$trait_instance> { fn decode(input: &mut I) -> Option { - let input_id = input.read_byte()?; - __impl_decode!(input; input_id; 0; $call_type; $( fn $fn_name( $( $param_name ),* ); )*) + let _input_id = input.read_byte()?; + __impl_decode!(input; _input_id; 0; $call_type; $( fn $fn_name( $( $param_name ),* ); )*) } } impl<$trait_instance: $trait_name> $crate::dispatch::Encode for $call_type<$trait_instance> { - fn encode_to(&self, dest: &mut W) { - __impl_encode!(dest; *self; 0; $call_type; $( fn $fn_name( $( $param_name ),* ); )*); + fn encode_to(&self, _dest: &mut W) { + __impl_encode!(_dest; *self; 0; $call_type; $( fn $fn_name( $( $param_name ),* ); )*); if let $call_type::__PhantomItem(_) = *self { unreachable!() } + if let $call_type::__OtherPhantomItem(_) = *self { unreachable!() } + } + } + impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable + for $call_type<$trait_instance> + { + type Trait = $trait_instance; + type Origin = $origin_type; + fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::Result { + match self { + $( + $call_type::$fn_name( $( $param_name ),* ) => + <$mod_type<$trait_instance>>::$fn_name( _origin $(, $param_name )* ), + )* + _ => { panic!("__PhantomItem should never be used.") }, + } + } + } + impl<$trait_instance: $trait_name> $crate::dispatch::Callable + for $mod_type<$trait_instance> + { + type Call = $call_type<$trait_instance>; + } + + impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { + pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::Result { + d.dispatch(origin) } } + + __impl_json_metadata! { + $mod_type $trait_instance $trait_name $call_type $origin_type + {$( $(#[doc = $doc_attr])* fn $fn_name(origin $(, $param_name : $param )*) -> $result; )*} + } } } @@ -492,10 +291,7 @@ macro_rules! __impl_encode { } pub trait IsSubType { - fn is_sub_type(&self) -> Option<&::Call>; -} -pub trait IsAuxSubType { - fn is_aux_sub_type(&self) -> Option<&::Call>; + fn is_aux_sub_type(&self) -> Option<&::Call>; } /// Implement a meta-dispatch module to dispatch to other dispatchers. @@ -504,47 +300,7 @@ macro_rules! impl_outer_dispatch { () => (); ( $(#[$attr:meta])* - pub enum $call_type:ident where aux: $aux:ty { - $( - $camelcase:ident, - )* - } - $( $rest:tt )* - ) => { - $(#[$attr])* - pub enum $call_type { - $( - $camelcase ( $crate::dispatch::AuxCallableCallFor<$camelcase> ) - ,)* - } - __impl_outer_dispatch_common! { $call_type, $($camelcase,)* } - impl $crate::dispatch::AuxDispatchable for $call_type { - type Aux = $aux; - type Trait = $call_type; - fn dispatch(self, aux: &$aux) -> $crate::dispatch::Result { - match self { - $( - $call_type::$camelcase(call) => call.dispatch(&aux), - )* - } - } - } - $( - impl $crate::dispatch::IsAuxSubType<$camelcase> for $call_type { - fn is_aux_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::AuxCallable>::Call> { - if let $call_type::$camelcase ( ref r ) = *self { - Some(r) - } else { - None - } - } - } - )* - impl_outer_dispatch!{ $($rest)* } - }; - ( - $(#[$attr:meta])* - pub enum $call_type:ident { + pub enum $call_type:ident where origin: $origin:ty { $( $camelcase:ident, )* @@ -552,6 +308,8 @@ macro_rules! impl_outer_dispatch { $( $rest:tt )* ) => { $(#[$attr])* + #[derive(Clone, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub enum $call_type { $( $camelcase ( $crate::dispatch::CallableCallFor<$camelcase> ) @@ -559,18 +317,19 @@ macro_rules! impl_outer_dispatch { } __impl_outer_dispatch_common! { $call_type, $($camelcase,)* } impl $crate::dispatch::Dispatchable for $call_type { + type Origin = $origin; type Trait = $call_type; - fn dispatch(self) -> $crate::dispatch::Result { + fn dispatch(self, origin: $origin) -> $crate::dispatch::Result { match self { $( - $call_type::$camelcase(call) => call.dispatch(), + $call_type::$camelcase(call) => call.dispatch(origin), )* } } } $( impl $crate::dispatch::IsSubType<$camelcase> for $call_type { - fn is_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::Callable>::Call> { + fn is_aux_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::Callable>::Call> { if let $call_type::$camelcase ( ref r ) = *self { Some(r) } else { @@ -611,13 +370,13 @@ macro_rules! __impl_outer_dispatch_common { #[doc(hidden)] macro_rules! __impl_json_metadata { ( - impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + $mod_type:ident $trait_instance:ident $trait_name:ident $($rest:tt)* ) => { impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { pub fn json_metadata() -> &'static str { - concat!(r#"{ "name": ""#, stringify!($mod_type), r#"", "calls": ["#, - __calls_to_json!(""; $($rest)*), " ] }") + concat!(r#"{ "name": ""#, stringify!($mod_type), r#"", "call": [ "#, + __call_to_json!($($rest)*), " ] }") } } } @@ -626,66 +385,31 @@ macro_rules! __impl_json_metadata { /// Convert the list of calls into their JSON representation, joined by ",". #[macro_export] #[doc(hidden)] -macro_rules! __calls_to_json { - // WITHOUT AUX - ( - $prefix_str:tt; - $(#[$attr:meta])* - pub enum $call_type:ident { - $( - $(#[doc = $doc_attr:tt])* - fn $fn_name:ident( - $( - $param_name:ident : $param:ty - ),* - ) -> $result:ty; - )* - } - $($rest:tt)* - ) => { - concat!($prefix_str, " ", - r#"{ "name": ""#, stringify!($call_type), - r#"", "functions": {"#, - __functions_to_json!(""; 0; $( - fn $fn_name( $( $param_name: $param ),* ) -> $result; - __function_doc_to_json!(""; $($doc_attr)*); - )*), " } }", __calls_to_json!(","; $($rest)*) - ) - }; +macro_rules! __call_to_json { // WITH AUX ( - $prefix_str:tt; - $(#[$attr:meta])* - pub enum $call_type:ident where aux: $aux_type:ty { - $( + $call_type:ident $origin_type:ty + {$( $(#[doc = $doc_attr:tt])* - fn $fn_name:ident(aux + fn $fn_name:ident(origin $( , $param_name:ident : $param:ty )* ) -> $result:ty; - )* - } - $($rest:tt)* + )*} ) => { - concat!($prefix_str, " ", + concat!( r#"{ "name": ""#, stringify!($call_type), r#"", "functions": {"#, - __functions_to_json!(""; 0; $aux_type; $( - fn $fn_name(aux $(, $param_name: $param )* ) -> $result; + __functions_to_json!(""; 0; $origin_type; $( + fn $fn_name(origin $(, $param_name: $param )* ) -> $result; __function_doc_to_json!(""; $($doc_attr)*); - )*), " } }", __calls_to_json!(","; $($rest)*) + )*), " } }" ) }; - // BASE CASE - ( - $prefix_str:tt; - ) => { - "" - } } -/// Convert a list of function into their JSON representation, joined by ",". +/// Convert a list of functions into their JSON representation, joined by ",". #[macro_export] #[doc(hidden)] macro_rules! __functions_to_json { @@ -713,8 +437,8 @@ macro_rules! __functions_to_json { ( $prefix_str:tt; $fn_id:expr; - $aux_type:ty; - fn $fn_name:ident(aux + $origin_type:ty; + fn $fn_name:ident(origin $( , $param_name:ident : $param:ty )* @@ -725,19 +449,19 @@ macro_rules! __functions_to_json { concat!($prefix_str, " ", __function_to_json!( fn $fn_name( - aux: $aux_type + origin: $origin_type $(, $param_name : $param)* ) -> $result; $fn_doc; $fn_id; - ), __functions_to_json!(","; $fn_id + 1; $aux_type; $($rest)*) + ), __functions_to_json!(","; $fn_id + 1; $origin_type; $($rest)*) ) }; // BASE CASE ( $prefix_str:tt; $fn_id:expr; - $($aux_type:ty;)* + $($origin_type:ty;)* ) => { "" } @@ -799,75 +523,47 @@ mod tests { use serde_json; pub trait Trait { - type PublicAux; + type Origin; } decl_module! { - pub struct Module; - - #[derive(Serialize, Deserialize)] - pub enum Call where aux: T::PublicAux { - /// Hi, this is a comment. - fn aux_0(aux) -> Result; - fn aux_1(aux, data: i32) -> Result; - fn aux_2(aux, data: i32, data2: String) -> Result; - } - - #[derive(Serialize, Deserialize)] - pub enum PrivCall { + pub struct Module for enum Call where origin: T::Origin { /// Hi, this is a comment. - /// Hi, this is a second comment. - fn priv_0(data: String) -> Result; - fn priv_1(data: String, data2: u32) -> Result; + fn aux_0(origin) -> Result; + fn aux_1(origin, data: i32) -> Result; + fn aux_2(origin, data: i32, data2: String) -> Result; } } const EXPECTED_METADATA: &str = concat!( - r#"{ "name": "Module", "calls": [ "#, + r#"{ "name": "Module", "call": [ "#, r#"{ "name": "Call", "functions": { "#, r#""0": { "name": "aux_0", "params": [ "#, - r#"{ "name": "aux", "type": "T::PublicAux" }"#, + r#"{ "name": "origin", "type": "T::Origin" }"#, r#" ], "description": [ " Hi, this is a comment." ] }, "#, r#""0 + 1": { "name": "aux_1", "params": [ "#, - r#"{ "name": "aux", "type": "T::PublicAux" }, "#, + r#"{ "name": "origin", "type": "T::Origin" }, "#, r#"{ "name": "data", "type": "i32" }"#, r#" ], "description": [ ] }, "#, r#""0 + 1 + 1": { "name": "aux_2", "params": [ "#, - r#"{ "name": "aux", "type": "T::PublicAux" }, "#, + r#"{ "name": "origin", "type": "T::Origin" }, "#, r#"{ "name": "data", "type": "i32" }, "#, r#"{ "name": "data2", "type": "String" }"#, r#" ], "description": [ ] }"#, - r#" } }, "#, - r#"{ "name": "PrivCall", "functions": { "#, - r#""0": { "name": "priv_0", "params": [ "#, - r#"{ "name": "data", "type": "String" }"#, - r#" ], "description": [ " Hi, this is a comment.", " Hi, this is a second comment." ] }, "#, - r#""0 + 1": { "name": "priv_1", "params": [ "#, - r#"{ "name": "data", "type": "String" }, "#, - r#"{ "name": "data2", "type": "u32" }"#, - r#" ], "description": [ ] }"#, r#" } }"#, r#" ] }"#, ); impl Module { - fn aux_0(_: &T::PublicAux) -> Result { - unreachable!() - } - - fn aux_1(_: &T::PublicAux, _: i32) -> Result { - unreachable!() - } - - fn aux_2(_: &T::PublicAux, _: i32, _: String) -> Result { + fn aux_0(_: T::Origin) -> Result { unreachable!() } - fn priv_0(_: String) -> Result { + fn aux_1(_: T::Origin, _: i32) -> Result { unreachable!() } - fn priv_1(_: String, _: u32) -> Result { + fn aux_2(_: T::Origin, _: i32, _: String) -> Result { unreachable!() } } @@ -875,7 +571,7 @@ mod tests { struct TraitImpl {} impl Trait for TraitImpl { - type PublicAux = u32; + type Origin = u32; } #[test] diff --git a/substrate/runtime-support/src/lib.rs b/substrate/runtime-support/src/lib.rs index d431d1a89aff9..21823b383fa32 100644 --- a/substrate/runtime-support/src/lib.rs +++ b/substrate/runtime-support/src/lib.rs @@ -50,7 +50,7 @@ mod event; pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap}; pub use self::hashable::Hashable; -pub use self::dispatch::{Parameter, Dispatchable, Callable, AuxDispatchable, AuxCallable, IsSubType, IsAuxSubType}; +pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType}; pub use runtime_io::print; @@ -99,6 +99,82 @@ macro_rules! assert_ok { } } +/// The void type - it cannot exist. +// Oh rust, you crack me up... +#[derive(Clone, Eq, PartialEq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum Void {} + +#[macro_export] +macro_rules! impl_outer_origin { + ($(#[$attr:meta])* pub enum $name:ident for $trait:ident where system = $system:ident { $( $module:ident ),* }) => { + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Debug))] + $(#[$attr])* + #[allow(non_camel_case_types)] + pub enum $name { + system($system::Origin<$trait>), + $( + $module($module::Origin<$trait>), + )* + #[allow(dead_code)] + Void($crate::Void) + } + #[allow(dead_code)] + impl $name { + pub const INHERENT: Self = $name::system($system::RawOrigin::Inherent); + pub const ROOT: Self = $name::system($system::RawOrigin::Root); + pub fn signed(by: <$trait as $system::Trait>::AccountId) -> Self { + $name::system($system::RawOrigin::Signed(by)) + } + } + impl From<$system::Origin<$trait>> for $name { + fn from(x: $system::Origin<$trait>) -> Self { + $name::system(x) + } + } + impl Into>> for $name { + fn into(self) -> Option<$system::Origin<$trait>> { + if let $name::system(l) = self { + Some(l) + } else { + None + } + } + } + impl From::AccountId>> for $name { + fn from(x: Option<<$trait as $system::Trait>::AccountId>) -> Self { + <$system::Origin<$trait>>::from(x).into() + } + } + $( + impl From<$module::Origin<$trait>> for $name { + fn from(x: $module::Origin<$trait>) -> Self { + $name::$module(x) + } + } + impl Into>> for $name { + fn into(self) -> Option<$module::Origin> { + if let $name::$module(l) = self { + Some(l) + } else { + None + } + } + } + )* + }; + ($(#[$attr:meta])* pub enum $name:ident for $trait:ident { $( $module:ident ),* }) => { + impl_outer_origin! { + $(#[$attr])* + pub enum $name for $trait where system = system { + $( $module ),* + } + } + } +} + #[macro_export] macro_rules! impl_outer_log { diff --git a/substrate/runtime-support/src/storage/generator.rs b/substrate/runtime-support/src/storage/generator.rs index 9c9b5223efba6..bcf134fc731fe 100644 --- a/substrate/runtime-support/src/storage/generator.rs +++ b/substrate/runtime-support/src/storage/generator.rs @@ -1456,11 +1456,11 @@ mod tests { } pub trait Trait { - type PublicAux; + type Origin; } decl_module! { - pub struct Module; + pub struct Module for enum Call where origin: T::Origin {} } decl_storage! { @@ -1500,7 +1500,7 @@ mod tests { struct TraitImpl {} impl Trait for TraitImpl { - type PublicAux = u32; + type Origin = u32; } const EXPECTED_METADATA: &str = concat!( diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index 46317cb1c64f4..71a2ba2bfe7e1 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -45,9 +45,10 @@ use rstd::{cmp, result}; use codec::{Encode, Decode, Codec, Input, Output}; use runtime_support::{StorageValue, StorageMap, Parameter}; use runtime_support::dispatch::Result; -use primitives::traits::{Zero, One, RefInto, SimpleArithmetic, OnFinalise, MakePayment, - As, AuxLookup, Member, CheckedAdd, CheckedSub}; +use primitives::traits::{Zero, One, SimpleArithmetic, OnFinalise, MakePayment, + As, Lookup, Member, CheckedAdd, CheckedSub}; use address::Address as RawAddress; +use system::{ensure_signed, ensure_root}; mod mock; @@ -132,16 +133,9 @@ pub trait Trait: system::Trait { } decl_module! { - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn transfer(aux, dest: RawAddress, value: T::Balance) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn set_balance(who: RawAddress, free: T::Balance, reserved: T::Balance) -> Result; + pub struct Module for enum Call where origin: T::Origin { + fn transfer(origin, dest: RawAddress, value: T::Balance) -> Result; + fn set_balance(origin, who: RawAddress, free: T::Balance, reserved: T::Balance) -> Result; } } @@ -233,6 +227,11 @@ pub enum UpdateBalanceOutcome { impl Module { + /// Deposit one of this module's events. + fn deposit_event(event: Event) { + >::deposit_event(::Event::from(event).into()); + } + // PUBLIC IMMUTABLES /// The combined balance of `who`. @@ -283,11 +282,11 @@ impl Module { // PUBLIC DISPATCH /// Transfer some liquid free balance to another staker. - pub fn transfer(aux: &T::PublicAux, dest: Address, value: T::Balance) -> Result { - let dest = Self::lookup(dest)?; + pub fn transfer(origin: T::Origin, dest: Address, value: T::Balance) -> Result { + let transactor = ensure_signed(origin)?; - let transactor = aux.ref_into(); - let from_balance = Self::free_balance(transactor); + let dest = Self::lookup(dest)?; + let from_balance = Self::free_balance(&transactor); let would_create = from_balance.is_zero(); let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; let liability = value + fee; @@ -299,7 +298,7 @@ impl Module { if would_create && value < Self::existential_deposit() { return Err("value too low to create account"); } - T::EnsureAccountLiquid::ensure_account_liquid(transactor)?; + T::EnsureAccountLiquid::ensure_account_liquid(&transactor)?; let to_balance = Self::free_balance(&dest); // NOTE: total stake being stored in the same type means that this could never overflow @@ -309,8 +308,8 @@ impl Module { None => return Err("destination balance too high to receive value"), }; - if transactor != &dest { - Self::set_free_balance(transactor, new_from_balance); + if transactor != dest { + Self::set_free_balance(&transactor, new_from_balance); Self::decrease_total_stake_by(fee); Self::set_free_balance_creating(&dest, new_to_balance); } @@ -318,15 +317,9 @@ impl Module { Ok(()) } - // PRIV DISPATCH - - /// Deposit one of this module's events. - fn deposit_event(event: Event) { - >::deposit_event(::Event::from(event).into()); - } - /// Set the balances of a given account. - fn set_balance(who: Address, free: T::Balance, reserved: T::Balance) -> Result { + fn set_balance(origin: T::Origin, who: Address, free: T::Balance, reserved: T::Balance) -> Result { + ensure_root(origin)?; let who = Self::lookup(who)?; Self::set_free_balance(&who, free); Self::set_reserved_balance(&who, reserved); @@ -647,7 +640,7 @@ impl OnFinalise for Module { } } -impl AuxLookup for Module { +impl Lookup for Module { type Source = address::Address; type Target = T::AccountId; fn lookup(a: Self::Source) -> result::Result { diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs index 803cd995649eb..99204b91d121d 100644 --- a/substrate/runtime/balances/src/mock.rs +++ b/substrate/runtime/balances/src/mock.rs @@ -24,11 +24,15 @@ use substrate_primitives::{H256, KeccakHasher}; use runtime_io; use {GenesisConfig, Module, Trait, system}; +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -pub struct Test; -impl system::Trait for Test { - type PublicAux = Self::AccountId; +pub struct Runtime; +impl system::Trait for Runtime { + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -38,7 +42,7 @@ impl system::Trait for Test { type Header = Header; type Event = (); } -impl Trait for Test { +impl Trait for Runtime { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = (); @@ -47,13 +51,13 @@ impl Trait for Test { } pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); let balance_factor = if ext_deposit > 0 { 256 } else { 1 }; - t.extend(GenesisConfig::{ + t.extend(GenesisConfig::{ balances: if monied { vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] } else { @@ -69,5 +73,5 @@ pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternali t.into() } -pub type System = system::Module; -pub type Balances = Module; +pub type System = system::Module; +pub type Balances = Module; diff --git a/substrate/runtime/balances/src/tests.rs b/substrate/runtime/balances/src/tests.rs index 7f3a740a931a9..7279474a1f9e0 100644 --- a/substrate/runtime/balances/src/tests.rs +++ b/substrate/runtime/balances/src/tests.rs @@ -20,7 +20,7 @@ use super::*; use runtime_io::with_externalities; -use mock::{Balances, System, Test, new_test_ext}; +use mock::{Balances, System, Runtime, new_test_ext}; #[test] fn reward_should_work() { @@ -28,7 +28,7 @@ fn reward_should_work() { assert_eq!(Balances::total_balance(&1), 10); assert_ok!(Balances::reward(&1, 10)); assert_eq!(Balances::total_balance(&1), 20); - assert_eq!(>::get(), 110); + assert_eq!(>::get(), 110); }); } @@ -47,7 +47,7 @@ fn indexing_lookup_should_work() { fn default_indexing_on_new_accounts_should_work() { with_externalities(&mut new_test_ext(10, true), || { assert_eq!(Balances::lookup_index(4), None); - assert_ok!(Balances::transfer(&1, 5.into(), 10)); + assert_ok!(Balances::transfer(Some(1).into(), 5.into(), 10)); assert_eq!(Balances::lookup_index(4), Some(5)); }); } @@ -59,7 +59,7 @@ fn dust_account_removal_should_work() { assert_eq!(System::account_nonce(&2), 1); assert_eq!(Balances::total_balance(&2), 256 * 20); - assert_ok!(Balances::transfer(&2, 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie + assert_ok!(Balances::transfer(Some(2).into(), 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie assert_eq!(Balances::total_balance(&2), 0); assert_eq!(Balances::total_balance(&5), 256 * 10 + 1); assert_eq!(System::account_nonce(&2), 0); @@ -73,10 +73,10 @@ fn reclaim_indexing_on_new_accounts_should_work() { assert_eq!(Balances::lookup_index(4), None); assert_eq!(Balances::total_balance(&2), 256 * 20); - assert_ok!(Balances::transfer(&2, 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) + assert_ok!(Balances::transfer(Some(2).into(), 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) assert_eq!(Balances::total_balance(&2), 0); - assert_ok!(Balances::transfer(&5, 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. + assert_ok!(Balances::transfer(Some(5).into(), 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); assert_eq!(Balances::lookup_index(1), Some(6)); }); @@ -95,7 +95,7 @@ fn reserved_balance_should_prevent_reclaim_count() { assert_eq!(Balances::total_balance(&2), 256 * 19 + 1); // reserve still exists. assert_eq!(System::account_nonce(&2), 1); - assert_ok!(Balances::transfer(&4, 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. + assert_ok!(Balances::transfer(Some(4).into(), 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); assert_eq!(Balances::lookup_index(1), Some(2)); // but fails. assert_eq!(System::account_nonce(&2), 1); @@ -104,7 +104,7 @@ fn reserved_balance_should_prevent_reclaim_count() { assert_eq!(Balances::total_balance(&2), 0); // "free" account deleted." assert_eq!(System::account_nonce(&2), 0); - assert_ok!(Balances::transfer(&4, 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. + assert_ok!(Balances::transfer(Some(4).into(), 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); assert_eq!(Balances::lookup_index(1), Some(6)); // and succeeds. }); @@ -128,7 +128,7 @@ fn balance_transfer_works() { with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); - assert_ok!(Balances::transfer(&1, 2.into(), 69)); + assert_ok!(Balances::transfer(Some(1).into(), 2.into(), 69)); assert_eq!(Balances::total_balance(&1), 42); assert_eq!(Balances::total_balance(&2), 69); }); @@ -156,7 +156,7 @@ fn balance_transfer_when_reserved_should_not_work() { with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 69)); - assert_noop!(Balances::transfer(&1, 2.into(), 69), "balance too low to send value"); + assert_noop!(Balances::transfer(Some(1).into(), 2.into(), 69), "balance too low to send value"); }); } @@ -189,7 +189,7 @@ fn slashing_balance_should_work() { assert!(Balances::slash(&1, 69).is_none()); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 42); - assert_eq!(>::get(), 44); + assert_eq!(>::get(), 44); }); } @@ -202,7 +202,7 @@ fn slashing_incomplete_balance_should_work() { assert!(Balances::slash(&1, 69).is_some()); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 2); + assert_eq!(>::get(), 2); }); } @@ -226,7 +226,7 @@ fn slashing_reserved_balance_should_work() { assert!(Balances::slash_reserved(&1, 42).is_none()); assert_eq!(Balances::reserved_balance(&1), 69); assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(>::get(), 71); + assert_eq!(>::get(), 71); }); } @@ -239,7 +239,7 @@ fn slashing_incomplete_reserved_balance_should_work() { assert!(Balances::slash_reserved(&1, 69).is_some()); assert_eq!(Balances::free_balance(&1), 69); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 71); + assert_eq!(>::get(), 71); }); } @@ -283,11 +283,11 @@ fn transferring_incomplete_reserved_balance_should_work() { #[test] fn transferring_too_high_value_should_not_panic() { with_externalities(&mut new_test_ext(0, false), || { - >::insert(1, u64::max_value()); - >::insert(2, 1); + >::insert(1, u64::max_value()); + >::insert(2, 1); assert_err!( - Balances::transfer(&1, 2.into(), u64::max_value()), + Balances::transfer(Some(1).into(), 2.into(), u64::max_value()), "destination balance too high to receive value" ); @@ -307,18 +307,18 @@ fn account_removal_on_free_too_low() { Balances::set_free_balance(&2, 110); Balances::increase_total_stake_by(110); - assert_eq!(>::get(), 732); + assert_eq!(>::get(), 732); } // Transfer funds from account 1 of such amount that after this transfer // the balance of account 1 will be below the exsistential threshold. // This should lead to the removal of all balance of this account. - assert_ok!(Balances::transfer(&1, 2.into(), 20)); + assert_ok!(Balances::transfer(Some(1).into(), 2.into(), 20)); // Verify free balance removal of account 1. assert_eq!(Balances::free_balance(&1), 0); // Verify that TotalIssuance tracks balance removal when free balance is too low. - assert_eq!(>::get(), 642); + assert_eq!(>::get(), 642); }); } diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index add01fa3cfb43..3e0be21131bcc 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -46,8 +46,9 @@ use runtime_support::{storage, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::StorageValue; use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::{MaybeSerializeDebug, MaybeEmpty, OnFinalise, Member, AuthoritiesChangeDigest}; +use primitives::traits::{MaybeSerializeDebug, OnFinalise, Member, AuthoritiesChangeDigest}; use primitives::bft::MisbehaviorReport; +use system::{ensure_signed, ensure_inherent, ensure_root}; #[cfg(any(feature = "std", test))] use substrate_primitives::KeccakHasher; @@ -141,19 +142,12 @@ decl_storage! { } decl_module! { - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn report_misbehavior(aux, report: MisbehaviorReport) -> Result; - fn note_offline(aux, offline_val_indices: Vec) -> Result; - fn remark(aux, remark: Vec) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn set_code(new: Vec) -> Result; - fn set_storage(items: Vec) -> Result; + pub struct Module for enum Call where origin: T::Origin { + fn report_misbehavior(origin, report: MisbehaviorReport) -> Result; + fn note_offline(origin, offline_val_indices: Vec) -> Result; + fn remark(origin, remark: Vec) -> Result; + fn set_code(origin, new: Vec) -> Result; + fn set_storage(origin, items: Vec) -> Result; } } @@ -164,13 +158,15 @@ impl Module { } /// Set the new code. - fn set_code(new: Vec) -> Result { + fn set_code(origin: T::Origin, new: Vec) -> Result { + ensure_root(origin)?; storage::unhashed::put_raw(CODE, &new); Ok(()) } /// Set some items of storage. - fn set_storage(items: Vec) -> Result { + fn set_storage(origin: T::Origin, items: Vec) -> Result { + ensure_root(origin)?; for i in &items { storage::unhashed::put_raw(&i.0, &i.1); } @@ -178,7 +174,8 @@ impl Module { } /// Report some misbehaviour. - fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport) -> Result { + fn report_misbehavior(origin: T::Origin, _report: MisbehaviorReport) -> Result { + ensure_signed(origin)?; // TODO. Ok(()) } @@ -186,8 +183,8 @@ impl Module { /// Note the previous block's validator missed their opportunity to propose a block. This only comes in /// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant /// for the previous block. - fn note_offline(aux: &T::PublicAux, offline_val_indices: Vec) -> Result { - assert!(aux.is_empty()); + fn note_offline(origin: T::Origin, offline_val_indices: Vec) -> Result { + ensure_inherent(origin)?; assert!( >::extrinsic_index() == Some(T::NOTE_OFFLINE_POSITION), "note_offline extrinsic must be at position {} in the block", @@ -202,7 +199,8 @@ impl Module { } /// Make some on-chain remark. - fn remark(_aux: &T::PublicAux, _remark: Vec) -> Result { + fn remark(origin: T::Origin, _remark: Vec) -> Result { + ensure_signed(origin)?; Ok(()) } diff --git a/substrate/runtime/contract/Cargo.toml b/substrate/runtime/contract/Cargo.toml index f72c2b490ed75..a53cb5e886c6b 100644 --- a/substrate/runtime/contract/Cargo.toml +++ b/substrate/runtime/contract/Cargo.toml @@ -7,8 +7,8 @@ authors = ["Parity Technologies "] serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } substrate-codec = { path = "../../codec", default_features = false } -substrate-primitives = { path = "../../primitives" } -substrate-runtime-primitives = { path = "../../runtime/primitives" } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-primitives = { path = "../../runtime/primitives", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } @@ -28,6 +28,7 @@ std = [ "serde_derive", "serde/std", "substrate-codec/std", + "substrate-primitives/std", "substrate-runtime-primitives/std", "substrate-runtime-io/std", "substrate-runtime-std/std", diff --git a/substrate/runtime/contract/src/lib.rs b/substrate/runtime/contract/src/lib.rs index 6092787cfddb9..cb5697cd89910 100644 --- a/substrate/runtime/contract/src/lib.rs +++ b/substrate/runtime/contract/src/lib.rs @@ -101,9 +101,10 @@ use account_db::{AccountDb, OverlayAccountDb}; use double_map::StorageDoubleMap; use codec::Codec; -use runtime_primitives::traits::{As, RefInto, SimpleArithmetic, OnFinalise}; +use runtime_primitives::traits::{As, SimpleArithmetic, OnFinalise}; use runtime_support::dispatch::Result; use runtime_support::{Parameter, StorageMap, StorageValue}; +use system::ensure_signed; pub trait Trait: balances::Trait { /// Function type to get the contract address given the creator. @@ -119,13 +120,10 @@ pub trait ContractAddressFor { decl_module! { /// Contracts module. - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { + pub struct Module for enum Call where origin: T::Origin { // TODO: Change AccountId to staking::Address fn call( - aux, + origin, dest: T::AccountId, value: T::Balance, gas_limit: T::Gas, @@ -133,7 +131,7 @@ decl_module! { ) -> Result; fn create( - aux, + origin, value: T::Balance, gas_limit: T::Gas, ctor: Vec, @@ -181,26 +179,26 @@ impl double_map::StorageDoubleMap for StorageOf { impl Module { /// Make a call to a specified account, optionally transferring some balance. fn call( - aux: &::PublicAux, + origin: ::Origin, dest: T::AccountId, value: T::Balance, gas_limit: T::Gas, data: Vec, ) -> Result { - let aux = aux.ref_into(); + let origin = ensure_signed(origin)?; // Pay for the gas upfront. // // NOTE: it is very important to avoid any state changes before // paying for the gas. - let mut gas_meter = gas::buy_gas::(aux, gas_limit)?; + let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; let mut ctx = ExecutionContext { - self_account: aux.clone(), + self_account: origin.clone(), depth: 0, overlay: OverlayAccountDb::::new(&account_db::DirectAccountDb), }; - let result = ctx.call(aux.clone(), dest, value, &mut gas_meter, &data); + let result = ctx.call(origin.clone(), dest, value, &mut gas_meter, &data); if let Ok(_) = result { // Commit all changes that made it thus far into the persistant storage. @@ -211,7 +209,7 @@ impl Module { // // NOTE: this should go after the commit to the storage, since the storage changes // can alter the balance of the caller. - gas::refund_unused_gas::(aux, gas_meter); + gas::refund_unused_gas::(&origin, gas_meter); result.map(|_| ()) } @@ -226,26 +224,26 @@ impl Module { /// after the execution is saved as the `code` of the account. That code will be invoked /// upon any message received by this account. fn create( - aux: &::PublicAux, + origin: ::Origin, endowment: T::Balance, gas_limit: T::Gas, ctor_code: Vec, data: Vec, ) -> Result { - let aux = aux.ref_into(); + let origin = ensure_signed(origin)?; // Pay for the gas upfront. // // NOTE: it is very important to avoid any state changes before // paying for the gas. - let mut gas_meter = gas::buy_gas::(aux, gas_limit)?; + let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; let mut ctx = ExecutionContext { - self_account: aux.clone(), + self_account: origin.clone(), depth: 0, overlay: OverlayAccountDb::::new(&account_db::DirectAccountDb), }; - let result = ctx.create(aux.clone(), endowment, &mut gas_meter, &ctor_code, &data); + let result = ctx.create(origin.clone(), endowment, &mut gas_meter, &ctor_code, &data); if let Ok(_) = result { // Commit all changes that made it thus far into the persistant storage. @@ -256,7 +254,7 @@ impl Module { // // NOTE: this should go after the commit to the storage, since the storage changes // can alter the balance of the caller. - gas::refund_unused_gas::(aux, gas_meter); + gas::refund_unused_gas::(&origin, gas_meter); result.map(|_| ()) } diff --git a/substrate/runtime/contract/src/tests.rs b/substrate/runtime/contract/src/tests.rs index f96a6fd2c5133..9968f804c7b24 100644 --- a/substrate/runtime/contract/src/tests.rs +++ b/substrate/runtime/contract/src/tests.rs @@ -27,10 +27,14 @@ use { GenesisConfig, Module, StorageOf, Trait, }; +impl_outer_origin! { + pub enum Origin for Test {} +} + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -170,7 +174,7 @@ fn contract_transfer() { Balances::set_free_balance(&1, 11); Balances::increase_total_stake_by(11); - assert_ok!(Contract::call(&0, 1, 3, 100_000, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), 1, 3, 100_000, Vec::new())); assert_eq!( Balances::free_balance(&0), @@ -205,7 +209,7 @@ fn contract_transfer_oog() { Balances::set_free_balance(&1, 11); Balances::increase_total_stake_by(11); - assert_ok!(Contract::call(&0, 1, 3, 135 + 135 + 7, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), 1, 3, 135 + 135 + 7, Vec::new())); assert_eq!( Balances::free_balance(&0), @@ -237,7 +241,7 @@ fn contract_transfer_max_depth() { Balances::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 11); Balances::increase_total_stake_by(11); - assert_ok!(Contract::call(&0, CONTRACT_SHOULD_TRANSFER_TO, 3, 100_000, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), CONTRACT_SHOULD_TRANSFER_TO, 3, 100_000, Vec::new())); assert_eq!( Balances::free_balance(&0), @@ -349,7 +353,7 @@ fn contract_create() { >::insert(1, code_create.to_vec()); // When invoked, the contract at address `1` must create a contract with 'transfer' code. - assert_ok!(Contract::call(&0, 1, 11, 100_000, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), 1, 11, 100_000, Vec::new())); let derived_address = ::DetermineContractAddress::contract_address_for( &code_ctor_transfer, @@ -368,7 +372,7 @@ fn contract_create() { assert_eq!(Balances::free_balance(&derived_address), 3); // Initiate transfer to the newly created contract. - assert_ok!(Contract::call(&0, derived_address, 22, 100_000, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), derived_address, 22, 100_000, Vec::new())); assert_eq!( Balances::free_balance(&0), @@ -400,7 +404,7 @@ fn top_level_create() { Balances::increase_total_stake_by(30); assert_ok!(Contract::create( - &0, + Origin::signed(0), 11, 100_000, code_ctor_transfer.clone(), @@ -439,7 +443,7 @@ fn refunds_unused_gas() { Balances::set_free_balance(&0, 100_000_000); Balances::increase_total_stake_by(100_000_000); - assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), 1, 0, 100_000, Vec::new())); assert_eq!(Balances::free_balance(&0), 100_000_000 - 4 - (2 * 135)); }); @@ -453,7 +457,7 @@ fn call_with_zero_value() { Balances::set_free_balance(&0, 100_000_000); Balances::increase_total_stake_by(100_000_000); - assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new())); + assert_ok!(Contract::call(Origin::signed(0), 1, 0, 100_000, Vec::new())); assert_eq!(Balances::free_balance(&0), 100_000_000 - (2 * 135)); }); @@ -467,7 +471,7 @@ fn create_with_zero_endowment() { Balances::set_free_balance(&0, 100_000_000); Balances::increase_total_stake_by(100_000_000); - assert_ok!(Contract::create(&0, 0, 100_000, code_nop, Vec::new())); + assert_ok!(Contract::create(Origin::signed(0), 0, 100_000, code_nop, Vec::new())); assert_eq!( Balances::free_balance(&0), @@ -500,7 +504,7 @@ fn account_removal_removes_storage() { // the balance of account 1 is will be below than exsistential threshold. // // This should lead to the removal of all storage associated with this account. - assert_ok!(Balances::transfer(&1, 2.into(), 20)); + assert_ok!(Balances::transfer(Origin::signed(1), 2.into(), 20)); // Verify that all entries from account 1 is removed, while // entries from account 2 is in place. @@ -540,7 +544,7 @@ fn top_level_call_refunds_even_if_fails() { Balances::increase_total_stake_by(100_000_000); assert_err!( - Contract::call(&0, 1, 0, 100_000, Vec::new()), + Contract::call(Origin::signed(0), 1, 0, 100_000, Vec::new()), "vm execute returned error while call" ); @@ -571,19 +575,19 @@ fn block_gas_limit() { // Spend 50_000 units of gas (OOG). assert_err!( - Contract::call(&0, 1, 0, 50_000, Vec::new()), + Contract::call(Origin::signed(0), 1, 0, 50_000, Vec::new()), "vm execute returned error while call" ); // Ensure we can't spend more gas than available in block gas limit. assert_err!( - Contract::call(&0, 1, 0, 50_001, Vec::new()), + Contract::call(Origin::signed(0), 1, 0, 50_001, Vec::new()), "block gas limit is reached" ); // However, we can spend another 50_000 assert_err!( - Contract::call(&0, 1, 0, 50_000, Vec::new()), + Contract::call(Origin::signed(0), 1, 0, 50_000, Vec::new()), "vm execute returned error while call" ); }, @@ -656,7 +660,7 @@ fn input_data() { Balances::set_free_balance(&0, 100_000_000); Balances::increase_total_stake_by(100_000_000); - assert_ok!(Contract::call(&0, 1, 0, 50_000, vec![0, 1, 2, 3])); + assert_ok!(Contract::call(Origin::signed(0), 1, 0, 50_000, vec![0, 1, 2, 3])); // all asserts are made within contract code itself. }, diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 8672a581fe2c8..0ff41c2743f9f 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -28,7 +28,7 @@ extern crate serde_derive; extern crate integer_sqrt; extern crate substrate_codec as codec; extern crate substrate_primitives; -#[cfg(any(feature = "std", test))] extern crate substrate_keyring as keyring; +#[cfg(feature = "std")] extern crate substrate_keyring as keyring; #[macro_use] extern crate substrate_runtime_std as rstd; extern crate substrate_runtime_io as runtime_io; #[macro_use] extern crate substrate_runtime_support; @@ -38,12 +38,13 @@ extern crate substrate_runtime_democracy as democracy; extern crate substrate_runtime_system as system; use rstd::prelude::*; -use primitives::traits::{Zero, One, RefInto, As, AuxLookup}; +#[cfg(feature = "std")] +use std::collections::HashMap; +use primitives::traits::{Zero, One, As, Lookup}; use substrate_runtime_support::{StorageValue, StorageMap}; use substrate_runtime_support::dispatch::Result; use balances::address::Address; -#[cfg(any(feature = "std", test))] -use std::collections::HashMap; +use system::{ensure_signed, ensure_root}; pub mod voting; @@ -106,23 +107,17 @@ pub type VoteIndex = u32; pub trait Trait: democracy::Trait {} decl_module! { - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn set_approvals(aux, votes: Vec, index: VoteIndex) -> Result; - fn reap_inactive_voter(aux, signed_index: u32, who: Address, who_index: u32, assumed_vote_index: VoteIndex) -> Result; - fn retract_voter(aux, index: u32) -> Result; - fn submit_candidacy(aux, slot: u32) -> Result; - fn present_winner(aux, candidate: Address, total: T::Balance, index: VoteIndex) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn set_desired_seats(count: u32) -> Result; - fn remove_member(who: Address) -> Result; - fn set_presentation_duration(count: T::BlockNumber) -> Result; - fn set_term_duration(count: T::BlockNumber) -> Result; + pub struct Module for enum Call where origin: T::Origin { + fn set_approvals(origin, votes: Vec, index: VoteIndex) -> Result; + fn reap_inactive_voter(origin, reporter_index: u32, who: Address, who_index: u32, assumed_vote_index: VoteIndex) -> Result; + fn retract_voter(origin, index: u32) -> Result; + fn submit_candidacy(origin, slot: u32) -> Result; + fn present_winner(origin, candidate: Address, total: T::Balance, index: VoteIndex) -> Result; + + fn set_desired_seats(origin, count: u32) -> Result; + fn remove_member(origin, who: Address) -> Result; + fn set_presentation_duration(origin, count: T::BlockNumber) -> Result; + fn set_term_duration(origin, count: T::BlockNumber) -> Result; } } @@ -235,22 +230,24 @@ impl Module { /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots /// are registered. - fn set_approvals(aux: &T::PublicAux, votes: Vec, index: VoteIndex) -> Result { + 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(aux.ref_into()) { + if !>::exists(&who) { // not yet a voter - deduct bond. // NOTE: this must be the last potential bailer, since it changes state. - >::reserve(aux.ref_into(), Self::voting_bond())?; + >::reserve(&who, Self::voting_bond())?; >::put({ let mut v = Self::voters(); - v.push(aux.ref_into().clone()); + v.push(who.clone()); v }); } - >::insert(aux.ref_into().clone(), votes); - >::insert(aux.ref_into(), index); + >::insert(&who, index); + >::insert(&who, votes); Ok(()) } @@ -260,22 +257,24 @@ impl Module { /// /// May be called by anyone. Returns the voter deposit to `signed`. fn reap_inactive_voter( - aux: &T::PublicAux, - signed_index: u32, + origin: T::Origin, + reporter_index: u32, who: Address, who_index: u32, 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(aux.ref_into()).is_some(), "reaper must be a voter"); + ensure!(Self::voter_last_active(&reporter).is_some(), "reporter must be a voter"); let last_active = Self::voter_last_active(&who).ok_or("target for inactivity cleanup must be active")?; ensure!(assumed_vote_index == Self::vote_index(), "vote index not current"); ensure!(last_active < assumed_vote_index - Self::inactivity_grace_period(), "cannot reap during grace perid"); let voters = Self::voters(); - let signed_index = signed_index as usize; + let reporter_index = reporter_index as usize; let who_index = who_index as usize; - ensure!(signed_index < voters.len() && &voters[signed_index] == aux.ref_into(), "bad reporter index"); + ensure!(reporter_index < voters.len() && voters[reporter_index] == reporter, "bad reporter index"); ensure!(who_index < voters.len() && voters[who_index] == who, "bad target index"); // will definitely kill one of signed or who now. @@ -289,39 +288,43 @@ impl Module { ); Self::remove_voter( - if valid { &who } else { aux.ref_into() }, - if valid { who_index } else { signed_index }, + if valid { &who } else { &reporter }, + if valid { who_index } else { reporter_index }, voters ); if valid { - // This only fails if `who` doesn't exist, which it clearly must do since its the aux. + // This only fails if `who` doesn't exist, which it clearly must do since its the origin. // Still, it's no more harmful to propagate any error at this point. - >::repatriate_reserved(&who, aux.ref_into(), Self::voting_bond())?; + >::repatriate_reserved(&who, &reporter, Self::voting_bond())?; } else { - >::slash_reserved(aux.ref_into(), Self::voting_bond()); + >::slash_reserved(&reporter, Self::voting_bond()); } Ok(()) } /// Remove a voter. All votes are cancelled and the voter deposit is returned. - fn retract_voter(aux: &T::PublicAux, index: u32) -> Result { + fn retract_voter(origin: T::Origin, index: u32) -> Result { + let who = ensure_signed(origin)?; + ensure!(!Self::presentation_active(), "cannot retract when presenting"); - ensure!(>::exists(aux.ref_into()), "cannot retract non-voter"); + ensure!(>::exists(&who), "cannot retract non-voter"); let voters = Self::voters(); let index = index as usize; ensure!(index < voters.len(), "retraction index invalid"); - ensure!(&voters[index] == aux.ref_into(), "retraction index mismatch"); + ensure!(voters[index] == who, "retraction index mismatch"); - Self::remove_voter(aux.ref_into(), index, voters); - >::unreserve(aux.ref_into(), Self::voting_bond()); + Self::remove_voter(&who, index, voters); + >::unreserve(&who, Self::voting_bond()); Ok(()) } /// Submit oneself for candidacy. /// /// Account must have enough transferrable funds in it to pay the bond. - fn submit_candidacy(aux: &T::PublicAux, slot: u32) -> Result { - ensure!(!Self::is_a_candidate(aux.ref_into()), "duplicate candidate submission"); + 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; let candidates = Self::candidates(); @@ -331,18 +334,18 @@ impl Module { "invalid candidate slot" ); // NOTE: This must be last as it has side-effects. - >::reserve(aux.ref_into(), Self::candidacy_bond()) + >::reserve(&who, Self::candidacy_bond()) .map_err(|_| "candidate has not enough funds")?; + >::insert(&who, (Self::vote_index(), slot as u32)); let mut candidates = candidates; if slot == candidates.len() { - candidates.push(aux.ref_into().clone()); + candidates.push(who); } else { - candidates[slot] = aux.ref_into().clone(); + candidates[slot] = who; } >::put(candidates); >::put(count as u32 + 1); - >::insert(aux.ref_into(), (Self::vote_index(), slot as u32)); Ok(()) } @@ -350,18 +353,20 @@ impl Module { /// Only works if the `block_number >= current_vote().0` and `< current_vote().0 + presentation_duration()`` /// `signed` should have at least fn present_winner( - aux: &T::PublicAux, + origin: T::Origin, candidate: Address, total: T::Balance, index: VoteIndex ) -> Result { + let who = ensure_signed(origin)?; + let candidate = >::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalise().ok_or("cannot present outside of presentation period")?; let stakes = Self::snapshoted_stakes(); let voters = Self::voters(); let bad_presentation_punishment = Self::present_slash_per_voter() * T::Balance::sa(voters.len() as u64); - ensure!(>::can_slash(aux.ref_into(), bad_presentation_punishment), "presenter must have sufficient slashable funds"); + ensure!(>::can_slash(&who, bad_presentation_punishment), "presenter must have sufficient slashable funds"); let mut leaderboard = Self::leaderboard().ok_or("leaderboard must exist while present phase active")?; ensure!(total > leaderboard[0].0, "candidate not worthy of leaderboard"); @@ -392,7 +397,7 @@ impl Module { } else { // we can rest assured it will be Ok since we checked `can_slash` earlier; still // better safe than sorry. - let _ = >::slash(aux.ref_into(), bad_presentation_punishment); + let _ = >::slash(&who, bad_presentation_punishment); Err(if dupe { "duplicate presentation" } else { "incorrect total" }) } } @@ -400,7 +405,8 @@ impl Module { /// Set the desired member count; if lower than the current count, then seats will not be up /// election when they expire. If more, then a new vote will be started if one is not already /// in progress. - fn set_desired_seats(count: u32) -> Result { + fn set_desired_seats(origin: T::Origin, count: u32) -> Result { + ensure_root(origin)?; >::put(count); Ok(()) } @@ -408,7 +414,8 @@ impl Module { /// Remove a particular member. A tally will happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. /// This is effective immediately. - fn remove_member(who: Address) -> Result { + fn remove_member(origin: T::Origin, who: Address) -> Result { + ensure_root(origin)?; let who = >::lookup(who)?; let new_council: Vec<(T::AccountId, T::BlockNumber)> = Self::active_council() .into_iter() @@ -420,14 +427,16 @@ impl Module { /// Set the presentation duration. If there is current a vote being presented for, will /// invoke `finalise_vote`. - fn set_presentation_duration(count: T::BlockNumber) -> Result { + fn set_presentation_duration(origin: T::Origin, count: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(count); Ok(()) } /// Set the presentation duration. If there is current a vote being presented for, will /// invoke `finalise_vote`. - fn set_term_duration(count: T::BlockNumber) -> Result { + fn set_term_duration(origin: T::Origin, count: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(count); Ok(()) } @@ -543,7 +552,7 @@ impl Module { } } -#[cfg(any(feature = "std", test))] +#[cfg(feature = "std")] #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] @@ -566,7 +575,7 @@ pub struct GenesisConfig { pub voting_period: T::BlockNumber, } -#[cfg(any(feature = "std", test))] +#[cfg(feature = "std")] impl Default for GenesisConfig { fn default() -> Self { GenesisConfig { @@ -586,7 +595,7 @@ impl Default for GenesisConfig { } } -#[cfg(any(feature = "std", test))] +#[cfg(feature = "std")] impl primitives::BuildStorage for GenesisConfig { fn build_storage(self) -> ::std::result::Result, Vec>, String> { @@ -622,9 +631,12 @@ mod tests { use primitives::testing::{Digest, Header}; use substrate_primitives::KeccakHasher; + impl_outer_origin! { + pub enum Origin for Test {} + } + impl_outer_dispatch! { - #[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)] - pub enum Proposal { + pub enum Call where origin: Origin { Balances, Democracy, } @@ -634,7 +646,7 @@ mod tests { #[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct Test; impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -652,7 +664,7 @@ mod tests { type Event = (); } impl democracy::Trait for Test { - type Proposal = Proposal; + type Proposal = Call; } impl Trait for Test {} @@ -740,14 +752,14 @@ mod tests { assert_eq!(Council::is_a_candidate(&1), false); assert_eq!(Council::is_a_candidate(&2), false); - assert_ok!(Council::submit_candidacy(&1, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_eq!(Council::candidates(), vec![1]); assert_eq!(Council::candidate_reg_info(1), Some((0, 0))); assert_eq!(Council::candidate_reg_info(2), None); assert_eq!(Council::is_a_candidate(&1), true); assert_eq!(Council::is_a_candidate(&2), false); - assert_ok!(Council::submit_candidacy(&2, 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); assert_eq!(Council::candidates(), vec![1, 2]); assert_eq!(Council::candidate_reg_info(1), Some((0, 0))); assert_eq!(Council::candidate_reg_info(2), Some((0, 1))); @@ -774,10 +786,10 @@ mod tests { System::set_block_number(1); assert_eq!(Council::candidates(), vec![0, 0, 1]); - assert_ok!(Council::submit_candidacy(&2, 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); assert_eq!(Council::candidates(), vec![0, 2, 1]); - assert_ok!(Council::submit_candidacy(&3, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); assert_eq!(Council::candidates(), vec![3, 2, 1]); }); } @@ -790,10 +802,10 @@ mod tests { System::set_block_number(1); assert_eq!(Council::candidates(), vec![0, 0, 1]); - assert_ok!(Council::submit_candidacy(&2, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); assert_eq!(Council::candidates(), vec![2, 0, 1]); - assert_ok!(Council::submit_candidacy(&3, 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 1)); assert_eq!(Council::candidates(), vec![2, 3, 1]); }); } @@ -802,7 +814,7 @@ mod tests { fn candidate_submission_not_using_free_slot_should_not_work() { with_externalities(&mut new_test_ext_with_candidate_holes(), || { System::set_block_number(1); - assert_noop!(Council::submit_candidacy(&4, 3), "invalid candidate slot"); + assert_noop!(Council::submit_candidacy(Origin::signed(4), 3), "invalid candidate slot"); }); } @@ -811,7 +823,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_noop!(Council::submit_candidacy(&1, 1), "invalid candidate slot"); + assert_noop!(Council::submit_candidacy(Origin::signed(1), 1), "invalid candidate slot"); }); } @@ -820,9 +832,9 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_ok!(Council::submit_candidacy(&1, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_eq!(Council::candidates(), vec![1]); - assert_noop!(Council::submit_candidacy(&2, 0), "invalid candidate slot"); + assert_noop!(Council::submit_candidacy(Origin::signed(2), 0), "invalid candidate slot"); }); } @@ -831,9 +843,9 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_ok!(Council::submit_candidacy(&1, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_eq!(Council::candidates(), vec![1]); - assert_noop!(Council::submit_candidacy(&1, 1), "duplicate candidate submission"); + assert_noop!(Council::submit_candidacy(Origin::signed(1), 1), "duplicate candidate submission"); }); } @@ -842,7 +854,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_noop!(Council::submit_candidacy(&7, 0), "candidate has not enough funds"); + assert_noop!(Council::submit_candidacy(Origin::signed(7), 0), "candidate has not enough funds"); }); } @@ -851,20 +863,20 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(&5, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Council::set_approvals(&1, vec![true], 0)); - assert_ok!(Council::set_approvals(&4, vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true], 0)); assert_eq!(Council::approvals_of(1), vec![true]); assert_eq!(Council::approvals_of(4), vec![true]); assert_eq!(Council::voters(), vec![1, 4]); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::submit_candidacy(&3, 2)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Council::set_approvals(&2, vec![false, true, true], 0)); - assert_ok!(Council::set_approvals(&3, vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, true], 0)); assert_eq!(Council::approvals_of(1), vec![true]); assert_eq!(Council::approvals_of(4), vec![true]); @@ -880,14 +892,14 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::set_approvals(&4, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true], 0)); assert_eq!(Council::approvals_of(4), vec![true]); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::submit_candidacy(&3, 2)); - assert_ok!(Council::set_approvals(&4, vec![true, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true, false, true], 0)); assert_eq!(Council::approvals_of(4), vec![true, false, true]); }); @@ -898,14 +910,14 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::submit_candidacy(&3, 2)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Council::set_approvals(&1, vec![true], 0)); - assert_ok!(Council::set_approvals(&2, vec![false, true, true], 0)); - assert_ok!(Council::set_approvals(&3, vec![false, true, true], 0)); - assert_ok!(Council::set_approvals(&4, vec![true, false, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true, false, true], 0)); assert_eq!(Council::voters(), vec![1, 2, 3, 4]); assert_eq!(Council::approvals_of(1), vec![true]); @@ -913,7 +925,7 @@ mod tests { assert_eq!(Council::approvals_of(3), vec![false, true, true]); assert_eq!(Council::approvals_of(4), vec![true, false, true]); - assert_ok!(Council::retract_voter(&1, 0)); + assert_ok!(Council::retract_voter(Origin::signed(1), 0)); assert_eq!(Council::voters(), vec![4, 2, 3]); assert_eq!(Council::approvals_of(1), Vec::::new()); @@ -921,7 +933,7 @@ mod tests { assert_eq!(Council::approvals_of(3), vec![false, true, true]); assert_eq!(Council::approvals_of(4), vec![true, false, true]); - assert_ok!(Council::retract_voter(&2, 1)); + assert_ok!(Council::retract_voter(Origin::signed(2), 1)); assert_eq!(Council::voters(), vec![4, 3]); assert_eq!(Council::approvals_of(1), Vec::::new()); @@ -929,7 +941,7 @@ mod tests { assert_eq!(Council::approvals_of(3), vec![false, true, true]); assert_eq!(Council::approvals_of(4), vec![true, false, true]); - assert_ok!(Council::retract_voter(&3, 1)); + assert_ok!(Council::retract_voter(Origin::signed(3), 1)); assert_eq!(Council::voters(), vec![4]); assert_eq!(Council::approvals_of(1), Vec::::new()); @@ -943,11 +955,11 @@ mod tests { fn invalid_retraction_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(&3, 0)); - assert_ok!(Council::set_approvals(&1, vec![true], 0)); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_eq!(Council::voters(), vec![1, 2]); - assert_noop!(Council::retract_voter(&1, 1), "retraction index mismatch"); + assert_noop!(Council::retract_voter(Origin::signed(1), 1), "retraction index mismatch"); }); } @@ -955,9 +967,9 @@ mod tests { fn overflow_retraction_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(&3, 0)); - assert_ok!(Council::set_approvals(&1, vec![true], 0)); - assert_noop!(Council::retract_voter(&1, 1), "retraction index invalid"); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_noop!(Council::retract_voter(Origin::signed(1), 1), "retraction index invalid"); }); } @@ -965,9 +977,9 @@ mod tests { fn non_voter_retraction_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(&3, 0)); - assert_ok!(Council::set_approvals(&1, vec![true], 0)); - assert_noop!(Council::retract_voter(&2, 0), "cannot retract non-voter"); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_noop!(Council::retract_voter(Origin::signed(2), 0), "cannot retract non-voter"); }); } @@ -977,10 +989,10 @@ mod tests { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::submit_candidacy(&5, 1)); - assert_ok!(Council::set_approvals(&2, vec![true, false], 0)); - assert_ok!(Council::set_approvals(&5, vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_eq!(Council::voters(), vec![2, 5]); assert_eq!(Council::approvals_of(2), vec![true, false]); assert_eq!(Council::approvals_of(5), vec![false, true]); @@ -988,8 +1000,8 @@ mod tests { System::set_block_number(6); assert!(Council::presentation_active()); - assert_eq!(Council::present_winner(&4, 2.into(), 20, 0), Ok(())); - assert_eq!(Council::present_winner(&4, 5.into(), 50, 0), Ok(())); + assert_eq!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0), Ok(())); + assert_eq!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0), Ok(())); assert_eq!(Council::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); assert_ok!(Council::end_block(System::block_number())); @@ -1011,16 +1023,16 @@ mod tests { assert!(Balances::can_slash(&4, 10)); System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::submit_candidacy(&5, 1)); - assert_ok!(Council::set_approvals(&2, vec![true, false], 0)); - assert_ok!(Council::set_approvals(&5, vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 0)); - assert_eq!(Council::present_winner(&4, 5.into(), 50, 0), Err("duplicate presentation")); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0)); + assert_eq!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0), Err("duplicate presentation")); assert_ok!(Council::end_block(System::block_number())); assert_eq!(Council::active_council(), vec![(5, 11), (2, 11)]); @@ -1032,24 +1044,24 @@ mod tests { fn retracting_inactive_voter_should_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::set_approvals(&5, vec![true], 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 1)); assert_ok!(Council::end_block(System::block_number())); - assert_ok!(Council::reap_inactive_voter(&5, + assert_ok!(Council::reap_inactive_voter(Origin::signed(5), Council::voters().iter().position(|&i| i == 5).unwrap() as u32, 2.into(), Council::voters().iter().position(|&i| i == 2).unwrap() as u32, 2 @@ -1066,21 +1078,21 @@ mod tests { fn presenting_for_double_election_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_eq!(Council::submit_candidacy(&2, 0), Ok(())); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_eq!(Council::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_eq!(Council::submit_candidacy(&2, 0), Ok(())); - assert_ok!(Council::set_approvals(&2, vec![true], 1)); + assert_eq!(Council::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_noop!(Council::present_winner(&4, 2.into(), 20, 1), "candidate must not form a duplicated member if elected"); + assert_noop!(Council::present_winner(Origin::signed(4), 2.into(), 20, 1), "candidate must not form a duplicated member if elected"); }); } @@ -1088,27 +1100,27 @@ mod tests { fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::set_approvals(&5, vec![true], 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(11); - assert_ok!(Council::submit_candidacy(&1, 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Council::reap_inactive_voter(&5, + assert_ok!(Council::reap_inactive_voter(Origin::signed(5), Council::voters().iter().position(|&i| i == 5).unwrap() as u32, 2.into(), Council::voters().iter().position(|&i| i == 2).unwrap() as u32, 2 @@ -1125,24 +1137,24 @@ mod tests { fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::set_approvals(&5, vec![true], 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 1)); assert_ok!(Council::end_block(System::block_number())); - assert_noop!(Council::reap_inactive_voter(&2, + assert_noop!(Council::reap_inactive_voter(Origin::signed(2), 42, 2.into(), Council::voters().iter().position(|&i| i == 2).unwrap() as u32, 2 @@ -1154,24 +1166,24 @@ mod tests { fn retracting_inactive_voter_with_bad_target_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::set_approvals(&5, vec![true], 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 1)); assert_ok!(Council::end_block(System::block_number())); - assert_noop!(Council::reap_inactive_voter(&2, + assert_noop!(Council::reap_inactive_voter(Origin::signed(2), Council::voters().iter().position(|&i| i == 2).unwrap() as u32, 2.into(), 42, 2 @@ -1183,33 +1195,33 @@ mod tests { fn attempting_to_retract_active_voter_should_slash_reporter() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::submit_candidacy(&3, 1)); - assert_ok!(Council::submit_candidacy(&4, 2)); - assert_ok!(Council::submit_candidacy(&5, 3)); - assert_ok!(Council::set_approvals(&2, vec![true, false, false, false], 0)); - assert_ok!(Council::set_approvals(&3, vec![false, true, false, false], 0)); - assert_ok!(Council::set_approvals(&4, vec![false, false, true, false], 0)); - assert_ok!(Council::set_approvals(&5, vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 2)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 3)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false, false, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, false, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); - assert_ok!(Council::present_winner(&4, 3.into(), 30, 0)); - assert_ok!(Council::present_winner(&4, 4.into(), 40, 0)); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::set_desired_seats(3)); + assert_ok!(Council::set_desired_seats(Origin::ROOT, 3)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 1)); - assert_ok!(Council::present_winner(&4, 3.into(), 30, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30, 1)); assert_ok!(Council::end_block(System::block_number())); - assert_ok!(Council::reap_inactive_voter(&4, + assert_ok!(Council::reap_inactive_voter(Origin::signed(4), Council::voters().iter().position(|&i| i == 4).unwrap() as u32, 2.into(), Council::voters().iter().position(|&i| i == 2).unwrap() as u32, 2 @@ -1225,28 +1237,28 @@ mod tests { fn attempting_to_retract_inactive_voter_by_nonvoter_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::set_approvals(&2, vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(&5, 0)); - assert_ok!(Council::set_approvals(&5, vec![true], 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 1)); assert_ok!(Council::end_block(System::block_number())); - assert_noop!(Council::reap_inactive_voter(&4, + assert_noop!(Council::reap_inactive_voter(Origin::signed(4), 0, 2.into(), Council::voters().iter().position(|&i| i == 2).unwrap() as u32, 2 - ), "reaper must be a voter"); + ), "reporter must be a voter"); }); } @@ -1254,24 +1266,24 @@ mod tests { fn presenting_loser_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&1, 0)); - assert_ok!(Council::set_approvals(&6, vec![true], 0)); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::set_approvals(&2, vec![false, true], 0)); - assert_ok!(Council::submit_candidacy(&3, 2)); - assert_ok!(Council::set_approvals(&3, vec![false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&4, 3)); - assert_ok!(Council::set_approvals(&4, vec![false, false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&5, 4)); - assert_ok!(Council::set_approvals(&5, vec![false, false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 1.into(), 60, 0)); - assert_ok!(Council::present_winner(&4, 3.into(), 30, 0)); - assert_ok!(Council::present_winner(&4, 4.into(), 40, 0)); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 0)); - assert_noop!(Council::present_winner(&4, 2.into(), 20, 0), "candidate not worthy of leaderboard"); + assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0)); + assert_noop!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0), "candidate not worthy of leaderboard"); }); } @@ -1279,24 +1291,24 @@ mod tests { fn presenting_loser_first_should_not_matter() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&1, 0)); - assert_ok!(Council::set_approvals(&6, vec![true], 0)); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::set_approvals(&2, vec![false, true], 0)); - assert_ok!(Council::submit_candidacy(&3, 2)); - assert_ok!(Council::set_approvals(&3, vec![false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&4, 3)); - assert_ok!(Council::set_approvals(&4, vec![false, false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&5, 4)); - assert_ok!(Council::set_approvals(&5, vec![false, false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 2.into(), 20, 0)); - assert_ok!(Council::present_winner(&4, 1.into(), 60, 0)); - assert_ok!(Council::present_winner(&4, 3.into(), 30, 0)); - assert_ok!(Council::present_winner(&4, 4.into(), 40, 0)); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0)); assert_eq!(Council::leaderboard(), Some(vec![ (30, 3), @@ -1312,7 +1324,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_noop!(Council::present_winner(&5, 5.into(), 1, 0), "cannot present outside of presentation period"); + assert_noop!(Council::present_winner(Origin::signed(5), 5.into(), 1, 0), "cannot present outside of presentation period"); }); } @@ -1320,14 +1332,14 @@ mod tests { fn present_with_invalid_vote_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::submit_candidacy(&5, 1)); - assert_ok!(Council::set_approvals(&2, vec![true, false], 0)); - assert_ok!(Council::set_approvals(&5, vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_noop!(Council::present_winner(&4, 2.into(), 20, 1), "index not current"); + assert_noop!(Council::present_winner(Origin::signed(4), 2.into(), 20, 1), "index not current"); }); } @@ -1337,16 +1349,16 @@ mod tests { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_ok!(Council::submit_candidacy(&1, 0)); - assert_ok!(Council::submit_candidacy(&5, 1)); - assert_ok!(Council::set_approvals(&2, vec![true, false], 0)); - assert_ok!(Council::set_approvals(&5, vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); assert_eq!(Balances::free_balance(&1), 1); assert_eq!(Balances::reserved_balance(&1), 9); - assert_noop!(Council::present_winner(&1, 1.into(), 20, 0), "presenter must have sufficient slashable funds"); + assert_noop!(Council::present_winner(Origin::signed(1), 1.into(), 20, 0), "presenter must have sufficient slashable funds"); }); } @@ -1357,14 +1369,14 @@ mod tests { assert!(!Council::presentation_active()); assert_eq!(Balances::total_balance(&4), 40); - assert_ok!(Council::submit_candidacy(&2, 0)); - assert_ok!(Council::submit_candidacy(&5, 1)); - assert_ok!(Council::set_approvals(&2, vec![true, false], 0)); - assert_ok!(Council::set_approvals(&5, vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_err!(Council::present_winner(&4, 2.into(), 80, 0), "incorrect total"); + assert_err!(Council::present_winner(Origin::signed(4), 2.into(), 80, 0), "incorrect total"); assert_eq!(Balances::total_balance(&4), 38); }); @@ -1376,31 +1388,31 @@ mod tests { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_ok!(Council::submit_candidacy(&1, 0)); - assert_ok!(Council::set_approvals(&6, vec![true], 0)); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::set_approvals(&2, vec![false, true], 0)); - assert_ok!(Council::submit_candidacy(&3, 2)); - assert_ok!(Council::set_approvals(&3, vec![false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&4, 3)); - assert_ok!(Council::set_approvals(&4, vec![false, false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&5, 4)); - assert_ok!(Council::set_approvals(&5, vec![false, false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); assert!(Council::presentation_active()); - assert_ok!(Council::present_winner(&4, 1.into(), 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60, 0)); assert_eq!(Council::leaderboard(), Some(vec![ (0, 0), (0, 0), (0, 0), (60, 1) ])); - assert_ok!(Council::present_winner(&4, 3.into(), 30, 0)); - assert_ok!(Council::present_winner(&4, 4.into(), 40, 0)); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0)); assert_eq!(Council::leaderboard(), Some(vec![ (30, 3), (40, 4), @@ -1433,33 +1445,33 @@ mod tests { fn second_tally_should_use_runners_up() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(&1, 0)); - assert_ok!(Council::set_approvals(&6, vec![true], 0)); - assert_ok!(Council::submit_candidacy(&2, 1)); - assert_ok!(Council::set_approvals(&2, vec![false, true], 0)); - assert_ok!(Council::submit_candidacy(&3, 2)); - assert_ok!(Council::set_approvals(&3, vec![false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&4, 3)); - assert_ok!(Council::set_approvals(&4, vec![false, false, false, true], 0)); - assert_ok!(Council::submit_candidacy(&5, 4)); - assert_ok!(Council::set_approvals(&5, vec![false, false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(&4, 1.into(), 60, 0)); - assert_ok!(Council::present_winner(&4, 3.into(), 30, 0)); - assert_ok!(Council::present_winner(&4, 4.into(), 40, 0)); - assert_ok!(Council::present_winner(&4, 5.into(), 50, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::set_approvals(&6, vec![false, false, true, false], 1)); - assert_ok!(Council::set_desired_seats(3)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![false, false, true, false], 1)); + assert_ok!(Council::set_desired_seats(Origin::ROOT, 3)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(&4, 3.into(), 90, 1)); - assert_ok!(Council::present_winner(&4, 4.into(), 40, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 90, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40, 1)); assert_ok!(Council::end_block(System::block_number())); assert!(!Council::presentation_active()); diff --git a/substrate/runtime/council/src/voting.rs b/substrate/runtime/council/src/voting.rs index 41910d2074a02..5d14f68c9d5e1 100644 --- a/substrate/runtime/council/src/voting.rs +++ b/substrate/runtime/council/src/voting.rs @@ -18,27 +18,22 @@ use rstd::prelude::*; use rstd::borrow::Borrow; -use primitives::traits::{OnFinalise, RefInto, Hash}; +use primitives::traits::{OnFinalise, Hash}; use runtime_io::print; use substrate_runtime_support::dispatch::Result; use substrate_runtime_support::{StorageValue, StorageMap, IsSubType}; use {system, democracy}; use super::{Trait, Module as Council}; +use system::{ensure_signed, ensure_root}; decl_module! { - pub struct Module; + pub struct Module for enum Call where origin: T::Origin { + fn propose(origin, proposal: Box) -> Result; + fn vote(origin, proposal: T::Hash, approve: bool) -> Result; + fn veto(origin, proposal_hash: T::Hash) -> Result; - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn propose(aux, proposal: Box) -> Result; - fn vote(aux, proposal: T::Hash, approve: bool) -> Result; - fn veto(aux, proposal_hash: T::Hash) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn set_cooloff_period(blocks: T::BlockNumber) -> Result; - fn set_voting_period(blocks: T::BlockNumber) -> Result; + fn set_cooloff_period(origin, blocks: T::BlockNumber) -> Result; + fn set_voting_period(origin, blocks: T::BlockNumber) -> Result; } } @@ -78,9 +73,11 @@ impl Module { } // Dispatch - fn propose(aux: &T::PublicAux, proposal: Box) -> Result { + fn propose(origin: T::Origin, proposal: Box) -> Result { + let who = ensure_signed(origin)?; + let expiry = >::block_number() + Self::voting_period(); - ensure!(Self::will_still_be_councillor_at(aux.ref_into(), expiry), "proposer would not be on council"); + ensure!(Self::will_still_be_councillor_at(&who, expiry), "proposer would not be on council"); let proposal_hash = T::Hashing::hash_of(&proposal); @@ -93,31 +90,35 @@ impl Module { Self::set_proposals(&proposals); >::insert(proposal_hash, *proposal); - >::insert(proposal_hash, vec![aux.ref_into().clone()]); - >::insert((proposal_hash, aux.ref_into().clone()), true); + >::insert(proposal_hash, vec![who.clone()]); + >::insert((proposal_hash, who), true); Ok(()) } - fn vote(aux: &T::PublicAux, proposal: T::Hash, approve: bool) -> Result { - if Self::vote_of((proposal, aux.ref_into().clone())).is_none() { + fn vote(origin: T::Origin, proposal: T::Hash, approve: bool) -> Result { + let who = ensure_signed(origin)?; + + if Self::vote_of((proposal, who.clone())).is_none() { let mut voters = Self::proposal_voters(&proposal); - voters.push(aux.ref_into().clone()); + voters.push(who.clone()); >::insert(proposal, voters); } - >::insert((proposal, aux.ref_into().clone()), approve); + >::insert((proposal, who), approve); Ok(()) } - fn veto(aux: &T::PublicAux, proposal_hash: T::Hash) -> Result { - ensure!(Self::is_councillor(aux.ref_into()), "only councillors may veto council proposals"); + fn veto(origin: T::Origin, proposal_hash: T::Hash) -> Result { + let who = ensure_signed(origin)?; + + ensure!(Self::is_councillor(&who), "only councillors may veto council proposals"); ensure!(>::exists(&proposal_hash), "proposal must exist to be vetoed"); let mut existing_vetoers = Self::veto_of(&proposal_hash) .map(|pair| pair.1) .unwrap_or_else(Vec::new); - let insert_position = existing_vetoers.binary_search(aux.ref_into()) + let insert_position = existing_vetoers.binary_search(&who) .err().ok_or("a councillor may not veto a proposal twice")?; - existing_vetoers.insert(insert_position, aux.ref_into().clone()); + existing_vetoers.insert(insert_position, who); Self::set_veto_of(&proposal_hash, >::block_number() + Self::cooloff_period(), existing_vetoers); Self::set_proposals(&Self::proposals().into_iter().filter(|&(_, h)| h != proposal_hash).collect::>()); @@ -129,12 +130,14 @@ impl Module { Ok(()) } - fn set_cooloff_period(blocks: T::BlockNumber) -> Result { + fn set_cooloff_period(origin: T::Origin, blocks: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(blocks); Ok(()) } - fn set_voting_period(blocks: T::BlockNumber) -> Result { + fn set_voting_period(origin: T::Origin, blocks: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(blocks); Ok(()) } @@ -182,7 +185,7 @@ impl Module { fn end_block(now: T::BlockNumber) -> Result { while let Some((proposal, proposal_hash)) = Self::take_proposal_if_expiring_at(now) { let tally = Self::take_tally(&proposal_hash); - if let Some(&democracy::PrivCall::cancel_referendum(ref_index)) = IsSubType::>::is_sub_type(&proposal) { + if let Some(&democracy::Call::cancel_referendum(ref_index)) = IsSubType::>::is_aux_sub_type(&proposal) { if let (_, 0, 0) = tally { >::internal_cancel_referendum(ref_index); } @@ -217,6 +220,7 @@ impl OnFinalise for Council { mod tests { use super::*; use ::tests::*; + use ::tests::Call; use substrate_runtime_support::Hashable; use democracy::VoteThreshold; @@ -242,12 +246,12 @@ mod tests { }); } - fn set_balance_proposal(value: u64) -> Proposal { - Proposal::Balances(balances::PrivCall::set_balance(balances::address::Address::Id(42), value, 0)) + fn set_balance_proposal(value: u64) -> Call { + Call::Balances(balances::Call::set_balance(balances::address::Address::Id(42), value, 0)) } - fn cancel_referendum_proposal(id: u32) -> Proposal { - Proposal::Democracy(democracy::PrivCall::cancel_referendum(id)) + fn cancel_referendum_proposal(id: u32) -> Call { + Call::Democracy(democracy::Call::cancel_referendum(id)) } #[test] @@ -260,9 +264,9 @@ mod tests { let cancellation = cancel_referendum_proposal(0); let hash = cancellation.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(cancellation))); - assert_ok!(CouncilVoting::vote(&2, hash, true)); - assert_ok!(CouncilVoting::vote(&3, hash, true)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(cancellation))); + assert_ok!(CouncilVoting::vote(Origin::signed(2), hash, true)); + assert_ok!(CouncilVoting::vote(Origin::signed(3), hash, true)); assert_eq!(CouncilVoting::proposals(), vec![(2, hash)]); assert_ok!(CouncilVoting::end_block(System::block_number())); @@ -282,9 +286,9 @@ mod tests { let cancellation = cancel_referendum_proposal(0); let hash = cancellation.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(cancellation))); - assert_ok!(CouncilVoting::vote(&2, hash, true)); - assert_ok!(CouncilVoting::vote(&3, hash, false)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(cancellation))); + assert_ok!(CouncilVoting::vote(Origin::signed(2), hash, true)); + assert_ok!(CouncilVoting::vote(Origin::signed(3), hash, false)); assert_ok!(CouncilVoting::end_block(System::block_number())); System::set_block_number(2); @@ -302,8 +306,8 @@ mod tests { let cancellation = cancel_referendum_proposal(0); let hash = cancellation.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(cancellation))); - assert_ok!(CouncilVoting::vote(&2, hash, true)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(cancellation))); + assert_ok!(CouncilVoting::vote(Origin::signed(2), hash, true)); assert_ok!(CouncilVoting::end_block(System::block_number())); System::set_block_number(2); @@ -318,8 +322,8 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::veto(&2, hash)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::veto(Origin::signed(2), hash)); assert_eq!(CouncilVoting::proposals().len(), 0); assert_eq!(Democracy::active_referendums().len(), 0); }); @@ -331,12 +335,12 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::veto(&2, hash)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::veto(Origin::signed(2), hash)); System::set_block_number(3); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_noop!(CouncilVoting::veto(&2, hash), "a councillor may not veto a proposal twice"); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_noop!(CouncilVoting::veto(Origin::signed(2), hash), "a councillor may not veto a proposal twice"); }); } @@ -346,11 +350,11 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::veto(&2, hash)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::veto(Origin::signed(2), hash)); System::set_block_number(2); - assert_noop!(CouncilVoting::propose(&1, Box::new(proposal.clone())), "proposal is vetoed"); + assert_noop!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone())), "proposal is vetoed"); }); } @@ -360,13 +364,13 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::veto(&2, hash)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::veto(Origin::signed(2), hash)); System::set_block_number(3); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::vote(&2, hash, false)); - assert_ok!(CouncilVoting::vote(&3, hash, true)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::vote(Origin::signed(2), hash, false)); + assert_ok!(CouncilVoting::vote(Origin::signed(3), hash, true)); assert_ok!(CouncilVoting::end_block(System::block_number())); System::set_block_number(4); @@ -382,12 +386,12 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::veto(&2, hash)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::veto(Origin::signed(2), hash)); System::set_block_number(3); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::veto(&3, hash)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::veto(Origin::signed(3), hash)); assert_eq!(CouncilVoting::proposals().len(), 0); assert_eq!(Democracy::active_referendums().len(), 0); }); @@ -399,7 +403,7 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); assert_eq!(CouncilVoting::proposals().len(), 1); assert_eq!(CouncilVoting::proposal_voters(&hash), vec![1]); assert_eq!(CouncilVoting::vote_of((hash, 1)), Some(true)); @@ -412,7 +416,7 @@ mod tests { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); let proposal = set_balance_proposal(42); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (1, 0, 2)); assert_ok!(CouncilVoting::end_block(System::block_number())); @@ -428,9 +432,9 @@ mod tests { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); let proposal = set_balance_proposal(42); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::vote(&2, proposal.blake2_256().into(), true)); - assert_ok!(CouncilVoting::vote(&3, proposal.blake2_256().into(), true)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::vote(Origin::signed(2), proposal.blake2_256().into(), true)); + assert_ok!(CouncilVoting::vote(Origin::signed(3), proposal.blake2_256().into(), true)); assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (3, 0, 0)); assert_ok!(CouncilVoting::end_block(System::block_number())); @@ -446,9 +450,9 @@ mod tests { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); let proposal = set_balance_proposal(42); - assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); - assert_ok!(CouncilVoting::vote(&2, proposal.blake2_256().into(), true)); - assert_ok!(CouncilVoting::vote(&3, proposal.blake2_256().into(), false)); + assert_ok!(CouncilVoting::propose(Origin::signed(1), Box::new(proposal.clone()))); + assert_ok!(CouncilVoting::vote(Origin::signed(2), proposal.blake2_256().into(), true)); + assert_ok!(CouncilVoting::vote(Origin::signed(3), proposal.blake2_256().into(), false)); assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (2, 1, 0)); assert_ok!(CouncilVoting::end_block(System::block_number())); @@ -464,7 +468,7 @@ mod tests { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); let proposal = set_balance_proposal(42); - assert_noop!(CouncilVoting::propose(&4, Box::new(proposal)), "proposer would not be on council"); + assert_noop!(CouncilVoting::propose(Origin::signed(4), Box::new(proposal)), "proposer would not be on council"); }); } } diff --git a/substrate/runtime/democracy/Cargo.toml b/substrate/runtime/democracy/Cargo.toml index 602bf1adb4190..4667e22be3781 100644 --- a/substrate/runtime/democracy/Cargo.toml +++ b/substrate/runtime/democracy/Cargo.toml @@ -31,6 +31,7 @@ std = [ "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", + "substrate-runtime-consensus/std", "substrate-runtime-balances/std", "substrate-runtime-system/std", ] diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index b68c072d15ba2..28e467296429a 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -43,9 +43,10 @@ extern crate substrate_runtime_system as system; use rstd::prelude::*; use rstd::result; -use primitives::traits::{Zero, OnFinalise, RefInto, As, MaybeSerializeDebug}; +use primitives::traits::{Zero, OnFinalise, As, MaybeSerializeDebug}; use substrate_runtime_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType}; use substrate_runtime_support::dispatch::Result; +use system::{ensure_signed, ensure_root}; #[cfg(any(feature = "std", test))] use std::collections::HashMap; @@ -59,23 +60,17 @@ pub type PropIndex = u32; pub type ReferendumIndex = u32; pub trait Trait: balances::Trait + Sized { - type Proposal: Parameter + Dispatchable + IsSubType> + MaybeSerializeDebug; + type Proposal: Parameter + Dispatchable + IsSubType> + MaybeSerializeDebug; } decl_module! { - pub struct Module; + pub struct Module for enum Call where origin: T::Origin { + fn propose(origin, proposal: Box, value: T::Balance) -> Result; + fn second(origin, proposal: PropIndex) -> Result; + fn vote(origin, ref_index: ReferendumIndex, approve_proposal: bool) -> Result; - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn propose(aux, proposal: Box, value: T::Balance) -> Result; - fn second(aux, proposal: PropIndex) -> Result; - fn vote(aux, ref_index: ReferendumIndex, approve_proposal: bool) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn start_referendum(proposal: Box, vote_threshold: VoteThreshold) -> Result; - fn cancel_referendum(ref_index: ReferendumIndex) -> Result; + fn start_referendum(origin, proposal: Box, vote_threshold: VoteThreshold) -> Result; + fn cancel_referendum(origin, ref_index: ReferendumIndex) -> Result; } } @@ -156,49 +151,53 @@ impl Module { // dispatching. /// Propose a sensitive action to be taken. - fn propose(aux: &T::PublicAux, proposal: Box, value: T::Balance) -> Result { + fn propose(origin: T::Origin, proposal: Box, value: T::Balance) -> Result { + let who = ensure_signed(origin)?; ensure!(value >= Self::minimum_deposit(), "value too low"); - >::reserve(aux.ref_into(), value) + >::reserve(&who, value) .map_err(|_| "proposer's balance too low")?; let index = Self::public_prop_count(); >::put(index + 1); - >::insert(index, (value, vec![aux.ref_into().clone()])); + >::insert(index, (value, vec![who.clone()])); let mut props = Self::public_props(); - props.push((index, (*proposal).clone(), aux.ref_into().clone())); + props.push((index, (*proposal).clone(), who)); >::put(props); Ok(()) } /// Propose a sensitive action to be taken. - fn second(aux: &T::PublicAux, proposal: PropIndex) -> Result { + fn second(origin: T::Origin, proposal: PropIndex) -> Result { + let who = ensure_signed(origin)?; let mut deposit = Self::deposit_of(proposal) .ok_or("can only second an existing proposal")?; - >::reserve(aux.ref_into(), deposit.0) + >::reserve(&who, deposit.0) .map_err(|_| "seconder's balance too low")?; - deposit.1.push(aux.ref_into().clone()); + deposit.1.push(who); >::insert(proposal, deposit); Ok(()) } /// Vote in a referendum. If `approve_proposal` is true, the vote is to enact the proposal; /// false would be a vote to keep the status quo.. - fn vote(aux: &T::PublicAux, ref_index: ReferendumIndex, approve_proposal: bool) -> Result { + fn vote(origin: T::Origin, ref_index: ReferendumIndex, approve_proposal: bool) -> Result { + let who = ensure_signed(origin)?; ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - ensure!(!>::total_balance(aux.ref_into()).is_zero(), + ensure!(!>::total_balance(&who).is_zero(), "transactor must have balance to signal approval."); - if !>::exists(&(ref_index, aux.ref_into().clone())) { + if !>::exists(&(ref_index, who.clone())) { let mut voters = Self::voters_for(ref_index); - voters.push(aux.ref_into().clone()); + voters.push(who.clone()); >::insert(ref_index, voters); } - >::insert(&(ref_index, aux.ref_into().clone()), approve_proposal); + >::insert(&(ref_index, who), approve_proposal); Ok(()) } /// Start a referendum. - fn start_referendum(proposal: Box, vote_threshold: VoteThreshold) -> Result { + fn start_referendum(origin: T::Origin, proposal: Box, vote_threshold: VoteThreshold) -> Result { + ensure_root(origin)?; Self::inject_referendum( >::block_number() + Self::voting_period(), *proposal, @@ -207,7 +206,8 @@ impl Module { } /// Remove a referendum. - fn cancel_referendum(ref_index: ReferendumIndex) -> Result { + fn cancel_referendum(origin: T::Origin, ref_index: ReferendumIndex) -> Result { + ensure_root(origin)?; Self::clear_referendum(ref_index); Ok(()) } @@ -280,7 +280,7 @@ impl Module { let total_stake = >::total_stake(); Self::clear_referendum(index); if vote_threshold.approved(approve, against, total_stake) { - proposal.dispatch()?; + proposal.dispatch(system::RawOrigin::Root.into())?; } >::put(index + 1); } @@ -354,9 +354,12 @@ mod tests { use primitives::traits::{BlakeTwo256}; use primitives::testing::{Digest, Header}; + impl_outer_origin! { + pub enum Origin for Test {} + } + impl_outer_dispatch! { - #[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)] - pub enum Proposal { + pub enum Call where origin: Origin { Balances, Democracy, } @@ -366,7 +369,7 @@ mod tests { #[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct Test; impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -384,7 +387,7 @@ mod tests { type Event = (); } impl Trait for Test { - type Proposal = Proposal; + type Proposal = Call; } fn new_test_ext() -> runtime_io::TestExternalities { @@ -422,12 +425,12 @@ mod tests { }); } - fn set_balance_proposal(value: u64) -> Proposal { - Proposal::Balances(balances::PrivCall::set_balance(balances::address::Address::Id(42), value, 0)) + fn set_balance_proposal(value: u64) -> Call { + Call::Balances(balances::Call::set_balance(balances::address::Address::Id(42), value, 0)) } fn propose_set_balance(who: u64, value: u64, locked: u64) -> super::Result { - Democracy::propose(&who, Box::new(set_balance_proposal(value)), locked) + Democracy::propose(Origin::signed(who), Box::new(set_balance_proposal(value)), locked) } #[test] @@ -452,7 +455,7 @@ mod tests { System::set_block_number(2); let r = 0; - assert_ok!(Democracy::vote(&1, r, true)); + assert_ok!(Democracy::vote(Origin::signed(1), r, true)); assert_eq!(Democracy::referendum_count(), 1); assert_eq!(Democracy::voters_for(r), vec![1]); @@ -470,10 +473,10 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 5)); - assert_ok!(Democracy::second(&2, 0)); - assert_ok!(Democracy::second(&5, 0)); - assert_ok!(Democracy::second(&5, 0)); - assert_ok!(Democracy::second(&5, 0)); + assert_ok!(Democracy::second(Origin::signed(2), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); assert_eq!(Balances::free_balance(&1), 5); assert_eq!(Balances::free_balance(&2), 15); assert_eq!(Balances::free_balance(&5), 35); @@ -485,10 +488,10 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 5)); - assert_ok!(Democracy::second(&2, 0)); - assert_ok!(Democracy::second(&5, 0)); - assert_ok!(Democracy::second(&5, 0)); - assert_ok!(Democracy::second(&5, 0)); + assert_ok!(Democracy::second(Origin::signed(2), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&1), 10); assert_eq!(Balances::free_balance(&2), 20); @@ -517,7 +520,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); assert_ok!(propose_set_balance(2, 2, 11)); - assert_noop!(Democracy::second(&1, 0), "seconder\'s balance too low"); + assert_noop!(Democracy::second(Origin::signed(1), 0), "seconder\'s balance too low"); }); } @@ -531,17 +534,17 @@ mod tests { assert_eq!(Democracy::end_block(System::block_number()), Ok(())); System::set_block_number(1); - assert_ok!(Democracy::vote(&1, 0, true)); + assert_ok!(Democracy::vote(Origin::signed(1), 0, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&42), 4); System::set_block_number(2); - assert_ok!(Democracy::vote(&1, 1, true)); + assert_ok!(Democracy::vote(Origin::signed(1), 1, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&42), 3); System::set_block_number(3); - assert_ok!(Democracy::vote(&1, 2, true)); + assert_ok!(Democracy::vote(Origin::signed(1), 2, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); }); } @@ -551,7 +554,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); - assert_ok!(Democracy::vote(&1, r, true)); + assert_ok!(Democracy::vote(Origin::signed(1), r, true)); assert_eq!(Democracy::voters_for(r), vec![1]); assert_eq!(Democracy::vote_of((r, 1)), Some(true)); @@ -568,8 +571,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); - assert_ok!(Democracy::vote(&1, r, true)); - assert_ok!(Democracy::cancel_referendum(r)); + assert_ok!(Democracy::vote(Origin::signed(1), r, true)); + assert_ok!(Democracy::cancel_referendum(Origin::ROOT, r)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); @@ -582,7 +585,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); - assert_ok!(Democracy::vote(&1, r, false)); + assert_ok!(Democracy::vote(Origin::signed(1), r, false)); assert_eq!(Democracy::voters_for(r), vec![1]); assert_eq!(Democracy::vote_of((r, 1)), Some(false)); @@ -599,12 +602,12 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); - assert_ok!(Democracy::vote(&1, r, true)); - assert_ok!(Democracy::vote(&2, r, false)); - assert_ok!(Democracy::vote(&3, r, false)); - assert_ok!(Democracy::vote(&4, r, true)); - assert_ok!(Democracy::vote(&5, r, false)); - assert_ok!(Democracy::vote(&6, r, true)); + assert_ok!(Democracy::vote(Origin::signed(1), r, true)); + assert_ok!(Democracy::vote(Origin::signed(2), r, false)); + assert_ok!(Democracy::vote(Origin::signed(3), r, false)); + assert_ok!(Democracy::vote(Origin::signed(4), r, true)); + assert_ok!(Democracy::vote(Origin::signed(5), r, false)); + assert_ok!(Democracy::vote(Origin::signed(6), r, true)); assert_eq!(Democracy::tally(r), (110, 100)); @@ -619,8 +622,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); - assert_ok!(Democracy::vote(&5, r, false)); - assert_ok!(Democracy::vote(&6, r, true)); + assert_ok!(Democracy::vote(Origin::signed(5), r, false)); + assert_ok!(Democracy::vote(Origin::signed(6), r, true)); assert_eq!(Democracy::tally(r), (60, 50)); @@ -638,9 +641,9 @@ mod tests { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); - assert_ok!(Democracy::vote(&4, r, true)); - assert_ok!(Democracy::vote(&5, r, false)); - assert_ok!(Democracy::vote(&6, r, true)); + assert_ok!(Democracy::vote(Origin::signed(4), r, true)); + assert_ok!(Democracy::vote(Origin::signed(5), r, false)); + assert_ok!(Democracy::vote(Origin::signed(6), r, true)); assert_eq!(Democracy::tally(r), (100, 50)); diff --git a/substrate/runtime/example/src/lib.rs b/substrate/runtime/example/src/lib.rs index aa17511869572..a7953074c1048 100644 --- a/substrate/runtime/example/src/lib.rs +++ b/substrate/runtime/example/src/lib.rs @@ -60,6 +60,7 @@ extern crate substrate_runtime_balances as balances; use runtime_primitives::traits::OnFinalise; use runtime_support::{StorageValue, dispatch::Result}; +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 @@ -73,45 +74,44 @@ pub trait Trait: balances::Trait { // The module declaration. This states the entry points that we handle. The // macro takes care of the marshalling of arguments and dispatch. +// +// Anyone can have these functions execute by signing and submitting +// an extrinsic. Ensure that calls into each of these execute in a time, memory and +// using storage space proportional to any costs paid for by the caller or otherwise the +// difficulty of forcing the call to happen. +// +// Generally you'll want to split these into three groups: +// - Public calls that are signed by an external account. +// - Root calls that are allowed to be made only by the governance system. +// - Inherent calls that are allowed to be made only by the block authors and validators. +// +// 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) { ... }` +// +// There are three entries in the `system::Origin` enum that correspond +// 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`. decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. - pub struct Module; - - // The unpriviledged entry points. Any account can call into these by signing and submitting - // an extrinsic. Ensure that calls into each of these execute in a time, memory and - // using storage space proportional to any costs paid for by the caller. - // - // The account that is calling this (i.e. the one that signed the extrinsic) is provided - // via the `aux` argument, always first in each function call. As such functions must - // always look like: - // - // `fn foo(aux, 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>`). The index after `=` must be unique within this - // enum (the `PrivCall` enum is allowed to reuse indexes). - // - // When you come to `impl` them later in the module, you must specify the full type for `aux`: - // - // `fn foo(aux: T::PublicAux, bar: Bar, baz: Baz) { ... }` - // - // This is your public interface. Be extremely careful. - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - // This is just a simple example of how to interact with the module from the external - // world. - fn accumulate_dummy(aux, increase_by: T::Balance) -> Result; - } - - // The priviledged entry points. These are provided to allow any governance modules in - // the runtime to be able to execute common functions. Unlike for `Call` there is no - // auxilliary data to encode the sender (since there is no sender). Though still important - // to ensure that these execute in reasonable time and space, they can do what would - // otherwise be costly or unsafe operations. - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - // A priviledged call; in this case it resets our dummy value to something new. - fn set_dummy(new_dummy: T::Balance) -> Result; + pub struct Module for enum Call where origin: T::Origin { + /// This is your public interface. Be extremely careful. + /// This is just a simple example of how to interact with the module from the external + /// world. + fn accumulate_dummy(origin, increase_by: T::Balance) -> Result; + + /// A priviledged call; in this case it resets our dummy value to something new. + fn set_dummy(origin, new_dummy: T::Balance) -> Result; } } @@ -190,7 +190,7 @@ impl Module { >::deposit_event(::Event::from(event).into()); } - // Implement Calls/PrivCalls and add public immutables and private mutables. + // Implement Calls and add public immutables and private mutables. // Implement dispatched function `accumulate_dummy`. This just increases the value // of `Dummy` by `increase_by`. @@ -206,7 +206,7 @@ impl Module { // 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 // is followed, you should do all tests for validity at the top of your function. This - // is stuff like checking the sender (`aux`) or that state is such that the operation + // 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. @@ -227,7 +227,10 @@ impl Module { // no progress. // // If you don't respect these rules, it is likely that your chain will be attackable. - fn accumulate_dummy(_aux: &T::PublicAux, increase_by: T::Balance) -> Result { + fn accumulate_dummy(origin: T::Origin, increase_by: T::Balance) -> Result { + // This is a public call, so we ensure that the origin is some signed account. + let _sender = ensure_signed(origin)?; + // Read the value of dummy from storage. let dummy = Self::dummy(); // Will also work using the `::get` on the storage item type iself: @@ -248,13 +251,16 @@ impl Module { Ok(()) } - // Implementation of a priviledged call. This doesn't have an `aux` parameter because + // Implementation of a priviledged call. This doesn't have an `origin` parameter because // it's not (directly) from an extrinsic, but rather the system as a whole has decided // to execute it. Different runtimes have different reasons for allow priviledged // calls to be executed - we don't need to care why. Because it's priviledged, we can // assume it's a one-off operation and substantial processing/storage/memory can be used // without worrying about gameability or attack scenarios. - fn set_dummy(new_value: T::Balance) -> Result { + fn set_dummy(origin: T::Origin, new_value: T::Balance) -> Result { + // This is a privileged call, so we ensure that the origin is "Root". + ensure_root(origin)?; + // Put the new value into storage. >::put(new_value); @@ -323,13 +329,17 @@ mod tests { // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. use runtime_primitives::testing::{Digest, Header}; + impl_outer_origin! { + pub enum Origin for Test {} + } + // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -370,7 +380,7 @@ mod tests { assert_eq!(Example::dummy(), Some(42)); // Check that accumulate works when we have Some value in Dummy already. - assert_ok!(Example::accumulate_dummy(&0, 27)); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); assert_eq!(Example::dummy(), Some(69)); // Check that finalising the block removes Dummy from storage. @@ -378,7 +388,7 @@ mod tests { assert_eq!(Example::dummy(), None); // Check that accumulate works when we Dummy has None in it. - assert_ok!(Example::accumulate_dummy(&0, 42)); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); assert_eq!(Example::dummy(), Some(42)); }); } diff --git a/substrate/runtime/executive/Cargo.toml b/substrate/runtime/executive/Cargo.toml index 74a10d18f8642..965bbe2a1e2c1 100644 --- a/substrate/runtime/executive/Cargo.toml +++ b/substrate/runtime/executive/Cargo.toml @@ -8,7 +8,6 @@ hex-literal = "0.1.0" serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } substrate-codec = { path = "../../codec", default_features = false } -substrate-codec-derive = { path = "../../codec/derive", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } @@ -18,10 +17,7 @@ substrate-runtime-system = { path = "../system", default_features = false } [dev-dependencies] substrate-primitives = { path = "../../primitives" } substrate-runtime-balances = { path = "../balances" } -substrate-runtime-session = { path = "../session" } -substrate-runtime-staking = { path = "../staking" } -substrate-runtime-consensus = { path = "../consensus" } -substrate-runtime-timestamp = { path = "../timestamp" } +substrate-codec-derive = { path = "../../codec/derive" } [features] default = ["std"] @@ -31,7 +27,6 @@ std = [ "serde/std", "serde_derive", "substrate-codec/std", - "substrate-codec-derive/std", "substrate-runtime-primitives/std", "substrate-runtime-io/std", "substrate-runtime-system/std", diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 9e0db49391fa2..060e0c32e99e6 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -37,9 +37,6 @@ extern crate substrate_codec as codec; extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_system as system; -#[cfg(test)] -extern crate substrate_runtime_timestamp as timestamp; - #[cfg(test)] #[macro_use] extern crate hex_literal; @@ -47,23 +44,14 @@ extern crate hex_literal; #[cfg(test)] extern crate substrate_primitives; -#[cfg(test)] -extern crate substrate_runtime_consensus as consensus; - -#[cfg(test)] -extern crate substrate_runtime_session as session; - #[cfg(test)] extern crate substrate_runtime_balances as balances; -#[cfg(test)] -extern crate substrate_runtime_staking as staking; - use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::result; use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise, - MakePayment, Hash, AuxLookup}; + MakePayment, Hash}; use codec::{Codec, Encode}; use system::extrinsics_root; use primitives::{ApplyOutcome, ApplyError}; @@ -94,7 +82,7 @@ impl< Address, System: system::Trait, Block: traits::Block, - Lookup: AuxLookup, + Lookup: traits::Lookup, Payment: MakePayment, Finalisation: OnFinalise, > Executive where @@ -186,20 +174,20 @@ impl< // Verify the signature is good. let xt = uxt.check_with(Lookup::lookup).map_err(internal::ApplyError::BadSignature)?; - if xt.sender() != &Default::default() { + if let Some(sender) = xt.sender() { // check index - let expected_index = >::account_nonce(xt.sender()); + let expected_index = >::account_nonce(sender); if xt.index() != &expected_index { return Err( if xt.index() < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future } ) } // pay any fees. - Payment::make_payment(xt.sender(), encoded_len).map_err(|_| internal::ApplyError::CantPay)?; + Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; // AUDIT: Under no circumstances may this function panic from here onwards. // increment nonce in storage - >::inc_account_nonce(xt.sender()); + >::inc_account_nonce(sender); } // decode parameters and dispatch @@ -231,12 +219,12 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, KeccakHasher}; use primitives::BuildStorage; - use primitives::traits::{Identity, Header as HeaderT, BlakeTwo256, AuxLookup}; + use primitives::traits::{Header as HeaderT, BlakeTwo256, Lookup}; use primitives::testing::{Digest, Header, Block}; use system; struct NullLookup; - impl AuxLookup for NullLookup { + impl Lookup for NullLookup { type Source = u64; type Target = u64; fn lookup(s: Self::Source) -> Result { @@ -244,30 +232,22 @@ mod tests { } } + impl_outer_origin! { + pub enum Origin for Runtime { + } + } + impl_outer_event!{ - pub enum MetaEvent for Test { - balances, session, staking + pub enum MetaEvent for Runtime { + balances } } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] - pub struct Test; - impl consensus::Trait for Test { - const NOTE_OFFLINE_POSITION: u32 = 1; - type Log = u64; - type SessionKey = u64; - type OnOfflineValidator = staking::Module; - } - impl balances::Trait for Test { - type Balance = u64; - type AccountIndex = u64; - type OnFreeBalanceZero = staking::Module; - type EnsureAccountLiquid = staking::Module; - type Event = MetaEvent; - } - impl system::Trait for Test { - type PublicAux = Self::AccountId; + pub struct Runtime; + impl system::Trait for Runtime { + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = substrate_primitives::H256; @@ -277,27 +257,21 @@ mod tests { type Header = Header; type Event = MetaEvent; } - impl session::Trait for Test { - type ConvertAccountIdToSessionKey = Identity; - type OnSessionChange = staking::Module; - type Event = MetaEvent; - } - impl staking::Trait for Test { - type OnRewardMinted = (); + impl balances::Trait for Runtime { + type Balance = u64; + type AccountIndex = u64; + type OnFreeBalanceZero = (); + type EnsureAccountLiquid = (); type Event = MetaEvent; } - impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; - type Moment = u64; - } - type TestXt = primitives::testing::TestXt>; - type Executive = super::Executive, NullLookup, balances::Module, (session::Module, staking::Module)>; + type TestXt = primitives::testing::TestXt>; + type Executive = super::Executive, NullLookup, balances::Module, ()>; #[test] - fn staking_balance_transfer_dispatch_works() { - let mut t = system::GenesisConfig::::default().build_storage().unwrap(); - t.extend(balances::GenesisConfig:: { + fn balance_transfer_dispatch_works() { + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(balances::GenesisConfig:: { balances: vec![(1, 111)], transaction_base_fee: 10, transaction_byte_fee: 0, @@ -306,34 +280,19 @@ mod tests { creation_fee: 0, reclaim_rebate: 0, }.build_storage().unwrap()); - t.extend(staking::GenesisConfig:: { - sessions_per_era: 0, - current_era: 0, - intentions: vec![], - validator_count: 0, - minimum_validator_count: 0, - bonding_duration: 0, - early_era_slash: 0, - session_reward: 0, - offline_slash_grace: 0, - }.build_storage().unwrap()); - let xt = primitives::testing::TestXt((1, 0, Call::transfer(2.into(), 69))); + let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2.into(), 69)); let mut t = runtime_io::TestExternalities::from(t); with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); Executive::apply_extrinsic(xt).unwrap(); - assert_eq!(>::total_balance(&1), 32); - assert_eq!(>::total_balance(&2), 69); + assert_eq!(>::total_balance(&1), 32); + assert_eq!(>::total_balance(&2), 69); }); } fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage().unwrap(); - t.extend(balances::GenesisConfig::::default().build_storage().unwrap()); - t.extend(consensus::GenesisConfig::::default().build_storage().unwrap()); - t.extend(session::GenesisConfig::::default().build_storage().unwrap()); - t.extend(staking::GenesisConfig::::default().build_storage().unwrap()); - t.extend(timestamp::GenesisConfig::::default().build_storage().unwrap()); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(balances::GenesisConfig::::default().build_storage().unwrap()); t.into() } @@ -347,7 +306,7 @@ mod tests { // Blake // state_root: hex!("02532989c613369596025dfcfc821339fc9861987003924913a5a1382f87034a").into(), // Keccak - state_root: hex!("ffe27b4c3a8b421fa10592be61fb28eca7ebbe04cbfa99cdda9f703f35522569").into(), + state_root: hex!("14a253cb1c5f38beeec8bee962a941b2ba0773b7593564fbe62b9c3a46784df5").into(), extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }, @@ -381,7 +340,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("ffe27b4c3a8b421fa10592be61fb28eca7ebbe04cbfa99cdda9f703f35522569").into(), + state_root: hex!("14a253cb1c5f38beeec8bee962a941b2ba0773b7593564fbe62b9c3a46784df5").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, @@ -393,11 +352,11 @@ mod tests { #[test] fn bad_extrinsic_not_inserted() { let mut t = new_test_ext(); - let xt = primitives::testing::TestXt((1, 42, Call::transfer(33.into(), 69))); + let xt = primitives::testing::TestXt(Some(1), 42, Call::transfer(33.into(), 69)); with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); assert!(Executive::apply_extrinsic(xt).is_err()); - assert_eq!(>::extrinsic_index(), Some(0)); + assert_eq!(>::extrinsic_index(), Some(0)); }); } } diff --git a/substrate/runtime/primitives/src/generic.rs b/substrate/runtime/primitives/src/generic.rs deleted file mode 100644 index 6305bac8d6c99..0000000000000 --- a/substrate/runtime/primitives/src/generic.rs +++ /dev/null @@ -1,514 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// 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 -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Generic implementations of Extrinsic/Header/Block. - -#[cfg(feature = "std")] -use std::fmt; - -#[cfg(feature = "std")] -use serde::{Deserialize, Deserializer}; - -use rstd::prelude::*; -use codec::{Decode, Encode, Codec, Input, Output}; -use runtime_support::AuxDispatchable; -use traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Block as BlockT, - Header as HeaderT, Hash as HashT, DigestItem as DigestItemT}; -use rstd::ops; -use bft::Justification; - -/// Definition of something that the external world might want to say. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Extrinsic { - /// Who signed it (note this is not a signature). - pub signed: Address, - /// The number of extrinsics have come before from the same signer. - pub index: Index, - /// The function that should be called. - pub function: Call, -} - -/// A extrinsic right from the external world. Unchecked. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct UncheckedExtrinsic { - /// The actual extrinsic information. - pub extrinsic: Extrinsic, - /// The signature. - pub signature: Signature, -} - -impl UncheckedExtrinsic { - /// New instance. - pub fn new(extrinsic: Extrinsic, signature: Signature) -> Self { - UncheckedExtrinsic { - extrinsic, - signature, - } - } -} - -impl UncheckedExtrinsic> where - Signature: traits::Verify + Default + Eq, - AccountId: Default + Eq, -{ - /// `true` if this extrinsic is signed. - pub fn is_signed(&self) -> bool { - self.signature.is_signed() - } -} - -impl traits::Checkable - for UncheckedExtrinsic> -where - Address: Member + Default + MaybeDisplay, - Index: Member + MaybeDisplay + SimpleArithmetic, - Call: Member, - Signature: traits::Verify + Eq + Default, - AccountId: Member + Default + MaybeDisplay, - ::MaybeUnsigned: Member, - Extrinsic: Codec, - ThisLookup: FnOnce(Address) -> Result, -{ - type Checked = CheckedExtrinsic; - - fn check_with(self, lookup: ThisLookup) -> Result { - if !self.is_signed() { - Ok(CheckedExtrinsic(Extrinsic { - signed: Default::default(), - index: self.extrinsic.index, - function: self.extrinsic.function, - })) - } else { - let extrinsic: Extrinsic - = Extrinsic { - signed: lookup(self.extrinsic.signed)?, - index: self.extrinsic.index, - function: self.extrinsic.function, - }; - if ::verify_encoded_lazy(&self.signature, &extrinsic, &extrinsic.signed) { - Ok(CheckedExtrinsic(extrinsic)) - } else { - Err("bad signature in extrinsic") - } - } - } -} - -impl Decode - for UncheckedExtrinsic -where - Signature: Decode, - Extrinsic: Decode, -{ - fn decode(input: &mut I) -> Option { - // This is a little more complicated than usual since the binary format must be compatible - // with substrate's generic `Vec` type. Basically this just means accepting that there - // will be a prefix of u32, which has the total number of bytes following (we don't need - // to use this). - let _length_do_not_remove_me_see_above: u32 = Decode::decode(input)?; - - Some(UncheckedExtrinsic::new( - Decode::decode(input)?, - Decode::decode(input)? - )) - } -} - -impl Encode - for UncheckedExtrinsic -where - Signature: Encode, - Extrinsic: Encode, -{ - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - // need to prefix with the total length as u32 to ensure it's binary comptible with - // Vec. we'll make room for it here, then overwrite once we know the length. - v.extend(&[0u8; 4]); - - self.extrinsic.encode_to(&mut v); - self.signature.encode_to(&mut v); - - let length = (v.len() - 4) as u32; - length.using_encoded(|s| v[0..4].copy_from_slice(s)); - - v - } -} - -/// TODO: use derive when possible. -#[cfg(feature = "std")] -impl fmt::Debug for UncheckedExtrinsic where - Address: fmt::Debug, - Index: fmt::Debug, - Call: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedExtrinsic({:?})", self.extrinsic) - } -} - -/// A type-safe indicator that a extrinsic has been checked. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct CheckedExtrinsic - (Extrinsic); - -impl ops::Deref - for CheckedExtrinsic -where - AccountId: Member + MaybeDisplay, - Index: Member + MaybeDisplay + SimpleArithmetic, - Call: Member, -{ - type Target = Extrinsic; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl traits::Applyable - for CheckedExtrinsic -where - AccountId: Member + MaybeDisplay, - Index: Member + MaybeDisplay + SimpleArithmetic, - Call: Member + AuxDispatchable, -{ - type Index = Index; - type AccountId = AccountId; - - fn index(&self) -> &Self::Index { - &self.0.index - } - - fn sender(&self) -> &Self::AccountId { - &self.0.signed - } - - fn apply(self) -> Result<(), &'static str> { - let xt = self.0; - xt.function.dispatch(&xt.signed) - } -} - -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct Digest { - pub logs: Vec, -} - -impl Default for Digest { - fn default() -> Self { - Digest { logs: Vec::new(), } - } -} - -impl traits::Digest for Digest where - Item: DigestItemT + Codec -{ - type Item = Item; - - fn logs(&self) -> &[Self::Item] { - &self.logs - } - - fn push(&mut self, item: Self::Item) { - self.logs.push(item); - } -} - - -/// Abstraction over a block header for a substrate chain. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header { - /// The parent hash. - pub parent_hash: ::Output, - /// The block number. - pub number: Number, - /// The state trie merkle root - pub state_root: ::Output, - /// The merkle root of the extrinsics. - pub extrinsics_root: ::Output, - /// A chain-specific digest of data useful for light clients or referencing auxiliary data. - pub digest: Digest, -} - -// Hack to work around the fact that deriving deserialize doesn't work nicely with -// the `hashing` trait used as a parameter. -// dummy struct that uses the hash type directly. -// https://github.com/serde-rs/serde/issues/1296 -#[cfg(feature = "std")] -#[serde(rename_all = "camelCase")] -#[derive(Deserialize)] -struct DeserializeHeader { - parent_hash: H, - number: N, - state_root: H, - extrinsics_root: H, - digest: Digest, -} - -#[cfg(feature = "std")] -impl From> for Header { - fn from(other: DeserializeHeader) -> Self { - Header { - parent_hash: other.parent_hash, - number: other.number, - state_root: other.state_root, - extrinsics_root: other.extrinsics_root, - digest: other.digest, - } - } -} - -#[cfg(feature = "std")] -impl<'a, Number: 'a, Hash: 'a + HashT, DigestItem: 'a> Deserialize<'a> for Header where - Number: Deserialize<'a>, - Hash::Output: Deserialize<'a>, - DigestItem: Deserialize<'a>, -{ - fn deserialize>(de: D) -> Result { - DeserializeHeader::::deserialize(de).map(Into::into) - } -} - -// TODO [ToDr] Issue with bounds -impl Decode for Header where - Number: Decode, - Hash: HashT, - Hash::Output: Decode, - DigestItem: Decode, -{ - fn decode(input: &mut I) -> Option { - Some(Header { - parent_hash: Decode::decode(input)?, - number: Decode::decode(input)?, - state_root: Decode::decode(input)?, - extrinsics_root: Decode::decode(input)?, - digest: Decode::decode(input)?, - }) - } -} - -impl Encode for Header where - Number: Encode, - Hash: HashT, - Hash::Output: Encode, - DigestItem: Encode, -{ - fn encode_to(&self, dest: &mut T) { - dest.push(&self.parent_hash); - dest.push(&self.number); - dest.push(&self.state_root); - dest.push(&self.extrinsics_root); - dest.push(&self.digest); - } -} - -impl traits::Header for Header where - Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, - Hash: HashT, - DigestItem: DigestItemT + Codec, - Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, - { - type Number = Number; - type Hash = ::Output; - type Hashing = Hash; - type Digest = Digest; - - fn number(&self) -> &Self::Number { &self.number } - fn set_number(&mut self, num: Self::Number) { self.number = num } - - fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root } - fn set_extrinsics_root(&mut self, root: Self::Hash) { self.extrinsics_root = root } - - fn state_root(&self) -> &Self::Hash { &self.state_root } - fn set_state_root(&mut self, root: Self::Hash) { self.state_root = root } - - fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } - fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } - - fn digest(&self) -> &Self::Digest { &self.digest } - fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest } - - fn new( - number: Self::Number, - extrinsics_root: Self::Hash, - state_root: Self::Hash, - parent_hash: Self::Hash, - digest: Self::Digest - ) -> Self { - Header { - number, extrinsics_root: extrinsics_root, state_root, parent_hash, digest - } - } -} - -impl Header where - Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, - Hash: HashT, - DigestItem: DigestItemT + Codec, - Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, - { - /// Convenience helper for computing the hash of the header without having - /// to import the trait. - pub fn hash(&self) -> Hash::Output { - Hash::hash_of(self) - } -} - -/// Something to identify a block. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub enum BlockId { - /// Identify by block header hash. - Hash(<::Header as HeaderT>::Hash), - /// Identify by block number. - Number(<::Header as HeaderT>::Number), -} - -impl BlockId { - /// Create a block ID from a hash. - pub fn hash(hash: Block::Hash) -> Self { - BlockId::Hash(hash) - } - - /// Create a block ID from a number. - pub fn number(number: ::Number) -> Self { - BlockId::Number(number) - } -} - -impl Copy for BlockId {} - -#[cfg(feature = "std")] -impl fmt::Display for BlockId { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{:?}", self) - } -} - -/// Abstraction over a substrate block. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Block { - /// The block header. - pub header: Header, - /// The accompanying extrinsics. - pub extrinsics: Vec, -} - -impl traits::Block for Block -where - Header: HeaderT, - Extrinsic: Member + Codec, -{ - type Extrinsic = Extrinsic; - type Header = Header; - type Hash = ::Hash; - - fn header(&self) -> &Self::Header { - &self.header - } - fn extrinsics(&self) -> &[Self::Extrinsic] { - &self.extrinsics[..] - } - fn deconstruct(self) -> (Self::Header, Vec) { - (self.header, self.extrinsics) - } - fn new(header: Self::Header, extrinsics: Vec) -> Self { - Block { header, extrinsics } - } -} - -/// Abstraction over a substrate block and justification. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct SignedBlock { - /// Full block. - pub block: Block, - /// Block header justification. - pub justification: Justification, -} - -#[cfg(test)] -mod tests { - use codec::{Decode, Encode}; - use substrate_primitives::{H256, H512}; - use super::{Digest, Header, UncheckedExtrinsic, Extrinsic}; - - type Block = super::Block< - Header>, - UncheckedExtrinsic, - >; - - #[test] - fn block_roundtrip_serialization() { - let block: Block = Block { - header: Header { - parent_hash: [0u8; 32].into(), - number: 100_000, - state_root: [1u8; 32].into(), - extrinsics_root: [2u8; 32].into(), - digest: Digest { logs: vec![vec![1, 2, 3], vec![4, 5, 6]] }, - }, - extrinsics: vec![ - UncheckedExtrinsic::new( - Extrinsic { - signed: [255u8; 32].into(), - index: 0, - function: 100, - }, - H512::from([0u8; 64]).into() - ), - UncheckedExtrinsic::new( - Extrinsic { - signed: [128u8; 32].into(), - index: 100, - function: 99, - }, - H512::from([255u8; 64]).into() - ) - ] - }; - - { - let encoded = ::serde_json::to_vec(&block).unwrap(); - let decoded: Block = ::serde_json::from_slice(&encoded).unwrap(); - - assert_eq!(block, decoded); - } - { - let encoded = block.encode(); - let decoded = Block::decode(&mut &encoded[..]).unwrap(); - - assert_eq!(block, decoded); - } - } -} diff --git a/substrate/runtime/primitives/src/generic/block.rs b/substrate/runtime/primitives/src/generic/block.rs new file mode 100644 index 0000000000000..40538a392c3d0 --- /dev/null +++ b/substrate/runtime/primitives/src/generic/block.rs @@ -0,0 +1,105 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementation of a block and associated items. + +#[cfg(feature = "std")] +use std::fmt; + +use rstd::prelude::*; +use codec::Codec; +use traits::{self, Member, Block as BlockT, Header as HeaderT}; +use bft::Justification; + +/// Something to identify a block. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub enum BlockId { + /// Identify by block header hash. + Hash(<::Header as HeaderT>::Hash), + /// Identify by block number. + Number(<::Header as HeaderT>::Number), +} + +impl BlockId { + /// Create a block ID from a hash. + pub fn hash(hash: Block::Hash) -> Self { + BlockId::Hash(hash) + } + + /// Create a block ID from a number. + pub fn number(number: ::Number) -> Self { + BlockId::Number(number) + } +} + +impl Copy for BlockId {} + +#[cfg(feature = "std")] +impl fmt::Display for BlockId { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{:?}", self) + } +} + +/// Abstraction over a substrate block. +#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct Block { + /// The block header. + pub header: Header, + /// The accompanying extrinsics. + pub extrinsics: Vec, +} + +impl traits::Block for Block +where + Header: HeaderT, + Extrinsic: Member + Codec, +{ + type Extrinsic = Extrinsic; + type Header = Header; + type Hash = ::Hash; + + fn header(&self) -> &Self::Header { + &self.header + } + fn extrinsics(&self) -> &[Self::Extrinsic] { + &self.extrinsics[..] + } + fn deconstruct(self) -> (Self::Header, Vec) { + (self.header, self.extrinsics) + } + fn new(header: Self::Header, extrinsics: Vec) -> Self { + Block { header, extrinsics } + } +} + +/// Abstraction over a substrate block and justification. +#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct SignedBlock { + /// Full block. + pub block: Block, + /// Block header justification. + pub justification: Justification, +} diff --git a/substrate/runtime/primitives/src/generic/checked_extrinsic.rs b/substrate/runtime/primitives/src/generic/checked_extrinsic.rs new file mode 100644 index 0000000000000..e5aee32a02c58 --- /dev/null +++ b/substrate/runtime/primitives/src/generic/checked_extrinsic.rs @@ -0,0 +1,59 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementation of an extrinsic that has passed the verification +//! stage. + +use runtime_support::Dispatchable; +use traits::{self, Member, SimpleArithmetic, MaybeDisplay}; + +/// Definition of something that the external world might want to say; its +/// existence implies that it has been checked and is good, particularly with +/// regards to the signature. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +pub struct CheckedExtrinsic { + /// Who this purports to be from, if anyone (note this is not a signature). + pub signed: Option, + /// The number of extrinsics have come before from the same signer. + pub index: Index, + /// The function that should be called. + pub function: Call, +} + +impl traits::Applyable + for CheckedExtrinsic +where + AccountId: Member + MaybeDisplay, + Index: Member + MaybeDisplay + SimpleArithmetic, + Call: Member + Dispatchable, + ::Origin: From> +{ + type Index = Index; + type AccountId = AccountId; + + fn index(&self) -> &Self::Index { + &self.index + } + + fn sender(&self) -> Option<&Self::AccountId> { + self.signed.as_ref() + } + + fn apply(self) -> Result<(), &'static str> { + self.function.dispatch(self.signed.into()) + } +} diff --git a/substrate/runtime/primitives/src/generic/header.rs b/substrate/runtime/primitives/src/generic/header.rs new file mode 100644 index 0000000000000..fc4b3d0842223 --- /dev/null +++ b/substrate/runtime/primitives/src/generic/header.rs @@ -0,0 +1,193 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementation of a header and digest. + +#[cfg(feature = "std")] +use serde::{Deserialize, Deserializer}; + +use rstd::prelude::*; +use codec::{Decode, Encode, Codec, Input, Output}; +use traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, + Hash as HashT, DigestItem as DigestItemT}; + +#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct Digest { + pub logs: Vec, +} + +impl Default for Digest { + fn default() -> Self { + Digest { logs: Vec::new(), } + } +} + +impl traits::Digest for Digest where + Item: DigestItemT + Codec +{ + type Item = Item; + + fn logs(&self) -> &[Self::Item] { + &self.logs + } + + fn push(&mut self, item: Self::Item) { + self.logs.push(item); + } +} + +/// Abstraction over a block header for a substrate chain. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct Header { + /// The parent hash. + pub parent_hash: ::Output, + /// The block number. + pub number: Number, + /// The state trie merkle root + pub state_root: ::Output, + /// The merkle root of the extrinsics. + pub extrinsics_root: ::Output, + /// A chain-specific digest of data useful for light clients or referencing auxiliary data. + pub digest: Digest, +} + +// Hack to work around the fact that deriving deserialize doesn't work nicely with +// the `hashing` trait used as a parameter. +// dummy struct that uses the hash type directly. +// https://github.com/serde-rs/serde/issues/1296 +#[cfg(feature = "std")] +#[serde(rename_all = "camelCase")] +#[derive(Deserialize)] +struct DeserializeHeader { + parent_hash: H, + number: N, + state_root: H, + extrinsics_root: H, + digest: Digest, +} + +#[cfg(feature = "std")] +impl From> for Header { + fn from(other: DeserializeHeader) -> Self { + Header { + parent_hash: other.parent_hash, + number: other.number, + state_root: other.state_root, + extrinsics_root: other.extrinsics_root, + digest: other.digest, + } + } +} + +#[cfg(feature = "std")] +impl<'a, Number: 'a, Hash: 'a + HashT, DigestItem: 'a> Deserialize<'a> for Header where + Number: Deserialize<'a>, + Hash::Output: Deserialize<'a>, + DigestItem: Deserialize<'a>, +{ + fn deserialize>(de: D) -> Result { + DeserializeHeader::::deserialize(de).map(Into::into) + } +} + +// TODO [ToDr] Issue with bounds +impl Decode for Header where + Number: Decode, + Hash: HashT, + Hash::Output: Decode, + DigestItem: Decode, +{ + fn decode(input: &mut I) -> Option { + Some(Header { + parent_hash: Decode::decode(input)?, + number: Decode::decode(input)?, + state_root: Decode::decode(input)?, + extrinsics_root: Decode::decode(input)?, + digest: Decode::decode(input)?, + }) + } +} + +impl Encode for Header where + Number: Encode, + Hash: HashT, + Hash::Output: Encode, + DigestItem: Encode, +{ + fn encode_to(&self, dest: &mut T) { + dest.push(&self.parent_hash); + dest.push(&self.number); + dest.push(&self.state_root); + dest.push(&self.extrinsics_root); + dest.push(&self.digest); + } +} + +impl traits::Header for Header where + Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, + Hash: HashT, + DigestItem: DigestItemT + Codec, + Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, + { + type Number = Number; + type Hash = ::Output; + type Hashing = Hash; + type Digest = Digest; + + fn number(&self) -> &Self::Number { &self.number } + fn set_number(&mut self, num: Self::Number) { self.number = num } + + fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root } + fn set_extrinsics_root(&mut self, root: Self::Hash) { self.extrinsics_root = root } + + fn state_root(&self) -> &Self::Hash { &self.state_root } + fn set_state_root(&mut self, root: Self::Hash) { self.state_root = root } + + fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } + fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } + + fn digest(&self) -> &Self::Digest { &self.digest } + fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest } + + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Self::Digest + ) -> Self { + Header { + number, extrinsics_root: extrinsics_root, state_root, parent_hash, digest + } + } +} + +impl Header where + Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, + Hash: HashT, + DigestItem: DigestItemT + Codec, + Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, + { + /// Convenience helper for computing the hash of the header without having + /// to import the trait. + pub fn hash(&self) -> Hash::Output { + Hash::hash_of(self) + } +} diff --git a/substrate/runtime/primitives/src/generic/mod.rs b/substrate/runtime/primitives/src/generic/mod.rs new file mode 100644 index 0000000000000..fd56cb4015421 --- /dev/null +++ b/substrate/runtime/primitives/src/generic/mod.rs @@ -0,0 +1,29 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementations of Extrinsic/Header/Block. + +mod unchecked_extrinsic; +mod checked_extrinsic; +mod header; +mod block; +#[cfg(test)] +mod tests; + +pub use self::unchecked_extrinsic::UncheckedExtrinsic; +pub use self::checked_extrinsic::CheckedExtrinsic; +pub use self::header::{Header, Digest}; +pub use self::block::{Block, SignedBlock, BlockId}; diff --git a/substrate/runtime/primitives/src/generic/tests.rs b/substrate/runtime/primitives/src/generic/tests.rs new file mode 100644 index 0000000000000..bbe5d00ed36f8 --- /dev/null +++ b/substrate/runtime/primitives/src/generic/tests.rs @@ -0,0 +1,66 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the generic implementations of Extrinsic/Header/Block. + +use codec::{Decode, Encode}; +use substrate_primitives::{H256, H512}; +use super::{Digest, Header, UncheckedExtrinsic}; + +type Block = super::Block< + Header>, + UncheckedExtrinsic, +>; + +#[test] +fn block_roundtrip_serialization() { + let block: Block = Block { + header: Header { + parent_hash: [0u8; 32].into(), + number: 100_000, + state_root: [1u8; 32].into(), + extrinsics_root: [2u8; 32].into(), + digest: Digest { logs: vec![vec![1, 2, 3], vec![4, 5, 6]] }, + }, + extrinsics: vec![ + UncheckedExtrinsic::new_signed( + 0, + 100, + [255u8; 32].into(), + H512::from([0u8; 64]).into() + ), + UncheckedExtrinsic::new_signed( + 100, + 99, + [128u8; 32].into(), + H512::from([255u8; 64]).into() + ) + ] + }; + + { + let encoded = ::serde_json::to_vec(&block).unwrap(); + let decoded: Block = ::serde_json::from_slice(&encoded).unwrap(); + + assert_eq!(block, decoded); + } + { + let encoded = block.encode(); + let decoded = Block::decode(&mut &encoded[..]).unwrap(); + + assert_eq!(block, decoded); + } +} diff --git a/substrate/runtime/primitives/src/generic/unchecked_extrinsic.rs b/substrate/runtime/primitives/src/generic/unchecked_extrinsic.rs new file mode 100644 index 0000000000000..c7e3693fbf187 --- /dev/null +++ b/substrate/runtime/primitives/src/generic/unchecked_extrinsic.rs @@ -0,0 +1,159 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementation of an unchecked (pre-verification) extrinsic. + +#[cfg(feature = "std")] +use std::fmt; + +use rstd::prelude::*; +use codec::{Decode, Encode, Input}; +use traits::{self, Member, SimpleArithmetic, MaybeDisplay}; +use super::CheckedExtrinsic; + +/// A extrinsic right from the external world. This is unchecked and so +/// can contain a signature. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct UncheckedExtrinsic { + /// The signature and address, if this is a signed extrinsic. + pub signature: Option<(Address, Signature)>, + /// The number of extrinsics have come before from the same signer. + pub index: Index, + /// The function that should be called. + pub function: Call, +} + +impl UncheckedExtrinsic { + /// New instance of a signed extrinsic aka "transaction". + pub fn new_signed(index: Index, function: Call, signed: Address, signature: Signature) -> Self { + UncheckedExtrinsic { + signature: Some((signed, signature)), + index, + function, + } + } + + /// New instance of an unsigned extrinsic aka "inherent". + pub fn new_unsigned(index: Index, function: Call) -> Self { + UncheckedExtrinsic { + signature: None, + index, + function, + } + } + + /// `true` if there is a signature. + pub fn is_signed(&self) -> bool { + self.signature.is_some() + } +} + +impl traits::Checkable + for UncheckedExtrinsic +where + Address: Member + MaybeDisplay, + Index: Encode + Member + MaybeDisplay + SimpleArithmetic, + Call: Encode + Member, + Signature: Member + traits::Verify, + AccountId: Member + MaybeDisplay, + ThisLookup: FnOnce(Address) -> Result, +{ + type Checked = CheckedExtrinsic; + + fn check_with(self, lookup: ThisLookup) -> Result { + Ok(match self.signature { + Some((signed, signature)) => { + let payload = (self.index, self.function); + let signed = lookup(signed)?; + if !::verify_encoded_lazy(&signature, &payload, &signed) { + return Err("bad signature in extrinsic") + } + CheckedExtrinsic { + signed: Some(signed), + index: payload.0, + function: payload.1, + } + } + None => CheckedExtrinsic { + signed: None, + index: self.index, + function: self.function, + }, + }) + } +} + +impl Decode + for UncheckedExtrinsic +where + Address: Decode, + Signature: Decode, + Index: Decode, + Call: Decode, +{ + fn decode(input: &mut I) -> Option { + // This is a little more complicated than usual since the binary format must be compatible + // with substrate's generic `Vec` type. Basically this just means accepting that there + // will be a prefix of u32, which has the total number of bytes following (we don't need + // to use this). + let _length_do_not_remove_me_see_above: u32 = Decode::decode(input)?; + + Some(UncheckedExtrinsic { + signature: Decode::decode(input)?, + index: Decode::decode(input)?, + function: Decode::decode(input)?, + }) + } +} + +impl Encode + for UncheckedExtrinsic +where + Address: Encode, + Signature: Encode, + Index: Encode, + Call: Encode, +{ + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + // need to prefix with the total length as u32 to ensure it's binary comptible with + // Vec. we'll make room for it here, then overwrite once we know the length. + v.extend(&[0u8; 4]); + + self.signature.encode_to(&mut v); + self.index.encode_to(&mut v); + self.function.encode_to(&mut v); + + let length = (v.len() - 4) as u32; + length.using_encoded(|s| v[0..4].copy_from_slice(s)); + + v + } +} + +/// TODO: use derive when possible. +#[cfg(feature = "std")] +impl fmt::Debug for UncheckedExtrinsic where + Address: fmt::Debug, + Index: fmt::Debug, + Call: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedExtrinsic({:?}, {:?}, {:?})", self.signature.as_ref().map(|x| &x.0), self.function, self.index) + } +} diff --git a/substrate/runtime/primitives/src/lib.rs b/substrate/runtime/primitives/src/lib.rs index 87553942b921e..6bea27f4d6acc 100644 --- a/substrate/runtime/primitives/src/lib.rs +++ b/substrate/runtime/primitives/src/lib.rs @@ -146,44 +146,6 @@ impl codec::Encode for ApplyError { /// Result from attempt to apply an extrinsic. pub type ApplyResult = Result; -/// Potentially "unsigned" signature verification. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct MaybeUnsigned(pub T); - -impl MaybeUnsigned where - T: Default + Eq, - ::Signer: Default + Eq, -{ - fn is_signed(&self) -> bool { - self.0 != T::default() - } - - fn is_addressed(&self, signer: &::Signer) -> bool { - signer != &Default::default() - } -} - -impl Verify for MaybeUnsigned where - T: Default + Eq, - ::Signer: Default + Eq, -{ - type Signer = T::Signer; - fn verify>(&self, msg: L, signer: &Self::Signer) -> bool { - if !self.is_signed() { - !self.is_addressed(signer) - } else { - self.0.verify(msg, signer) - } - } -} - -impl From for MaybeUnsigned { - fn from(t: T) -> Self { - MaybeUnsigned(t) - } -} - /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. pub fn verify_encoded_lazy(sig: &V, item: &T, signer: &V::Signer) -> bool { diff --git a/substrate/runtime/primitives/src/testing.rs b/substrate/runtime/primitives/src/testing.rs index 9ac86d7747c82..3442bfedf4729 100644 --- a/substrate/runtime/primitives/src/testing.rs +++ b/substrate/runtime/primitives/src/testing.rs @@ -19,7 +19,7 @@ use serde::{Serialize, de::DeserializeOwned}; use std::fmt::Debug; use codec::Codec; -use runtime_support::AuxDispatchable; +use runtime_support::Dispatchable; use traits::{self, Checkable, Applyable, BlakeTwo256}; pub use substrate_primitives::H256; @@ -116,16 +116,19 @@ impl(pub (u64, u64, Call)); +pub struct TestXt(pub Option, pub u64, pub Call); -impl Checkable for TestXt { +impl Checkable for TestXt { type Checked = Self; fn check_with(self, _: Context) -> Result { Ok(self) } } -impl + Codec + Sized + Send + Sync + Serialize + DeserializeOwned + Clone + Eq + Debug> Applyable for TestXt { +impl Applyable for TestXt where + Call: Sized + Send + Sync + Clone + Eq + Dispatchable + Codec + Debug + Serialize + DeserializeOwned, + ::Origin: From> +{ type AccountId = u64; type Index = u64; - fn sender(&self) -> &u64 { &(self.0).0 } - fn index(&self) -> &u64 { &(self.0).1 } - fn apply(self) -> Result<(), &'static str> { (self.0).2.dispatch(&(self.0).0) } + fn sender(&self) -> Option<&u64> { self.0.as_ref() } + fn index(&self) -> &u64 { &self.1 } + fn apply(self) -> Result<(), &'static str> { self.2.dispatch(self.0.into()) } } diff --git a/substrate/runtime/primitives/src/traits.rs b/substrate/runtime/primitives/src/traits.rs index 2d674f1e933f8..f3c27e19c4c71 100644 --- a/substrate/runtime/primitives/src/traits.rs +++ b/substrate/runtime/primitives/src/traits.rs @@ -47,7 +47,7 @@ pub trait Verify { } /// Means of changing one type into another in a manner dependent on the source type. -pub trait AuxLookup { +pub trait Lookup { /// Type to lookup from. type Source; /// Type to lookup into. @@ -108,24 +108,6 @@ impl Convert for () { fn convert(_: T) -> () { () } } -pub trait MaybeEmpty { - fn is_empty(&self) -> bool; -} - -// AccountId is `u64` in tests -impl MaybeEmpty for u64 { - fn is_empty(&self) -> bool { - self.is_zero() - } -} - -// AccountId is H256 in production -impl MaybeEmpty for substrate_primitives::H256 { - fn is_empty(&self) -> bool { - self.is_zero() - } -} - pub trait RefInto { fn ref_into(&self) -> &T; } @@ -427,7 +409,7 @@ pub trait Applyable: Sized + Send + Sync { type AccountId: Member + MaybeDisplay; type Index: Member + MaybeDisplay + SimpleArithmetic; fn index(&self) -> &Self::Index; - fn sender(&self) -> &Self::AccountId; + fn sender(&self) -> Option<&Self::AccountId>; fn apply(self) -> Result<(), &'static str>; } diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index b155053fe49ab..deb138f7e3cbd 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -49,9 +49,10 @@ extern crate substrate_runtime_system as system; extern crate substrate_runtime_timestamp as timestamp; use rstd::prelude::*; -use primitives::traits::{Zero, One, RefInto, OnFinalise, Convert, As}; +use primitives::traits::{Zero, One, OnFinalise, Convert, As}; use runtime_support::{StorageValue, StorageMap}; use runtime_support::dispatch::Result; +use system::{ensure_signed, ensure_root}; #[cfg(any(feature = "std", test))] use std::collections::HashMap; @@ -75,17 +76,11 @@ pub trait Trait: timestamp::Trait { pub type Event = RawEvent<::BlockNumber>; decl_module! { - pub struct Module; + pub struct Module for enum Call where origin: T::Origin { + fn set_key(origin, key: T::SessionKey) -> Result; - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn set_key(aux, key: T::SessionKey) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn set_length(new: T::BlockNumber) -> Result; - fn force_new_session(apply_rewards: bool) -> Result; + fn set_length(origin, new: T::BlockNumber) -> Result; + fn force_new_session(origin, apply_rewards: bool) -> Result; } } @@ -139,26 +134,34 @@ impl Module { /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next /// session. - fn set_key(aux: &T::PublicAux, key: T::SessionKey) -> Result { + fn set_key(origin: T::Origin, key: T::SessionKey) -> Result { + let who = ensure_signed(origin)?; // set new value for next session - >::insert(aux.ref_into(), key); + >::insert(who, key); Ok(()) } /// Set a new era length. Won't kick in until the next era change (at current length). - fn set_length(new: T::BlockNumber) -> Result { + fn set_length(origin: T::Origin, new: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(new); Ok(()) } /// Forces a new session. - pub fn force_new_session(apply_rewards: bool) -> Result { - >::put(apply_rewards); - Ok(()) + pub fn force_new_session(origin: T::Origin, apply_rewards: bool) -> Result { + ensure_root(origin)?; + Self::apply_force_new_session(apply_rewards) } // INTERNAL API (available to other runtime modules) + /// Forces a new session, no origin. + pub fn apply_force_new_session(apply_rewards: bool) -> Result { + >::put(apply_rewards); + Ok(()) + } + /// Set the current set of validators. /// /// Called by `staking::next_era()` only. `next_session` should be called after this in order to @@ -291,6 +294,10 @@ mod tests { use primitives::traits::{Identity, BlakeTwo256}; use primitives::testing::{Digest, Header}; + impl_outer_origin!{ + pub enum Origin for Test {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl consensus::Trait for Test { @@ -300,7 +307,7 @@ mod tests { type OnOfflineValidator = (); } impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -353,7 +360,7 @@ mod tests { fn should_work_with_early_exit() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(Session::set_length(10)); + assert_ok!(Session::set_length(Origin::ROOT, 10)); assert_eq!(Session::blocks_remaining(), 1); Session::check_rotate_session(1); @@ -365,7 +372,7 @@ mod tests { System::set_block_number(7); assert_eq!(Session::current_index(), 1); assert_eq!(Session::blocks_remaining(), 5); - assert_ok!(Session::force_new_session(false)); + assert_ok!(Session::force_new_session(Origin::ROOT, false)); Session::check_rotate_session(7); System::set_block_number(8); @@ -388,14 +395,14 @@ mod tests { with_externalities(&mut new_test_ext(), || { // Block 1: Change to length 3; no visible change. System::set_block_number(1); - assert_ok!(Session::set_length(3)); + assert_ok!(Session::set_length(Origin::ROOT, 3)); Session::check_rotate_session(1); assert_eq!(Session::length(), 2); assert_eq!(Session::current_index(), 0); // Block 2: Length now changed to 3. Index incremented. System::set_block_number(2); - assert_ok!(Session::set_length(3)); + assert_ok!(Session::set_length(Origin::ROOT, 3)); Session::check_rotate_session(2); assert_eq!(Session::length(), 3); assert_eq!(Session::current_index(), 1); @@ -408,7 +415,7 @@ mod tests { // Block 4: Change to length 2; no visible change. System::set_block_number(4); - assert_ok!(Session::set_length(2)); + assert_ok!(Session::set_length(Origin::ROOT, 2)); Session::check_rotate_session(4); assert_eq!(Session::length(), 3); assert_eq!(Session::current_index(), 1); @@ -448,7 +455,7 @@ mod tests { // Block 3: Set new key for validator 2; no visible change. System::set_block_number(3); - assert_ok!(Session::set_key(&2, 5)); + assert_ok!(Session::set_key(Origin::signed(2), 5)); assert_eq!(Consensus::authorities(), vec![1, 2, 3]); Session::check_rotate_session(3); diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 4242fa01e152d..9b25ecb4d9c54 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -49,9 +49,10 @@ use rstd::prelude::*; use runtime_support::{Parameter, StorageValue, StorageMap}; use runtime_support::dispatch::Result; use session::OnSessionChange; -use primitives::traits::{Zero, One, Bounded, RefInto, OnFinalise, - As, AuxLookup}; +use primitives::traits::{Zero, One, Bounded, OnFinalise, + As, Lookup}; use balances::{address::Address, OnMinted}; +use system::{ensure_root, ensure_signed}; mod mock; @@ -104,25 +105,19 @@ pub trait Trait: balances::Trait + session::Trait { } decl_module! { - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(bound(deserialize = "T::Balance: ::serde::de::DeserializeOwned")))] - pub enum Call where aux: T::PublicAux { - fn stake(aux) -> Result; - fn unstake(aux, intentions_index: u32) -> Result; - fn nominate(aux, target: Address) -> Result; - fn unnominate(aux, target_index: u32) -> Result; - fn register_preferences(aux, intentions_index: u32, prefs: ValidatorPrefs) -> Result; - } - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { - fn set_sessions_per_era(new: T::BlockNumber) -> Result; - fn set_bonding_duration(new: T::BlockNumber) -> Result; - fn set_validator_count(new: u32) -> Result; - fn force_new_era(apply_rewards: bool) -> Result; - fn set_offline_slash_grace(new: u32) -> Result; + pub struct Module for enum Call where origin: T::Origin { + fn stake(origin) -> Result; + fn unstake(origin, intentions_index: u32) -> Result; + fn nominate(origin, target: Address) -> Result; + fn unnominate(origin, target_index: u32) -> Result; + fn register_preferences(origin, intentions_index: u32, prefs: ValidatorPrefs) -> Result; + + fn set_sessions_per_era(origin, new: T::BlockNumber) -> Result; + fn set_bonding_duration(origin, new: T::BlockNumber) -> Result; + fn set_validator_count(origin, new: u32) -> Result; + fn force_new_era(origin, apply_rewards: bool) -> Result; + fn set_offline_slash_grace(origin, new: u32) -> Result; } } @@ -192,6 +187,11 @@ decl_storage! { impl Module { + /// Deposit one of this module's events. + fn deposit_event(event: Event) { + >::deposit_event(::Event::from(event).into()); + } + // PUBLIC IMMUTABLES /// MinimumValidatorCount getter, introduces a default. @@ -232,60 +232,62 @@ impl Module { /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - fn stake(aux: &T::PublicAux) -> Result { - let aux = aux.ref_into(); - ensure!(Self::nominating(aux).is_none(), "Cannot stake if already nominating."); + fn stake(origin: T::Origin) -> Result { + let who = ensure_signed(origin)?; + ensure!(Self::nominating(&who).is_none(), "Cannot stake if already nominating."); let mut intentions = >::get(); // can't be in the list twice. - ensure!(intentions.iter().find(|&t| t == aux).is_none(), "Cannot stake if already staked."); - intentions.push(aux.clone()); + ensure!(intentions.iter().find(|&t| t == &who).is_none(), "Cannot stake if already staked."); + + >::insert(&who, T::BlockNumber::max_value()); + intentions.push(who); >::put(intentions); - >::insert(aux, T::BlockNumber::max_value()); Ok(()) } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - fn unstake(aux: &T::PublicAux, intentions_index: u32) -> Result { + fn unstake(origin: T::Origin, intentions_index: u32) -> Result { + let who = ensure_signed(origin)?; // unstake fails in degenerate case of having too few existing staked parties if Self::intentions().len() <= Self::minimum_validator_count() { return Err("cannot unstake when there are too few staked participants") } - Self::apply_unstake(aux.ref_into(), intentions_index as usize) + Self::apply_unstake(&who, intentions_index as usize) } - fn nominate(aux: &T::PublicAux, target: Address) -> Result { + fn nominate(origin: T::Origin, target: Address) -> Result { + let who = ensure_signed(origin)?; let target = >::lookup(target)?; - let aux = aux.ref_into(); - ensure!(Self::nominating(aux).is_none(), "Cannot nominate if already nominating."); - ensure!(Self::intentions().iter().find(|&t| t == aux.ref_into()).is_none(), "Cannot nominate if already staked."); + ensure!(Self::nominating(&who).is_none(), "Cannot nominate if already nominating."); + ensure!(Self::intentions().iter().find(|&t| t == &who).is_none(), "Cannot nominate if already staked."); // update nominators_for let mut t = Self::nominators_for(&target); - t.push(aux.clone()); + t.push(who.clone()); >::insert(&target, t); // update nominating - >::insert(aux, &target); + >::insert(&who, &target); // Update bondage - >::insert(aux.ref_into(), T::BlockNumber::max_value()); + >::insert(&who, T::BlockNumber::max_value()); Ok(()) } /// Will panic if called when source isn't currently nominating target. /// Updates Nominating, NominatorsFor and NominationBalance. - fn unnominate(aux: &T::PublicAux, target_index: u32) -> Result { - let source = aux.ref_into(); + fn unnominate(origin: T::Origin, target_index: u32) -> Result { + let source = ensure_signed(origin)?; let target_index = target_index as usize; - let target = >::get(source).ok_or("Account must be nominating")?; + let target = >::get(&source).ok_or("Account must be nominating")?; let mut t = Self::nominators_for(&target); - if t.get(target_index) != Some(source) { + if t.get(target_index) != Some(&source) { return Err("Invalid target index") } @@ -296,66 +298,72 @@ impl Module { >::insert(&target, t); // update nominating - >::remove(source); + >::remove(&source); // update bondage - >::insert(aux.ref_into(), >::block_number() + Self::bonding_duration()); + >::insert(source, >::block_number() + Self::bonding_duration()); Ok(()) } /// Set the given account's preference for slashing behaviour should they be a validator. /// - /// An error (no-op) if `Self::intentions()[intentions_index] != aux`. + /// An error (no-op) if `Self::intentions()[intentions_index] != origin`. fn register_preferences( - aux: &T::PublicAux, + origin: T::Origin, intentions_index: u32, prefs: ValidatorPrefs ) -> Result { - let aux = aux.ref_into(); + let who = ensure_signed(origin)?; - if Self::intentions().get(intentions_index as usize) != Some(aux) { + if Self::intentions().get(intentions_index as usize) != Some(&who) { return Err("Invalid index") } - >::insert(aux, prefs); + >::insert(who, prefs); Ok(()) } // PRIV DISPATCH - /// Deposit one of this module's events. - fn deposit_event(event: Event) { - >::deposit_event(::Event::from(event).into()); - } - /// Set the number of sessions in an era. - fn set_sessions_per_era(new: T::BlockNumber) -> Result { + fn set_sessions_per_era(origin: T::Origin, new: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(&new); Ok(()) } /// The length of the bonding duration in eras. - fn set_bonding_duration(new: T::BlockNumber) -> Result { + fn set_bonding_duration(origin: T::Origin, new: T::BlockNumber) -> Result { + ensure_root(origin)?; >::put(&new); Ok(()) } /// The length of a staking era in sessions. - fn set_validator_count(new: u32) -> Result { + fn set_validator_count(origin: T::Origin, new: u32) -> Result { + ensure_root(origin)?; >::put(&new); Ok(()) } /// Force there to be a new era. This also forces a new session immediately after. /// `apply_rewards` should be true for validators to get the session reward. - fn force_new_era(apply_rewards: bool) -> Result { + fn force_new_era(origin: T::Origin, apply_rewards: bool) -> Result { + ensure_root(origin)?; + Self::apply_force_new_era(apply_rewards) + } + + // Just force_new_era without origin check. + fn apply_force_new_era(apply_rewards: bool) -> Result { >::put(()); - >::force_new_session(apply_rewards) + >::apply_force_new_session(apply_rewards) } + /// Set the offline slash grace period. - fn set_offline_slash_grace(new: u32) -> Result { + fn set_offline_slash_grace(origin: T::Origin, new: u32) -> Result { + ensure_root(origin)?; >::put(&new); Ok(()) } @@ -555,7 +563,7 @@ impl consensus::OnOfflineValidator for Module { apply_unstake can only fail if pos wrong; \ Self::intentions() doesn't change; qed"); } - let _ = Self::force_new_era(false); + let _ = Self::apply_force_new_era(false); } RawEvent::OfflineSlash(v, slash) } else { diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index b8ae013b38dfc..d603e372f272e 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -25,6 +25,10 @@ use substrate_primitives::{H256, KeccakHasher}; use runtime_io; use {GenesisConfig, Module, Trait, consensus, session, system, timestamp, balances}; +impl_outer_origin!{ + pub enum Origin for Test {} +} + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct Test; @@ -35,7 +39,7 @@ impl consensus::Trait for Test { type OnOfflineValidator = (); } impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 4bf9ce9f41051..66da1ed1737be 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -21,7 +21,7 @@ use super::*; use consensus::OnOfflineValidator; use runtime_io::with_externalities; -use mock::{Balances, Session, Staking, System, Timestamp, Test, new_test_ext}; +use mock::{Balances, Session, Staking, System, Timestamp, Test, new_test_ext, Origin}; #[test] fn note_null_offline_should_work() { @@ -75,7 +75,7 @@ fn note_offline_grace_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 70); Balances::set_free_balance(&20, 70); - assert_ok!(Staking::set_offline_slash_grace(1)); + assert_ok!(Staking::set_offline_slash_grace(Origin::ROOT, 1)); assert_eq!(Staking::offline_slash_grace(), 1); assert_eq!(Staking::slash_count(&10), 0); @@ -104,7 +104,7 @@ fn note_offline_force_unstake_session_change_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 70); Balances::set_free_balance(&20, 70); - assert_ok!(Staking::stake(&1)); + assert_ok!(Staking::stake(Origin::signed(1))); assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 70); @@ -130,7 +130,7 @@ fn note_offline_auto_unstake_session_change_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 7000); Balances::set_free_balance(&20, 7000); - assert_ok!(Staking::register_preferences(&10, 0, ValidatorPrefs { unstake_threshold: 1, validator_payment: 0 })); + assert_ok!(Staking::register_preferences(Origin::signed(10), 0, ValidatorPrefs { unstake_threshold: 1, validator_payment: 0 })); assert_eq!(Staking::intentions(), vec![10, 20]); @@ -236,14 +236,14 @@ fn staking_should_work() { assert_eq!(Staking::validator_count(), 2); assert_eq!(Session::validators(), vec![10, 20]); - assert_ok!(Staking::set_bonding_duration(2)); + assert_ok!(Staking::set_bonding_duration(Origin::ROOT, 2)); assert_eq!(Staking::bonding_duration(), 2); // Block 1: Add three validators. No obvious change. System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::stake(&2)); - assert_ok!(Staking::stake(&4)); + assert_ok!(Staking::stake(Origin::signed(1))); + assert_ok!(Staking::stake(Origin::signed(2))); + assert_ok!(Staking::stake(Origin::signed(4))); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::validators(), vec![10, 20]); @@ -256,8 +256,8 @@ fn staking_should_work() { // Block 3: Unstake highest, introduce another staker. No change yet. System::set_block_number(3); - assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::unstake(&4, Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32)); + assert_ok!(Staking::stake(Origin::signed(3))); + assert_ok!(Staking::unstake(Origin::signed(4), Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32)); assert_eq!(Staking::current_era(), 1); Session::check_rotate_session(System::block_number()); @@ -269,7 +269,7 @@ fn staking_should_work() { // Block 5: Transfer stake from highest to lowest. No change yet. System::set_block_number(5); - assert_ok!(Balances::transfer(&4, 1.into(), 40)); + assert_ok!(Balances::transfer(Origin::signed(4), 1.into(), 40)); Session::check_rotate_session(System::block_number()); // Block 6: Lowest now validator. @@ -279,7 +279,7 @@ fn staking_should_work() { // Block 7: Unstake three. No change yet. System::set_block_number(7); - assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); + assert_ok!(Staking::unstake(Origin::signed(3), Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); Session::check_rotate_session(System::block_number()); assert_eq!(Session::validators(), vec![1, 3]); @@ -299,10 +299,10 @@ fn nominating_and_rewards_should_work() { assert_eq!(Session::validators(), vec![10, 20]); System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::stake(&2)); - assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::nominate(&4, 1.into())); + assert_ok!(Staking::stake(Origin::signed(1))); + assert_ok!(Staking::stake(Origin::signed(2))); + assert_ok!(Staking::stake(Origin::signed(3))); + assert_ok!(Staking::nominate(Origin::signed(4), 1.into())); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 @@ -312,7 +312,7 @@ fn nominating_and_rewards_should_work() { assert_eq!(Balances::total_balance(&4), 40); System::set_block_number(2); - assert_ok!(Staking::unnominate(&4, 0)); + assert_ok!(Staking::unnominate(Origin::signed(4), 0)); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 2); assert_eq!(Session::validators(), vec![3, 2]); @@ -322,9 +322,9 @@ fn nominating_and_rewards_should_work() { assert_eq!(Balances::total_balance(&4), 48); System::set_block_number(3); - assert_ok!(Staking::stake(&4)); - assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); - assert_ok!(Staking::nominate(&3, 1.into())); + assert_ok!(Staking::stake(Origin::signed(4))); + assert_ok!(Staking::unstake(Origin::signed(3), Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); + assert_ok!(Staking::nominate(Origin::signed(3), 1.into())); Session::check_rotate_session(System::block_number()); assert_eq!(Session::validators(), vec![1, 4]); assert_eq!(Balances::total_balance(&1), 12); @@ -345,9 +345,9 @@ fn nominating_and_rewards_should_work() { fn rewards_with_off_the_table_should_work() { with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || { System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::nominate(&2, 1.into())); - assert_ok!(Staking::stake(&3)); + assert_ok!(Staking::stake(Origin::signed(1))); + assert_ok!(Staking::nominate(Origin::signed(2), 1.into())); + assert_ok!(Staking::stake(Origin::signed(3))); Session::check_rotate_session(System::block_number()); assert_eq!(Session::validators(), vec![1, 3]); // 1 + 2, 3 assert_eq!(Balances::total_balance(&1), 10); @@ -355,7 +355,7 @@ fn rewards_with_off_the_table_should_work() { assert_eq!(Balances::total_balance(&3), 30); System::set_block_number(2); - assert_ok!(Staking::register_preferences(&1, Staking::intentions().into_iter().position(|i| i == 1).unwrap() as u32, ValidatorPrefs { unstake_threshold: 3, validator_payment: 4 })); + assert_ok!(Staking::register_preferences(Origin::signed(1), Staking::intentions().into_iter().position(|i| i == 1).unwrap() as u32, ValidatorPrefs { unstake_threshold: 3, validator_payment: 4 })); Session::check_rotate_session(System::block_number()); assert_eq!(Balances::total_balance(&1), 16); assert_eq!(Balances::total_balance(&2), 24); @@ -376,10 +376,10 @@ fn nominating_slashes_should_work() { Timestamp::set_timestamp(15); System::set_block_number(4); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::nominate(&2, 3.into())); - assert_ok!(Staking::nominate(&4, 1.into())); + assert_ok!(Staking::stake(Origin::signed(1))); + assert_ok!(Staking::stake(Origin::signed(3))); + assert_ok!(Staking::nominate(Origin::signed(2), 3.into())); + assert_ok!(Staking::nominate(Origin::signed(4), 1.into())); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 1); @@ -404,12 +404,12 @@ fn nominating_slashes_should_work() { fn double_staking_should_fail() { with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_noop!(Staking::stake(&1), "Cannot stake if already staked."); - assert_noop!(Staking::nominate(&1, 1.into()), "Cannot nominate if already staked."); - assert_ok!(Staking::nominate(&2, 1.into())); - assert_noop!(Staking::stake(&2), "Cannot stake if already nominating."); - assert_noop!(Staking::nominate(&2, 1.into()), "Cannot nominate if already nominating."); + assert_ok!(Staking::stake(Origin::signed(1))); + assert_noop!(Staking::stake(Origin::signed(1)), "Cannot stake if already staked."); + assert_noop!(Staking::nominate(Origin::signed(1), 1.into()), "Cannot nominate if already staked."); + assert_ok!(Staking::nominate(Origin::signed(2), 1.into())); + assert_noop!(Staking::stake(Origin::signed(2)), "Cannot stake if already nominating."); + assert_noop!(Staking::nominate(Origin::signed(2), 1.into()), "Cannot nominate if already nominating."); }); } @@ -440,7 +440,7 @@ fn staking_eras_work() { // Block 3: Schedule an era length change; no visible changes. System::set_block_number(3); - assert_ok!(Staking::set_sessions_per_era(3)); + assert_ok!(Staking::set_sessions_per_era(Origin::ROOT, 3)); Session::check_rotate_session(System::block_number()); assert_eq!(Session::current_index(), 3); assert_eq!(Staking::sessions_per_era(), 2); @@ -485,8 +485,8 @@ fn staking_eras_work() { fn staking_balance_transfer_when_bonded_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { Balances::set_free_balance(&1, 111); - assert_ok!(Staking::stake(&1)); - assert_noop!(Balances::transfer(&1, 2.into(), 69), "cannot transfer illiquid funds"); + assert_ok!(Staking::stake(Origin::signed(1))); + assert_noop!(Balances::transfer(Origin::signed(1), 2.into(), 69), "cannot transfer illiquid funds"); }); } diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index 4f691c89afde9..cd83ce0f09450 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -45,7 +45,7 @@ extern crate safe_mix; use rstd::prelude::*; use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded, - Hash, Member, MaybeDisplay, RefInto, MaybeEmpty}; + Hash, Member, MaybeDisplay}; use runtime_support::{StorageValue, StorageMap, Parameter}; use safe_mix::TripletMix; @@ -69,9 +69,7 @@ pub fn extrinsics_data_root(xts: Vec>) -> H::Output { } pub trait Trait: Eq + Clone { - // We require that PublicAux impl MaybeEmpty, since we require that inherents - or unsigned - // user-level extrinsics - can exist. - type PublicAux: RefInto + MaybeEmpty; + type Origin: Into>> + From>; type Index: Parameter + Member + Default + MaybeDisplay + SimpleArithmetic + Copy; type BlockNumber: Parameter + Member + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + rstd::hash::Hash; type Hash: Parameter + Member + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]>; @@ -89,7 +87,7 @@ pub trait Trait: Eq + Clone { pub type DigestItemOf = <::Digest as traits::Digest>::Item; decl_module! { - pub struct Module; + pub struct Module for enum Call where origin: T::Origin {} } /// A phase of a block's execution. @@ -126,6 +124,30 @@ impl From for () { fn from(_: Event) -> () { () } } +/// Origin for the system module. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum RawOrigin { + /// The system itself ordained this dispatch to happen: this is the highest privilege level. + Root, + /// It is signed by some public key and we provide the AccountId. + Signed(AccountId), + /// It is signed by nobody but included and agreed upon by the validators anyway: it's "inherently" true. + Inherent, +} + +impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::Inherent, + } + } +} + +/// Exposed trait-generic origin type. +pub type Origin = RawOrigin<::AccountId>; + decl_storage! { trait Store for Module as System { @@ -146,6 +168,37 @@ decl_storage! { } } +/// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction). +/// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise. +pub fn ensure_signed(o: OuterOrigin) -> Result + where OuterOrigin: Into>> +{ + match o.into() { + Some(RawOrigin::Signed(t)) => Ok(t), + _ => Err("bad origin: expected to be a signed origin"), + } +} + +/// Ensure that the origin `o` represents the root. Returns `Ok` or an `Err` otherwise. +pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> + where OuterOrigin: Into>> +{ + match o.into() { + Some(RawOrigin::Root) => Ok(()), + _ => Err("bad origin: expected to be a root origin"), + } +} + +/// Ensure that the origin `o` represents an unsigned extrinsic. Returns `Ok` or an `Err` otherwise. +pub fn ensure_inherent(o: OuterOrigin) -> Result<(), &'static str> + where OuterOrigin: Into>> +{ + match o.into() { + Some(RawOrigin::Inherent) => Ok(()), + _ => Err("bad origin: expected to be an inherent origin"), + } +} + impl Module { /// Start the execution of a particular block. pub fn initialise(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) { @@ -307,10 +360,14 @@ mod tests { use primitives::traits::BlakeTwo256; use primitives::testing::{Digest, Header}; + impl_outer_origin!{ + pub enum Origin for Test where system = super {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl Trait for Test { - type PublicAux = u64; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -332,6 +389,8 @@ mod tests { type System = Module; + + fn new_test_ext() -> runtime_io::TestExternalities { GenesisConfig::::default().build_storage().unwrap().into() } diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index b8938e7e198f9..b586dae19b914 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -40,11 +40,10 @@ extern crate substrate_codec as codec; use runtime_support::{StorageValue, Parameter}; use runtime_support::dispatch::Result; -use runtime_primitives::traits::{OnFinalise, MaybeEmpty, SimpleArithmetic, As, Zero}; +use runtime_primitives::traits::{OnFinalise, SimpleArithmetic, As, Zero}; +use system::ensure_inherent; -pub trait Trait: consensus::Trait where - ::PublicAux: MaybeEmpty -{ +pub trait Trait: consensus::Trait + system::Trait { // the position of the required timestamp-set extrinsic. const TIMESTAMP_SET_POSITION: u32; @@ -52,11 +51,8 @@ pub trait Trait: consensus::Trait where } decl_module! { - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { - fn set(aux, now: T::Moment) -> Result; + pub struct Module for enum Call where origin: T::Origin { + fn set(origin, now: T::Moment) -> Result; } } @@ -77,8 +73,8 @@ impl Module { } /// Set the current time. - fn set(aux: &T::PublicAux, now: T::Moment) -> Result { - assert!(aux.is_empty()); + fn set(origin: T::Origin, now: T::Moment) -> Result { + ensure_inherent(origin)?; assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); assert!( >::extrinsic_index() == Some(T::TIMESTAMP_SET_POSITION), @@ -146,10 +142,14 @@ mod tests { use runtime_primitives::traits::{BlakeTwo256}; use runtime_primitives::testing::{Digest, Header}; + impl_outer_origin! { + pub enum Origin for Test {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -178,7 +178,7 @@ mod tests { let mut t = runtime_io::TestExternalities::from(t); with_externalities(&mut t, || { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::aux_dispatch(Call::set(69), &0)); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::INHERENT)); assert_eq!(Timestamp::now(), 69); }); } @@ -191,8 +191,8 @@ mod tests { let mut t = runtime_io::TestExternalities::from(t); with_externalities(&mut t, || { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::aux_dispatch(Call::set(69), &0)); - let _ = Timestamp::aux_dispatch(Call::set(70), &0); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::INHERENT)); + let _ = Timestamp::dispatch(Call::set(70), Origin::INHERENT); }); } @@ -204,7 +204,7 @@ mod tests { let mut t = runtime_io::TestExternalities::from(t); with_externalities(&mut t, || { Timestamp::set_timestamp(42); - let _ = Timestamp::aux_dispatch(Call::set(46), &0); + let _ = Timestamp::dispatch(Call::set(46), Origin::INHERENT); }); } } diff --git a/substrate/runtime/treasury/src/lib.rs b/substrate/runtime/treasury/src/lib.rs index c6ddd21c8ad49..b0b962a7d58d5 100644 --- a/substrate/runtime/treasury/src/lib.rs +++ b/substrate/runtime/treasury/src/lib.rs @@ -44,8 +44,9 @@ extern crate substrate_runtime_balances as balances; use rstd::ops::{Mul, Div}; use runtime_support::{StorageValue, StorageMap}; use runtime_support::dispatch::Result; -use runtime_primitives::traits::{As, OnFinalise, Zero, RefInto}; +use runtime_primitives::traits::{As, OnFinalise, Zero}; use balances::OnMinted; +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 @@ -63,35 +64,24 @@ type ProposalIndex = u32; // macro takes care of the marshalling of arguments and dispatch. decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. - pub struct Module; - - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { + pub struct Module for enum Call where origin: T::Origin { // Put forward a suggestion for spending. A deposit proportional to the value // is reserved and slashed if the proposal is rejected. It is returned once the // proposal is awarded. - fn propose_spend(aux, value: T::Balance, beneficiary: T::AccountId) -> Result; - } + fn propose_spend(origin, value: T::Balance, beneficiary: T::AccountId) -> Result; - // The priviledged entry points. These are provided to allow any governance modules in - // the runtime to be able to execute common functions. Unlike for `Call` there is no - // auxilliary data to encode the sender (since there is no sender). Though still important - // to ensure that these execute in reasonable time and space, they can do what would - // otherwise be costly or unsafe operations. - #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum PrivCall { // Set the balance of funds available to spend. - fn set_pot(new_pot: T::Balance) -> Result; + fn set_pot(origin, new_pot: T::Balance) -> Result; // (Re-)configure this module. - fn configure(proposal_bond: Permill, proposal_bond_minimum: T::Balance, spend_period: T::BlockNumber, burn: Permill) -> Result; + fn configure(origin, proposal_bond: Permill, proposal_bond_minimum: T::Balance, spend_period: T::BlockNumber, burn: Permill) -> Result; // Reject a proposed spend. The original deposit will be slashed. - fn reject_proposal(proposal_id: ProposalIndex) -> Result; + fn reject_proposal(origin, roposal_id: ProposalIndex) -> Result; // Approve a proposal. At a later time, the proposal will be allocated to the beneficiary // and the original deposit will be returned. - fn approve_proposal(proposal_id: ProposalIndex) -> Result; + fn approve_proposal(origin, proposal_id: ProposalIndex) -> Result; } } @@ -183,25 +173,26 @@ impl Module { >::deposit_event(::Event::from(event).into()); } - // Implement Calls/PrivCalls and add public immutables and private mutables. + // Implement Calls and add public immutables and private mutables. - fn propose_spend(aux: &T::PublicAux, value: T::Balance, beneficiary: T::AccountId) -> Result { - let proposer = aux.ref_into(); + fn propose_spend(origin: T::Origin, value: T::Balance, beneficiary: T::AccountId) -> Result { + let proposer = ensure_signed(origin)?; let bond = Self::calculate_bond(value); - >::reserve(proposer, bond) + >::reserve(&proposer, bond) .map_err(|_| "Proposer's balance too low")?; let c = Self::proposal_count(); >::put(c + 1); - >::insert(c, Proposal { proposer: proposer.clone(), value, beneficiary, bond }); + >::insert(c, Proposal { proposer, value, beneficiary, bond }); Self::deposit_event(RawEvent::Proposed(c)); Ok(()) } - fn reject_proposal(proposal_id: ProposalIndex) -> Result { + fn reject_proposal(origin: T::Origin, proposal_id: ProposalIndex) -> Result { + ensure_root(origin)?; let proposal = >::take(proposal_id).ok_or("No proposal at that index")?; let value = proposal.bond; @@ -210,7 +201,8 @@ impl Module { Ok(()) } - fn approve_proposal(proposal_id: ProposalIndex) -> Result { + fn approve_proposal(origin: T::Origin, proposal_id: ProposalIndex) -> Result { + ensure_root(origin)?; ensure!(>::exists(proposal_id), "No proposal at that index"); { @@ -224,7 +216,8 @@ impl Module { Ok(()) } - fn set_pot(new_pot: T::Balance) -> Result { + fn set_pot(origin: T::Origin, new_pot: T::Balance) -> Result { + ensure_root(origin)?; // Put the new value into storage. >::put(new_pot); @@ -233,11 +226,13 @@ impl Module { } fn configure( + origin: T::Origin, proposal_bond: Permill, proposal_bond_minimum: T::Balance, spend_period: T::BlockNumber, burn: Permill ) -> Result { + ensure_root(origin)?; >::put(proposal_bond); >::put(proposal_bond_minimum); >::put(spend_period); @@ -358,10 +353,14 @@ mod tests { use runtime_primitives::traits::{BlakeTwo256}; use runtime_primitives::testing::{Digest, Header}; + impl_outer_origin! { + pub enum Origin for Test {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { - type PublicAux = Self::AccountId; + type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -428,7 +427,7 @@ mod tests { #[test] fn spend_proposal_takes_min_deposit() { with_externalities(&mut new_test_ext(), || { - assert_ok!(Treasury::propose_spend(&0, 1, 3)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); assert_eq!(Balances::free_balance(&0), 99); assert_eq!(Balances::reserved_balance(&0), 1); }); @@ -437,7 +436,7 @@ mod tests { #[test] fn spend_proposal_takes_proportional_deposit() { with_externalities(&mut new_test_ext(), || { - assert_ok!(Treasury::propose_spend(&0, 100, 3)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_eq!(Balances::free_balance(&0), 95); assert_eq!(Balances::reserved_balance(&0), 5); }); @@ -446,7 +445,7 @@ mod tests { #[test] fn spend_proposal_fails_when_proposer_poor() { with_externalities(&mut new_test_ext(), || { - assert_noop!(Treasury::propose_spend(&2, 100, 3), "Proposer's balance too low"); + assert_noop!(Treasury::propose_spend(Origin::signed(2), 100, 3), "Proposer's balance too low"); }); } @@ -455,8 +454,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_minted(100); - assert_ok!(Treasury::propose_spend(&0, 100, 3)); - assert_ok!(Treasury::approve_proposal(0)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalise(1); assert_eq!(Balances::free_balance(&3), 0); @@ -479,8 +478,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_minted(100); - assert_ok!(Treasury::propose_spend(&0, 100, 3)); - assert_ok!(Treasury::reject_proposal(0)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); >::on_finalise(2); assert_eq!(Balances::free_balance(&3), 0); @@ -493,23 +492,23 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_minted(100); - assert_ok!(Treasury::propose_spend(&0, 100, 3)); - assert_ok!(Treasury::reject_proposal(0)); - assert_noop!(Treasury::reject_proposal(0), "No proposal at that index"); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } #[test] fn reject_non_existant_spend_proposal_fails() { with_externalities(&mut new_test_ext(), || { - assert_noop!(Treasury::reject_proposal(0), "No proposal at that index"); + assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } #[test] fn accept_non_existant_spend_proposal_fails() { with_externalities(&mut new_test_ext(), || { - assert_noop!(Treasury::approve_proposal(0), "No proposal at that index"); + assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } @@ -518,9 +517,9 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_minted(100); - assert_ok!(Treasury::propose_spend(&0, 100, 3)); - assert_ok!(Treasury::reject_proposal(0)); - assert_noop!(Treasury::approve_proposal(0), "No proposal at that index"); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } @@ -529,8 +528,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_minted(100); - assert_ok!(Treasury::propose_spend(&0, 100, 3)); - assert_ok!(Treasury::approve_proposal(0)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalise(2); assert_eq!(Balances::free_balance(&3), 100); @@ -543,8 +542,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_minted(100); - assert_ok!(Treasury::propose_spend(&0, 150, 3)); - assert_ok!(Treasury::approve_proposal(0)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalise(2); assert_eq!(Treasury::pot(), 100); diff --git a/substrate/runtime/version/src/lib.rs b/substrate/runtime/version/src/lib.rs index ab66ecc88d25d..c8e3b8f4a6dc1 100644 --- a/substrate/runtime/version/src/lib.rs +++ b/substrate/runtime/version/src/lib.rs @@ -29,16 +29,11 @@ extern crate serde_derive; #[macro_use] extern crate substrate_runtime_std as rstd; -#[macro_use] -extern crate substrate_runtime_support as runtime_support; - #[macro_use] extern crate substrate_codec_derive; extern crate substrate_codec as codec; -use rstd::prelude::*; - #[cfg(feature = "std")] use std::fmt; @@ -133,18 +128,3 @@ impl RuntimeVersion { self.spec_name == other.spec_name } } - -pub trait Trait { - const VERSION: RuntimeVersion; -} - -decl_module! { - pub struct Module; -} - -impl Module { - /// Get runtime version. - pub fn version() -> RuntimeVersion { - T::VERSION.clone() - } -} diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 0afb7c9f18416..b9e122e56f184 100644 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 674df04b2bdbf..19ea6f6adaa8e 100755 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ