mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 00:28:01 +00:00
Decouple Staking and Election - Part 2.1: Unleash Multi Phase (#8113)
* Base features and traits. * pallet and unsigned phase * Undo bad formattings. * some formatting cleanup. * Small self-cleanup. * Make it all build * self-review * Some doc tests. * Some changes from other PR * Fix session test * Update Cargo.lock * Update frame/election-provider-multi-phase/src/lib.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Some review comments * Rename + make encode/decode * Do an assert as well, just in case. * Fix build * Update frame/election-provider-multi-phase/src/unsigned.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Las comment * fix staking fuzzer. * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_election_provider_multi_phase --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/election-provider-multi-phase/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Add one last layer of feasibility check as well. * Last fixes to benchmarks * Some more docs. * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_election_provider_multi_phase --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/election-provider-multi-phase/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_election_provider_multi_phase --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/election-provider-multi-phase/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Some nits * It all works * Some self cleanup * Update frame/staking/src/lib.rs Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com> * remove most todos. * Round of self-review. * Fix migration * clean macro * Revert wrong merge * remove fuzzer stuff. * Self review * Update frame/staking/src/lib.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * review comments * add logs * Add tests to demonstrate the capacity of the snapshot. * Replace upgrade * Last touches * Fix benchmakrs * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_election_provider_multi_phase --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/election-provider-multi-phase/src/weights.rs --template=./.maintain/frame-weight-template.hbs * remove unused stuff * Fix tests. Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Parity Benchmarking Bot <admin@parity.io> Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>
This commit is contained in:
@@ -24,7 +24,6 @@ use frame_benchmarking::account;
|
||||
use frame_system::RawOrigin;
|
||||
use sp_io::hashing::blake2_256;
|
||||
use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng};
|
||||
use sp_npos_elections::*;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
@@ -143,7 +142,7 @@ pub fn create_validators_with_nominators_for_era<T: Config>(
|
||||
}
|
||||
|
||||
let to_nominate = to_nominate.unwrap_or(validators_stash.len() as u32) as usize;
|
||||
let validator_choosen = validators_stash[0..to_nominate].to_vec();
|
||||
let validator_chosen = validators_stash[0..to_nominate].to_vec();
|
||||
|
||||
// Create nominators
|
||||
for j in 0 .. nominators {
|
||||
@@ -155,7 +154,7 @@ pub fn create_validators_with_nominators_for_era<T: Config>(
|
||||
)?;
|
||||
|
||||
// Have them randomly validate
|
||||
let mut available_validators = validator_choosen.clone();
|
||||
let mut available_validators = validator_chosen.clone();
|
||||
let mut selected_validators: Vec<<T::Lookup as StaticLookup>::Source> =
|
||||
Vec::with_capacity(edge_per_nominator);
|
||||
|
||||
@@ -169,227 +168,10 @@ pub fn create_validators_with_nominators_for_era<T: Config>(
|
||||
|
||||
ValidatorCount::put(validators);
|
||||
|
||||
Ok(validator_choosen)
|
||||
Ok(validator_chosen)
|
||||
}
|
||||
|
||||
|
||||
/// Build a _really bad_ but acceptable solution for election. This should always yield a solution
|
||||
/// which has a less score than the seq-phragmen.
|
||||
pub fn get_weak_solution<T: Config>(
|
||||
do_reduce: bool,
|
||||
) -> (Vec<ValidatorIndex>, CompactAssignments, ElectionScore, ElectionSize) {
|
||||
let mut backing_stake_of: BTreeMap<T::AccountId, BalanceOf<T>> = BTreeMap::new();
|
||||
|
||||
// self stake
|
||||
<Validators<T>>::iter().for_each(|(who, _p)| {
|
||||
*backing_stake_of.entry(who.clone()).or_insert_with(|| Zero::zero()) +=
|
||||
<Module<T>>::slashable_balance_of(&who)
|
||||
});
|
||||
|
||||
// elect winners. We chose the.. least backed ones.
|
||||
let mut sorted: Vec<T::AccountId> = backing_stake_of.keys().cloned().collect();
|
||||
sorted.sort_by_key(|x| backing_stake_of.get(x).unwrap());
|
||||
let winners: Vec<T::AccountId> = sorted
|
||||
.iter()
|
||||
.rev()
|
||||
.cloned()
|
||||
.take(<Module<T>>::validator_count() as usize)
|
||||
.collect();
|
||||
|
||||
let mut staked_assignments: Vec<StakedAssignment<T::AccountId>> = Vec::new();
|
||||
// you could at this point start adding some of the nominator's stake, but for now we don't.
|
||||
// This solution must be bad.
|
||||
|
||||
// add self support to winners.
|
||||
winners.iter().for_each(|w| {
|
||||
staked_assignments.push(StakedAssignment {
|
||||
who: w.clone(),
|
||||
distribution: vec![(
|
||||
w.clone(),
|
||||
<Module<T>>::slashable_balance_of_vote_weight(
|
||||
&w,
|
||||
T::Currency::total_issuance(),
|
||||
).into(),
|
||||
)],
|
||||
})
|
||||
});
|
||||
|
||||
if do_reduce {
|
||||
reduce(&mut staked_assignments);
|
||||
}
|
||||
|
||||
// helpers for building the compact
|
||||
let snapshot_validators = <Module<T>>::snapshot_validators().unwrap();
|
||||
let snapshot_nominators = <Module<T>>::snapshot_nominators().unwrap();
|
||||
|
||||
let nominator_index = |a: &T::AccountId| -> Option<NominatorIndex> {
|
||||
snapshot_nominators
|
||||
.iter()
|
||||
.position(|x| x == a)
|
||||
.and_then(|i| <usize as TryInto<NominatorIndex>>::try_into(i).ok())
|
||||
};
|
||||
let validator_index = |a: &T::AccountId| -> Option<ValidatorIndex> {
|
||||
snapshot_validators
|
||||
.iter()
|
||||
.position(|x| x == a)
|
||||
.and_then(|i| <usize as TryInto<ValidatorIndex>>::try_into(i).ok())
|
||||
};
|
||||
|
||||
// convert back to ratio assignment. This takes less space.
|
||||
let low_accuracy_assignment = assignment_staked_to_ratio_normalized(staked_assignments)
|
||||
.expect("Failed to normalize");
|
||||
|
||||
// re-calculate score based on what the chain will decode.
|
||||
let score = {
|
||||
let staked = assignment_ratio_to_staked::<_, OffchainAccuracy, _>(
|
||||
low_accuracy_assignment.clone(),
|
||||
<Module<T>>::slashable_balance_of_fn(),
|
||||
);
|
||||
|
||||
let support_map =
|
||||
to_supports::<T::AccountId>(winners.as_slice(), staked.as_slice()).unwrap();
|
||||
support_map.evaluate()
|
||||
};
|
||||
|
||||
// compact encode the assignment.
|
||||
let compact = CompactAssignments::from_assignment(
|
||||
low_accuracy_assignment,
|
||||
nominator_index,
|
||||
validator_index,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// winners to index.
|
||||
let winners = winners
|
||||
.into_iter()
|
||||
.map(|w| {
|
||||
snapshot_validators
|
||||
.iter()
|
||||
.position(|v| *v == w)
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<ValidatorIndex>>();
|
||||
|
||||
let size = ElectionSize {
|
||||
validators: snapshot_validators.len() as ValidatorIndex,
|
||||
nominators: snapshot_nominators.len() as NominatorIndex,
|
||||
};
|
||||
|
||||
(winners, compact, score, size)
|
||||
}
|
||||
|
||||
/// Create a solution for seq-phragmen. This uses the same internal function as used by the offchain
|
||||
/// worker code.
|
||||
pub fn get_seq_phragmen_solution<T: Config>(
|
||||
do_reduce: bool,
|
||||
) -> (
|
||||
Vec<ValidatorIndex>,
|
||||
CompactAssignments,
|
||||
ElectionScore,
|
||||
ElectionSize,
|
||||
) {
|
||||
let iters = offchain_election::get_balancing_iters::<T>();
|
||||
|
||||
let sp_npos_elections::ElectionResult {
|
||||
winners,
|
||||
assignments,
|
||||
} = <Module<T>>::do_phragmen::<OffchainAccuracy>(iters).unwrap();
|
||||
|
||||
offchain_election::prepare_submission::<T>(
|
||||
assignments,
|
||||
winners,
|
||||
do_reduce,
|
||||
T::BlockWeights::get().max_block,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Returns a solution in which only one winner is elected with just a self vote.
|
||||
pub fn get_single_winner_solution<T: Config>(
|
||||
winner: T::AccountId,
|
||||
) -> Result<
|
||||
(
|
||||
Vec<ValidatorIndex>,
|
||||
CompactAssignments,
|
||||
ElectionScore,
|
||||
ElectionSize,
|
||||
),
|
||||
&'static str,
|
||||
> {
|
||||
let snapshot_validators = <Module<T>>::snapshot_validators().unwrap();
|
||||
let snapshot_nominators = <Module<T>>::snapshot_nominators().unwrap();
|
||||
|
||||
let val_index = snapshot_validators
|
||||
.iter()
|
||||
.position(|x| *x == winner)
|
||||
.ok_or("not a validator")?;
|
||||
let nom_index = snapshot_nominators
|
||||
.iter()
|
||||
.position(|x| *x == winner)
|
||||
.ok_or("not a nominator")?;
|
||||
|
||||
let stake = <Staking<T>>::slashable_balance_of(&winner);
|
||||
let stake =
|
||||
<T::CurrencyToVote>::to_vote(stake, T::Currency::total_issuance()) as ExtendedBalance;
|
||||
|
||||
let val_index = val_index as ValidatorIndex;
|
||||
let nom_index = nom_index as NominatorIndex;
|
||||
|
||||
let winners = vec![val_index];
|
||||
let compact = CompactAssignments {
|
||||
votes1: vec![(nom_index, val_index)],
|
||||
..Default::default()
|
||||
};
|
||||
let score = [stake, stake, stake * stake];
|
||||
let size = ElectionSize {
|
||||
validators: snapshot_validators.len() as ValidatorIndex,
|
||||
nominators: snapshot_nominators.len() as NominatorIndex,
|
||||
};
|
||||
|
||||
Ok((winners, compact, score, size))
|
||||
}
|
||||
|
||||
/// get the active era.
|
||||
/// get the current era.
|
||||
pub fn current_era<T: Config>() -> EraIndex {
|
||||
<Module<T>>::current_era().unwrap_or(0)
|
||||
}
|
||||
|
||||
/// initialize the first era.
|
||||
pub fn init_active_era() {
|
||||
ActiveEra::put(ActiveEraInfo {
|
||||
index: 1,
|
||||
start: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create random assignments for the given list of winners. Each assignment will have
|
||||
/// MAX_NOMINATIONS edges.
|
||||
pub fn create_assignments_for_offchain<T: Config>(
|
||||
num_assignments: u32,
|
||||
winners: Vec<<T::Lookup as StaticLookup>::Source>,
|
||||
) -> Result<
|
||||
(
|
||||
Vec<(T::AccountId, ExtendedBalance)>,
|
||||
Vec<Assignment<T::AccountId, OffchainAccuracy>>,
|
||||
),
|
||||
&'static str
|
||||
> {
|
||||
let ratio = OffchainAccuracy::from_rational(1, MAX_NOMINATIONS);
|
||||
let assignments: Vec<Assignment<T::AccountId, OffchainAccuracy>> = <Nominators<T>>::iter()
|
||||
.take(num_assignments as usize)
|
||||
.map(|(n, t)| Assignment {
|
||||
who: n,
|
||||
distribution: t.targets.iter().map(|v| (v.clone(), ratio)).collect(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
ensure!(assignments.len() == num_assignments as usize, "must bench for `a` assignments");
|
||||
|
||||
let winners = winners.into_iter().map(|v| {
|
||||
(<T::Lookup as StaticLookup>::lookup(v).unwrap(), 0)
|
||||
}).collect();
|
||||
|
||||
Ok((winners, assignments))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user