mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-08-09 07:35:45 +00:00
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:
@@ -133,11 +133,16 @@ pub trait Proposer {
|
||||
|
||||
/// Create a proposal.
|
||||
fn propose(&self) -> Self::Create;
|
||||
|
||||
/// Evaluate proposal. True means valid.
|
||||
// TODO: change this to a future.
|
||||
fn evaluate(&self, proposal: &Block) -> Self::Evaluate;
|
||||
|
||||
/// Import witnessed misbehavior.
|
||||
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, Misbehavior)>);
|
||||
|
||||
/// Determine the proposer for a given round. This should be a deterministic function
|
||||
/// with consistent results across all authorities.
|
||||
fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId;
|
||||
}
|
||||
|
||||
/// Block import trait.
|
||||
@@ -189,20 +194,7 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
|
||||
}
|
||||
|
||||
fn round_proposer(&self, round: usize) -> AuthorityId {
|
||||
use primitives::hashing::blake2_256;
|
||||
|
||||
// repeat blake2_256 on parent hash round + 1 times.
|
||||
// use as index into authorities vec.
|
||||
// TODO: parent hash is really insecure as a randomness beacon as
|
||||
// the prior can easily influence the block hash.
|
||||
let hashed = (0..round + 1).fold(self.parent_hash.0, |a, _| {
|
||||
blake2_256(&a[..])
|
||||
});
|
||||
|
||||
let index = u32::decode(&mut &hashed[..])
|
||||
.expect("there are more than 4 bytes in a 32 byte hash; qed");
|
||||
|
||||
self.authorities[(index as usize) % self.authorities.len()]
|
||||
self.proposer.round_proposer(round, &self.authorities[..])
|
||||
}
|
||||
|
||||
fn proposal_valid(&self, proposal: &Block) -> Self::EvaluateProposal {
|
||||
@@ -649,6 +641,10 @@ mod tests {
|
||||
}
|
||||
|
||||
fn import_misbehavior(&self, _misbehavior: Vec<(AuthorityId, Misbehavior)>) {}
|
||||
|
||||
fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId {
|
||||
authorities[round_number % authorities.len()].clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_service(client: FakeClient)
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -23,8 +23,9 @@ mod tests;
|
||||
|
||||
use std::sync::Arc;
|
||||
use client::{self, Client};
|
||||
use primitives::block;
|
||||
use primitives::{block, Hash, blake2_256};
|
||||
use primitives::storage::{StorageKey, StorageData};
|
||||
use primitives::hexdisplay::HexDisplay;
|
||||
use state_machine;
|
||||
|
||||
use self::error::Result;
|
||||
@@ -40,6 +41,22 @@ build_rpc_trait! {
|
||||
#[rpc(name = "state_callAt")]
|
||||
fn call_at(&self, String, Vec<u8>, block::HeaderHash) -> Result<Vec<u8>>;
|
||||
|
||||
/// Returns the hash of a storage entry.
|
||||
#[rpc(name = "state_getStorageHashAt")]
|
||||
fn storage_hash_at(&self, StorageKey, block::HeaderHash) -> Result<Hash>;
|
||||
|
||||
/// Returns the size of a storage entry.
|
||||
#[rpc(name = "state_getStorageSizeAt")]
|
||||
fn storage_size_at(&self, StorageKey, block::HeaderHash) -> Result<u64>;
|
||||
|
||||
/// Returns the hash of a storage entry.
|
||||
#[rpc(name = "state_getStorageHash")]
|
||||
fn storage_hash(&self, StorageKey) -> Result<Hash>;
|
||||
|
||||
/// Returns the size of a storage entry.
|
||||
#[rpc(name = "state_getStorageSize")]
|
||||
fn storage_size(&self, StorageKey) -> Result<u64>;
|
||||
|
||||
/// Returns a storage entry.
|
||||
#[rpc(name = "state_getStorage")]
|
||||
fn storage(&self, StorageKey) -> Result<StorageData>;
|
||||
@@ -56,21 +73,36 @@ impl<B, E> StateApi for Arc<Client<B, E>> where
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
fn storage_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<StorageData> {
|
||||
trace!(target: "rpc", "Querying storage at {:?} for key {}", block, HexDisplay::from(&key.0));
|
||||
Ok(self.as_ref().storage(&block::Id::Hash(block), &key)?)
|
||||
}
|
||||
|
||||
fn call_at(&self, method: String, data: Vec<u8>, block: block::HeaderHash) -> Result<Vec<u8>> {
|
||||
trace!(target: "rpc", "Calling runtime at {:?} for method {} ({})", block, method, HexDisplay::from(&data));
|
||||
Ok(self.as_ref().call(&block::Id::Hash(block), &method, &data)?.return_data)
|
||||
}
|
||||
|
||||
fn storage_hash_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<Hash> {
|
||||
self.storage_at(key, block).map(|x| blake2_256(&x.0).into())
|
||||
}
|
||||
|
||||
fn storage_size_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<u64> {
|
||||
self.storage_at(key, block).map(|x| x.0.len() as u64)
|
||||
}
|
||||
|
||||
fn storage_hash(&self, key: StorageKey) -> Result<Hash> {
|
||||
self.storage_hash_at(key, self.as_ref().info()?.chain.best_hash)
|
||||
}
|
||||
|
||||
fn storage_size(&self, key: StorageKey) -> Result<u64> {
|
||||
self.storage_size_at(key, self.as_ref().info()?.chain.best_hash)
|
||||
}
|
||||
|
||||
fn storage(&self, key: StorageKey) -> Result<StorageData> {
|
||||
let at = block::Id::Hash(self.as_ref().info()?.chain.best_hash);
|
||||
use primitives::hexdisplay::HexDisplay;
|
||||
info!("Querying storage at {:?} for key {}", at, HexDisplay::from(&key.0));
|
||||
Ok(self.as_ref().storage(&at, &key)?)
|
||||
self.storage_at(key, self.as_ref().info()?.chain.best_hash)
|
||||
}
|
||||
|
||||
fn call(&self, method: String, data: Vec<u8>) -> Result<Vec<u8>> {
|
||||
Ok(self.as_ref().call(&block::Id::Hash(self.as_ref().info()?.chain.best_hash), &method, &data)?.return_data)
|
||||
self.call_at(method, data, self.as_ref().info()?.chain.best_hash)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#![cfg_attr(not(feature = "std"), feature(lang_items))]
|
||||
#![cfg_attr(not(feature = "std"), feature(core_intrinsics))]
|
||||
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
||||
#![cfg_attr(not(feature = "std"), feature(macro_reexport))]
|
||||
#![cfg_attr(not(feature = "std"), feature(use_extern_macros))]
|
||||
|
||||
#![cfg_attr(feature = "std", doc = "Polkadot runtime standard library as compiled when linked with Rust's standard library.")]
|
||||
#![cfg_attr(not(feature = "std"), doc = "Polkadot's runtime standard library as compiled without Rust's standard library.")]
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
#[macro_reexport(vec)]
|
||||
extern crate alloc;
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate pwasm_libc;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user