Cleanups and introduce all dispatchable endpoints.

This commit is contained in:
Gav
2018-03-12 10:15:30 +01:00
parent 873b579726
commit 550ec8cdf5
7 changed files with 154 additions and 138 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ pub mod transaction;
pub use self::block::{Header, Block, Log, Digest}; pub use self::block::{Header, Block, Log, Digest};
pub use self::block::Number as BlockNumber; 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 /// 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`. /// certainly continue to be the same as the substrate's `AuthorityId`.
+62 -17
View File
@@ -17,7 +17,7 @@
//! Transaction type. //! Transaction type.
use rstd::vec::Vec; use rstd::vec::Vec;
use codec::{Input, Slicable}; use codec::{Input, Slicable, NonTrivialSlicable};
use {AccountId, SessionKey}; use {AccountId, SessionKey};
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -29,24 +29,26 @@ use block::Number as BlockNumber;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[repr(u8)] #[repr(u8)]
enum InternalFunctionId { enum InternalFunctionId {
/// Set the system's code.
SystemSetCode = 0x00, SystemSetCode = 0x00,
/// Set the session length.
SessionSetLength = 0x10, SessionSetLength = 0x10,
/// Force a new session.
SessionForceNewSession = 0x11, SessionForceNewSession = 0x11,
/// Set the number of sessions per era.
StakingSetSessionsPerEra = 0x20, StakingSetSessionsPerEra = 0x20,
/// Set the minimum bonding duration for staking.
StakingSetBondingDuration = 0x21, StakingSetBondingDuration = 0x21,
/// Set the validator count for staking.
StakingSetValidatorCount = 0x22, StakingSetValidatorCount = 0x22,
/// Force a new staking era.
StakingForceNewEra = 0x23, StakingForceNewEra = 0x23,
/// See below.
DemocracyCancelReferendum = 0x30, DemocracyCancelReferendum = 0x30,
DemocracyStartReferendum = 0x31,
CouncilSetDesiredSeats = 0x40,
CouncilRemoveMember = 0x41,
CouncilSetPresentationDuration = 0x42,
CouncilSetTermDuration = 0x43,
CouncilVoteSetCooloffPeriod = 0x50,
CouncilVoteSetVotingPeriod = 0x51,
} }
impl InternalFunctionId { 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<I: Input>(input: &mut I) -> Option<Self> {
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, F: FnOnce(&[u8]) -> 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. /// Internal functions that can be dispatched to.
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[allow(missing_docs)]
pub enum Proposal { pub enum Proposal {
/// Set the system's code.
SystemSetCode(Vec<u8>), SystemSetCode(Vec<u8>),
/// Set the session length.
SessionSetLength(BlockNumber), SessionSetLength(BlockNumber),
/// Force a new session.
SessionForceNewSession, SessionForceNewSession,
/// Set the number of sessions per era.
StakingSetSessionsPerEra(BlockNumber), StakingSetSessionsPerEra(BlockNumber),
/// Set the minimum bonding duration for staking.
StakingSetBondingDuration(BlockNumber), StakingSetBondingDuration(BlockNumber),
/// Set the validator count for staking.
StakingSetValidatorCount(u32), StakingSetValidatorCount(u32),
/// Force a new staking era.
StakingForceNewEra, StakingForceNewEra,
/// Cancel a referendum. DemocracyStartReferendum(Box<Proposal>, VoteThreshold),
DemocracyCancelReferendum(u32), DemocracyCancelReferendum(u32),
CouncilSetDesiredSeats(u32),
CouncilRemoveMember(AccountId),
CouncilSetPresentationDuration(BlockNumber),
CouncilSetTermDuration(BlockNumber),
CouncilVoteSetCooloffPeriod(BlockNumber),
CouncilVoteSetVotingPeriod(BlockNumber),
} }
impl Slicable for Proposal { impl Slicable for Proposal {
@@ -104,7 +137,18 @@ impl Slicable for Proposal {
InternalFunctionId::StakingSetValidatorCount => InternalFunctionId::StakingSetValidatorCount =>
Proposal::StakingSetValidatorCount(Slicable::decode(input)?), Proposal::StakingSetValidatorCount(Slicable::decode(input)?),
InternalFunctionId::StakingForceNewEra => Proposal::StakingForceNewEra, 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::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) Some(function)
@@ -143,6 +187,7 @@ impl Slicable for Proposal {
(InternalFunctionId::DemocracyCancelReferendum as u8).using_encoded(|s| v.extend(s)); (InternalFunctionId::DemocracyCancelReferendum as u8).using_encoded(|s| v.extend(s));
data.using_encoded(|s| v.extend(s)); data.using_encoded(|s| v.extend(s));
} }
_ => { unimplemented!() }
} }
v v
+75 -28
View File
@@ -14,36 +14,83 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate Demo. If not, see <http://www.gnu.org/licenses/>. // along with Substrate Demo. If not, see <http://www.gnu.org/licenses/>.
//! Democratic system: Handles administration of general stakeholder voting. //! Dispatch system. Just dispatches calls.
use demo_primitives::Proposal; use demo_primitives::{Function, Proposal, AccountId};
use runtime::{staking, system, session, democracy}; 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 { match proposal {
Proposal::SystemSetCode(code) => { Proposal::SystemSetCode(ref a) =>
system::privileged::set_code(&code); system::privileged::set_code(a),
} Proposal::SessionSetLength(a) =>
Proposal::SessionSetLength(value) => { session::privileged::set_length(a),
session::privileged::set_length(value); Proposal::SessionForceNewSession =>
} session::privileged::force_new_session(),
Proposal::SessionForceNewSession => { Proposal::StakingSetSessionsPerEra(a) =>
session::privileged::force_new_session(); staking::privileged::set_sessions_per_era(a),
} Proposal::StakingSetBondingDuration(a) =>
Proposal::StakingSetSessionsPerEra(value) => { staking::privileged::set_bonding_duration(a),
staking::privileged::set_sessions_per_era(value); Proposal::StakingSetValidatorCount(a) =>
} staking::privileged::set_validator_count(a),
Proposal::StakingSetBondingDuration(value) => { Proposal::StakingForceNewEra =>
staking::privileged::set_bonding_duration(value); staking::privileged::force_new_era(),
} Proposal::DemocracyCancelReferendum(a) =>
Proposal::StakingSetValidatorCount(value) => { democracy::privileged::cancel_referendum(a),
staking::privileged::set_validator_count(value); Proposal::DemocracyStartReferendum(a, b) =>
} democracy::privileged::start_referendum(*a, b),
Proposal::StakingForceNewEra => { Proposal::DemocracyCancelReferendum(a) =>
staking::privileged::force_new_era() democracy::privileged::cancel_referendum(a),
} Proposal::CouncilSetDesiredSeats(a) =>
Proposal::DemocracyCancelReferendum(ref_index) => { council::privileged::set_desired_seats(a),
democracy::privileged::cancel_referendum(ref_index) 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),
} }
} }
@@ -434,7 +434,6 @@ pub mod privileged {
pub mod internal { pub mod internal {
use super::*; use super::*;
use demo_primitives::Proposal; use demo_primitives::Proposal;
use dispatch::enact_proposal;
/// Check there's nothing to do this block /// Check there's nothing to do this block
pub fn end_block() { pub fn end_block() {
@@ -184,8 +184,8 @@ pub mod privileged {
pub mod internal { pub mod internal {
use super::*; use super::*;
use runtime::democracy::VoteThreshold;
use runtime::democracy::privileged::start_referendum; use runtime::democracy::privileged::start_referendum;
use demo_primitives::VoteThreshold;
pub fn end_block(now: BlockNumber) { pub fn end_block(now: BlockNumber) {
while let Some((proposal, proposal_hash)) = take_proposal_if_expiring_at(now) { while let Some((proposal, proposal_hash)) = take_proposal_if_expiring_at(now) {
@@ -240,9 +240,8 @@ mod tests {
use codec::{KeyedVec, Joiner}; use codec::{KeyedVec, Joiner};
use keyring::Keyring::{Alice, Bob, Charlie, Dave}; use keyring::Keyring::{Alice, Bob, Charlie, Dave};
use environment::with_env; use environment::with_env;
use demo_primitives::{AccountId, Proposal}; use demo_primitives::{AccountId, Proposal, VoteThreshold};
use runtime::{staking, council, democracy}; use runtime::{staking, council, democracy};
use runtime::democracy::VoteThreshold;
fn new_test_ext() -> TestExternalities { fn new_test_ext() -> TestExternalities {
testing::externalities() testing::externalities()
+12 -33
View File
@@ -20,46 +20,25 @@ use rstd::prelude::*;
use integer_sqrt::IntegerSquareRoot; use integer_sqrt::IntegerSquareRoot;
use codec::{KeyedVec, Slicable, Input, NonTrivialSlicable}; use codec::{KeyedVec, Slicable, Input, NonTrivialSlicable};
use runtime_support::storage; 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, system, session};
use runtime::staking::Balance; use runtime::staking::Balance;
pub type PropIndex = u32; pub type PropIndex = u32;
pub type ReferendumIndex = u32; pub type ReferendumIndex = u32;
#[cfg_attr(test, derive(Debug))] trait Approved {
#[derive(Clone, Copy, PartialEq)]
pub enum VoteThreshold {
SuperMajorityApprove,
SuperMajorityAgainst,
SimpleMajority,
}
impl Slicable for VoteThreshold {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
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, F: FnOnce(&[u8]) -> 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 {
/// Given `approve` votes for and `against` votes against from a total electorate size of /// 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 /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the
/// overall outcome is in favour of approval. /// 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; let voters = approve + against;
match *self { match *self {
VoteThreshold::SuperMajorityApprove => VoteThreshold::SuperMajorityApprove =>
@@ -236,7 +215,7 @@ pub mod privileged {
pub mod internal { pub mod internal {
use super::*; use super::*;
use demo_primitives::Proposal; use demo_primitives::Proposal;
use dispatch::enact_proposal; use dispatch;
/// Current era is ending; we should finish up any proposals. /// Current era is ending; we should finish up any proposals.
pub fn end_block(now: BlockNumber) { pub fn end_block(now: BlockNumber) {
@@ -266,7 +245,7 @@ pub mod internal {
let total_stake = staking::total_stake(); let total_stake = staking::total_stake();
clear_referendum(index); clear_referendum(index);
if vote_threshold.approved(approve, against, total_stake) { if vote_threshold.approved(approve, against, total_stake) {
enact_proposal(proposal); dispatch::proposal(proposal);
} }
storage::put(NEXT_TALLY, &(index + 1)); storage::put(NEXT_TALLY, &(index + 1));
} }
+2 -55
View File
@@ -26,6 +26,7 @@ use environment::with_env;
use demo_primitives::{AccountId, Hash, TxOrder, BlockNumber, Block, Header, use demo_primitives::{AccountId, Hash, TxOrder, BlockNumber, Block, Header,
UncheckedTransaction, Function, Log}; UncheckedTransaction, Function, Log};
use runtime::{staking, session}; use runtime::{staking, session};
use dispatch;
pub const NONCE_OF: &[u8] = b"sys:non:"; pub const NONCE_OF: &[u8] = b"sys:non:";
pub const BLOCK_HASH_AT: &[u8] = b"sys:old:"; pub const BLOCK_HASH_AT: &[u8] = b"sys:old:";
@@ -125,60 +126,6 @@ pub mod internal {
header 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) { fn execute_transaction(utx: UncheckedTransaction) {
@@ -199,7 +146,7 @@ fn execute_transaction(utx: UncheckedTransaction) {
storage::put(&nonce_key, &(expected_nonce + 1)); storage::put(&nonce_key, &(expected_nonce + 1));
// decode parameters and dispatch // decode parameters and dispatch
internal::dispatch_function(&tx.function, &tx.signed); dispatch::function(&tx.function, &tx.signed);
} }
fn initial_checks(block: &Block) { fn initial_checks(block: &Block) {