Introduce logic for deposits.

This commit is contained in:
Gav
2018-03-03 14:36:37 +01:00
parent 6cf236fb02
commit e07aef7766
+66 -49
View File
@@ -72,15 +72,15 @@ impl VoteThreshold {
// public proposals
const PUBLIC_PROP_COUNT: &[u8] = b"dem:cou"; // PropIndex
const PUBLIC_PROPS: &[u8] = b"dem:pub"; // Vec<(PropIndex, Proposal)>
const LOCKED_FOR: &[u8] = b"dem:loc:"; // PropIndex -> Balance
const DEPOSIT_OF: &[u8] = b"dem:dep:"; // PropIndex -> (Balance, Vec<AccountId>)
const LAUNCH_PERIOD: &[u8] = b"dem:lau"; // BlockNumber
// referenda
const VOTING_PERIOD: &[u8] = b"dem:per"; // BlockNumber
const REFERENDUM_COUNT: &[u8] = b"dem:cou"; // ReferendumIndex
const NEXT_TALLY: &[u8] = b"dem:nxt"; // ReferendumIndex
const REFERENDUM_INFO_OF: &[u8] = b"dem:pro"; // ReferendumIndex -> (BlockNumber, Proposal, VoteThreshold)
const VOTERS: &[u8] = b"dem:vtr:"; // ReferendumIndex -> Vec<AccountId>
const REFERENDUM_INFO_OF: &[u8] = b"dem:pro:"; // ReferendumIndex -> (BlockNumber, Proposal, VoteThreshold)
const VOTERS_FOR: &[u8] = b"dem:vtr:"; // ReferendumIndex -> Vec<AccountId>
const VOTE_OF: &[u8] = b"dem:vot:"; // (ReferendumIndex, AccountId) -> bool
/// How often (in blocks) to check for new votes.
@@ -96,14 +96,19 @@ pub fn launch_period() -> BlockNumber {
}
/// The public proposals. Unsorted.
pub fn public_props() -> Vec<(PropIndex, Proposal)> {
pub fn public_props() -> Vec<(PropIndex, Proposal, Balance)> {
storage::get_or_default(PUBLIC_PROPS)
}
/// Those who have locked a deposit.
pub fn deposit_lockers(proposal: PropIndex) -> Option<(Balance, Vec<AccountId>)> {
storage::get(DEPOSIT_OF)
}
/// Get the amount locked in support of `proposal`; false if proposal isn't a valid proposal
/// index.
pub fn locked_for(proposal: PropIndex) -> Option<Balance> {
storage::get(&proposal.to_keyed_vec(LOCKED_FOR))
deposit_lockers(proposal).map(|(d, l)| d * (l.len() as Balance))
}
/// Return true if `ref_index` is an on-going referendum.
@@ -113,7 +118,7 @@ pub fn is_active_referendum(ref_index: ReferendumIndex) -> bool {
/// Get the voters for the current proposal.
pub fn voters_for(ref_index: ReferendumIndex) -> Vec<AccountId> {
storage::get_or_default(&ref_index.to_keyed_vec(VOTERS))
storage::get_or_default(&ref_index.to_keyed_vec(VOTERS_FOR))
}
/// Get the vote, if Some, of `who`.
@@ -153,15 +158,15 @@ pub mod public {
use super::*;
/// Propose a sensitive action to be taken.
pub fn propose(signed: &AccountId, proposal: &Proposal, lock: Balance) {
pub fn propose(signed: &AccountId, proposal: &Proposal, value: Balance) {
let b = staking::balance(signed);
assert!(b >= lock);
assert!(b >= value);
staking::internal::set_balance(signed, b - lock);
staking::internal::set_balance(signed, b - value);
let index: PropIndex = storage::get_or_default(PUBLIC_PROP_COUNT);
storage::put(PUBLIC_PROP_COUNT, &(index + 1));
storage::put(&index.to_keyed_vec(LOCKED_FOR), &lock);
storage::put(&index.to_keyed_vec(DEPOSIT_OF), &(value, vec![*signed]));
let mut props: Vec<(PropIndex, Proposal)> = storage::get_or_default(PUBLIC_PROPS);
props.push((index, proposal.clone()));
@@ -169,14 +174,15 @@ pub mod public {
}
/// Propose a sensitive action to be taken.
pub fn second(signed: &AccountId, proposal: PropIndex, lock: Balance) {
pub fn second(signed: &AccountId, proposal: PropIndex) {
let b = staking::balance(signed);
assert!(b >= lock);
let key = proposal.to_keyed_vec(LOCKED_FOR);
let balance: Balance = storage::get(&key).expect("can only second an existing proposal");
let key = proposal.to_keyed_vec(DEPOSIT_OF);
let mut deposit: (Balance, Vec<AccountId>) = storage::get(&key).expect("can only second an existing proposal");
assert!(b >= deposit.0);
deposit.1.push(*signed);
staking::internal::set_balance(signed, b - lock);
storage::put(&key, &(balance + lock));
staking::internal::set_balance(signed, b - deposit.0);
storage::put(&key, &deposit);
}
/// Vote in a referendum. If `approve_proposal` is true, the vote is to enact the proposal;
@@ -192,7 +198,7 @@ pub mod public {
if !storage::exists(&key) {
let mut voters = voters_for(ref_index);
voters.push(signed.clone());
storage::put(VOTERS, &voters);
storage::put(&ref_index.to_keyed_vec(VOTERS_FOR), &voters);
}
storage::put(&key, &approve_proposal);
}
@@ -214,7 +220,7 @@ pub mod privileged {
for v in voters_for(ref_index) {
storage::kill(&(v, ref_index).to_keyed_vec(VOTE_OF));
}
storage::kill(&ref_index.to_keyed_vec(VOTERS));
storage::kill(&ref_index.to_keyed_vec(VOTERS_FOR));
}
}
@@ -234,7 +240,8 @@ pub mod internal {
.enumerate()
.max_by_key(|x| locked_for((x.1).0))
{
let (_, proposal) = public_props.swap_remove(winner_index);
let (prop_index, proposal, _) = public_props.swap_remove(winner_index);
storage::kill(&prop_index.to_keyed_vec(DEPOSIT_OF));
storage::put(PUBLIC_PROPS, &public_props);
inject_referendum(now + voting_period(), proposal, VoteThreshold::SuperMajorityApprove);
@@ -259,7 +266,7 @@ fn inject_referendum(
end: BlockNumber,
proposal: Proposal,
vote_threshold: VoteThreshold
) {
) -> ReferendumIndex {
let ref_index: ReferendumIndex = storage::get_or_default(REFERENDUM_COUNT);
if ref_index > 0 && referendum_info(ref_index - 1).map(|i| i.0 < end).unwrap_or(false) {
panic!("Cannot inject a referendum that ends earlier than preceeding referendum");
@@ -267,6 +274,7 @@ fn inject_referendum(
storage::put(REFERENDUM_COUNT, &(ref_index + 1));
storage::put(&ref_index.to_keyed_vec(REFERENDUM_INFO_OF), &(end, proposal, vote_threshold));
ref_index
}
#[cfg(test)]
@@ -308,26 +316,39 @@ mod tests {
twox_128(b"sta:tot").to_vec() => vec![].and(&210u64),
twox_128(b"sta:spe").to_vec() => vec![].and(&1u64),
twox_128(b"sta:vac").to_vec() => vec![].and(&3u64),
twox_128(b"sta:era").to_vec() => vec![].and(&1u64)
twox_128(b"sta:era").to_vec() => vec![].and(&1u64),
twox_128(LAUNCH_PERIOD).to_vec() => vec![].and(&1u64),
twox_128(VOTING_PERIOD).to_vec() => vec![].and(&1u64)
]
}
#[test]
fn params_should_work() {
let mut t = new_test_ext();
with_externalities(&mut t, || {
assert_eq!(launch_period(), 1u64);
assert_eq!(voting_period(), 1u64);
assert_eq!(staking::sessions_per_era(), 1u64);
assert_eq!(staking::total_stake(), 210u64);
});
}
#[test]
fn simple_passing_should_work() {
let alice = Keyring::Alice.to_raw_public();
let mut t = new_test_ext();
with_externalities(&mut t, || {
assert_eq!(staking::era_length(), 1u64);
assert_eq!(staking::total_stake(), 210u64);
with_env(|e| e.block_number = 1);
public::propose(&alice, &Proposal::StakingSetSessionsPerEra(2));
public::vote(&alice, 1, true);
let r = inject_referendum(1, Proposal::StakingSetSessionsPerEra(2), VoteThreshold::SuperMajorityApprove);
public::vote(&alice, r, true);
assert_eq!(public::tally(), (10, 0));
assert_eq!(voters_for(r), vec![alice.clone()]);
assert_eq!(vote_of(&alice, r), Some(true));
assert_eq!(tally(r), (10, 0));
democracy::internal::end_of_an_era();
democracy::internal::end_block();
staking::internal::check_new_era();
assert_eq!(staking::era_length(), 2u64);
@@ -340,16 +361,15 @@ mod tests {
let mut t = new_test_ext();
with_externalities(&mut t, || {
assert_eq!(staking::era_length(), 1u64);
assert_eq!(staking::total_stake(), 210u64);
with_env(|e| e.block_number = 1);
public::propose(&alice, &Proposal::StakingSetSessionsPerEra(2));
public::vote(&alice, 1, false);
let r = inject_referendum(1, Proposal::StakingSetSessionsPerEra(2), VoteThreshold::SuperMajorityApprove);
public::vote(&alice, r, false);
assert_eq!(public::tally(), (0, 10));
assert_eq!(voters_for(r), vec![alice.clone()]);
assert_eq!(vote_of(&alice, r), Some(false));
assert_eq!(tally(r), (0, 10));
democracy::internal::end_of_an_era();
democracy::internal::end_block();
staking::internal::check_new_era();
assert_eq!(staking::era_length(), 1u64);
@@ -368,27 +388,24 @@ mod tests {
let mut t = new_test_ext();
with_externalities(&mut t, || {
assert_eq!(staking::era_length(), 1u64);
assert_eq!(staking::total_stake(), 210u64);
with_env(|e| e.block_number = 1);
public::propose(&alice, &Proposal::StakingSetSessionsPerEra(2));
public::vote(&alice, 1, true);
public::vote(&bob, 1, false);
public::vote(&charlie, 1, false);
public::vote(&dave, 1, true);
public::vote(&eve, 1, false);
public::vote(&ferdie, 1, true);
let r = inject_referendum(1, Proposal::StakingSetSessionsPerEra(2), VoteThreshold::SuperMajorityApprove);
public::vote(&alice, r, true);
public::vote(&bob, r, false);
public::vote(&charlie, r, false);
public::vote(&dave, r, true);
public::vote(&eve, r, false);
public::vote(&ferdie, r, true);
assert_eq!(public::tally(), (110, 100));
assert_eq!(tally(r), (110, 100));
democracy::internal::end_of_an_era();
democracy::internal::end_block();
staking::internal::check_new_era();
assert_eq!(staking::era_length(), 2u64);
});
}
/*
#[test]
fn controversial_low_turnout_voting_should_work() {
let alice = Keyring::Alice.to_raw_public();
@@ -446,5 +463,5 @@ mod tests {
assert_eq!(staking::era_length(), 2u64);
});
}
}*/
}