Fixes and improvements for PoC-1 Testnet (#143)

* Fix initialisations and add a test.

* Fix test.

* Fix overflow bug.

* Minor refactoring and fixes.

* Fix vote threshold.

* Add note.

* Fixes for latest rust and the readme.

* Better readme.

* An extra validator for PoC-1

* Update README.

* PoC-1 bootnodes.

* don't return async::notready for messages without scheduling wakeup

* Fix endowed account

* give polkadot control over round proposer based on random seed

* address grumbles.
This commit is contained in:
Gav Wood
2018-05-07 15:25:47 +02:00
committed by GitHub
parent 2232da2d53
commit 5d9481140c
27 changed files with 307 additions and 59 deletions
@@ -49,6 +49,8 @@ impl<S: codec::Slicable + Default> StorageVec for AuthorityStorageVec<S> {
pub const CODE: &'static [u8] = b":code";
pub type KeyValue = (Vec<u8>, Vec<u8>);
pub trait Trait: system::Trait {
type PublicAux: RefInto<Self::AccountId>;
type SessionKey: Parameter + Default;
@@ -61,6 +63,7 @@ decl_module! {
}
pub enum PrivCall {
fn set_code(new: Vec<u8>) = 0;
fn set_storage(items: Vec<KeyValue>) = 1;
}
}
@@ -75,6 +78,13 @@ impl<T: Trait> Module<T> {
storage::unhashed::put_raw(CODE, &new);
}
/// Set some items of storage.
fn set_storage(items: Vec<KeyValue>) {
for i in &items {
storage::unhashed::put_raw(&i.0, &i.1);
}
}
/// Report some misbehaviour.
fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport) {
// TODO.
@@ -558,7 +558,8 @@ impl<T: Trait> primitives::BuildExternalities for GenesisConfig<T>
twox_128(<ActiveCouncil<T>>::key()).to_vec() => self.active_council.encode(),
twox_128(<voting::CooloffPeriod<T>>::key()).to_vec() => self.cooloff_period.encode(),
twox_128(<voting::VotingPeriod<T>>::key()).to_vec() => self.voting_period.encode()
twox_128(<voting::VotingPeriod<T>>::key()).to_vec() => self.voting_period.encode(),
twox_128(<voting::Proposals<T>>::key()).to_vec() => vec![0u8; 0].encode()
]
}
}
@@ -42,7 +42,7 @@ decl_storage! {
pub CooloffPeriod get(cooloff_period): b"cov:cooloff" => required T::BlockNumber;
pub VotingPeriod get(voting_period): b"cov:period" => required T::BlockNumber;
pub Proposals get(proposals): b"cov:prs" => default Vec<(T::BlockNumber, T::Hash)>; // ordered by expiry.
pub Proposals get(proposals): b"cov:prs" => required Vec<(T::BlockNumber, T::Hash)>; // ordered by expiry.
pub ProposalOf get(proposal_of): b"cov:pro" => map [ T::Hash => T::Proposal ];
pub ProposalVoters get(proposal_voters): b"cov:voters:" => default map [ T::Hash => Vec<T::AccountId> ];
pub CouncilVoteOf get(vote_of): b"cov:vote:" => map [ (T::Hash, T::AccountId) => bool ];
@@ -79,6 +79,7 @@ impl<T: Trait> Module<T> {
let proposal_hash = T::Hashing::hash_of(&proposal);
assert!(!<ProposalOf<T>>::exists(proposal_hash), "No duplicate proposals allowed");
assert!(!Self::is_vetoed(&proposal_hash));
let mut proposals = Self::proposals();
@@ -85,9 +85,9 @@ decl_storage! {
pub VotingPeriod get(voting_period): b"dem:per" => required T::BlockNumber;
// The next free referendum index, aka the number of referendums started so far.
pub ReferendumCount get(referendum_count): b"dem:rco" => default ReferendumIndex;
pub ReferendumCount get(referendum_count): b"dem:rco" => required ReferendumIndex;
// The next referendum index that should be tallied.
pub NextTally get(next_tally): b"dem:nxt" => default ReferendumIndex;
pub NextTally get(next_tally): b"dem:nxt" => required ReferendumIndex;
// Information concerning any given referendum.
pub ReferendumInfoOf get(referendum_info): b"dem:pro:" => map [ ReferendumIndex => (T::BlockNumber, T::Proposal, VoteThreshold) ];
@@ -318,7 +318,10 @@ impl<T: Trait> primitives::BuildExternalities for GenesisConfig<T>
map![
twox_128(<LaunchPeriod<T>>::key()).to_vec() => self.launch_period.encode(),
twox_128(<VotingPeriod<T>>::key()).to_vec() => self.voting_period.encode(),
twox_128(<MinimumDeposit<T>>::key()).to_vec() => self.minimum_deposit.encode()
twox_128(<MinimumDeposit<T>>::key()).to_vec() => self.minimum_deposit.encode(),
twox_128(<ReferendumCount<T>>::key()).to_vec() => (0 as ReferendumIndex).encode(),
twox_128(<NextTally<T>>::key()).to_vec() => (0 as ReferendumIndex).encode(),
twox_128(<PublicPropCount<T>>::key()).to_vec() => (0 as PropIndex).encode()
]
}
}
@@ -16,9 +16,9 @@
//! Voting thresholds.
use primitives::traits::IntegerSquareRoot;
use primitives::traits::{Zero, IntegerSquareRoot};
use codec::{Input, Slicable};
use rstd::ops::{Add, Mul, Div};
use rstd::ops::{Add, Mul, Div, Rem};
/// A means of determining if a vote is past pass threshold.
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -58,18 +58,60 @@ pub trait Approved<Balance> {
fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool;
}
impl<Balance: IntegerSquareRoot + Ord + Add<Balance, Output = Balance> + Mul<Balance, Output = Balance> + Div<Balance, Output = Balance> + Copy> Approved<Balance> for VoteThreshold {
/// Return `true` iff `n1 / d1 < n2 / d2`. `d1` and `d2` may not be zero.
fn compare_rationals<T: Zero + Mul<T, Output = T> + Div<T, Output = T> + Rem<T, Output = T> + Ord + Copy>(mut n1: T, mut d1: T, mut n2: T, mut d2: T) -> bool {
// Uses a continued fractional representation for a non-overflowing compare.
// Detailed at https://janmr.com/blog/2014/05/comparing-rational-numbers-without-overflow/.
loop {
let q1 = n1 / d1;
let q2 = n2 / d2;
if q1 < q2 {
return true;
}
if q2 < q1 {
return false;
}
let r1 = n1 % d1;
let r2 = n2 % d2;
if r2.is_zero() {
return false;
}
if r1.is_zero() {
return true;
}
n1 = d2;
n2 = d1;
d1 = r2;
d2 = r1;
}
}
impl<Balance: IntegerSquareRoot + Zero + Ord + Add<Balance, Output = Balance> + Mul<Balance, Output = Balance> + Div<Balance, Output = Balance> + Rem<Balance, Output = Balance> + Copy> Approved<Balance> 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 sqrt_voters = voters.integer_sqrt();
let sqrt_electorate = electorate.integer_sqrt();
if sqrt_voters.is_zero() { return false; }
match *self {
VoteThreshold::SuperMajorityApprove =>
voters.integer_sqrt() * approve / electorate.integer_sqrt() > against,
compare_rationals(against, sqrt_voters, approve, sqrt_electorate),
VoteThreshold::SuperMajorityAgainst =>
approve > voters.integer_sqrt() * against / electorate.integer_sqrt(),
compare_rationals(against, sqrt_electorate, approve, sqrt_voters),
VoteThreshold::SimpleMajority => approve > against,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_work() {
assert_eq!(VoteThreshold::SuperMajorityApprove.approved(60, 50, 210), false);
assert_eq!(VoteThreshold::SuperMajorityApprove.approved(100, 50, 210), true);
}
}