Governance: Voters put money where mouth is (#1183)

* Referendums only gett enacted after a delay; successful voters must
lock funds up until enactment.

* Build fixes.

* Configurable council enact delay, fix test builds.

* Fix spelling

* Remove TODO
This commit is contained in:
Gav Wood
2018-12-10 17:29:40 +01:00
committed by GitHub
parent 6c0cfd1781
commit 66cbe232f5
12 changed files with 776 additions and 489 deletions
File diff suppressed because it is too large Load Diff
+4
View File
@@ -91,6 +91,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
launch_period: 5 * MINUTES, // 1 day per public referendum
voting_period: 5 * MINUTES, // 3 days to discuss & vote on an active referendum
minimum_deposit: 50 * DOLLARS, // 12000 as the minimum deposit for a referendum
public_delay: 0,
}),
council_seats: Some(CouncilSeatsConfig {
active_council: vec![],
@@ -107,6 +108,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
council_voting: Some(CouncilVotingConfig {
cooloff_period: 4 * DAYS,
voting_period: 1 * DAYS,
enact_delay_period: 0,
}),
timestamp: Some(TimestampConfig {
period: SECS_PER_BLOCK,
@@ -210,6 +212,7 @@ pub fn testnet_genesis(
launch_period: 9,
voting_period: 18,
minimum_deposit: 10,
public_delay: 0,
}),
council_seats: Some(CouncilSeatsConfig {
active_council: endowed_accounts.iter()
@@ -228,6 +231,7 @@ pub fn testnet_genesis(
council_voting: Some(CouncilVotingConfig {
cooloff_period: 75,
voting_period: 20,
enact_delay_period: 0,
}),
timestamp: Some(TimestampConfig {
period: 5, // 5 second block time.
+5 -5
View File
@@ -311,9 +311,9 @@ mod tests {
1,
GENESIS_HASH.into(),
if support_changes_trie {
hex!("df90128fe9ee27bd61d90308cc25ad262e518d4ba09e5077558be2389780d8e5").into()
hex!("7c00d30974b6d709766e5b231295b6b5ff7ffd42ef1385853c0a29859723d147").into()
} else {
hex!("3cb0654b6c47c6532108695327fc68e22f2e67a4b20029c3c9d05a285f9e80a2").into()
hex!("e96a29fe7f7aba0e4a06837d4a5a4201f60bf613b9947ce5772559ef525f4268").into()
},
if support_changes_trie {
vec![changes_trie_log(
@@ -339,7 +339,7 @@ mod tests {
construct_block(
2,
block1(false).1,
hex!("612d3e3c542b4ce62105f2f1fbc4fef1652d5ba38401795115042bee56a50752").into(),
hex!("80e77e443da5f81fab7265acae6cbdfff79e02eaa90306d9dd14dabddad5f99d").into(),
vec![ // session changes here, so we add a grandpa change signal log.
Log::from(::grandpa::RawLog::AuthoritiesChangeSignal(0, vec![
(Keyring::One.to_raw_public().into(), 1),
@@ -368,7 +368,7 @@ mod tests {
construct_block(
1,
GENESIS_HASH.into(),
hex!("17df8f360a4a1bd8d5dc23f05b044f5b14ece43555f97d2058ded47d5e7fb64d").into(),
hex!("337c94adf2041fa953d5afaf8919032e3b88ee440c88c48a231856306991dca1").into(),
vec![],
vec![
CheckedExtrinsic {
@@ -658,7 +658,7 @@ mod tests {
let b = construct_block(
1,
GENESIS_HASH.into(),
hex!("81f45b36d1c8f667ac948bc48f8fb61d12aae87d841b6303ab0320ca906d01d2").into(),
hex!("10cb18e5a4e000690aaa3e2f0165c1cc563d38eb6736aa79c5a0ea4868042671").into(),
vec![],
vec![
CheckedExtrinsic {
+2 -2
View File
@@ -124,8 +124,8 @@ impl system::Trait for Runtime {
impl balances::Trait for Runtime {
type Balance = Balance;
type AccountIndex = AccountIndex;
type OnFreeBalanceZero = (Staking, Contract);
type EnsureAccountLiquid = Staking;
type OnFreeBalanceZero = ((Staking, Contract), Democracy);
type EnsureAccountLiquid = (Staking, Democracy);
type Event = Event;
}
+328 -225
View File
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -101,7 +101,16 @@ pub trait EnsureAccountLiquid<AccountId> {
/// with the reason why not otherwise.
fn ensure_account_liquid(who: &AccountId) -> Result;
}
impl<
AccountId,
X: EnsureAccountLiquid<AccountId>,
Y: EnsureAccountLiquid<AccountId>,
> EnsureAccountLiquid<AccountId> for (X, Y) {
fn ensure_account_liquid(who: &AccountId) -> Result {
X::ensure_account_liquid(who)?;
Y::ensure_account_liquid(who)
}
}
impl<AccountId> EnsureAccountLiquid<AccountId> for () {
fn ensure_account_liquid(_who: &AccountId) -> Result { Ok(()) }
}
+2
View File
@@ -127,6 +127,7 @@ mod tests {
launch_period: 1,
voting_period: 3,
minimum_deposit: 1,
public_delay: 0,
}.build_storage().unwrap().0);
t.extend(seats::GenesisConfig::<Test> {
candidacy_bond: 9,
@@ -147,6 +148,7 @@ mod tests {
t.extend(voting::GenesisConfig::<Test> {
cooloff_period: 2,
voting_period: 1,
enact_delay_period: 0,
}.build_storage().unwrap().0);
runtime_io::TestExternalities::new(t)
}
+23 -13
View File
@@ -19,7 +19,7 @@
use rstd::prelude::*;
use rstd::borrow::Borrow;
use codec::HasCompact;
use primitives::traits::{Hash, As};
use primitives::traits::{Hash, As, Zero};
use runtime_io::print;
use srml_support::dispatch::Result;
use srml_support::{StorageValue, StorageMap, IsSubType};
@@ -116,6 +116,8 @@ decl_storage! {
trait Store for Module<T: Trait> as CouncilVoting {
pub CooloffPeriod get(cooloff_period) config(): T::BlockNumber = T::BlockNumber::sa(1000);
pub VotingPeriod get(voting_period) config(): T::BlockNumber = T::BlockNumber::sa(3);
/// Number of blocks by which to delay enactment of successful, non-unanimous-council-instigated referendum proposals.
pub EnactDelayPeriod get(enact_delay_period) config(): T::BlockNumber = T::BlockNumber::sa(0);
pub Proposals get(proposals) build(|_| vec![0u8; 0]): Vec<(T::BlockNumber, T::Hash)>; // ordered by expiry.
pub ProposalOf get(proposal_of): map T::Hash => Option<T::Proposal>;
pub ProposalVoters get(proposal_voters): map T::Hash => Vec<T::AccountId>;
@@ -209,10 +211,18 @@ impl<T: Trait> Module<T> {
Self::deposit_event(RawEvent::TallyReferendum(proposal_hash.clone(), tally.0, tally.1, tally.2));
if tally.0 > tally.1 + tally.2 {
Self::kill_veto_of(&proposal_hash);
match tally {
(_, 0, 0) => <democracy::Module<T>>::internal_start_referendum(proposal, democracy::VoteThreshold::SuperMajorityAgainst).map(|_| ())?,
_ => <democracy::Module<T>>::internal_start_referendum(proposal, democracy::VoteThreshold::SimpleMajority).map(|_| ())?,
// If there were no nay-votes from the council, then it's weakly uncontroversial; we enact immediately.
let period = match tally.1 {
0 => Zero::zero(),
_ => Self::enact_delay_period(),
};
// If all council members voted yes, then it's strongly uncontroversial; we require a negative
// super-majority at referendum in order to defeat it.
let threshold = match tally {
(_, 0, 0) => democracy::VoteThreshold::SuperMajorityAgainst,
_ => democracy::VoteThreshold::SimpleMajority,
};
<democracy::Module<T>>::internal_start_referendum(proposal, threshold, period).map(|_| ())?;
}
}
}
@@ -261,8 +271,8 @@ mod tests {
with_externalities(&mut new_test_ext(true), || {
System::set_block_number(1);
let proposal = set_balance_proposal(42);
assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove), 0);
assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]);
assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove, 0), 0);
assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove, 0)]);
let cancellation = cancel_referendum_proposal(0);
let hash = cancellation.blake2_256().into();
@@ -284,7 +294,7 @@ mod tests {
with_externalities(&mut new_test_ext(true), || {
System::set_block_number(1);
let proposal = set_balance_proposal(42);
assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove), 0);
assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove, 0), 0);
let cancellation = cancel_referendum_proposal(0);
let hash = cancellation.blake2_256().into();
@@ -295,7 +305,7 @@ mod tests {
System::set_block_number(2);
assert_ok!(CouncilVoting::end_block(System::block_number()));
assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]);
assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove, 0)]);
});
}
@@ -304,7 +314,7 @@ mod tests {
with_externalities(&mut new_test_ext(true), || {
System::set_block_number(1);
let proposal = set_balance_proposal(42);
assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove), 0);
assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove, 0), 0);
let cancellation = cancel_referendum_proposal(0);
let hash = cancellation.blake2_256().into();
@@ -314,7 +324,7 @@ mod tests {
System::set_block_number(2);
assert_ok!(CouncilVoting::end_block(System::block_number()));
assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]);
assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove, 0)]);
});
}
@@ -378,7 +388,7 @@ mod tests {
System::set_block_number(4);
assert_ok!(CouncilVoting::end_block(System::block_number()));
assert_eq!(CouncilVoting::proposals().len(), 0);
assert_eq!(Democracy::active_referendums(), vec![(0, 7, set_balance_proposal(42), VoteThreshold::SimpleMajority)]);
assert_eq!(Democracy::active_referendums(), vec![(0, 7, set_balance_proposal(42), VoteThreshold::SimpleMajority, 0)]);
});
}
@@ -443,7 +453,7 @@ mod tests {
System::set_block_number(2);
assert_ok!(CouncilVoting::end_block(System::block_number()));
assert_eq!(CouncilVoting::proposals().len(), 0);
assert_eq!(Democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SuperMajorityAgainst)]);
assert_eq!(Democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SuperMajorityAgainst, 0)]);
});
}
@@ -461,7 +471,7 @@ mod tests {
System::set_block_number(2);
assert_ok!(CouncilVoting::end_block(System::block_number()));
assert_eq!(CouncilVoting::proposals().len(), 0);
assert_eq!(Democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SimpleMajority)]);
assert_eq!(Democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SimpleMajority, 0)]);
});
}
+91 -25
View File
@@ -109,11 +109,12 @@ decl_module! {
}
/// Start a referendum.
fn start_referendum(proposal: Box<T::Proposal>, vote_threshold: VoteThreshold) -> Result {
fn start_referendum(proposal: Box<T::Proposal>, threshold: VoteThreshold, delay: T::BlockNumber) -> Result {
Self::inject_referendum(
<system::Module<T>>::block_number() + Self::voting_period(),
*proposal,
vote_threshold
threshold,
delay,
).map(|_| ())
}
@@ -122,6 +123,13 @@ decl_module! {
Self::clear_referendum(ref_index.into());
}
/// Cancel a proposal queued for enactment.
pub fn cancel_queued(when: T::BlockNumber, which: u32) -> Result {
let which = which as usize;
<DispatchQueue<T>>::mutate(when, |items| if items.len() > which { items[which] = None });
Ok(())
}
fn on_finalise(n: T::BlockNumber) {
if let Err(e) = Self::end_block(n) {
runtime_io::print(e);
@@ -130,6 +138,20 @@ decl_module! {
}
}
/// Info regarding an ongoing referendum.
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct ReferendumInfo<BlockNumber: Parameter, Proposal: Parameter> {
/// When voting on this referendum will end.
end: BlockNumber,
/// The proposal being voted on.
proposal: Proposal,
/// The thresholding mechanism to determine whether it passed.
threshold: VoteThreshold,
/// The delay (in blocks) to wait after a successful referendum before deploying.
delay: BlockNumber,
}
decl_storage! {
trait Store for Module<T: Trait> as Democracy {
@@ -143,6 +165,8 @@ decl_storage! {
pub LaunchPeriod get(launch_period) config(): T::BlockNumber = T::BlockNumber::sa(1000);
/// The minimum amount to be used as a deposit for a public referendum proposal.
pub MinimumDeposit get(minimum_deposit) config(): T::Balance;
/// The delay before enactment for all public referenda.
pub PublicDelay get(public_delay) config(): T::BlockNumber;
/// How often (in blocks) to check for new votes.
pub VotingPeriod get(voting_period) config(): T::BlockNumber = T::BlockNumber::sa(1000);
@@ -152,7 +176,12 @@ decl_storage! {
/// The next referendum index that should be tallied.
pub NextTally get(next_tally) build(|_| 0 as ReferendumIndex): ReferendumIndex;
/// Information concerning any given referendum.
pub ReferendumInfoOf get(referendum_info): map ReferendumIndex => Option<(T::BlockNumber, T::Proposal, VoteThreshold)>;
pub ReferendumInfoOf get(referendum_info): map ReferendumIndex => Option<(ReferendumInfo<T::BlockNumber, T::Proposal>)>;
/// Queue of successful referenda to be dispatched.
pub DispatchQueue get(dispatch_queue): map T::BlockNumber => Vec<Option<(T::Proposal, ReferendumIndex)>>;
/// The block at which the `who`'s funds become liquid.
pub Bondage get(bondage): map T::AccountId => T::BlockNumber;
/// Get the voters for the current proposal.
pub VotersFor get(voters_for): map ReferendumIndex => Vec<T::AccountId>;
@@ -189,21 +218,21 @@ impl<T: Trait> Module<T> {
}
/// Get all referendums currently active.
pub fn active_referendums() -> Vec<(ReferendumIndex, T::BlockNumber, T::Proposal, VoteThreshold)> {
pub fn active_referendums() -> Vec<(ReferendumIndex, T::BlockNumber, T::Proposal, VoteThreshold, T::BlockNumber)> {
let next = Self::next_tally();
let last = Self::referendum_count();
(next..last).into_iter()
.filter_map(|i| Self::referendum_info(i).map(|(n, p, t)| (i, n, p, t)))
.filter_map(|i| Self::referendum_info(i).map(|ReferendumInfo{ end, proposal, threshold, delay }| (i, end, proposal, threshold, delay)))
.collect()
}
/// Get all referendums ready for tally at block `n`.
pub fn maturing_referendums_at(n: T::BlockNumber) -> Vec<(ReferendumIndex, T::BlockNumber, T::Proposal, VoteThreshold)> {
pub fn maturing_referendums_at(n: T::BlockNumber) -> Vec<(ReferendumIndex, T::BlockNumber, T::Proposal, VoteThreshold, T::BlockNumber)> {
let next = Self::next_tally();
let last = Self::referendum_count();
(next..last).into_iter()
.filter_map(|i| Self::referendum_info(i).map(|(n, p, t)| (i, n, p, t)))
.take_while(|&(_, block_number, _, _)| block_number == n)
.filter_map(|i| Self::referendum_info(i).map(|ReferendumInfo{ end, proposal, threshold, delay }| (i, end, proposal, threshold, delay)))
.take_while(|&(_, block_number, _, _, _)| block_number == n)
.collect()
}
@@ -218,8 +247,8 @@ impl<T: Trait> Module<T> {
// Exposed mutables.
/// Start a referendum. Can be called directly by the council.
pub fn internal_start_referendum(proposal: T::Proposal, vote_threshold: VoteThreshold) -> result::Result<ReferendumIndex, &'static str> {
<Module<T>>::inject_referendum(<system::Module<T>>::block_number() + <Module<T>>::voting_period(), proposal, vote_threshold)
pub fn internal_start_referendum(proposal: T::Proposal, threshold: VoteThreshold, delay: T::BlockNumber) -> result::Result<ReferendumIndex, &'static str> {
<Module<T>>::inject_referendum(<system::Module<T>>::block_number() + <Module<T>>::voting_period(), proposal, threshold, delay)
}
/// Remove a referendum. Can be called directly by the council.
@@ -234,16 +263,17 @@ impl<T: Trait> Module<T> {
fn inject_referendum(
end: T::BlockNumber,
proposal: T::Proposal,
vote_threshold: VoteThreshold
threshold: VoteThreshold,
delay: T::BlockNumber,
) -> result::Result<ReferendumIndex, &'static str> {
let ref_index = Self::referendum_count();
if ref_index > 0 && Self::referendum_info(ref_index - 1).map(|i| i.0 > end).unwrap_or(false) {
if ref_index > 0 && Self::referendum_info(ref_index - 1).map(|i| i.end > end).unwrap_or(false) {
Err("Cannot inject a referendum that ends earlier than preceeding referendum")?
}
<ReferendumCount<T>>::put(ref_index + 1);
<ReferendumInfoOf<T>>::insert(ref_index, (end, proposal, vote_threshold));
Self::deposit_event(RawEvent::Started(ref_index, vote_threshold));
<ReferendumInfoOf<T>>::insert(ref_index, ReferendumInfo { end, proposal, threshold, delay });
Self::deposit_event(RawEvent::Started(ref_index, threshold));
Ok(ref_index)
}
@@ -256,6 +286,12 @@ impl<T: Trait> Module<T> {
}
}
/// Enact a proposal from a referendum.
fn enact_proposal(proposal: T::Proposal, index: ReferendumIndex) {
let ok = proposal.dispatch(system::RawOrigin::Root.into()).is_ok();
Self::deposit_event(RawEvent::Executed(index, ok));
}
/// Current era is ending; we should finish up any proposals.
fn end_block(now: T::BlockNumber) -> Result {
// pick out another public referendum if it's time.
@@ -274,29 +310,58 @@ impl<T: Trait> Module<T> {
<balances::Module<T>>::unreserve(d, deposit);
}
Self::deposit_event(RawEvent::Tabled(prop_index, deposit, depositors));
Self::inject_referendum(now + Self::voting_period(), proposal, VoteThreshold::SuperMajorityApprove)?;
Self::inject_referendum(now + Self::voting_period(), proposal, VoteThreshold::SuperMajorityApprove, Self::public_delay())?;
}
}
}
// tally up votes for any expiring referenda.
for (index, _, proposal, vote_threshold) in Self::maturing_referendums_at(now) {
for (index, _, proposal, threshold, delay) in Self::maturing_referendums_at(now) {
let (approve, against) = Self::tally(index);
let total_issuance = <balances::Module<T>>::total_issuance();
let approved = threshold.approved(approve, against, total_issuance);
Self::voters_for(index).into_iter()
.filter(|a| (Self::vote_of((index, a.clone())).unwrap_or(false)/*defensive only: all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed*/ == approved))
.for_each(|a| <Bondage<T>>::mutate(a, |b| if *b < now + delay { *b = now + delay }));
Self::clear_referendum(index);
if vote_threshold.approved(approve, against, total_issuance) {
if approved {
Self::deposit_event(RawEvent::Passed(index));
let ok = proposal.dispatch(system::RawOrigin::Root.into()).is_ok();
Self::deposit_event(RawEvent::Executed(index, ok));
if delay.is_zero() {
Self::enact_proposal(proposal, index);
} else {
<DispatchQueue<T>>::mutate(now + delay, |q| q.push(Some((proposal, index))));
}
} else {
Self::deposit_event(RawEvent::NotPassed(index));
}
<NextTally<T>>::put(index + 1);
}
for (proposal, index) in <DispatchQueue<T>>::take(now).into_iter().filter_map(|x| x) {
Self::enact_proposal(proposal, index);
}
Ok(())
}
}
impl<T: Trait> balances::OnFreeBalanceZero<T::AccountId> for Module<T> {
fn on_free_balance_zero(who: &T::AccountId) {
<Bondage<T>>::remove(who);
}
}
impl<T: Trait> balances::EnsureAccountLiquid<T::AccountId> for Module<T> {
fn ensure_account_liquid(who: &T::AccountId) -> Result {
if Self::bondage(who) <= <system::Module<T>>::block_number() {
Ok(())
} else {
Err("cannot transfer illiquid funds")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -359,6 +424,7 @@ mod tests {
launch_period: 1,
voting_period: 1,
minimum_deposit: 1,
public_delay: 0,
}.build_storage().unwrap().0);
runtime_io::TestExternalities::new(t)
}
@@ -507,7 +573,7 @@ mod tests {
fn simple_passing_should_work() {
with_externalities(&mut new_test_ext(), || {
System::set_block_number(1);
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap();
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap();
assert_ok!(Democracy::vote(Origin::signed(1), r.into(), true));
assert_eq!(Democracy::voters_for(r), vec![1]);
@@ -524,7 +590,7 @@ mod tests {
fn cancel_referendum_should_work() {
with_externalities(&mut new_test_ext(), || {
System::set_block_number(1);
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap();
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap();
assert_ok!(Democracy::vote(Origin::signed(1), r.into(), true));
assert_ok!(Democracy::cancel_referendum(r.into()));
@@ -538,7 +604,7 @@ mod tests {
fn simple_failing_should_work() {
with_externalities(&mut new_test_ext(), || {
System::set_block_number(1);
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap();
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap();
assert_ok!(Democracy::vote(Origin::signed(1), r.into(), false));
assert_eq!(Democracy::voters_for(r), vec![1]);
@@ -555,7 +621,7 @@ mod tests {
fn controversial_voting_should_work() {
with_externalities(&mut new_test_ext(), || {
System::set_block_number(1);
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap();
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap();
assert_ok!(Democracy::vote(Origin::signed(1), r.into(), true));
assert_ok!(Democracy::vote(Origin::signed(2), r.into(), false));
assert_ok!(Democracy::vote(Origin::signed(3), r.into(), false));
@@ -575,7 +641,7 @@ mod tests {
fn controversial_low_turnout_voting_should_work() {
with_externalities(&mut new_test_ext(), || {
System::set_block_number(1);
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap();
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap();
assert_ok!(Democracy::vote(Origin::signed(5), r.into(), false));
assert_ok!(Democracy::vote(Origin::signed(6), r.into(), true));
@@ -594,7 +660,7 @@ mod tests {
assert_eq!(Balances::total_issuance(), 210);
System::set_block_number(1);
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap();
let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap();
assert_ok!(Democracy::vote(Origin::signed(4), r.into(), true));
assert_ok!(Democracy::vote(Origin::signed(5), r.into(), false));
assert_ok!(Democracy::vote(Origin::signed(6), r.into(), true));
-10
View File
@@ -63,13 +63,8 @@ use runtime_support::storage::unhashed::StorageVec;
use primitives::traits::{CurrentHeight, Convert};
use substrate_primitives::AuthorityId;
use system::ensure_signed;
#[cfg(feature = "std")]
use primitives::traits::MaybeSerializeDebug;
#[cfg(not(feature = "std"))]
use primitives::traits::MaybeSerializeDebugButNotDeserialize;
mod mock;
mod tests;
@@ -128,11 +123,6 @@ pub trait Trait: system::Trait {
type Log: From<Log<Self>> + Into<system::DigestItemOf<Self>>;
/// The session key type used by authorities.
#[cfg(not(feature = "std"))]
type SessionKey: Parameter + Default + MaybeSerializeDebugButNotDeserialize;
/// The session key type used by authorities.
#[cfg(feature = "std")]
type SessionKey: Parameter + Default + MaybeSerializeDebug;
/// The event type of this module.