mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 05:51:02 +00:00
Fix Collective <-> Elections initialization. (#5454)
* A patch * Fix * Better approach. * Fix grumbles
This commit is contained in:
@@ -91,7 +91,7 @@ use frame_support::{
|
||||
weights::{SimpleDispatchInfo, Weight, WeighData}, storage::{StorageMap, IterableStorageMap},
|
||||
traits::{
|
||||
Currency, Get, LockableCurrency, LockIdentifier, ReservableCurrency, WithdrawReasons,
|
||||
ChangeMembers, OnUnbalanced, WithdrawReason, Contains, BalanceStatus
|
||||
ChangeMembers, OnUnbalanced, WithdrawReason, Contains, BalanceStatus, InitializeMembers,
|
||||
}
|
||||
};
|
||||
use sp_phragmen::{build_support_map, ExtendedBalance};
|
||||
@@ -118,6 +118,9 @@ pub trait Trait: frame_system::Trait {
|
||||
/// What to do when the members change.
|
||||
type ChangeMembers: ChangeMembers<Self::AccountId>;
|
||||
|
||||
/// What to do with genesis members
|
||||
type InitializeMembers: InitializeMembers<Self::AccountId>;
|
||||
|
||||
/// Convert a balance into a number used for election calculation.
|
||||
/// This must fit into a `u64` but is allowed to be sensibly lossy.
|
||||
type CurrencyToVote: Convert<BalanceOf<Self>, u64> + Convert<u128, BalanceOf<Self>>;
|
||||
@@ -160,11 +163,44 @@ decl_storage! {
|
||||
pub ElectionRounds get(fn election_rounds): u32 = Zero::zero();
|
||||
|
||||
/// Votes and locked stake of a particular voter.
|
||||
pub Voting: map hasher(twox_64_concat) T::AccountId => (BalanceOf<T>, Vec<T::AccountId>);
|
||||
pub Voting get(fn voting): map hasher(twox_64_concat) T::AccountId => (BalanceOf<T>, Vec<T::AccountId>);
|
||||
|
||||
/// The present candidate list. Sorted based on account-id. A current member or runner-up
|
||||
/// can never enter this vector and is always implicitly assumed to be a candidate.
|
||||
pub Candidates get(fn candidates): Vec<T::AccountId>;
|
||||
} add_extra_genesis {
|
||||
config(members): Vec<(T::AccountId, BalanceOf<T>)>;
|
||||
build(|config: &GenesisConfig<T>| {
|
||||
let members = config.members.iter().map(|(ref member, ref stake)| {
|
||||
// make sure they have enough stake
|
||||
assert!(
|
||||
T::Currency::free_balance(member) >= *stake,
|
||||
"Genesis member does not have enough stake",
|
||||
);
|
||||
|
||||
// reserve candidacy bond and set as members.
|
||||
T::Currency::reserve(&member, T::CandidacyBond::get())
|
||||
.expect("Genesis member does not have enough balance to be a candidate");
|
||||
|
||||
// Note: all members will only vote for themselves, hence they must be given exactly
|
||||
// their own stake as total backing. Any sane election should behave as such.
|
||||
// Nonetheless, stakes will be updated for term 1 onwards according to the election.
|
||||
<Members<T>>::append(&[(member.clone(), *stake)])
|
||||
.expect("Failed to append genesis members.");
|
||||
|
||||
// set self-votes to make persistent.
|
||||
<Module<T>>::vote(
|
||||
T::Origin::from(Some(member.clone()).into()),
|
||||
vec![member.clone()],
|
||||
*stake,
|
||||
).expect("Genesis member could not vote.");
|
||||
|
||||
member.clone()
|
||||
}).collect::<Vec<T::AccountId>>();
|
||||
|
||||
// report genesis members to upstream, if any.
|
||||
T::InitializeMembers::initialize_members(&members);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -844,7 +880,7 @@ mod tests {
|
||||
Perbill, testing::Header, BuildStorage,
|
||||
traits::{BlakeTwo256, IdentityLookup, Block as BlockT},
|
||||
};
|
||||
use crate as elections;
|
||||
use crate as elections_phragmen;
|
||||
use frame_system as system;
|
||||
|
||||
parameter_types! {
|
||||
@@ -980,6 +1016,7 @@ mod tests {
|
||||
type Currency = Balances;
|
||||
type CurrencyToVote = CurrencyToVoteHandler;
|
||||
type ChangeMembers = TestChangeMembers;
|
||||
type InitializeMembers = ();
|
||||
type CandidacyBond = CandidacyBond;
|
||||
type VotingBond = VotingBond;
|
||||
type TermDuration = TermDuration;
|
||||
@@ -1001,11 +1038,12 @@ mod tests {
|
||||
{
|
||||
System: system::{Module, Call, Event<T>},
|
||||
Balances: pallet_balances::{Module, Call, Event<T>, Config<T>},
|
||||
Elections: elections::{Module, Call, Event<T>},
|
||||
Elections: elections_phragmen::{Module, Call, Event<T>, Config<T>},
|
||||
}
|
||||
);
|
||||
|
||||
pub struct ExtBuilder {
|
||||
genesis_members: Vec<(u64, u64)>,
|
||||
balance_factor: u64,
|
||||
voter_bond: u64,
|
||||
term_duration: u64,
|
||||
@@ -1015,6 +1053,7 @@ mod tests {
|
||||
impl Default for ExtBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
genesis_members: vec![],
|
||||
balance_factor: 1,
|
||||
voter_bond: 2,
|
||||
desired_runners_up: 0,
|
||||
@@ -1036,10 +1075,15 @@ mod tests {
|
||||
self.term_duration = duration;
|
||||
self
|
||||
}
|
||||
pub fn genesis_members(mut self, members: Vec<(u64, u64)>) -> Self {
|
||||
self.genesis_members = members;
|
||||
self
|
||||
}
|
||||
pub fn build(self) -> sp_io::TestExternalities {
|
||||
VOTING_BOND.with(|v| *v.borrow_mut() = self.voter_bond);
|
||||
TERM_DURATION.with(|v| *v.borrow_mut() = self.term_duration);
|
||||
DESIRED_RUNNERS_UP.with(|v| *v.borrow_mut() = self.desired_runners_up);
|
||||
MEMBERS.with(|m| *m.borrow_mut() = self.genesis_members.iter().map(|(m, _)| m.clone()).collect::<Vec<_>>());
|
||||
let mut ext: sp_io::TestExternalities = GenesisConfig {
|
||||
pallet_balances: Some(pallet_balances::GenesisConfig::<Test>{
|
||||
balances: vec![
|
||||
@@ -1051,6 +1095,9 @@ mod tests {
|
||||
(6, 60 * self.balance_factor)
|
||||
],
|
||||
}),
|
||||
elections_phragmen: Some(elections_phragmen::GenesisConfig::<Test> {
|
||||
members: self.genesis_members
|
||||
}),
|
||||
}.build_storage().unwrap().into();
|
||||
ext.execute_with(|| System::set_block_number(1));
|
||||
ext
|
||||
@@ -1090,6 +1137,37 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn genesis_members_should_work() {
|
||||
ExtBuilder::default().genesis_members(vec![(1, 10), (2, 20)]).build().execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
assert_eq!(Elections::members(), vec![(1, 10), (2, 20)]);
|
||||
|
||||
assert_eq!(Elections::voting(1), (10, vec![1]));
|
||||
assert_eq!(Elections::voting(2), (20, vec![2]));
|
||||
|
||||
// they will persist since they have self vote.
|
||||
System::set_block_number(5);
|
||||
assert_ok!(Elections::end_block(System::block_number()));
|
||||
|
||||
assert_eq!(Elections::members_ids(), vec![1, 2]);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Genesis member does not have enough stake"]
|
||||
fn genesis_members_cannot_over_stake_0() {
|
||||
// 10 cannot lock 20 as their stake and extra genesis will panic.
|
||||
ExtBuilder::default().genesis_members(vec![(1, 20), (2, 20)]).build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn genesis_members_cannot_over_stake_1() {
|
||||
// 10 cannot reserve 20 as voting bond and extra genesis will panic.
|
||||
ExtBuilder::default().voter_bond(20).genesis_members(vec![(1, 10), (2, 20)]).build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn term_duration_zero_is_passive() {
|
||||
ExtBuilder::default()
|
||||
@@ -1538,7 +1616,7 @@ mod tests {
|
||||
|
||||
assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 3));
|
||||
assert!(System::events().iter().any(|event| {
|
||||
event.event == Event::elections(RawEvent::VoterReported(3, 5, true))
|
||||
event.event == Event::elections_phragmen(RawEvent::VoterReported(3, 5, true))
|
||||
}));
|
||||
|
||||
assert_eq!(balances(&3), (28, 0));
|
||||
@@ -1566,7 +1644,7 @@ mod tests {
|
||||
|
||||
assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 4));
|
||||
assert!(System::events().iter().any(|event| {
|
||||
event.event == Event::elections(RawEvent::VoterReported(4, 5, false))
|
||||
event.event == Event::elections_phragmen(RawEvent::VoterReported(4, 5, false))
|
||||
}));
|
||||
|
||||
assert_eq!(balances(&4), (35, 5));
|
||||
@@ -1976,7 +2054,7 @@ mod tests {
|
||||
assert_eq!(balances(&5), (45, 2));
|
||||
|
||||
assert!(System::events().iter().any(|event| {
|
||||
event.event == Event::elections(RawEvent::NewTerm(vec![(4, 40), (5, 50)]))
|
||||
event.event == Event::elections_phragmen(RawEvent::NewTerm(vec![(4, 40), (5, 50)]))
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user