diff --git a/substrate/demo/primitives/src/lib.rs b/substrate/demo/primitives/src/lib.rs index b0b9837de5..e68d6d8727 100644 --- a/substrate/demo/primitives/src/lib.rs +++ b/substrate/demo/primitives/src/lib.rs @@ -49,7 +49,7 @@ pub mod transaction; pub use self::block::{Header, Block, Log, Digest}; pub use self::block::Number as BlockNumber; -pub use self::transaction::{Transaction, UncheckedTransaction, Function, Proposal}; +pub use self::transaction::{Transaction, UncheckedTransaction, Function, Proposal, VoteThreshold}; /// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost /// certainly continue to be the same as the substrate's `AuthorityId`. diff --git a/substrate/demo/primitives/src/transaction.rs b/substrate/demo/primitives/src/transaction.rs index 6a3c8e8316..b8e6693721 100644 --- a/substrate/demo/primitives/src/transaction.rs +++ b/substrate/demo/primitives/src/transaction.rs @@ -17,7 +17,7 @@ //! Transaction type. use rstd::vec::Vec; -use codec::{Input, Slicable}; +use codec::{Input, Slicable, NonTrivialSlicable}; use {AccountId, SessionKey}; #[cfg(feature = "std")] @@ -29,24 +29,26 @@ use block::Number as BlockNumber; #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[repr(u8)] enum InternalFunctionId { - /// Set the system's code. SystemSetCode = 0x00, - /// Set the session length. SessionSetLength = 0x10, - /// Force a new session. SessionForceNewSession = 0x11, - /// Set the number of sessions per era. StakingSetSessionsPerEra = 0x20, - /// Set the minimum bonding duration for staking. StakingSetBondingDuration = 0x21, - /// Set the validator count for staking. StakingSetValidatorCount = 0x22, - /// Force a new staking era. StakingForceNewEra = 0x23, - /// See below. + DemocracyCancelReferendum = 0x30, + DemocracyStartReferendum = 0x31, + + CouncilSetDesiredSeats = 0x40, + CouncilRemoveMember = 0x41, + CouncilSetPresentationDuration = 0x42, + CouncilSetTermDuration = 0x43, + + CouncilVoteSetCooloffPeriod = 0x50, + CouncilVoteSetVotingPeriod = 0x51, } impl InternalFunctionId { @@ -66,26 +68,57 @@ impl InternalFunctionId { } } +#[derive(Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +pub enum VoteThreshold { + /// A supermajority of approvals is needed to pass this vote. + SuperMajorityApprove, + /// A supermajority of rejects is needed to fail this vote. + SuperMajorityAgainst, + /// A simple majority of approvals is needed to pass this vote. + SimpleMajority, +} + +impl Slicable for VoteThreshold { + fn decode(input: &mut I) -> Option { + u8::decode(input).and_then(|v| match v { + 0 => Some(VoteThreshold::SuperMajorityApprove), + 1 => Some(VoteThreshold::SuperMajorityAgainst), + 2 => Some(VoteThreshold::SimpleMajority), + _ => None, + }) + } + + fn using_encoded R>(&self, f: F) -> R { + match *self { + VoteThreshold::SuperMajorityApprove => 0u8, + VoteThreshold::SuperMajorityAgainst => 1u8, + VoteThreshold::SimpleMajority => 2u8, + }.using_encoded(f) + } +} +impl NonTrivialSlicable for VoteThreshold {} + /// Internal functions that can be dispatched to. #[derive(Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[allow(missing_docs)] pub enum Proposal { - /// Set the system's code. SystemSetCode(Vec), - /// Set the session length. SessionSetLength(BlockNumber), - /// Force a new session. SessionForceNewSession, - /// Set the number of sessions per era. StakingSetSessionsPerEra(BlockNumber), - /// Set the minimum bonding duration for staking. StakingSetBondingDuration(BlockNumber), - /// Set the validator count for staking. StakingSetValidatorCount(u32), - /// Force a new staking era. StakingForceNewEra, - /// Cancel a referendum. + DemocracyStartReferendum(Box, VoteThreshold), DemocracyCancelReferendum(u32), + CouncilSetDesiredSeats(u32), + CouncilRemoveMember(AccountId), + CouncilSetPresentationDuration(BlockNumber), + CouncilSetTermDuration(BlockNumber), + CouncilVoteSetCooloffPeriod(BlockNumber), + CouncilVoteSetVotingPeriod(BlockNumber), } impl Slicable for Proposal { @@ -104,7 +137,18 @@ impl Slicable for Proposal { InternalFunctionId::StakingSetValidatorCount => Proposal::StakingSetValidatorCount(Slicable::decode(input)?), InternalFunctionId::StakingForceNewEra => Proposal::StakingForceNewEra, + InternalFunctionId::DemocracyStartReferendum => { + let a = Slicable::decode(input)?; + let b = Slicable::decode(input)?; + Proposal::DemocracyStartReferendum(Box::new(a), b) + } InternalFunctionId::DemocracyCancelReferendum => Proposal::DemocracyCancelReferendum(Slicable::decode(input)?), + InternalFunctionId::CouncilSetDesiredSeats => Proposal::CouncilSetDesiredSeats(Slicable::decode(input)?), + InternalFunctionId::CouncilRemoveMember => Proposal::CouncilRemoveMember(Slicable::decode(input)?), + InternalFunctionId::CouncilSetPresentationDuration => Proposal::CouncilSetPresentationDuration(Slicable::decode(input)?), + InternalFunctionId::CouncilSetTermDuration => Proposal::CouncilSetTermDuration(Slicable::decode(input)?), + InternalFunctionId::CouncilVoteSetCooloffPeriod => Proposal::CouncilVoteSetCooloffPeriod(Slicable::decode(input)?), + InternalFunctionId::CouncilVoteSetVotingPeriod => Proposal::CouncilVoteSetVotingPeriod(Slicable::decode(input)?), }; Some(function) @@ -143,6 +187,7 @@ impl Slicable for Proposal { (InternalFunctionId::DemocracyCancelReferendum as u8).using_encoded(|s| v.extend(s)); data.using_encoded(|s| v.extend(s)); } + _ => { unimplemented!() } } v diff --git a/substrate/demo/runtime/src/dispatch.rs b/substrate/demo/runtime/src/dispatch.rs index bc5a501705..9a9aded039 100644 --- a/substrate/demo/runtime/src/dispatch.rs +++ b/substrate/demo/runtime/src/dispatch.rs @@ -14,36 +14,83 @@ // You should have received a copy of the GNU General Public License // along with Substrate Demo. If not, see . -//! Democratic system: Handles administration of general stakeholder voting. +//! Dispatch system. Just dispatches calls. -use demo_primitives::Proposal; -use runtime::{staking, system, session, democracy}; +use demo_primitives::{Function, Proposal, AccountId}; +use runtime::{staking, system, session, democracy, council, council_vote, timestamp}; -pub fn enact_proposal(proposal: Proposal) { +/// Dispatch a proposal. +pub fn proposal(proposal: Proposal) { match proposal { - Proposal::SystemSetCode(code) => { - system::privileged::set_code(&code); - } - Proposal::SessionSetLength(value) => { - session::privileged::set_length(value); - } - Proposal::SessionForceNewSession => { - session::privileged::force_new_session(); - } - Proposal::StakingSetSessionsPerEra(value) => { - staking::privileged::set_sessions_per_era(value); - } - Proposal::StakingSetBondingDuration(value) => { - staking::privileged::set_bonding_duration(value); - } - Proposal::StakingSetValidatorCount(value) => { - staking::privileged::set_validator_count(value); - } - Proposal::StakingForceNewEra => { - staking::privileged::force_new_era() - } - Proposal::DemocracyCancelReferendum(ref_index) => { - democracy::privileged::cancel_referendum(ref_index) - } + Proposal::SystemSetCode(ref a) => + system::privileged::set_code(a), + Proposal::SessionSetLength(a) => + session::privileged::set_length(a), + Proposal::SessionForceNewSession => + session::privileged::force_new_session(), + Proposal::StakingSetSessionsPerEra(a) => + staking::privileged::set_sessions_per_era(a), + Proposal::StakingSetBondingDuration(a) => + staking::privileged::set_bonding_duration(a), + Proposal::StakingSetValidatorCount(a) => + staking::privileged::set_validator_count(a), + Proposal::StakingForceNewEra => + staking::privileged::force_new_era(), + Proposal::DemocracyCancelReferendum(a) => + democracy::privileged::cancel_referendum(a), + Proposal::DemocracyStartReferendum(a, b) => + democracy::privileged::start_referendum(*a, b), + Proposal::DemocracyCancelReferendum(a) => + democracy::privileged::cancel_referendum(a), + Proposal::CouncilSetDesiredSeats(a) => + council::privileged::set_desired_seats(a), + Proposal::CouncilRemoveMember(a) => + council::privileged::remove_member(&a), + Proposal::CouncilSetPresentationDuration(a) => + council::privileged::set_presentation_duration(a), + Proposal::CouncilSetTermDuration(a) => + council::privileged::set_term_duration(a), + Proposal::CouncilVoteSetCooloffPeriod(a) => + council_vote::privileged::set_cooloff_period(a), + Proposal::CouncilVoteSetVotingPeriod(a) => + council_vote::privileged::set_voting_period(a), + } +} + +/// Dispatch a function. +pub fn function(function: &Function, transactor: &AccountId) { + match *function { + Function::StakingStake => + staking::public::stake(transactor), + Function::StakingUnstake => + staking::public::unstake(transactor), + Function::StakingTransfer(dest, value) => + staking::public::transfer(transactor, &dest, value), + Function::SessionSetKey(session) => + session::public::set_key(transactor, &session), + Function::TimestampSet(t) => + timestamp::public::set(t), + Function::CouncilVotePropose(ref a) => + council_vote::public::propose(transactor, a), + Function::CouncilVoteVote(ref a, b) => + council_vote::public::vote(transactor, a, b), + Function::CouncilVoteVeto(ref a) => + council_vote::public::veto(transactor, a), + Function::CouncilSetApprovals(ref a, b) => + council::public::set_approvals(transactor, a, b), + Function::CouncilReapInactiveVoter(a, ref b, c, d) => + council::public::reap_inactive_voter(transactor, a, b, c, d), + Function::CouncilRetractVoter(a) => + council::public::retract_voter(transactor, a), + Function::CouncilSubmitCandidacy(a) => + council::public::submit_candidacy(transactor, a), + Function::CouncilPresentWinner(ref a, b, c) => + council::public::present_winner(transactor, a, b, c), + Function::DemocracyPropose(ref a, b) => + democracy::public::propose(transactor, a, b), + Function::DemocracySecond(a) => + democracy::public::second(transactor, a), + Function::DemocracyVote(a, b) => + democracy::public::vote(transactor, a, b), } } diff --git a/substrate/demo/runtime/src/runtime/council.rs b/substrate/demo/runtime/src/runtime/council.rs index f1e1456e77..ce922f8971 100644 --- a/substrate/demo/runtime/src/runtime/council.rs +++ b/substrate/demo/runtime/src/runtime/council.rs @@ -434,7 +434,6 @@ pub mod privileged { pub mod internal { use super::*; use demo_primitives::Proposal; - use dispatch::enact_proposal; /// Check there's nothing to do this block pub fn end_block() { diff --git a/substrate/demo/runtime/src/runtime/council_vote.rs b/substrate/demo/runtime/src/runtime/council_vote.rs index ce0e7117ee..b40c79d79b 100644 --- a/substrate/demo/runtime/src/runtime/council_vote.rs +++ b/substrate/demo/runtime/src/runtime/council_vote.rs @@ -184,8 +184,8 @@ pub mod privileged { pub mod internal { use super::*; - use runtime::democracy::VoteThreshold; use runtime::democracy::privileged::start_referendum; + use demo_primitives::VoteThreshold; pub fn end_block(now: BlockNumber) { while let Some((proposal, proposal_hash)) = take_proposal_if_expiring_at(now) { @@ -240,9 +240,8 @@ mod tests { use codec::{KeyedVec, Joiner}; use keyring::Keyring::{Alice, Bob, Charlie, Dave}; use environment::with_env; - use demo_primitives::{AccountId, Proposal}; + use demo_primitives::{AccountId, Proposal, VoteThreshold}; use runtime::{staking, council, democracy}; - use runtime::democracy::VoteThreshold; fn new_test_ext() -> TestExternalities { testing::externalities() diff --git a/substrate/demo/runtime/src/runtime/democracy.rs b/substrate/demo/runtime/src/runtime/democracy.rs index 41c635ddee..2273628188 100644 --- a/substrate/demo/runtime/src/runtime/democracy.rs +++ b/substrate/demo/runtime/src/runtime/democracy.rs @@ -20,46 +20,25 @@ use rstd::prelude::*; use integer_sqrt::IntegerSquareRoot; use codec::{KeyedVec, Slicable, Input, NonTrivialSlicable}; use runtime_support::storage; -use demo_primitives::{Proposal, AccountId, Hash, BlockNumber}; +use demo_primitives::{Proposal, AccountId, Hash, BlockNumber, VoteThreshold}; use runtime::{staking, system, session}; use runtime::staking::Balance; pub type PropIndex = u32; pub type ReferendumIndex = u32; -#[cfg_attr(test, derive(Debug))] -#[derive(Clone, Copy, PartialEq)] -pub enum VoteThreshold { - SuperMajorityApprove, - SuperMajorityAgainst, - SimpleMajority, -} - -impl Slicable for VoteThreshold { - fn decode(input: &mut I) -> Option { - u8::decode(input).and_then(|v| match v { - 0 => Some(VoteThreshold::SuperMajorityApprove), - 1 => Some(VoteThreshold::SuperMajorityAgainst), - 2 => Some(VoteThreshold::SimpleMajority), - _ => None, - }) - } - - fn using_encoded R>(&self, f: F) -> R { - match *self { - VoteThreshold::SuperMajorityApprove => 0u8, - VoteThreshold::SuperMajorityAgainst => 1u8, - VoteThreshold::SimpleMajority => 2u8, - }.using_encoded(f) - } -} -impl NonTrivialSlicable for VoteThreshold {} - -impl VoteThreshold { +trait Approved { /// Given `approve` votes for and `against` votes against from a total electorate size of /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the /// overall outcome is in favour of approval. - pub fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool { + fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool; +} + +impl Approved for VoteThreshold { + /// Given `approve` votes for and `against` votes against from a total electorate size of + /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the + /// overall outcome is in favour of approval. + fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool { let voters = approve + against; match *self { VoteThreshold::SuperMajorityApprove => @@ -236,7 +215,7 @@ pub mod privileged { pub mod internal { use super::*; use demo_primitives::Proposal; - use dispatch::enact_proposal; + use dispatch; /// Current era is ending; we should finish up any proposals. pub fn end_block(now: BlockNumber) { @@ -266,7 +245,7 @@ pub mod internal { let total_stake = staking::total_stake(); clear_referendum(index); if vote_threshold.approved(approve, against, total_stake) { - enact_proposal(proposal); + dispatch::proposal(proposal); } storage::put(NEXT_TALLY, &(index + 1)); } diff --git a/substrate/demo/runtime/src/runtime/system.rs b/substrate/demo/runtime/src/runtime/system.rs index 8cb06c34be..4add4dd146 100644 --- a/substrate/demo/runtime/src/runtime/system.rs +++ b/substrate/demo/runtime/src/runtime/system.rs @@ -26,6 +26,7 @@ use environment::with_env; use demo_primitives::{AccountId, Hash, TxOrder, BlockNumber, Block, Header, UncheckedTransaction, Function, Log}; use runtime::{staking, session}; +use dispatch; pub const NONCE_OF: &[u8] = b"sys:non:"; pub const BLOCK_HASH_AT: &[u8] = b"sys:old:"; @@ -125,60 +126,6 @@ pub mod internal { header } - - /// Dispatch a function. - pub fn dispatch_function(function: &Function, transactor: &AccountId) { - match *function { - Function::StakingStake => { - ::runtime::staking::public::stake(transactor); - } - Function::StakingUnstake => { - ::runtime::staking::public::unstake(transactor); - } - Function::StakingTransfer(dest, value) => { - ::runtime::staking::public::transfer(transactor, &dest, value); - } - Function::SessionSetKey(session) => { - ::runtime::session::public::set_key(transactor, &session); - } - Function::TimestampSet(t) => { - ::runtime::timestamp::public::set(t); - } - Function::CouncilVotePropose(ref a) => { - ::runtime::council_vote::public::propose(transactor, a); - } - Function::CouncilVoteVote(ref a, b) => { - ::runtime::council_vote::public::vote(transactor, a, b); - } - Function::CouncilVoteVeto(ref a) => { - ::runtime::council_vote::public::veto(transactor, a); - } - Function::CouncilSetApprovals(ref a, b) => { - ::runtime::council::public::set_approvals(transactor, a, b); - } - Function::CouncilReapInactiveVoter(a, ref b, c, d) => { - ::runtime::council::public::reap_inactive_voter(transactor, a, b, c, d); - } - Function::CouncilRetractVoter(a) => { - ::runtime::council::public::retract_voter(transactor, a); - } - Function::CouncilSubmitCandidacy(a) => { - ::runtime::council::public::submit_candidacy(transactor, a); - } - Function::CouncilPresentWinner(ref a, b, c) => { - ::runtime::council::public::present_winner(transactor, a, b, c); - } - Function::DemocracyPropose(ref a, b) => { - ::runtime::democracy::public::propose(transactor, a, b); - } - Function::DemocracySecond(a) => { - ::runtime::democracy::public::second(transactor, a); - } - Function::DemocracyVote(a, b) => { - ::runtime::democracy::public::vote(transactor, a, b); - } - } - } } fn execute_transaction(utx: UncheckedTransaction) { @@ -199,7 +146,7 @@ fn execute_transaction(utx: UncheckedTransaction) { storage::put(&nonce_key, &(expected_nonce + 1)); // decode parameters and dispatch - internal::dispatch_function(&tx.function, &tx.signed); + dispatch::function(&tx.function, &tx.signed); } fn initial_checks(block: &Block) {