Skip to content

Commit

Permalink
Permissionless elections (#688)
Browse files Browse the repository at this point in the history
* Add election types

* Rename Kickout to Ban

* unban after elections

* change election logic

* fix tests

* fix compilation

* bump spec version

* Fix tests

* fix workflow e2e test list

* Fix storage name

* review

* Changed elect() so that NonReserved are written in Permissionless mode. (#692)

* Moves unban to beginning of an era

* review2

* missed negation

* change active era to current era in giving bans

* add comments and unban ext

* fix mock and test

* Fix event definition

* fix import

* fix it!!!

* change reason to info in tests

* fix ban_expired check

* remove leftover check

* final comments

Co-authored-by: Damian Straszak <[email protected]>
  • Loading branch information
mike1729 and DamianStraszak authored Oct 28, 2022
1 parent 0a3399b commit a433672
Show file tree
Hide file tree
Showing 26 changed files with 349 additions and 246 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/e2e-tests-main-devnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,9 @@ jobs:
follow-up-finalization-check: true
timeout-minutes: 15

run-e2e-kick-out-automatic:
run-e2e-ban-automatic:
needs: [build-test-docker, build-test-client]
name: Run kick out automatic test
name: Run ban automatic test
runs-on: ubuntu-20.04
steps:
- name: Checkout source code
Expand All @@ -413,7 +413,7 @@ jobs:
- name: Run e2e test
uses: ./.github/actions/run-e2e-test
with:
test-case: kick_out_automatic
test-case: ban_automatic
follow-up-finalization-check: true
timeout-minutes: 15

Expand Down Expand Up @@ -455,7 +455,7 @@ jobs:
run-e2e-rewards-change-stake-force-new-era,
run-e2e-rewards-points-basic,
run-e2e-authorities-are-staking,
run-e2e-kick-out-automatic,
run-e2e-ban-automatic,
run-e2e-version-upgrade,
]
name: Check e2e test suite completion
Expand Down
2 changes: 1 addition & 1 deletion aleph-client/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion aleph-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aleph_client"
version = "1.10.0"
version = "1.11.0"
edition = "2021"
license = "Apache 2.0"

Expand Down
15 changes: 6 additions & 9 deletions aleph-client/src/elections.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use primitives::{
CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount,
SessionIndex,
};
use primitives::{BanConfig, BanInfo, CommitteeSeats, EraValidators, SessionCount, SessionIndex};
use sp_core::H256;

use crate::{get_session_first_block, AccountId, ReadStorage};
Expand Down Expand Up @@ -66,8 +63,8 @@ pub fn get_era_validators<C: ReadStorage>(
connection.read_storage_value_at_block(PALLET, "CurrentEraValidators", Some(block_hash))
}

pub fn get_committee_kick_out_config<C: ReadStorage>(connection: &C) -> CommitteeKickOutConfig {
connection.read_storage_value(PALLET, "CommitteeKickOutConfig")
pub fn get_ban_config<C: ReadStorage>(connection: &C) -> BanConfig {
connection.read_storage_value(PALLET, "BanConfig")
}

pub fn get_underperformed_validator_session_count<C: ReadStorage>(
Expand All @@ -84,9 +81,9 @@ pub fn get_underperformed_validator_session_count<C: ReadStorage>(
.unwrap_or(0)
}

pub fn get_kick_out_reason_for_validator<C: ReadStorage>(
pub fn get_ban_reason_for_validator<C: ReadStorage>(
connection: &C,
account_id: &AccountId,
) -> Option<KickOutReason> {
connection.read_storage_map(PALLET, "ToBeKickedOutFromCommittee", account_id, None)
) -> Option<BanInfo> {
connection.read_storage_map(PALLET, "Banned", account_id, None)
}
12 changes: 6 additions & 6 deletions aleph-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ pub use balances::total_issuance;
use codec::{Decode, Encode};
pub use debug::print_storages;
pub use elections::{
get_committee_kick_out_config, get_committee_seats, get_current_era_non_reserved_validators,
get_current_era_reserved_validators, get_current_era_validators, get_era_validators,
get_kick_out_reason_for_validator, get_next_era_committee_seats,
get_ban_config, get_ban_reason_for_validator, get_committee_seats,
get_current_era_non_reserved_validators, get_current_era_reserved_validators,
get_current_era_validators, get_era_validators, get_next_era_committee_seats,
get_next_era_non_reserved_validators, get_next_era_reserved_validators,
get_next_era_validators, get_underperformed_validator_session_count, get_validator_block_count,
};
Expand All @@ -33,9 +33,9 @@ pub use staking::{
batch_bond as staking_batch_bond, batch_nominate as staking_batch_nominate,
bond as staking_bond, bond_extra_stake, bonded as staking_bonded,
chill_validator as staking_chill_validator, chill_validators as staking_chill_validators,
force_new_era as staking_force_new_era, get_current_era, get_era, get_era_reward_points,
get_eras_stakers_storage_key, get_exposure, get_minimum_validator_count, get_payout_for_era,
get_sessions_per_era, get_stakers_as_storage_keys,
force_new_era as staking_force_new_era, get_active_era, get_current_era, get_era,
get_era_reward_points, get_eras_stakers_storage_key, get_exposure, get_minimum_validator_count,
get_payout_for_era, get_sessions_per_era, get_stakers_as_storage_keys,
get_stakers_as_storage_keys_from_storage_key, ledger as staking_ledger,
multi_bond as staking_multi_bond, nominate as staking_nominate, payout_stakers,
payout_stakers_and_assert_locked_balance, set_staking_limits as staking_set_staking_limits,
Expand Down
14 changes: 11 additions & 3 deletions aleph-client/src/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ pub fn wait_for_full_era_completion<C: ReadStorage>(connection: &C) -> anyhow::R
// staking works in such a way, that when we request a controller to be a validator in era N,
// then the changes are applied in the era N+1 (so the new validator is receiving points in N+1),
// so that we need N+1 to finish in order to claim the reward in era N+2 for the N+1 era
wait_for_era_completion(connection, get_current_era(connection) + 2)
wait_for_era_completion(connection, get_active_era(connection) + 2)
}

pub fn wait_for_next_era<C: ReadStorage>(connection: &C) -> anyhow::Result<EraIndex> {
wait_for_era_completion(connection, get_current_era(connection) + 1)
wait_for_era_completion(connection, get_active_era(connection) + 1)
}

pub fn wait_for_at_least_era<C: ReadStorage>(
Expand Down Expand Up @@ -154,10 +154,18 @@ pub fn get_era<C: AnyConnection>(connection: &C, block: Option<H256>) -> EraInde
.expect("ActiveEra is empty in the storage!")
}

pub fn get_current_era<C: AnyConnection>(connection: &C) -> EraIndex {
pub fn get_active_era<C: AnyConnection>(connection: &C) -> EraIndex {
get_era(connection, None)
}

pub fn get_current_era<C: AnyConnection>(connection: &C) -> EraIndex {
connection
.as_connection()
.get_storage_value(PALLET, "CurrentEra", None)
.expect("Failed to obtain CurrentEra extrinsic!")
.expect("CurrentEra is empty in the storage!")
}

pub fn payout_stakers(
stash_connection: &SignedConnection,
stash_account: &AccountId,
Expand Down
2 changes: 1 addition & 1 deletion benches/payout-stakers/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/cliain/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ fn generate_genesis_config(
reserved_validators: accounts_config.members.clone(),
non_reserved_validators: vec![],
committee_seats: Default::default(),
committee_kick_out_config: Default::default(),
committee_ban_config: Default::default(),
},
session: SessionConfig {
keys: accounts_config.keys,
Expand Down
10 changes: 5 additions & 5 deletions bin/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use primitives::Balance;
use primitives::{
staking::MAX_NOMINATORS_REWARDED_PER_VALIDATOR, wrap_methods, ApiError as AlephApiError,
AuthorityId as AlephId, SessionAuthorityData, Version as FinalityVersion, ADDRESSES_ENCODING,
DEFAULT_KICK_OUT_REASON_LENGTH, DEFAULT_SESSIONS_PER_ERA, DEFAULT_SESSION_PERIOD,
DEFAULT_BAN_REASON_LENGTH, DEFAULT_SESSIONS_PER_ERA, DEFAULT_SESSION_PERIOD,
MILLISECS_PER_BLOCK, TOKEN,
};
use sp_api::impl_runtime_apis;
Expand Down Expand Up @@ -108,10 +108,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("aleph-node"),
impl_name: create_runtime_str!("aleph-node"),
authoring_version: 1,
spec_version: 37,
spec_version: 38,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 12,
transaction_version: 13,
state_version: 0,
};

Expand Down Expand Up @@ -326,7 +326,7 @@ impl_opaque_keys! {

parameter_types! {
pub const SessionPeriod: u32 = DEFAULT_SESSION_PERIOD;
pub const MaximumKickOutReasonLength: u32 = DEFAULT_KICK_OUT_REASON_LENGTH;
pub const MaximumBanReasonLength: u32 = DEFAULT_BAN_REASON_LENGTH;
}

impl pallet_elections::Config for Runtime {
Expand All @@ -337,7 +337,7 @@ impl pallet_elections::Config for Runtime {
type SessionPeriod = SessionPeriod;
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Runtime, Staking>;
type ValidatorRewardsHandler = Staking;
type MaximumKickOutReasonLength = MaximumKickOutReasonLength;
type MaximumBanReasonLength = MaximumBanReasonLength;
}

impl pallet_randomness_collective_flip::Config for Runtime {}
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion e2e-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aleph-e2e-client"
version = "0.5.0"
version = "0.6.0"
edition = "2021"
license = "Apache 2.0"

Expand Down
57 changes: 24 additions & 33 deletions e2e-tests/src/kick_out.rs → e2e-tests/src/ban.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use aleph_client::{
change_validators, get_committee_kick_out_config, get_kick_out_reason_for_validator,
change_validators, get_ban_config, get_ban_reason_for_validator,
get_underperformed_validator_session_count, wait_for_event, wait_for_full_era_completion,
AccountId, AnyConnection, RootConnection, XtStatus,
};
use codec::Decode;
use log::info;
use primitives::{
CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount,
};
use primitives::{BanConfig, BanInfo, CommitteeSeats, EraValidators, SessionCount};
use sp_runtime::Perbill;

use crate::{accounts::account_ids_from_keys, validators::get_test_validators, Config};
Expand Down Expand Up @@ -57,28 +55,28 @@ pub fn check_validators<C: AnyConnection>(
era_validators
}

pub fn check_committee_kick_out_config(
pub fn check_ban_config(
connection: &RootConnection,
expected_minimal_expected_performance: Perbill,
expected_session_count_threshold: SessionCount,
expected_clean_session_counter_delay: SessionCount,
) -> CommitteeKickOutConfig {
let committee_kick_out_config = get_committee_kick_out_config(connection);
) -> BanConfig {
let ban_config = get_ban_config(connection);

assert_eq!(
committee_kick_out_config.minimal_expected_performance,
ban_config.minimal_expected_performance,
expected_minimal_expected_performance
);
assert_eq!(
committee_kick_out_config.underperformed_session_count_threshold,
ban_config.underperformed_session_count_threshold,
expected_session_count_threshold
);
assert_eq!(
committee_kick_out_config.clean_session_counter_delay,
ban_config.clean_session_counter_delay,
expected_clean_session_counter_delay
);

committee_kick_out_config
ban_config
}

pub fn check_underperformed_validator_session_count<C: AnyConnection>(
Expand All @@ -100,36 +98,29 @@ pub fn check_underperformed_validator_session_count<C: AnyConnection>(
pub fn check_underperformed_validator_reason<C: AnyConnection>(
connection: &C,
validator: &AccountId,
expected_reason: Option<&KickOutReason>,
) -> Option<KickOutReason> {
let validator_kick_out_reason = get_kick_out_reason_for_validator(connection, validator);
expected_info: Option<&BanInfo>,
) -> Option<BanInfo> {
let validator_ban_info = get_ban_reason_for_validator(connection, validator);

assert_eq!(validator_kick_out_reason.as_ref(), expected_reason);
assert_eq!(validator_ban_info.as_ref(), expected_info);

validator_kick_out_reason
validator_ban_info
}

#[derive(Debug, Decode, Clone)]
pub struct KickOutEvent {
kicked_out_validators: Vec<(AccountId, KickOutReason)>,
pub struct BanEvent {
banned_validators: Vec<(AccountId, BanInfo)>,
}

pub fn check_kick_out_event<C: AnyConnection>(
pub fn check_ban_event<C: AnyConnection>(
connection: &C,
expected_kicked_out_validators: &[(AccountId, KickOutReason)],
) -> anyhow::Result<KickOutEvent> {
let event = wait_for_event(
connection,
("Elections", "KickOutValidators"),
|e: KickOutEvent| {
info!(
"Received KickOutValidators event: {:?}",
e.kicked_out_validators
);
assert_eq!(e.kicked_out_validators, expected_kicked_out_validators);
true
},
)?;
expected_banned_validators: &[(AccountId, BanInfo)],
) -> anyhow::Result<BanEvent> {
let event = wait_for_event(connection, ("Elections", "BanValidators"), |e: BanEvent| {
info!("Received BanValidators event: {:?}", e.banned_validators);
assert_eq!(e.banned_validators, expected_banned_validators);
true
})?;

Ok(event)
}
8 changes: 4 additions & 4 deletions e2e-tests/src/cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use crate::{
config::Config,
test::{
authorities_are_staking as test_authorities_are_staking,
batch_transactions as test_batch_transactions,
ban_automatic as test_ban_automatic, batch_transactions as test_batch_transactions,
change_stake_and_force_new_era as test_change_stake_and_force_new_era,
change_validators as test_change_validators,
channeling_fee_and_tip as test_channeling_fee_and_tip, disable_node as test_disable_node,
era_payouts_calculated_correctly as test_era_payout, era_validators as test_era_validators,
fee_calculation as test_fee_calculation, finalization as test_finalization,
force_new_era as test_force_new_era, kick_out_automatic as test_kick_out_automatic,
points_basic as test_points_basic, points_stake_change as test_points_stake_change,
force_new_era as test_force_new_era, points_basic as test_points_basic,
points_stake_change as test_points_stake_change,
schedule_version_change as test_schedule_version_change,
staking_era_payouts as test_staking_era_payouts,
staking_new_validator as test_staking_new_validator, token_transfer as test_token_transfer,
Expand Down Expand Up @@ -57,6 +57,6 @@ pub fn possible_test_cases() -> PossibleTestCases {
"authorities_are_staking",
test_authorities_are_staking as TestCase,
),
("kick_out_automatic", test_kick_out_automatic as TestCase),
("ban_automatic", test_ban_automatic as TestCase),
]
}
2 changes: 1 addition & 1 deletion e2e-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ pub use cases::{possible_test_cases, PossibleTestCases};
pub use config::Config;

mod accounts;
mod ban;
mod cases;
mod config;
mod elections;
mod kick_out;
mod rewards;
mod test;
mod transfer;
Expand Down
Loading

0 comments on commit a433672

Please sign in to comment.