Proper loser handling in approval election. (#3392)

* Fix how we treat loser candidates.

* Bump.

* Improve doc.

* Update srml/elections/src/lib.rs

* Fix test
This commit is contained in:
Kian Paimani
2019-08-17 22:43:21 +02:00
committed by GitHub
parent a3618ef197
commit 0e56b56a86
3 changed files with 61 additions and 8 deletions
+4 -4
View File
@@ -1727,7 +1727,7 @@ dependencies = [
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2864,7 +2864,7 @@ dependencies = [
"fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"impl-codec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -5617,7 +5617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uint"
version = "0.8.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -6501,7 +6501,7 @@ dependencies = [
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874"
"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701"
"checksum uint 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5375d2c574f89adad4108ad525c93e39669853a602560bf5ed4ca9943b10799"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+1 -1
View File
@@ -81,7 +81,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 146,
impl_version: 146,
impl_version: 147,
apis: RUNTIME_API_VERSIONS,
};
+56 -3
View File
@@ -892,9 +892,17 @@ impl<T: Trait> Module<T> {
count += 1;
}
for (old, new) in candidates.iter().zip(new_candidates.iter()) {
// candidate is not a runner up.
if old != new {
// removed - kill it
<RegisterInfoOf<T>>::remove(old);
// and candidate is not a winner.
if incoming.iter().find(|e| *e == old).is_none() {
// slash the bond.
let (imbalance, _) = T::Currency::slash_reserved(&old, T::CandidacyBond::get());
T::LoserCandidate::on_unbalanced(imbalance);
}
}
}
// discard any superfluous slots.
@@ -1253,6 +1261,7 @@ mod tests {
pub struct ExtBuilder {
balance_factor: u64,
decay_ratio: u32,
desired_seats: u32,
voting_fee: u64,
voter_bond: u64,
bad_presentation_punishment: u64,
@@ -1263,6 +1272,7 @@ mod tests {
Self {
balance_factor: 1,
decay_ratio: 24,
desired_seats: 2,
voting_fee: 0,
voter_bond: 0,
bad_presentation_punishment: 1,
@@ -1291,6 +1301,10 @@ mod tests {
self.voter_bond = fee;
self
}
pub fn desired_seats(mut self, seats: u32) -> Self {
self.desired_seats = seats;
self
}
pub fn build(self) -> runtime_io::TestExternalities<Blake2Hasher> {
VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond);
VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee);
@@ -1310,7 +1324,7 @@ mod tests {
}),
elections: Some(elections::GenesisConfig::<Test>{
members: vec![],
desired_seats: 2,
desired_seats: self.desired_seats,
presentation_duration: 2,
term_duration: 5,
}),
@@ -1341,6 +1355,10 @@ mod tests {
<Test as Trait>::VotingBond::get()
}
fn balances(who: &u64) -> (u64, u64) {
(Balances::free_balance(who), Balances::reserved_balance(who))
}
#[test]
fn bool_to_flag_should_work() {
with_externalities(&mut ExtBuilder::default().build(), || {
@@ -2471,8 +2489,6 @@ mod tests {
assert_eq!(voter_ids(), vec![0, 5]);
assert_eq!(Elections::all_approvals_of(&2).len(), 0);
assert_eq!(Balances::total_balance(&2), 18);
assert_eq!(Balances::total_balance(&5), 52);
});
}
@@ -2873,4 +2889,41 @@ mod tests {
assert_eq!(Elections::candidate_reg_info(4), Some((0, 3)));
});
}
#[test]
fn loser_candidates_bond_gets_slashed() {
with_externalities(&mut ExtBuilder::default().desired_seats(1).build(), || {
System::set_block_number(4);
assert!(!Elections::presentation_active());
assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0));
assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1));
assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2));
assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3));
assert_eq!(balances(&2), (17, 3));
assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 0));
assert_ok!(Elections::set_approvals(Origin::signed(1), vec![false, true, true, true], 0, 0));
assert_ok!(Elections::end_block(System::block_number()));
System::set_block_number(6);
assert!(Elections::presentation_active());
assert_eq!(Elections::present_winner(Origin::signed(4), 4, 10, 0), Ok(()));
assert_eq!(Elections::present_winner(Origin::signed(3), 3, 10, 0), Ok(()));
assert_eq!(Elections::present_winner(Origin::signed(2), 2, 10, 0), Ok(()));
assert_eq!(Elections::present_winner(Origin::signed(1), 1, 50, 0), Ok(()));
// winner + carry
assert_eq!(Elections::leaderboard(), Some(vec![(10, 3), (10, 4), (50, 1)]));
assert_ok!(Elections::end_block(System::block_number()));
assert!(!Elections::presentation_active());
assert_eq!(Elections::members(), vec![(1, 11)]);
// account 2 is not a runner up or in leaderboard.
assert_eq!(balances(&2), (17, 0));
});
}
}