Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Integration tests for staking + election-provider-multi-phase #12972

Merged
merged 23 commits into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cb10d13
EPM and staking pallets: Adds new crate for integration tests
gpestana Dec 14, 2022
3ec1541
Adds ExtBuilder and helpers with initial conditions assertions
gpestana Dec 16, 2022
b818b29
removes account helpers; adds staking, session, etc genesis
gpestana Jan 1, 2023
624c728
Adds kusama incident test case
gpestana Jan 2, 2023
73197ae
Prepare for slashing test
gpestana Jan 5, 2023
762b0c0
Adds solution submission
gpestana Jan 6, 2023
869b677
slash_through_offending_threshold
gpestana Jan 6, 2023
eeb0438
Renames e2e integration tests dir and crate
gpestana Jan 8, 2023
888fa74
consistently slash 10% of validator set
gpestana Jan 9, 2023
8e73538
finishes continous_slashes_below_offending_threshold test
gpestana Jan 9, 2023
632e209
Update frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
gpestana Mar 13, 2023
ffc9aae
Update frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
gpestana Mar 13, 2023
81b2275
Update frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
gpestana Mar 13, 2023
b3c6e98
Update frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
gpestana Mar 15, 2023
a1dcd6c
Update frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
gpestana Mar 15, 2023
79d8d4b
Update frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
gpestana Mar 15, 2023
ac52c0b
mock fixes
gpestana Mar 15, 2023
40ac80f
Additional checks to delayed solution eras and mock fixes
gpestana Mar 15, 2023
f1de0a9
nits and addresses review comments; splits ext_builder into one per p…
gpestana Mar 15, 2023
84dfba6
helper to set balances ext builder
gpestana Mar 15, 2023
3597015
Merge branch 'master' into gpestana/9057-EPM-integration-tests
gpestana Mar 15, 2023
9829cc1
bring up mock.rs to master
gpestana Mar 15, 2023
3eb15b6
integration test fixes and additions
gpestana Mar 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
finishes continous_slashes_below_offending_threshold test
  • Loading branch information
gpestana committed Jan 9, 2023
commit 8e735387f0f63c726e89f81e7d23e0412613b638
45 changes: 30 additions & 15 deletions frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ fn setup_works() {
ExtBuilder::default().initialize_first_session(true).build_and_execute(|| {
assert_eq!(active_era(), 0);

start_next_active_era();
start_next_active_era();
assert!(start_next_active_era().is_ok());
assert!(start_next_active_era().is_ok());
assert_eq!(active_era(), 2);

// if the solution is delayed, EPM will end up in emergency mode and eras won't progress.
start_next_active_era_delayed_solution();
start_next_active_era_delayed_solution();
assert!(start_next_active_era_delayed_solution().is_ok());
gpestana marked this conversation as resolved.
Show resolved Hide resolved
assert!(start_next_active_era_delayed_solution().is_ok());
assert!(ElectionProviderMultiPhase::current_phase().is_emergency());
assert_eq!(active_era(), 3);
});
Expand Down Expand Up @@ -104,8 +104,8 @@ fn enters_emergency_phase_after_forcing_before_elect() {
log_current_time();

// try to advance 2 eras with a delayed solution.
start_next_active_era_delayed_solution();
start_next_active_era_delayed_solution();
assert!(start_next_active_era_delayed_solution().is_ok());
assert!(start_next_active_era_delayed_solution().is_ok());
gpestana marked this conversation as resolved.
Show resolved Hide resolved

// EPM is still in emergency phase.
assert!(ElectionProviderMultiPhase::current_phase().is_emergency());
Expand Down Expand Up @@ -135,25 +135,40 @@ fn enters_emergency_phase_after_forcing_before_elect() {
}

#[test]
/// Continously slash 10% of the active validators per era, even during the emergency phase.
fn continous_slashes() {
/// Continously slash 10% of the active validators per era.
gpestana marked this conversation as resolved.
Show resolved Hide resolved
gpestana marked this conversation as resolved.
Show resolved Hide resolved
///
/// Since the `OffendingValidatorsThreshold` is only checked per era staking does not force a new
/// era even as the number of active validators is decreasing across eras. When processing a new
/// slash, staking calculates the offending threshold based on the lenght of the current list of
gpestana marked this conversation as resolved.
Show resolved Hide resolved
/// active validators. Thus, slashing a percentage of the current validators that is lower than
/// `OffendingValidatorsThreshold` will never force a new era. However, as the slashes progress, if
/// the subsequent elections do not meet the minimum election untrusted score, the election will
/// fail and enter in emenergency mode.
fn continous_slashes_below_offending_threshold() {
ExtBuilder::default()
.initialize_first_session(true)
.validator_count(10)
.build_and_execute(|| {
assert_eq!(Session::validators().len(), 10);
let mut active_validator_set = Session::validators();

// slash 10% of the active validators and progress era.
while active_validator_set.len() != 0 {
// set a minimum election score.
assert!(set_minimum_election_score(500, 1000, 500).is_ok());

// slash 10% of the active validators and progress era until the minimum trusted score
// is reached.
while active_validator_set.len() > 0 {
let slashed = slash_percentage(Perbill::from_percent(10));
assert_eq!(slashed.len(), 1);
start_next_active_era();

let _ = slashed
.iter()
.map(|s| active_validator_set.retain(|x| x != s))
.collect::<Vec<_>>();
// break loop when era does not progress; EPM is in emergency phase as election
// failed due to election minimum score.
if start_next_active_era().is_err() {
assert!(ElectionProviderMultiPhase::current_phase().is_emergency());
break
}

active_validator_set = Session::validators();

log!(
trace,
Expand Down
30 changes: 23 additions & 7 deletions frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@

#![allow(dead_code)]

use _feps::ExtendedBalance;
use frame_support::{
parameter_types, traits,
traits::{GenesisBuild, Hooks},
weights::constants,
};
use frame_system::EnsureRoot;
use sp_core::{ConstU32, Get, H256};
use sp_npos_elections::{BalancingConfig, VoteWeight};
use sp_npos_elections::{BalancingConfig, ElectionScore, VoteWeight};
use sp_runtime::{
testing,
traits::{IdentityLookup, Zero},
Expand Down Expand Up @@ -603,21 +604,22 @@ pub(crate) fn advance_session_delayed_solution() {
}

/// Progress until the given era.
pub(crate) fn start_active_era(era_index: EraIndex, delay_solution: bool) {
pub(crate) fn start_active_era(era_index: EraIndex, delay_solution: bool) -> Result<(), ()> {
start_session((era_index * <SessionsPerEra as Get<u32>>::get()).into(), delay_solution);

// if the solution was not delayed, era should have progressed.
if !delay_solution {
assert_eq!(active_era(), era_index);
assert_eq!(current_era(), active_era());
if !delay_solution && (active_era() != era_index || current_era() != active_era()) {
Err(())
} else {
Ok(())
}
}

pub(crate) fn start_next_active_era() {
pub(crate) fn start_next_active_era() -> Result<(), ()> {
start_active_era(active_era() + 1, false)
}

pub(crate) fn start_next_active_era_delayed_solution() {
pub(crate) fn start_next_active_era_delayed_solution() -> Result<(), ()> {
start_active_era(active_era() + 1, true)
}

Expand Down Expand Up @@ -727,3 +729,17 @@ pub(crate) fn slash_percentage(percentage: Perbill) -> Vec<u128> {
}
slashed
}

pub(crate) fn set_minimum_election_score(
minimal_stake: ExtendedBalance,
sum_stake: ExtendedBalance,
sum_stake_squared: ExtendedBalance,
) -> Result<(), ()> {
let election_score = ElectionScore { minimal_stake, sum_stake, sum_stake_squared };
ElectionProviderMultiPhase::set_minimum_untrusted_score(
RuntimeOrigin::root(),
Some(election_score),
)
.map(|_| ())
.map_err(|_| ())
}