Add extrinsic to improve position in a bag of bags-list (#9829)

* pallet-bags-list: Add `put_in_front_of` extrinsic

This PR adds the extrinsic `put_in_front_of` which allows the user to specify a `lighter` and `heavier` account within the same bag. The extrinsic will move `heavier` directly in front of `lighter`.  The parameter names refer to the fact that `lighter` must have a lower `VoteWeight` then `heavier`. 

In the ideal use case, where a user wants to improve the position of their account within a bag, the user would iterate the bag, starting from the head, and find the first node who's `VoteWeight` is less than theirs. They would then supply the `id` of the node as the `lighter` argument and their own `id` as the `heavier` argument.

* Test & Benchmarks

* Respect line width

* Remove List::put_in_fron_of tests; Remove AlreadyHigher error

* The dispatch origin for this call must be ...

* Add some periods

* Add back test to list module: put_in_front_of_exits_early_if_bag_not_found

* add test tests::pallet::heavier_is_head_lighter_is_not_terminal

* Cater for edge case of heavier being head

* Add ExtBuilder::add_aux_data; try to make some tests use simpler data

* Update frame/bags-list/src/list/tests.rs

* make insert_at_unchecked infallible

* Make it permissioned - only callable by heavier

* Add test cases for insert_at_unchecked

* Move counter update to insert_at; fix comments

* Address some feedback

* Make voteweight constructed with parameter_types

* Always set vote weight for Ids in build

* Add skip_genesis_ids

* Do not pass weight fn to List put_in_front_of

* Remove remants of CounterForListNodes

* fmt

* cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_bags_list --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/bags-list/src/weights.rs --template=./.maintain/frame-weight-template.hbs

* Delete messed up weights file

* Some place holder stuff so we can run bench in CI

* Fix

* cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_bags_list --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/bags-list/src/weights.rs --template=./.maintain/frame-weight-template.hbs

* Update frame/bags-list/src/list/mod.rs

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

* fmt

* Log + debug assert when refetching an Id

Co-authored-by: Parity Bot <admin@parity.io>
Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
Zeke Mostov
2021-12-07 20:35:44 -08:00
committed by GitHub
parent 752e050cf4
commit 4855eb6c40
7 changed files with 561 additions and 29 deletions
+23 -10
View File
@@ -21,28 +21,26 @@ use super::*;
use crate::{self as bags_list};
use frame_election_provider_support::VoteWeight;
use frame_support::parameter_types;
use std::collections::HashMap;
pub type AccountId = u32;
pub type Balance = u32;
parameter_types! {
// Set the vote weight for any id who's weight has _not_ been set with `set_vote_weight_of`.
pub static NextVoteWeight: VoteWeight = 0;
pub static NextVoteWeightMap: HashMap<AccountId, VoteWeight> = Default::default();
}
pub struct StakingMock;
impl frame_election_provider_support::VoteWeightProvider<AccountId> for StakingMock {
fn vote_weight(id: &AccountId) -> VoteWeight {
match id {
710 => 15,
711 => 16,
712 => 2_000, // special cases used for migrate test
_ => NextVoteWeight::get(),
}
*NextVoteWeightMap::get().get(id).unwrap_or(&NextVoteWeight::get())
}
#[cfg(any(feature = "runtime-benchmarks", test))]
fn set_vote_weight_of(_: &AccountId, weight: VoteWeight) {
// we don't really keep a mapping, just set weight for everyone.
NextVoteWeight::set(weight)
fn set_vote_weight_of(id: &AccountId, weight: VoteWeight) {
NEXT_VOTE_WEIGHT_MAP.with(|m| m.borrow_mut().insert(id.clone(), weight));
}
}
@@ -103,9 +101,17 @@ pub(crate) const GENESIS_IDS: [(AccountId, VoteWeight); 4] =
#[derive(Default)]
pub struct ExtBuilder {
ids: Vec<(AccountId, VoteWeight)>,
skip_genesis_ids: bool,
}
impl ExtBuilder {
/// Skip adding the default genesis ids to the list.
#[cfg(test)]
pub(crate) fn skip_genesis_ids(mut self) -> Self {
self.skip_genesis_ids = true;
self
}
/// Add some AccountIds to insert into `List`.
#[cfg(test)]
pub(crate) fn add_ids(mut self, ids: Vec<(AccountId, VoteWeight)>) -> Self {
@@ -117,10 +123,17 @@ impl ExtBuilder {
sp_tracing::try_init_simple();
let storage = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
let ids_with_weight: Vec<_> = if self.skip_genesis_ids {
self.ids.iter().collect()
} else {
GENESIS_IDS.iter().chain(self.ids.iter()).collect()
};
let mut ext = sp_io::TestExternalities::from(storage);
ext.execute_with(|| {
for (id, weight) in GENESIS_IDS.iter().chain(self.ids.iter()) {
for (id, weight) in ids_with_weight {
frame_support::assert_ok!(List::<Runtime>::insert(*id, *weight));
StakingMock::set_vote_weight_of(id, *weight);
}
});