mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 11:41:04 +00:00
Slash and prove membership of prior sessions (#2970)
* skeleton for tracking historical sessions * refactor OpaqueKeys * some more skeleton work * adjust session to new OpaqueKeys API * further refactoring of key-type-ids * session gets validator ID parameter * run up against compiler * tweak staking to support new session changes * first run at child storage for deduplication * Make session use `AccountId` as `ValidatorId` * run up against child trie issues * switch to using normal trie but with a fixed prefix * clear out some println * add dedup test * flesh out historical module more * introduce ExposureOf for staking * test the historical module * WASM compiles * tests all compile * do some mock change * fix bulk of tests * fix staking tests * test obsolecence mechanic * Apply suggestions from code review Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * some more style nits * a couple more nits * tweak tries * fix typo thie -> this
This commit is contained in:
committed by
GitHub
parent
bb7ff32e77
commit
7df8e52cfe
@@ -281,10 +281,10 @@ use srml_support::{
|
||||
WithdrawReasons, OnUnbalanced, Imbalance, Get
|
||||
}
|
||||
};
|
||||
use session::{OnSessionEnding, SelectInitialValidators, SessionIndex};
|
||||
use session::{historical::OnSessionEnding, SelectInitialValidators, SessionIndex};
|
||||
use primitives::Perbill;
|
||||
use primitives::traits::{
|
||||
Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating, Bounded
|
||||
Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating, Bounded,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use primitives::{Serialize, Deserialize};
|
||||
@@ -445,7 +445,43 @@ type ExpoMap<T> = BTreeMap<
|
||||
pub const DEFAULT_SESSIONS_PER_ERA: u32 = 3;
|
||||
pub const DEFAULT_BONDING_DURATION: u32 = 1;
|
||||
|
||||
pub trait Trait: system::Trait + session::Trait {
|
||||
/// Means for interacting with a specialized version of the `session` trait.
|
||||
///
|
||||
/// This is needed because `Staking` sets the `ValidatorId` of the `session::Trait`
|
||||
pub trait SessionInterface<AccountId>: system::Trait {
|
||||
/// Disable a given validator by stash ID.
|
||||
fn disable_validator(validator: &AccountId) -> Result<(), ()>;
|
||||
/// Get the validators from session.
|
||||
fn validators() -> Vec<AccountId>;
|
||||
/// Prune historical session tries up to but not including the given index.
|
||||
fn prune_historical_up_to(up_to: session::SessionIndex);
|
||||
}
|
||||
|
||||
impl<T: Trait> SessionInterface<<T as system::Trait>::AccountId> for T where
|
||||
T: session::Trait<ValidatorId = <T as system::Trait>::AccountId>,
|
||||
T: session::historical::Trait<
|
||||
FullIdentification = Exposure<<T as system::Trait>::AccountId, BalanceOf<T>>,
|
||||
FullIdentificationOf = ExposureOf<T>,
|
||||
>,
|
||||
T::SessionHandler: session::SessionHandler<<T as system::Trait>::AccountId>,
|
||||
T::OnSessionEnding: session::OnSessionEnding<<T as system::Trait>::AccountId>,
|
||||
T::SelectInitialValidators: session::SelectInitialValidators<<T as system::Trait>::AccountId>,
|
||||
T::ValidatorIdOf: Convert<<T as system::Trait>::AccountId, Option<<T as system::Trait>::AccountId>>
|
||||
{
|
||||
fn disable_validator(validator: &<T as system::Trait>::AccountId) -> Result<(), ()> {
|
||||
<session::Module<T>>::disable(validator)
|
||||
}
|
||||
|
||||
fn validators() -> Vec<<T as system::Trait>::AccountId> {
|
||||
<session::Module<T>>::validators()
|
||||
}
|
||||
|
||||
fn prune_historical_up_to(up_to: session::SessionIndex) {
|
||||
<session::historical::Module<T>>::prune_up_to(up_to);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Trait: system::Trait {
|
||||
/// The staking balance.
|
||||
type Currency: LockableCurrency<Self::AccountId, Moment=Self::BlockNumber>;
|
||||
|
||||
@@ -473,6 +509,9 @@ pub trait Trait: system::Trait + session::Trait {
|
||||
|
||||
/// Number of eras that staked funds must remain bonded for.
|
||||
type BondingDuration: Get<EraIndex>;
|
||||
|
||||
/// Interface for interacting with a session module.
|
||||
type SessionInterface: self::SessionInterface<Self::AccountId>;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
@@ -516,15 +555,6 @@ decl_storage! {
|
||||
/// This is keyed by the stash account.
|
||||
pub Stakers get(stakers): map T::AccountId => Exposure<T::AccountId, BalanceOf<T>>;
|
||||
|
||||
// The historical validators and their nominations for a given era. Stored as a trie root
|
||||
// of the mapping `T::AccountId` => `Exposure<T::AccountId, BalanceOf<T>>`, which is just
|
||||
// the contents of `Stakers`, under a key that is the `era`.
|
||||
//
|
||||
// Every era change, this will be appended with the trie root of the contents of `Stakers`,
|
||||
// and the oldest entry removed down to a specific number of entries (probably around 90 for
|
||||
// a 3 month history).
|
||||
// pub HistoricalStakers get(historical_stakers): map T::BlockNumber => Option<H256>;
|
||||
|
||||
/// The currently elected validator set keyed by stash account ID.
|
||||
pub CurrentElected get(current_elected): Vec<T::AccountId>;
|
||||
|
||||
@@ -555,6 +585,9 @@ decl_storage! {
|
||||
|
||||
/// True if the next session change will be a new era regardless of index.
|
||||
pub ForceNewEra get(forcing_new_era): bool;
|
||||
|
||||
/// A mapping from still-bonded eras to the first session index of that era.
|
||||
BondedEras: Vec<(EraIndex, SessionIndex)>;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(stakers):
|
||||
@@ -1003,14 +1036,22 @@ impl<T: Trait> Module<T> {
|
||||
T::Reward::on_unbalanced(imbalance);
|
||||
}
|
||||
|
||||
/// Session has just ended. Provide the validator set for the next session if it's an era-end.
|
||||
fn new_session(session_index: SessionIndex) -> Option<Vec<T::AccountId>> {
|
||||
/// Session has just ended. Provide the validator set for the next session if it's an era-end, along
|
||||
/// with the exposure of the prior validator set.
|
||||
fn new_session(session_index: SessionIndex)
|
||||
-> Option<(Vec<T::AccountId>, Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)>)>
|
||||
{
|
||||
// accumulate good session reward
|
||||
let reward = Self::current_session_reward();
|
||||
<CurrentEraReward<T>>::mutate(|r| *r += reward);
|
||||
|
||||
if ForceNewEra::take() || session_index % T::SessionsPerEra::get() == 0 {
|
||||
Self::new_era()
|
||||
let validators = T::SessionInterface::validators();
|
||||
let prior = validators.into_iter()
|
||||
.map(|v| { let e = Self::stakers(&v); (v, e) })
|
||||
.collect();
|
||||
|
||||
Self::new_era(session_index).map(move |new| (new, prior))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -1020,7 +1061,7 @@ impl<T: Trait> Module<T> {
|
||||
///
|
||||
/// NOTE: This always happens immediately before a session change to ensure that new validators
|
||||
/// get a chance to set their session keys.
|
||||
fn new_era() -> Option<Vec<T::AccountId>> {
|
||||
fn new_era(start_session_index: SessionIndex) -> Option<Vec<T::AccountId>> {
|
||||
// Payout
|
||||
let reward = <CurrentEraReward<T>>::take();
|
||||
if !reward.is_zero() {
|
||||
@@ -1037,7 +1078,26 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
// Increment current era.
|
||||
CurrentEra::mutate(|s| *s += 1);
|
||||
let current_era = CurrentEra::mutate(|s| { *s += 1; *s });
|
||||
let bonding_duration = T::BondingDuration::get();
|
||||
|
||||
if current_era > bonding_duration {
|
||||
let first_kept = current_era - bonding_duration;
|
||||
BondedEras::mutate(|bonded| {
|
||||
bonded.push((current_era, start_session_index));
|
||||
|
||||
// prune out everything that's from before the first-kept index.
|
||||
let n_to_prune = bonded.iter()
|
||||
.take_while(|&&(era_idx, _)| era_idx < first_kept)
|
||||
.count();
|
||||
|
||||
bonded.drain(..n_to_prune);
|
||||
|
||||
if let Some(&(_, first_session)) = bonded.first() {
|
||||
T::SessionInterface::prune_historical_up_to(first_session);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Reassign all Stakers.
|
||||
let (slot_stake, maybe_new_validators) = Self::select_validators();
|
||||
@@ -1054,7 +1114,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
/// Select a new validator set from the assembled stakers and their role preferences.
|
||||
///
|
||||
/// Returns the new `SlotStake` value.
|
||||
/// Returns the new `SlotStake` value and a set of newly selected _stash_ IDs.
|
||||
fn select_validators() -> (BalanceOf<T>, Option<Vec<T::AccountId>>) {
|
||||
let maybe_elected_set = elect::<T, _, _, _>(
|
||||
Self::validator_count() as usize,
|
||||
@@ -1157,10 +1217,8 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
// Set the new validator set in sessions.
|
||||
<CurrentElected<T>>::put(&elected_stashes);
|
||||
let validators = elected_stashes.into_iter()
|
||||
.map(|s| Self::bonded(s).unwrap_or_default())
|
||||
.collect::<Vec<_>>();
|
||||
(slot_stake, Some(validators))
|
||||
|
||||
(slot_stake, Some(elected_stashes))
|
||||
} else {
|
||||
// There were not enough candidates for even our minimal level of functionality.
|
||||
// This is bad.
|
||||
@@ -1222,7 +1280,7 @@ impl<T: Trait> Module<T> {
|
||||
.map(|x| x.min(slash_exposure))
|
||||
.unwrap_or(slash_exposure);
|
||||
let _ = Self::slash_validator(&stash, slash);
|
||||
let _ = <session::Module<T>>::disable(&controller);
|
||||
let _ = T::SessionInterface::disable_validator(&stash);
|
||||
|
||||
RawEvent::OfflineSlash(stash.clone(), slash)
|
||||
} else {
|
||||
@@ -1234,9 +1292,17 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnSessionEnding<T::AccountId> for Module<T> {
|
||||
fn on_session_ending(i: SessionIndex) -> Option<Vec<T::AccountId>> {
|
||||
Self::new_session(i + 1)
|
||||
impl<T: Trait> session::OnSessionEnding<T::AccountId> for Module<T> {
|
||||
fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) -> Option<Vec<T::AccountId>> {
|
||||
Self::new_session(start_session - 1).map(|(new, _old)| new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnSessionEnding<T::AccountId, Exposure<T::AccountId, BalanceOf<T>>> for Module<T> {
|
||||
fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex)
|
||||
-> Option<(Vec<T::AccountId>, Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)>)>
|
||||
{
|
||||
Self::new_session(start_session - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1252,7 +1318,29 @@ impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> SelectInitialValidators<T> for Module<T> {
|
||||
/// A `Convert` implementation that finds the stash of the given controller account,
|
||||
/// if any.
|
||||
pub struct StashOf<T>(rstd::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Trait> Convert<T::AccountId, Option<T::AccountId>> for StashOf<T> {
|
||||
fn convert(controller: T::AccountId) -> Option<T::AccountId> {
|
||||
<Module<T>>::ledger(&controller).map(|l| l.stash)
|
||||
}
|
||||
}
|
||||
|
||||
/// A typed conversion from stash account ID to the current exposure of nominators
|
||||
/// on that account.
|
||||
pub struct ExposureOf<T>(rstd::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Trait> Convert<T::AccountId, Option<Exposure<T::AccountId, BalanceOf<T>>>>
|
||||
for ExposureOf<T>
|
||||
{
|
||||
fn convert(validator: T::AccountId) -> Option<Exposure<T::AccountId, BalanceOf<T>>> {
|
||||
Some(<Module<T>>::stakers(&validator))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> SelectInitialValidators<T::AccountId> for Module<T> {
|
||||
fn select_initial_validators() -> Option<Vec<T::AccountId>> {
|
||||
<Module<T>>::select_validators().1
|
||||
}
|
||||
|
||||
@@ -52,23 +52,24 @@ thread_local! {
|
||||
pub struct TestSessionHandler;
|
||||
impl session::SessionHandler<AccountId> for TestSessionHandler {
|
||||
fn on_new_session<Ks: OpaqueKeys>(_changed: bool, validators: &[(AccountId, Ks)]) {
|
||||
SESSION.with(|x|
|
||||
SESSION.with(|x| {
|
||||
let v = validators.iter().map(|(ref a, _)| a).cloned().collect::<Vec<_>>();
|
||||
*x.borrow_mut() = (validators.iter().map(|x| x.0.clone()).collect(), HashSet::new())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn on_disabled(validator_index: usize) {
|
||||
SESSION.with(|d| {
|
||||
let mut d = d.borrow_mut();
|
||||
let value = d.0[validator_index];
|
||||
println!("on_disabled {} -> {}", validator_index, value);
|
||||
d.1.insert(value);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_disabled(validator: AccountId) -> bool {
|
||||
SESSION.with(|d| d.borrow().1.contains(&validator))
|
||||
let stash = Staking::ledger(&validator).unwrap().stash;
|
||||
SESSION.with(|d| d.borrow().1.contains(&stash))
|
||||
}
|
||||
|
||||
pub struct ExistentialDeposit;
|
||||
@@ -103,7 +104,7 @@ parameter_types! {
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type Balance = Balance;
|
||||
type OnFreeBalanceZero = Staking;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
@@ -121,13 +122,21 @@ parameter_types! {
|
||||
pub const Offset: BlockNumber = 0;
|
||||
}
|
||||
impl session::Trait for Test {
|
||||
type OnSessionEnding = Staking;
|
||||
type OnSessionEnding = session::historical::NoteHistoricalRoot<Test, Staking>;
|
||||
type Keys = UintAuthorityId;
|
||||
type ShouldEndSession = session::PeriodicSessions<Period, Offset>;
|
||||
type SessionHandler = TestSessionHandler;
|
||||
type Event = ();
|
||||
type ValidatorId = AccountId;
|
||||
type ValidatorIdOf = crate::StashOf<Test>;
|
||||
type SelectInitialValidators = Staking;
|
||||
}
|
||||
|
||||
impl session::historical::Trait for Test {
|
||||
type FullIdentification = crate::Exposure<AccountId, Balance>;
|
||||
type FullIdentificationOf = crate::ExposureOf<Test>;
|
||||
}
|
||||
|
||||
impl timestamp::Trait for Test {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = ();
|
||||
@@ -145,6 +154,7 @@ impl Trait for Test {
|
||||
type Reward = ();
|
||||
type SessionsPerEra = SessionsPerEra;
|
||||
type BondingDuration = BondingDuration;
|
||||
type SessionInterface = Self;
|
||||
}
|
||||
|
||||
pub struct ExtBuilder {
|
||||
@@ -216,7 +226,7 @@ impl ExtBuilder {
|
||||
|
||||
let num_validators = self.num_validators.unwrap_or(self.validator_count);
|
||||
let validators = (0..num_validators)
|
||||
.map(|x| ((x + 1) * 10) as u64)
|
||||
.map(|x| ((x + 1) * 10 + 1) as u64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let _ = balances::GenesisConfig::<Test>{
|
||||
@@ -360,6 +370,7 @@ pub fn start_session(session_index: session::SessionIndex) {
|
||||
System::set_block_number((i + 1).into());
|
||||
Session::on_initialize(System::block_number());
|
||||
}
|
||||
|
||||
assert_eq!(Session::current_index(), session_index);
|
||||
}
|
||||
|
||||
@@ -367,3 +378,7 @@ pub fn start_era(era_index: EraIndex) {
|
||||
start_session((era_index * 3).into());
|
||||
assert_eq!(Staking::current_era(), era_index);
|
||||
}
|
||||
|
||||
pub fn validator_controllers() -> Vec<AccountId> {
|
||||
Session::validators().into_iter().map(|s| Staking::bonded(&s).expect("no controller for validator")).collect()
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ fn staking_should_work() {
|
||||
.build(),
|
||||
|| {
|
||||
// remember + compare this along with the test.
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// put some money in account that we'll use.
|
||||
for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); }
|
||||
@@ -470,13 +470,13 @@ fn staking_should_work() {
|
||||
assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default()));
|
||||
|
||||
// No effects will be seen so far.
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// --- Block 2:
|
||||
start_session(2);
|
||||
|
||||
// No effects will be seen so far. Era has not been yet triggered.
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
|
||||
// --- Block 3: the validators will now be queued.
|
||||
@@ -486,18 +486,18 @@ fn staking_should_work() {
|
||||
// --- Block 4: the validators will now be changed.
|
||||
start_session(4);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 4]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 4]);
|
||||
// --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3
|
||||
// 4 will chill
|
||||
Staking::chill(Origin::signed(4)).unwrap();
|
||||
|
||||
// --- Block 5: nothing. 4 is still there.
|
||||
start_session(5);
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 4]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 4]);
|
||||
|
||||
// --- Block 6: 4 will not be a validator.
|
||||
start_session(7);
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// Note: the stashed value of 4 is still lock
|
||||
assert_eq!(
|
||||
@@ -521,12 +521,12 @@ fn less_than_needed_candidates_works() {
|
||||
|| {
|
||||
assert_eq!(Staking::validator_count(), 4);
|
||||
assert_eq!(Staking::minimum_validator_count(), 1);
|
||||
assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]);
|
||||
|
||||
start_era(1);
|
||||
|
||||
// Previous set is selected. NO election algorithm is even executed.
|
||||
assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]);
|
||||
|
||||
// But the exposure is updated in a simple way. No external votes exists. This is purely self-vote.
|
||||
assert_eq!(Staking::stakers(10).others.len(), 0);
|
||||
@@ -549,10 +549,14 @@ fn no_candidate_emergency_condition() {
|
||||
.nominate(false)
|
||||
.build(),
|
||||
|| {
|
||||
assert_eq!(Staking::validator_count(), 15);
|
||||
|
||||
// initial validators
|
||||
assert_eq_uvec!(Session::validators(), vec![10, 20, 30, 40]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]);
|
||||
|
||||
// set the minimum validator count.
|
||||
<Staking as crate::Store>::MinimumValidatorCount::put(10);
|
||||
<Staking as crate::Store>::ValidatorCount::put(15);
|
||||
assert_eq!(Staking::validator_count(), 15);
|
||||
|
||||
let _ = Staking::chill(Origin::signed(10));
|
||||
|
||||
@@ -561,7 +565,7 @@ fn no_candidate_emergency_condition() {
|
||||
Session::on_initialize(System::block_number());
|
||||
|
||||
// Previous ones are elected. chill is invalidates. TODO: #2494
|
||||
assert_eq_uvec!(Session::validators(), vec![10, 20, 30, 40]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]);
|
||||
assert_eq!(Staking::current_elected().len(), 0);
|
||||
});
|
||||
}
|
||||
@@ -610,7 +614,7 @@ fn nominating_and_rewards_should_work() {
|
||||
.build(),
|
||||
|| {
|
||||
// initial validators -- everyone is actually even.
|
||||
assert_eq_uvec!(Session::validators(), vec![40, 30]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![40, 30]);
|
||||
|
||||
// Set payee to controller
|
||||
assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller));
|
||||
@@ -639,7 +643,7 @@ fn nominating_and_rewards_should_work() {
|
||||
start_era(1);
|
||||
|
||||
// 10 and 20 have more votes, they will be chosen by phragmen.
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// OLD validators must have already received some rewards.
|
||||
assert_eq!(Balances::total_balance(&40), 1 + 3 * session_reward);
|
||||
@@ -1478,7 +1482,7 @@ fn phragmen_poc_works() {
|
||||
.build(),
|
||||
|| {
|
||||
// We don't really care about this. At this point everything is even.
|
||||
assert_eq_uvec!(Session::validators(), vec![40, 30]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![40, 30]);
|
||||
|
||||
// Set payees to Controller
|
||||
assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller));
|
||||
@@ -1502,7 +1506,7 @@ fn phragmen_poc_works() {
|
||||
// New era => election algorithm will trigger
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
assert_eq!(Staking::stakers(11).own, 1000);
|
||||
assert_eq!(Staking::stakers(21).own, 1000);
|
||||
@@ -1574,7 +1578,7 @@ fn phragmen_poc_2_works() {
|
||||
// 30 is elected with stake 1344.2622950819673 and score 0.0007439024390243903
|
||||
with_externalities(&mut ExtBuilder::default().nominate(false).build(), || {
|
||||
// initial setup of 10 and 20, both validators
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// Bond [30, 31] as the third validator
|
||||
assert_ok!(Staking::bond_extra(Origin::signed(31), 999));
|
||||
@@ -1620,7 +1624,7 @@ fn switching_roles() {
|
||||
// Reset reward destination
|
||||
for i in &[10, 20] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); }
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// put some money in account that we'll use.
|
||||
for i in 1..7 { let _ = Balances::deposit_creating(&i, 5000); }
|
||||
@@ -1640,19 +1644,19 @@ fn switching_roles() {
|
||||
start_session(1);
|
||||
|
||||
// no change
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// new block
|
||||
start_session(2);
|
||||
|
||||
// no change
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
|
||||
// new block --> ne era --> new validators
|
||||
start_session(3);
|
||||
|
||||
// with current nominators 10 and 5 have the most stake
|
||||
assert_eq_uvec!(Session::validators(), vec![6, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![6, 10]);
|
||||
|
||||
// 2 decides to be a validator. Consequences:
|
||||
assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default()));
|
||||
@@ -1664,14 +1668,14 @@ fn switching_roles() {
|
||||
// Winners: 20 and 2
|
||||
|
||||
start_session(4);
|
||||
assert_eq_uvec!(Session::validators(), vec![6, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![6, 10]);
|
||||
|
||||
start_session(5);
|
||||
assert_eq_uvec!(Session::validators(), vec![6, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![6, 10]);
|
||||
|
||||
// ne era
|
||||
start_session(6);
|
||||
assert_eq_uvec!(Session::validators(), vec![2, 20]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![2, 20]);
|
||||
|
||||
check_exposure_all();
|
||||
check_nominator_all();
|
||||
@@ -1685,7 +1689,7 @@ fn wrong_vote_is_null() {
|
||||
.validator_pool(true)
|
||||
.build(),
|
||||
|| {
|
||||
assert_eq_uvec!(Session::validators(), vec![40, 30]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![40, 30]);
|
||||
|
||||
// put some money in account that we'll use.
|
||||
for i in 1..3 { let _ = Balances::deposit_creating(&i, 5000); }
|
||||
@@ -1700,7 +1704,7 @@ fn wrong_vote_is_null() {
|
||||
// new block
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1725,7 +1729,7 @@ fn bond_with_no_staked_value() {
|
||||
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]);
|
||||
|
||||
// min of 10, 20 and 30 (30 got a payout into staking so it raised it from 1 to 31).
|
||||
assert_eq!(Staking::slot_stake(), 31);
|
||||
@@ -1741,7 +1745,7 @@ fn bond_with_no_staked_value() {
|
||||
start_era(2);
|
||||
|
||||
// Stingy one is selected
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10, 2]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]);
|
||||
assert_eq!(Staking::stakers(1), Exposure {
|
||||
own: 1,
|
||||
total: 501,
|
||||
@@ -1791,7 +1795,7 @@ fn bond_with_little_staked_value_bounded_by_slot_stake() {
|
||||
|
||||
// 2 is elected.
|
||||
// and fucks up the slot stake.
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10, 2]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]);
|
||||
assert_eq!(Staking::slot_stake(), 1);
|
||||
|
||||
// Old ones are rewarded.
|
||||
@@ -1801,7 +1805,7 @@ fn bond_with_little_staked_value_bounded_by_slot_stake() {
|
||||
|
||||
start_era(2);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![20, 10, 2]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]);
|
||||
assert_eq!(Staking::slot_stake(), 1);
|
||||
|
||||
let reward = Staking::current_session_reward();
|
||||
@@ -1841,12 +1845,12 @@ fn phragmen_linear_worse_case_equalize() {
|
||||
assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller));
|
||||
}
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![40, 30]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![40, 30]);
|
||||
assert_ok!(Staking::set_validator_count(7));
|
||||
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![10, 60, 40, 20, 50, 30, 70]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]);
|
||||
|
||||
assert_eq!(Staking::stakers(11).total, 3000);
|
||||
assert_eq!(Staking::stakers(21).total, 2254);
|
||||
@@ -1871,12 +1875,12 @@ fn phragmen_chooses_correct_number_of_validators() {
|
||||
.build(),
|
||||
|| {
|
||||
assert_eq!(Staking::validator_count(), 1);
|
||||
assert_eq!(Session::validators().len(), 1);
|
||||
assert_eq!(validator_controllers().len(), 1);
|
||||
|
||||
System::set_block_number(1);
|
||||
Session::on_initialize(System::block_number());
|
||||
|
||||
assert_eq!(Session::validators().len(), 1);
|
||||
assert_eq!(validator_controllers().len(), 1);
|
||||
check_exposure_all();
|
||||
check_nominator_all();
|
||||
})
|
||||
@@ -1896,7 +1900,7 @@ fn phragmen_score_should_be_accurate_on_large_stakes() {
|
||||
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Session::validators(), vec![4, 2]);
|
||||
assert_eq!(validator_controllers(), vec![4, 2]);
|
||||
check_exposure_all();
|
||||
check_nominator_all();
|
||||
})
|
||||
@@ -1919,7 +1923,7 @@ fn phragmen_should_not_overflow_validators() {
|
||||
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![4, 2]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![4, 2]);
|
||||
|
||||
// This test will fail this. Will saturate.
|
||||
// check_exposure_all();
|
||||
@@ -1945,7 +1949,7 @@ fn phragmen_should_not_overflow_nominators() {
|
||||
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![4, 2]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![4, 2]);
|
||||
|
||||
// Saturate.
|
||||
assert_eq!(Staking::stakers(3).total, u64::max_value());
|
||||
@@ -1967,7 +1971,7 @@ fn phragmen_should_not_overflow_ultimate() {
|
||||
|
||||
start_era(1);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![4, 2]);
|
||||
assert_eq_uvec!(validator_controllers(), vec![4, 2]);
|
||||
|
||||
// Saturate.
|
||||
assert_eq!(Staking::stakers(3).total, u64::max_value());
|
||||
|
||||
Reference in New Issue
Block a user