Fix offchain election to respect the weight (#7215)

* Mockup

* Fix offchain election to respect the weight

* Fix builds a bit

* Update frame/staking/src/offchain_election.rs

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* Update frame/staking/src/offchain_election.rs

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* Make it build, binary search

* Fix a number of grumbles

* one more fix.

* remove unwrap.

* better alg.

* Better alg again.

* Final fixes

* Fix

* Rollback to normal

* Final touches.

* Better tests.

* Update frame/staking/src/lib.rs

Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>

* Proper maxExtWeight

* Final fix

* Final fix for the find_voter

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
Kian Paimani
2020-10-02 15:45:17 +02:00
committed by GitHub
parent a772eb27a2
commit 4d036e0053
16 changed files with 585 additions and 82 deletions
@@ -152,6 +152,7 @@ fn struct_def(
let len_impl = len_impl(count);
let edge_count_impl = edge_count_impl(count);
let unique_targets_impl = unique_targets_impl(count);
let remove_voter_impl = remove_voter_impl(count);
let derives_and_maybe_compact_encoding = if compact_encoding {
// custom compact encoding.
@@ -220,10 +221,58 @@ fn struct_def(
pub fn average_edge_count(&self) -> usize {
self.edge_count().checked_div(self.len()).unwrap_or(0)
}
/// Remove a certain voter.
///
/// This will only search until the first instance of `to_remove`, and return true. If
/// no instance is found (no-op), then it returns false.
///
/// In other words, if this return true, exactly one element must have been removed from
/// `self.len()`.
pub fn remove_voter(&mut self, to_remove: #voter_type) -> bool {
#remove_voter_impl
return false
}
}
))
}
fn remove_voter_impl(count: usize) -> TokenStream2 {
let field_name = field_name_for(1);
let single = quote! {
if let Some(idx) = self.#field_name.iter().position(|(x, _)| *x == to_remove) {
self.#field_name.remove(idx);
return true
}
};
let field_name = field_name_for(2);
let double = quote! {
if let Some(idx) = self.#field_name.iter().position(|(x, _, _)| *x == to_remove) {
self.#field_name.remove(idx);
return true
}
};
let rest = (3..=count)
.map(|c| {
let field_name = field_name_for(c);
quote! {
if let Some(idx) = self.#field_name.iter().position(|(x, _, _)| *x == to_remove) {
self.#field_name.remove(idx);
return true
}
}
})
.collect::<TokenStream2>();
quote! {
#single
#double
#rest
}
}
fn len_impl(count: usize) -> TokenStream2 {
(1..=count).map(|c| {
let field_name = field_name_for(c);