diff --git a/substrate/demo/primitives/src/transaction.rs b/substrate/demo/primitives/src/transaction.rs
index 6f4feab790..090b64b27d 100644
--- a/substrate/demo/primitives/src/transaction.rs
+++ b/substrate/demo/primitives/src/transaction.rs
@@ -44,10 +44,6 @@ enum InternalFunctionId {
StakingSetValidatorCount = 0x22,
/// Force a new staking era.
StakingForceNewEra = 0x23,
-
- /// Set the per-mille of validator approval required for governance changes.
- GovernanceSetApprovalPpmRequired = 0x30,
-
}
impl InternalFunctionId {
@@ -61,7 +57,6 @@ impl InternalFunctionId {
InternalFunctionId::StakingSetBondingDuration,
InternalFunctionId::StakingSetValidatorCount,
InternalFunctionId::StakingForceNewEra,
- InternalFunctionId::GovernanceSetApprovalPpmRequired,
];
functions.iter().map(|&f| f).find(|&f| value == f as u8)
}
@@ -85,9 +80,6 @@ pub enum Proposal {
StakingSetValidatorCount(u32),
/// Force a new staking era.
StakingForceNewEra,
- /// Set the per-mille of validator approval required for governance changes.
- GovernanceSetApprovalPpmRequired(u32),
-
}
impl Slicable for Proposal {
@@ -106,8 +98,6 @@ impl Slicable for Proposal {
InternalFunctionId::StakingSetValidatorCount =>
Proposal::StakingSetValidatorCount(try_opt!(Slicable::decode(input))),
InternalFunctionId::StakingForceNewEra => Proposal::StakingForceNewEra,
- InternalFunctionId::GovernanceSetApprovalPpmRequired =>
- Proposal::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::decode(input))),
};
Some(function)
@@ -142,10 +132,6 @@ impl Slicable for Proposal {
Proposal::StakingForceNewEra => {
(InternalFunctionId::StakingForceNewEra as u8).using_encoded(|s| v.extend(s));
}
- Proposal::GovernanceSetApprovalPpmRequired(ref data) => {
- (InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).using_encoded(|s| v.extend(s));
- data.using_encoded(|s| v.extend(s));
- }
}
v
@@ -167,10 +153,6 @@ enum FunctionId {
StakingUnstake = 0x21,
/// Staking subsystem: transfer stake.
StakingTransfer = 0x22,
- /// Make a proposal for the governance system.
- GovernancePropose = 0x30,
- /// Approve a proposal for the governance system.
- GovernanceApprove = 0x31,
}
impl FunctionId {
@@ -179,7 +161,7 @@ impl FunctionId {
use self::*;
let functions = [FunctionId::StakingStake, FunctionId::StakingUnstake,
FunctionId::StakingTransfer, FunctionId::SessionSetKey, FunctionId::TimestampSet,
- FunctionId::GovernancePropose, FunctionId::GovernanceApprove];
+ ];
functions.iter().map(|&f| f).find(|&f| value == f as u8)
}
}
@@ -198,10 +180,6 @@ pub enum Function {
StakingUnstake,
/// Staking subsystem: transfer stake.
StakingTransfer(::AccountId, u64),
- /// Make a proposal for the governance system.
- GovernancePropose(Proposal),
- /// Approve a proposal for the governance system.
- GovernanceApprove(BlockNumber),
}
impl Slicable for Function {
@@ -220,10 +198,6 @@ impl Slicable for Function {
Function::StakingTransfer(to, amount)
}
- FunctionId::GovernancePropose =>
- Function::GovernancePropose(try_opt!(Slicable::decode(input))),
- FunctionId::GovernanceApprove =>
- Function::GovernanceApprove(try_opt!(Slicable::decode(input))),
})
}
@@ -249,14 +223,6 @@ impl Slicable for Function {
to.using_encoded(|s| v.extend(s));
amount.using_encoded(|s| v.extend(s));
}
- Function::GovernancePropose(ref data) => {
- (FunctionId::GovernancePropose as u8).using_encoded(|s| v.extend(s));
- data.using_encoded(|s| v.extend(s));
- }
- Function::GovernanceApprove(ref data) => {
- (FunctionId::GovernanceApprove as u8).using_encoded(|s| v.extend(s));
- data.using_encoded(|s| v.extend(s));
- }
}
v
diff --git a/substrate/demo/runtime/src/dispatch.rs b/substrate/demo/runtime/src/dispatch.rs
index 6b03667ff9..b473a6a878 100644
--- a/substrate/demo/runtime/src/dispatch.rs
+++ b/substrate/demo/runtime/src/dispatch.rs
@@ -17,7 +17,7 @@
//! Democratic system: Handles administration of general stakeholder voting.
use demo_primitives::Proposal;
-use runtime::{staking, system, session, governance};
+use runtime::{staking, system, session};
pub fn enact_proposal(proposal: Proposal) {
match proposal {
@@ -42,8 +42,5 @@ pub fn enact_proposal(proposal: Proposal) {
Proposal::StakingForceNewEra => {
staking::privileged::force_new_era()
}
- Proposal::GovernanceSetApprovalPpmRequired(value) => {
- governance::privileged::set_approval_ppm_required(value);
- }
}
}
diff --git a/substrate/demo/runtime/src/runtime/council_vote.rs b/substrate/demo/runtime/src/runtime/council_vote.rs
new file mode 100644
index 0000000000..394316a66e
--- /dev/null
+++ b/substrate/demo/runtime/src/runtime/council_vote.rs
@@ -0,0 +1,169 @@
+// Copyright 2017 Parity Technologies (UK) Ltd.
+// This file is part of Substrate Demo.
+
+// Substrate Demo 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 Demo 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 Demo. If not, see .
+
+//! Council voting system.
+
+use rstd::prelude::*;
+use codec::{KeyedVec, Slicable, Input, NonTrivialSlicable};
+use runtime_support::Hashable;
+use runtime_support::storage;
+use demo_primitives::{Proposal, AccountId, Hash, BlockNumber};
+use runtime::{system, democracy, council};
+use runtime::staking::Balance;
+
+type ProposalHash = [u8; 32];
+
+pub const COOLOFF_PERIOD: &[u8] = b"cov:cooloff"; // BlockNumber
+pub const VOTING_PERIOD: &[u8] = b"cov:period"; // BlockNumber
+
+pub const PROPOSALS: &[u8] = b"cov:prs"; // Vec<(expiry: BlockNumber, ProposalHash)> ordered by expiry.
+pub const PROPOSAL_OF: &[u8] = b"cov:pro"; // ProposalHash -> Proposal
+pub const PROPOSAL_VOTERS: &[u8] = b"cov:voters:"; // ProposalHash -> Vec
+pub const COUNCIL_VOTE_OF: &[u8] = b"cov:vote:"; // (ProposalHash, AccountId) -> bool
+pub const VETOED_PROPOSAL: &[u8] = b"cov:veto:"; // ProposalHash -> (BlockNumber, Vec)
+
+pub fn cooloff_period() -> BlockNumber {
+ storage::get(COOLOFF_PERIOD).expect("all parameters must be defined")
+}
+
+pub fn voting_period() -> BlockNumber {
+ storage::get(VOTING_PERIOD).expect("all parameters must be defined")
+}
+
+pub fn proposals() -> Vec<(BlockNumber, ProposalHash)> {
+ storage::get_or_default(PROPOSALS)
+}
+
+pub fn was_vetoed(proposal: &ProposalHash) -> bool {
+ storage::exists(&proposal.to_keyed_vec(VETOED_PROPOSAL))
+}
+
+pub fn will_still_be_councillor_at(who: &AccountId, n: BlockNumber) -> bool {
+ council::active_council().iter()
+ .find(|&&(ref a, _)| a == who)
+ .map(|&(_, expires)| expires > n)
+ .unwrap_or(false)
+}
+
+pub fn vote_of(who: &AccountId, proposal: &ProposalHash) -> Option {
+ storage::get(&(*who, *proposal).to_keyed_vec(COUNCIL_VOTE_OF))
+}
+
+pub fn take_vote_of(who: &AccountId, proposal: &ProposalHash) -> Option {
+ storage::get(&(*who, *proposal).to_keyed_vec(COUNCIL_VOTE_OF))
+}
+
+pub fn tally(proposal_hash: &ProposalHash) -> (u32, u32, u32) {
+ generic_tally(proposal_hash, vote_of)
+}
+
+fn take_tally(proposal_hash: &ProposalHash) -> (u32, u32, u32) {
+ generic_tally(proposal_hash, take_vote_of)
+}
+
+fn generic_tally Option>(proposal_hash: &ProposalHash, vote_of: F) -> (u32, u32, u32) {
+ let c = council::active_council();
+ let (approve, reject) = c.iter()
+ .filter_map(|&(ref a, _)| vote_of(a, proposal_hash))
+ .map(|approve| if approve { (1, 0) } else { (0, 1) })
+ .fold((0, 0), |(a, b), (c, d)| (a + c, b + d));
+ (approve, reject, c.len() as u32 - approve - reject)
+}
+
+fn set_proposals(p: &Vec<(BlockNumber, ProposalHash)>) {
+ storage::put(PROPOSALS, p)
+}
+
+fn take_proposal_if_expiring_at(n: BlockNumber) -> Option<(Proposal, ProposalHash)> {
+ let mut proposals = proposals();
+ match proposals.first() {
+ Some(&(expiry, hash)) if expiry == n => {
+ // yes this is horrible, but fixing it will need substantial work in storage.
+ set_proposals(&proposals[1..].to_vec());
+ let proposal = storage::take(&hash.to_keyed_vec(PROPOSAL_OF)).expect("all queued proposal hashes must have associated proposals");
+ Some((proposal, hash))
+ }
+ _ => None,
+ }
+}
+
+pub mod public {
+ use super::*;
+
+ pub fn propose(signed: &AccountId, proposal: &Proposal) {
+ let expiry = system::block_number() + voting_period();
+ assert!(will_still_be_councillor_at(signed, expiry));
+
+ let proposal_hash = proposal.blake2_256();
+ assert!(!was_vetoed(&proposal_hash));
+
+ let mut proposals = proposals();
+ proposals.push((expiry, proposal_hash));
+ proposals.sort_by_key(|&(expiry, _)| expiry);
+ set_proposals(&proposals);
+
+ storage::put(&proposal_hash.to_keyed_vec(PROPOSAL_OF), proposal);
+ storage::put(&proposal_hash.to_keyed_vec(PROPOSAL_VOTERS), &vec![*signed]);
+ storage::put(&(proposal_hash, *signed).to_keyed_vec(COUNCIL_VOTE_OF), &true);
+ }
+
+ pub fn vote(signed: AccountId, proposal: &ProposalHash, approve: bool) {
+
+ }
+
+ pub fn veto(signed: AccountId, proposal: &ProposalHash) {
+
+ }
+
+ pub fn repropose(signed: AccountId, proposal: &Proposal) {
+
+ }
+}
+
+pub mod privileged {
+ use super::*;
+
+ pub fn set_cooloff_period(blocks: BlockNumber) {
+ storage::put(COOLOFF_PERIOD, &blocks);
+ }
+
+ pub fn set_voting_period(blocks: BlockNumber) {
+ storage::put(VOTING_PERIOD, &blocks);
+ }
+}
+
+pub mod internal {
+ use super::*;
+ use runtime::democracy::VoteThreshold;
+ use runtime::democracy::privileged::start_referendum;
+
+ pub fn end_block(now: BlockNumber) {
+ while let Some((proposal, proposal_hash)) = take_proposal_if_expiring_at(now) {
+ let tally = take_tally(&proposal_hash);
+ let vote_threshold = match tally.0 {
+ x if x == tally.2 => VoteThreshold::SuperMajorityAgainst,
+ x if x > tally.2 / 2 => VoteThreshold::SimpleMajority,
+ _ => VoteThreshold::SuperMajorityApprove,
+ };
+ start_referendum(proposal, vote_threshold);
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+
+}
diff --git a/substrate/demo/runtime/src/runtime/democracy.rs b/substrate/demo/runtime/src/runtime/democracy.rs
index 3696515349..cbc82f458d 100644
--- a/substrate/demo/runtime/src/runtime/democracy.rs
+++ b/substrate/demo/runtime/src/runtime/democracy.rs
@@ -76,11 +76,6 @@ pub const DEPOSIT_OF: &[u8] = b"dem:dep:"; // PropIndex -> (Balance, Vec CouncilVote
-pub const COUNCIL_VOTERS: &[u8] = b"dem:cou:vts"; // Vec
-
// referenda
pub const VOTING_PERIOD: &[u8] = b"dem:per"; // BlockNumber
pub const REFERENDUM_COUNT: &[u8] = b"dem:rco"; // ReferendumIndex
diff --git a/substrate/demo/runtime/src/runtime/governance.rs b/substrate/demo/runtime/src/runtime/governance.rs
deleted file mode 100644
index 4689941de4..0000000000
--- a/substrate/demo/runtime/src/runtime/governance.rs
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright 2017 Parity Technologies (UK) Ltd.
-// This file is part of Substrate Demo.
-
-// Substrate Demo 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 Demo 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 Demo. If not, see .
-
-//! Governance system: Handles administration and dispatch of sensitive operations including
-//! setting new code, minting new tokens and changing parameters.
-//!
-//! For now this is limited to a simple qualified majority vote (whose parameter is retrieved from
-//! storage) between validators. A single vote may be proposed per era, and at most one approval
-//! vote may be cast by each validator. The tally is maintained through a simple tag in storage for
-//! each validator that has approved.
-//!
-//! At the end of the era, all validators approvals are tallied and if there are sufficient to pass
-//! the proposal then it is enacted. All items in storage concerning the proposal are reset.
-
-use rstd::prelude::*;
-use codec::KeyedVec;
-use runtime_support::storage;
-use demo_primitives::{Proposal, AccountId, Hash, BlockNumber};
-use runtime::{staking, system, session};
-use dispatch::enact_proposal;
-
-pub const APPROVALS_REQUIRED: &[u8] = b"gov:apr";
-pub const CURRENT_PROPOSAL: &[u8] = b"gov:pro";
-pub const APPROVAL_OF: &[u8] = b"gov:app:";
-
-/// The proportion of validators required for a propsal to be approved measured as the number out
-/// of 1000.
-pub fn approval_ppm_required() -> u32 {
- storage::get_or(APPROVALS_REQUIRED, 1000)
-}
-
-/// The number of concrete validator approvals required for a proposal to pass.
-pub fn approvals_required() -> u32 {
- approval_ppm_required() * session::validator_count() / 1000
-}
-
-pub mod public {
- use super::*;
-
- /// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid.
- /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must
- /// be a current validator. It is illegal to propose when there is already a proposal in effect.
- pub fn propose(validator: &AccountId, proposal: &Proposal) {
- if storage::exists(CURRENT_PROPOSAL) {
- panic!("there may only be one proposal per era.");
- }
- storage::put(CURRENT_PROPOSAL, proposal);
- approve(validator, staking::current_era());
- }
-
- /// Approve the current era's proposal. Transactor must be a validator. This may not be done more
- /// than once for any validator in an era.
- pub fn approve(validator: &AccountId, era_index: BlockNumber) {
- if era_index != staking::current_era() {
- panic!("approval vote applied on non-current era.")
- }
- if !storage::exists(CURRENT_PROPOSAL) {
- panic!("there must be a proposal in order to approve.");
- }
- if session::validators().into_iter().position(|v| &v == validator).is_none() {
- panic!("transactor must be a validator to approve.");
- }
- let key = validator.to_keyed_vec(APPROVAL_OF);
- if storage::exists(&key) {
- panic!("transactor may not approve a proposal twice in one era.");
- }
- storage::put(&key, &true);
- }
-}
-
-pub mod privileged {
- use super::*;
-
- /// Set the proportion of validators that must approve for a proposal to be enacted at the end of
- /// its era. The value, `ppm`, is measured as a fraction of 1000 rounded down to the nearest whole
- /// validator. `1000` would require the approval of all validators; `667` would require two-thirds
- /// (or there abouts) of validators.
- pub fn set_approval_ppm_required(ppm: u32) {
- storage::put(APPROVALS_REQUIRED, &ppm);
- }
-}
-
-pub mod internal {
- use super::*;
- use demo_primitives::Proposal;
-
- /// Current era is ending; we should finish up any proposals.
- pub fn end_of_an_era() {
- // tally up votes for the current proposal, if any. enact if there are sufficient approvals.
- if let Some(proposal) = storage::take::(CURRENT_PROPOSAL) {
- let approvals_required = approvals_required();
- let approved = session::validators().into_iter()
- .filter_map(|v| storage::take::(&v.to_keyed_vec(APPROVAL_OF)))
- .take(approvals_required as usize)
- .count() as u32;
- if approved == approvals_required {
- enact_proposal(proposal);
- }
- }
- }
-}
-
-#[cfg(test)]
-pub mod testing {
- use super::*;
- use runtime_io::{twox_128, TestExternalities};
- use codec::Joiner;
-
- pub fn externalities(session_length: u64, sessions_per_era: u64, current_era: u64) -> TestExternalities {
- let extras: TestExternalities = map![
- twox_128(APPROVALS_REQUIRED).to_vec() => vec![].and(&667u32)
- ];
- staking::testing::externalities(session_length, sessions_per_era, current_era)
- .into_iter().chain(extras.into_iter()).collect()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use runtime_io::{with_externalities, twox_128, TestExternalities};
- use codec::{KeyedVec, Joiner};
- use keyring::Keyring;
- use environment::with_env;
- use demo_primitives::{AccountId, Proposal};
- use runtime::{staking, session};
-
- fn new_test_ext() -> TestExternalities {
- testing::externalities(1, 1, 1)
- }
-
- #[test]
- fn majority_voting_should_work() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Approve it. Era length changes.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- public::approve(&two, 1);
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 2);
- });
- }
-
- #[test]
- fn majority_voting_should_work_after_unsuccessful_previous() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Fail it.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
-
- // Block 2: Make proposal. Approve it. It should change era length.
- with_env(|e| e.block_number = 2);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- public::approve(&two, 2);
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 2);
- });
- }
-
- #[test]
- fn minority_voting_should_not_succeed() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Will have only 1 vote. No change.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
- });
- }
-
- #[test]
- #[should_panic]
- fn old_voting_should_be_illegal() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Will have only 1 vote. No change.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- public::approve(&two, 0);
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
- });
- }
-
- #[test]
- #[should_panic]
- fn double_voting_should_be_illegal() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Will have only 1 vote. No change.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- public::approve(&two, 1);
- public::approve(&two, 1);
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
- });
- }
-
- #[test]
- #[should_panic]
- fn over_proposing_should_be_illegal() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Will have only 1 vote. No change.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- public::propose(&two, &Proposal::StakingSetSessionsPerEra(2));
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
- });
- }
-
- #[test]
- #[should_panic]
- fn approving_without_proposal_should_be_illegal() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Will have only 1 vote. No change.
- with_env(|e| e.block_number = 1);
- public::approve(&two, 1);
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
- });
- }
-
- #[test]
- #[should_panic]
- fn non_validator_approving_should_be_illegal() {
- let one = Keyring::One.to_raw_public();
- let two = Keyring::Two.to_raw_public();
- let three = [3u8; 32];
- let four = [4u8; 32];
- let mut t = new_test_ext();
-
- with_externalities(&mut t, || {
- assert_eq!(staking::era_length(), 1u64);
- assert_eq!(staking::current_era(), 1u64);
- assert_eq!(session::validator_count(), 3u32);
- assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]);
- assert!(!session::validators().into_iter().position(|v| &v == &one).is_none());
-
- // Block 1: Make proposal. Will have only 1 vote. No change.
- with_env(|e| e.block_number = 1);
- public::propose(&one, &Proposal::StakingSetSessionsPerEra(2));
- public::approve(&four, 1);
- staking::internal::check_new_era();
- assert_eq!(staking::era_length(), 1);
- });
- }
-}
diff --git a/substrate/demo/runtime/src/runtime/mod.rs b/substrate/demo/runtime/src/runtime/mod.rs
index 092b4eca23..e52e49c8aa 100644
--- a/substrate/demo/runtime/src/runtime/mod.rs
+++ b/substrate/demo/runtime/src/runtime/mod.rs
@@ -27,11 +27,8 @@ pub mod timestamp;
#[allow(unused)]
pub mod session;
#[allow(unused)]
-pub mod governance;
-#[allow(unused)]
pub mod democracy;
#[allow(unused)]
pub mod council;
-
-
-// TODO: polkadao
+#[allow(unused)]
+pub mod council_vote;
diff --git a/substrate/demo/runtime/src/runtime/staking.rs b/substrate/demo/runtime/src/runtime/staking.rs
index 6d357a52da..29b6ab793b 100644
--- a/substrate/demo/runtime/src/runtime/staking.rs
+++ b/substrate/demo/runtime/src/runtime/staking.rs
@@ -23,7 +23,7 @@ use runtime_io::{print, blake2_256};
use codec::KeyedVec;
use runtime_support::{storage, StorageVec};
use demo_primitives::{BlockNumber, AccountId};
-use runtime::{system, session, governance};
+use runtime::{system, session};
/// The balance of an account.
pub type Balance = u64;
@@ -406,9 +406,6 @@ pub mod internal {
/// NOTE: This always happens immediately before a session change to ensure that new validators
/// get a chance to set their session keys.
fn new_era() {
- // Inform governance module that it's the end of an era
- governance::internal::end_of_an_era();
-
// Increment current era.
storage::put(CURRENT_ERA, &(current_era() + 1));
diff --git a/substrate/demo/runtime/src/runtime/system.rs b/substrate/demo/runtime/src/runtime/system.rs
index 009dac8239..765e29e01e 100644
--- a/substrate/demo/runtime/src/runtime/system.rs
+++ b/substrate/demo/runtime/src/runtime/system.rs
@@ -144,12 +144,6 @@ pub mod internal {
Function::TimestampSet(t) => {
::runtime::timestamp::public::set(t);
}
- Function::GovernancePropose(ref proposal) => {
- ::runtime::governance::public::propose(transactor, proposal);
- }
- Function::GovernanceApprove(era_index) => {
- ::runtime::governance::public::approve(transactor, era_index);
- }
}
}
}
@@ -253,7 +247,7 @@ mod tests {
use environment::with_env;
use primitives::hexdisplay::HexDisplay;
use demo_primitives::{Header, Digest, UncheckedTransaction, Transaction, Function};
- use runtime::{governance, staking};
+ use runtime::staking;
#[test]
fn staking_balance_transfer_dispatch_works() {
@@ -281,7 +275,7 @@ mod tests {
}
fn new_test_ext() -> TestExternalities {
- governance::testing::externalities(2, 2, 0)
+ staking::testing::externalities(2, 2, 0)
}
#[test]
@@ -294,7 +288,7 @@ mod tests {
let h = Header {
parent_hash: [69u8; 32].into(),
number: 1,
- state_root: hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0").into(),
+ state_root: hex!("52eb24906a4110a605d29d4e2f01b43cb169d375d709b138cc8ce50ad5f7ce85").into(),
transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
digest: Digest { logs: vec![], },
};
diff --git a/substrate/substrate/codec/src/slicable.rs b/substrate/substrate/codec/src/slicable.rs
index 0304b51003..eb2b01db52 100644
--- a/substrate/substrate/codec/src/slicable.rs
+++ b/substrate/substrate/codec/src/slicable.rs
@@ -89,6 +89,26 @@ impl Slicable for T {
}
}
+impl Slicable for Option {
+ fn decode(input: &mut I) -> Option {
+ u8::decode(input).and_then(|v| match v {
+ 0 => Some(Some(false)),
+ 1 => Some(Some(true)),
+ 2 => Some(None),
+ _ => None,
+ })
+ }
+
+ fn using_encoded R>(&self, f: F) -> R {
+ match *self {
+ Some(false) => 0u8,
+ Some(true) => 1u8,
+ None => 2u8,
+ }.using_encoded(f)
+ }
+}
+impl NonTrivialSlicable for Option {}
+
impl Slicable for Vec {
fn decode(input: &mut I) -> Option {
u32::decode(input).and_then(move |len| {