Skip to content
Snippets Groups Projects
Commit c81e9df1 authored by Gavin Wood's avatar Gavin Wood Committed by GitHub
Browse files

Society pallet (#4170)


* Introduce efficient Hash-based RNG streamer

* Initial draft of the society module

* Introduce a test

* Dual-pot logic

* Vouching

* Use chacha

* Half way through moving to cliff payout.

* Fixes

* Add some tests

* Remove printlns

* Merge remote-tracking branch 'origin/gav-verified-id' into gav-verified-id

# Conflicts:
#	frame/identity/src/lib.rs

* Merge remote-tracking branch 'origin/gav-verified-id' into gav-verified-id

# Conflicts:
#	frame/identity/src/lib.rs

* Fix `slash_payout`, add test

* Test for multi-slash_payout

* Add docs to `put_bid` function and `bidding_works` test

* Add strikes to test

* Add comments to `rotate_period`

* Implement `suspend_member`

* Off chain iteration of suspended members using linked_map

* Half of suspended candidate

* Finish suspend_candidate, need tests

* Resolve mistakes and feedback, add `suspended_candidate_rejected` test

* Remove logic which increases payout time after un-suspension

* Fix error in `slash_suspended_candidates`, add member check to `vote`

* Fix vouch rewards, dont create zero payouts, add tests for vouch

* Test unvouch

* Unbid tests

* Add lifecycle events, fix `add_member` to update `MembershipChanged`

* Head cannot be removed from society

* Use `add_member` in `found` to ensure `MembershipChanged` is triggered

* Use `Judgement` enum for suspended candidate judgement

* Make society instantiable

* Implement challenges

* Remove extra text in test

* Remove `BlockNumber` return from `slash_payout`

* Add bad vote causes slash test

* Update frame/society/src/lib.rs

Co-Authored-By: default avatarthiolliere <gui.thiolliere@gmail.com>

* Add consts to module metadata

* Check `suspended_member` cant bid

* Increase strength of payout check, **must** be a member.

* Start pallet documentation

* Finish docs

* Update library names, use decl_error

* Prevent double bids, add test

* Use `map` for vouching member, and introduce banned vouchers

* Remove leftover docs

* Vouching handles removed member lifecycles w/ tests

* `take` the votes when tallying, add comprehensive checks before vouch or bid

* Check votes are cleaned up

* Check vote is for a valid candidate, add vote event

* Defender vote event

* Fix `judge_suspended_candidate`, add weight docs

* First pass fixes (blank lines, formatting, no operational)

* Bump copyright year

* Make `add_member` infallible

* More feedback updates

* Add storage access complexity

* Fix logic for AutoUnbid

* Complete weight documentation

* Optimize logic which used to result in double storage read.

* Use Bid struct rather than tuple

* Introduce `MaxMembers` configuration constant

* Add comment about fringe scenario where `MaxMembers` could go over, NBD

* Change MaxMembership to configurable storage item with ability for root to update

* Make membership challenges skew toward failure.

If no one at all votes, or the vote is tied, the user will be suspended from society. This means, that the user simply needs to vote for themselves to stay in society assuming no one else participates.

* Refactor `is_candidate`as to avoid possible double storage reads in the future.

* Blank lines

Co-authored-by: default avatarShawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: default avatarthiolliere <gui.thiolliere@gmail.com>
parent fd6b29dd
No related merge requests found
......@@ -3930,6 +3930,22 @@ dependencies = [
"sp-trie 2.0.0",
]
[[package]]
name = "pallet-society"
version = "2.0.0"
dependencies = [
"frame-support 2.0.0",
"frame-system 2.0.0",
"pallet-balances 2.0.0",
"parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-core 2.0.0",
"sp-io 2.0.0",
"sp-runtime 2.0.0",
"sp-std 2.0.0",
]
[[package]]
name = "pallet-staking"
version = "2.0.0"
......
......@@ -80,6 +80,7 @@ members = [
"frame/randomness-collective-flip",
"frame/scored-pool",
"frame/session",
"frame/society",
"frame/staking",
"frame/staking/reward-curve",
"frame/sudo",
......
[package]
name = "pallet-society"
version = "2.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
serde = { version = "1.0.101", optional = true }
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] }
sp-io ={ path = "../../primitives/io", default-features = false }
sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" }
frame-support = { version = "2.0.0", default-features = false, path = "../support" }
frame-system = { version = "2.0.0", default-features = false, path = "../system" }
rand_chacha = { version = "0.2", default-features = false }
[dev-dependencies]
sp-core = { version = "2.0.0", path = "../../primitives/core" }
pallet-balances = { version = "2.0.0", path = "../balances" }
[features]
default = ["std"]
std = [
"codec/std",
"serde",
"sp-io/std",
"sp-runtime/std",
"rand_chacha/std",
"sp-std/std",
"frame-support/std",
"frame-system/std",
]
This diff is collapsed.
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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 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. If not, see <http://www.gnu.org/licenses/>.
//! Test utilities
use super::*;
use frame_support::{impl_outer_origin, parameter_types};
use sp_core::H256;
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried.
use sp_runtime::{
Perbill, traits::{BlakeTwo256, IdentityLookup, OnInitialize, OnFinalize}, testing::Header,
};
use frame_system::EnsureSignedBy;
impl_outer_origin! {
pub enum Origin for Test {}
}
// For testing the module, we construct most of a mock runtime. This means
// first constructing a configuration type (`Test`) which `impl`s each of the
// configuration traits of modules we want to use.
#[derive(Clone, Eq, PartialEq)]
pub struct Test;
parameter_types! {
pub const CandidateDeposit: u64 = 25;
pub const WrongSideDeduction: u64 = 2;
pub const MaxStrikes: u32 = 2;
pub const RotationPeriod: u64 = 4;
pub const PeriodSpend: u64 = 1000;
pub const MaxLockDuration: u64 = 100;
pub const FounderSetAccount: u64 = 1;
pub const SuspensionJudgementSetAccount: u64 = 2;
pub const ChallengePeriod: u64 = 8;
pub const MaxMembers: u32 = 100;
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: u32 = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
pub const ExistentialDeposit: u64 = 0;
pub const TransferFee: u64 = 0;
pub const CreationFee: u64 = 0;
}
impl frame_system::Trait for Test {
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Call = ();
type Hashing = BlakeTwo256;
type AccountId = u128;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
type ModuleToIndex = ();
}
impl pallet_balances::Trait for Test {
type Balance = u64;
type OnFreeBalanceZero = ();
type OnNewAccount = ();
type Event = ();
type TransferPayment = ();
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type TransferFee = TransferFee;
type CreationFee = CreationFee;
}
impl Trait for Test {
type Event = ();
type Currency = pallet_balances::Module<Self>;
type Randomness = ();
type CandidateDeposit = CandidateDeposit;
type WrongSideDeduction = WrongSideDeduction;
type MaxStrikes = MaxStrikes;
type PeriodSpend = PeriodSpend;
type MembershipChanged = ();
type RotationPeriod = RotationPeriod;
type MaxLockDuration = MaxLockDuration;
type FounderOrigin = EnsureSignedBy<FounderSetAccount, u128>;
type SuspensionJudgementOrigin = EnsureSignedBy<SuspensionJudgementSetAccount, u128>;
type ChallengePeriod = ChallengePeriod;
}
pub type Society = Module<Test>;
pub type System = frame_system::Module<Test>;
pub type Balances = pallet_balances::Module<Test>;
pub struct EnvBuilder {
members: Vec<u128>,
balance: u64,
balances: Vec<(u128, u64)>,
pot: u64,
max_members: u32,
}
impl EnvBuilder {
pub fn new() -> Self {
Self {
members: vec![10],
balance: 10_000,
balances: vec![
(10, 50),
(20, 50),
(30, 50),
(40, 50),
(50, 50),
(60, 50),
],
pot: 0,
max_members: 100,
}
}
pub fn execute<R, F: FnOnce() -> R>(mut self, f: F) -> R {
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
self.balances.push((Society::account_id(), self.balance.max(self.pot)));
pallet_balances::GenesisConfig::<Test> {
balances: self.balances,
vesting: vec![],
}.assimilate_storage(&mut t).unwrap();
GenesisConfig::<Test>{
members: self.members,
pot: self.pot,
max_members: self.max_members,
}.assimilate_storage(&mut t).unwrap();
let mut ext: sp_io::TestExternalities = t.into();
ext.execute_with(f)
}
#[allow(dead_code)]
pub fn with_members(mut self, m: Vec<u128>) -> Self {
self.members = m;
self
}
#[allow(dead_code)]
pub fn with_balances(mut self, b: Vec<(u128, u64)>) -> Self {
self.balances = b;
self
}
#[allow(dead_code)]
pub fn with_pot(mut self, p: u64) -> Self {
self.pot = p;
self
}
#[allow(dead_code)]
pub fn with_balance(mut self, b: u64) -> Self {
self.balance = b;
self
}
#[allow(dead_code)]
pub fn with_max_members(mut self, n: u32) -> Self {
self.max_members = n;
self
}
}
/// Run until a particular block.
pub fn run_to_block(n: u64) {
while System::block_number() < n {
if System::block_number() > 1 {
System::on_finalize(System::block_number());
}
System::set_block_number(System::block_number() + 1);
System::on_initialize(System::block_number());
Society::on_initialize(System::block_number());
}
}
/// Creates a bid struct using input parameters.
pub fn create_bid<AccountId, Balance>(
value: Balance,
who: AccountId,
kind: BidKind<AccountId, Balance>
) -> Bid<AccountId, Balance>
{
Bid {
who,
kind,
value
}
}
This diff is collapsed.
......@@ -23,7 +23,7 @@ use codec::{FullCodec, Codec, Encode, Decode};
use sp_core::u32_trait::Value as U32;
use sp_runtime::{
ConsensusEngineId, DispatchResult, DispatchError,
traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating},
traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating, TrailingZeroInput},
};
use crate::dispatch::Parameter;
......@@ -777,6 +777,12 @@ pub trait Randomness<Output> {
}
}
impl<Output: Decode + Default> Randomness<Output> for () {
fn random(subject: &[u8]) -> Output {
Output::decode(&mut TrailingZeroInput::new(subject)).unwrap_or_default()
}
}
/// Implementors of this trait provide information about whether or not some validator has
/// been registered with them. The [Session module](../../pallet_session/index.html) is an implementor.
pub trait ValidatorRegistration<ValidatorId> {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment