From a858939ca1f9cb6eb682b89c59d34816be5c2842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 19 Oct 2022 13:16:41 +0200 Subject: [PATCH 01/42] Checkpoint --- e2e-tests/Cargo.lock | 5 ++-- e2e-tests/src/cases.rs | 2 ++ e2e-tests/src/test/kickout.rs | 43 +++++++++++++++++++++++++++++++++++ e2e-tests/src/test/mod.rs | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 e2e-tests/src/test/kickout.rs diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index 7429cfbc11..9edcaf01eb 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "aleph-e2e-client" -version = "0.3.1" +version = "0.4.0" dependencies = [ "aleph_client", "anyhow", @@ -1795,6 +1795,7 @@ dependencies = [ "scale-info", "sp-core", "sp-io", + "sp-runtime", "sp-staking", "sp-std", ] @@ -2075,7 +2076,7 @@ dependencies = [ [[package]] name = "primitives" -version = "0.4.1" +version = "0.5.0" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 0a1c55fc4c..41a71956f9 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -13,6 +13,7 @@ use crate::{ staking_era_payouts as test_staking_era_payouts, staking_new_validator as test_staking_new_validator, token_transfer as test_token_transfer, treasury_access as test_treasury_access, validators_rotate as test_validators_rotate, + kickout_automatic as test_kickout_automatic, }, }; @@ -25,6 +26,7 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ + ("kickout_automatic", test_kickout_automatic as TestCase), ("finalization", test_finalization as TestCase), ("rewards_disable_node", test_disable_node as TestCase), ("token_transfer", test_token_transfer as TestCase), diff --git a/e2e-tests/src/test/kickout.rs b/e2e-tests/src/test/kickout.rs new file mode 100644 index 0000000000..f8d95ed189 --- /dev/null +++ b/e2e-tests/src/test/kickout.rs @@ -0,0 +1,43 @@ +use log::info; + +use aleph_client::{change_validators, get_current_era_reserved_validators, get_current_era_non_reserved_validators, wait_for_full_era_completion, XtStatus}; +use primitives::CommitteeSeats; + +use crate::{ + accounts::account_ids_from_keys, + validators::get_test_validators, + Config, +}; + +pub fn kickout_automatic(config: &Config) -> anyhow::Result<()> { + let root_connection = config.create_root_connection(); + + let validator_count = config.validator_count; + let era_validators = get_test_validators(config); + let reserved_validators = account_ids_from_keys(&era_validators.reserved); + let non_reserved_validators = account_ids_from_keys(&era_validators.non_reserved); + + let seats = CommitteeSeats { + reserved_seats: 2, + non_reserved_seats: 2, + }; + + change_validators( + &root_connection, + Some(reserved_validators.clone()), + Some(non_reserved_validators.clone()), + Some(seats), + XtStatus::InBlock, + ); + wait_for_full_era_completion(&root_connection)?; + + let expected_current_era_validators = EraValidators { + resereved: reserved_validators, + non_reserved: non_reserved_validators, + }; + let current_era_validators = get_current_era_validators(&root_connection); + + assert_eq!(current_era_validators, expected_current_era_validators); + + Ok(()) +} \ No newline at end of file diff --git a/e2e-tests/src/test/mod.rs b/e2e-tests/src/test/mod.rs index 2be596662b..b8d4d716d1 100644 --- a/e2e-tests/src/test/mod.rs +++ b/e2e-tests/src/test/mod.rs @@ -3,6 +3,7 @@ pub use era_payout::era_payouts_calculated_correctly; pub use era_validators::era_validators; pub use fee::fee_calculation; pub use finalization::finalization; +pub use kickout::kickout_automatic; pub use rewards::{ change_stake_and_force_new_era, disable_node, force_new_era, points_basic, points_stake_change, }; @@ -18,6 +19,7 @@ mod era_payout; mod era_validators; mod fee; mod finalization; +mod kickout; mod rewards; mod staking; mod transfer; From f26695eca02855d37d68f42d0ee97b5b3b2a892f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 21 Oct 2022 08:12:20 +0200 Subject: [PATCH 02/42] Partial attempt --- aleph-client/Cargo.lock | 5 +- aleph-client/src/elections.rs | 34 +++++++- aleph-client/src/lib.rs | 7 +- e2e-tests/src/cases.rs | 7 +- e2e-tests/src/test/kick_out.rs | 140 +++++++++++++++++++++++++++++++++ e2e-tests/src/test/kickout.rs | 43 ---------- e2e-tests/src/test/mod.rs | 4 +- 7 files changed, 182 insertions(+), 58 deletions(-) create mode 100644 e2e-tests/src/test/kick_out.rs delete mode 100644 e2e-tests/src/test/kickout.rs diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index 45e07298d2..d90f11dbaf 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -1666,7 +1666,7 @@ dependencies = [ [[package]] name = "pallet-elections" -version = "0.4.0" +version = "0.5.0" dependencies = [ "frame-election-provider-support", "frame-support", @@ -1681,6 +1681,7 @@ dependencies = [ "scale-info", "sp-core", "sp-io", + "sp-runtime", "sp-staking", "sp-std", ] @@ -1961,7 +1962,7 @@ dependencies = [ [[package]] name = "primitives" -version = "0.4.1" +version = "0.5.0" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 3f80836c38..4bee09c540 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -1,9 +1,10 @@ -use primitives::SessionIndex; -pub use primitives::{CommitteeSeats, EraValidators}; +use primitives::{ + CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount, + SessionIndex, +}; use sp_core::H256; -use substrate_api_client::AccountId; -use crate::{get_session_first_block, ReadStorage}; +use crate::{get_session_first_block, AccountId, ReadStorage}; const PALLET: &str = "Elections"; @@ -53,3 +54,28 @@ pub fn get_era_validators( let block_hash = get_session_first_block(connection, session); connection.read_storage_value_at_block(PALLET, "CurrentEraValidators", Some(block_hash)) } + +pub fn get_committee_kick_out_config(connection: &C) -> CommitteeKickOutConfig { + connection.read_storage_value(PALLET, "CommitteeKickOutConfig") +} + +pub fn get_underperformed_validator_session_count( + connection: &C, + account_id: &AccountId, +) -> SessionCount { + connection + .read_storage_map( + PALLET, + "UnderperformedValidatorSessionCount", + account_id, + None, + ) + .unwrap_or(0) +} + +pub fn get_kick_out_reason_for_validator( + connection: &C, + account_id: &AccountId, +) -> Option { + connection.read_storage_map(PALLET, "ToBeKickedOutFromCommittee", account_id, None) +} diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index e2b94994cf..eefc54e408 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -6,10 +6,11 @@ pub use balances::total_issuance; use codec::{Decode, Encode}; pub use debug::print_storages; pub use elections::{ - get_committee_seats, get_current_era_non_reserved_validators, - get_current_era_reserved_validators, get_era_validators, get_next_era_committee_seats, + 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_next_era_non_reserved_validators, get_next_era_reserved_validators, - get_validator_block_count, + get_underperformed_validator_session_count, get_validator_block_count, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 41a71956f9..a562ccfac1 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -8,12 +8,11 @@ use crate::{ 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, points_basic as test_points_basic, - points_stake_change as test_points_stake_change, + 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, staking_era_payouts as test_staking_era_payouts, staking_new_validator as test_staking_new_validator, token_transfer as test_token_transfer, treasury_access as test_treasury_access, validators_rotate as test_validators_rotate, - kickout_automatic as test_kickout_automatic, }, }; @@ -26,7 +25,7 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ - ("kickout_automatic", test_kickout_automatic as TestCase), + ("kick_out_automatic", test_kick_out_automatic as TestCase), ("finalization", test_finalization as TestCase), ("rewards_disable_node", test_disable_node as TestCase), ("token_transfer", test_token_transfer as TestCase), diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs new file mode 100644 index 0000000000..f5684a03c2 --- /dev/null +++ b/e2e-tests/src/test/kick_out.rs @@ -0,0 +1,140 @@ +use aleph_client::{ + change_validators, get_committee_kick_out_config, get_current_era_validators, + get_current_session, get_kick_out_reason_for_validator, get_next_era_non_reserved_validators, + get_next_era_reserved_validators, get_underperformed_validator_session_count, + wait_for_at_least_session, wait_for_event, wait_for_full_era_completion, AccountId, + SignedConnection, XtStatus, +}; +use codec::Decode; +use log::info; +use primitives::{ + CommitteeSeats, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, +}; + +use crate::{ + accounts::account_ids_from_keys, rewards::set_invalid_keys_for_validator, + validators::get_test_validators, Config, +}; + +const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9943"; +const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; + +pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { + let root_connection = config.create_root_connection(); + + let validator_keys = get_test_validators(config); + let reserved_validators = account_ids_from_keys(&validator_keys.reserved); + let non_reserved_validators = account_ids_from_keys(&validator_keys.non_reserved); + + let seats = CommitteeSeats { + reserved_seats: 2, + non_reserved_seats: 2, + }; + + change_validators( + &root_connection, + Some(reserved_validators.clone()), + Some(non_reserved_validators.clone()), + Some(seats), + XtStatus::InBlock, + ); + wait_for_full_era_completion(&root_connection)?; + + let start_era_validators = get_current_era_validators(&root_connection); + + assert_eq!(start_era_validators.reserved, reserved_validators); + assert_eq!(start_era_validators.non_reserved, non_reserved_validators); + + let committee_kick_out_config = get_committee_kick_out_config(&root_connection); + + assert_eq!( + committee_kick_out_config.minimal_expected_performance, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE + ); + assert_eq!( + committee_kick_out_config.underperformed_session_count_threshold, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD + ); + assert_eq!( + committee_kick_out_config.clean_session_counter_delay, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY + ); + + let validator_to_disable = &non_reserved_validators[0]; + info!("Validator to disable: {}", validator_to_disable); + + let underperformed_validator_session_count = + get_underperformed_validator_session_count(&root_connection, validator_to_disable); + + assert_eq!(underperformed_validator_session_count, 0); + + let validator_to_disable_kick_out_reason = + get_kick_out_reason_for_validator(&root_connection, validator_to_disable); + + assert!(validator_to_disable_kick_out_reason.is_none()); + + let validator_key_to_disable = validator_keys.non_reserved[2].clone(); + + let connection_to_disable = + SignedConnection::new(NODE_TO_DISABLE_ADDRESS, validator_key_to_disable); + set_invalid_keys_for_validator(&connection_to_disable)?; + + let current_session = get_current_session(&root_connection); + wait_for_at_least_session( + &root_connection, + current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, + )?; + + let underperformed_validator_session_count = + get_underperformed_validator_session_count(&root_connection, validator_to_disable); + + assert_eq!(underperformed_validator_session_count, 0); + + let validator_to_disable_kick_out_reason = + get_kick_out_reason_for_validator(&root_connection, validator_to_disable) + .expect("Cannot obtain kick out reason for validator!"); + let expected_kick_out_reason = + KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); + + assert_eq!( + validator_to_disable_kick_out_reason, + expected_kick_out_reason + ); + + #[derive(Debug, Decode, Clone)] + struct KickOutEvent { + kicked_out_validators: Vec<(AccountId, KickOutReason)>, + } + + wait_for_event( + &root_connection, + ("Elections", "KickOutValidators"), + |e: KickOutEvent| { + info!("Received KickOutValidators event: {:?}", e); + true + }, + )?; + + let next_era_reserved_validators = get_next_era_reserved_validators(&root_connection); + let next_era_non_reserved_validators = get_next_era_non_reserved_validators(&root_connection); + + assert_eq!(next_era_reserved_validators, reserved_validators); + assert_eq!( + next_era_non_reserved_validators, + non_reserved_validators[1..] + ); + + let current_era_validators = get_current_era_validators(&root_connection); + + assert_eq!( + current_era_validators.reserved, + start_era_validators.reserved + ); + assert_eq!( + current_era_validators.non_reserved, + start_era_validators.non_reserved[1..] + ); + + Ok(()) +} diff --git a/e2e-tests/src/test/kickout.rs b/e2e-tests/src/test/kickout.rs deleted file mode 100644 index f8d95ed189..0000000000 --- a/e2e-tests/src/test/kickout.rs +++ /dev/null @@ -1,43 +0,0 @@ -use log::info; - -use aleph_client::{change_validators, get_current_era_reserved_validators, get_current_era_non_reserved_validators, wait_for_full_era_completion, XtStatus}; -use primitives::CommitteeSeats; - -use crate::{ - accounts::account_ids_from_keys, - validators::get_test_validators, - Config, -}; - -pub fn kickout_automatic(config: &Config) -> anyhow::Result<()> { - let root_connection = config.create_root_connection(); - - let validator_count = config.validator_count; - let era_validators = get_test_validators(config); - let reserved_validators = account_ids_from_keys(&era_validators.reserved); - let non_reserved_validators = account_ids_from_keys(&era_validators.non_reserved); - - let seats = CommitteeSeats { - reserved_seats: 2, - non_reserved_seats: 2, - }; - - change_validators( - &root_connection, - Some(reserved_validators.clone()), - Some(non_reserved_validators.clone()), - Some(seats), - XtStatus::InBlock, - ); - wait_for_full_era_completion(&root_connection)?; - - let expected_current_era_validators = EraValidators { - resereved: reserved_validators, - non_reserved: non_reserved_validators, - }; - let current_era_validators = get_current_era_validators(&root_connection); - - assert_eq!(current_era_validators, expected_current_era_validators); - - Ok(()) -} \ No newline at end of file diff --git a/e2e-tests/src/test/mod.rs b/e2e-tests/src/test/mod.rs index b8d4d716d1..cf9165fd9c 100644 --- a/e2e-tests/src/test/mod.rs +++ b/e2e-tests/src/test/mod.rs @@ -3,7 +3,7 @@ pub use era_payout::era_payouts_calculated_correctly; pub use era_validators::era_validators; pub use fee::fee_calculation; pub use finalization::finalization; -pub use kickout::kickout_automatic; +pub use kick_out::kick_out_automatic; pub use rewards::{ change_stake_and_force_new_era, disable_node, force_new_era, points_basic, points_stake_change, }; @@ -19,7 +19,7 @@ mod era_payout; mod era_validators; mod fee; mod finalization; -mod kickout; +mod kick_out; mod rewards; mod staking; mod transfer; From d55e50c7213fe762f6ea9d0ce8379977f91be344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 21 Oct 2022 08:56:58 +0200 Subject: [PATCH 03/42] Fixed index --- e2e-tests/src/test/kick_out.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index f5684a03c2..9e0b508db7 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -74,7 +74,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { assert!(validator_to_disable_kick_out_reason.is_none()); - let validator_key_to_disable = validator_keys.non_reserved[2].clone(); + let validator_key_to_disable = validator_keys.non_reserved[0].clone(); let connection_to_disable = SignedConnection::new(NODE_TO_DISABLE_ADDRESS, validator_key_to_disable); From d9991992bcb85d82e979806eb6aa95e34defbf04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 21 Oct 2022 13:10:32 +0200 Subject: [PATCH 04/42] Touch up --- e2e-tests/src/accounts.rs | 2 +- e2e-tests/src/cases.rs | 2 +- e2e-tests/src/test/kick_out.rs | 40 ++++++++++++++++++++++++---------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/e2e-tests/src/accounts.rs b/e2e-tests/src/accounts.rs index 2b752eee07..0292319366 100644 --- a/e2e-tests/src/accounts.rs +++ b/e2e-tests/src/accounts.rs @@ -3,7 +3,7 @@ use sp_core::Pair; use crate::config::Config; -fn get_validator_seed(seed: u32) -> String { +pub fn get_validator_seed(seed: u32) -> String { format!("//{}", seed) } diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index a562ccfac1..85b78b051a 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -25,7 +25,6 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ - ("kick_out_automatic", test_kick_out_automatic as TestCase), ("finalization", test_finalization as TestCase), ("rewards_disable_node", test_disable_node as TestCase), ("token_transfer", test_token_transfer as TestCase), @@ -56,5 +55,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), ] } diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 9e0b508db7..4f0fd1507e 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -13,13 +13,21 @@ use primitives::{ }; use crate::{ - accounts::account_ids_from_keys, rewards::set_invalid_keys_for_validator, - validators::get_test_validators, Config, + accounts::{account_ids_from_keys, get_validator_seed, NodeKeys}, + rewards::set_invalid_keys_for_validator, + validators::get_test_validators, + Config, }; -const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9943"; +const VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX: u32 = 0; +const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; +const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; +/// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the +/// validators. Waits for the offending validator to hit the kick-out threshold of sessions without +/// producing blocks. Verifies that the offending validator has in fact been kicked out for the +/// appropriate reason. pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { let root_connection = config.create_root_connection(); @@ -39,6 +47,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { Some(seats), XtStatus::InBlock, ); + wait_for_full_era_completion(&root_connection)?; let start_era_validators = get_current_era_validators(&root_connection); @@ -61,8 +70,9 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { DEFAULT_CLEAN_SESSION_COUNTER_DELAY ); - let validator_to_disable = &non_reserved_validators[0]; - info!("Validator to disable: {}", validator_to_disable); + let validator_to_disable = + &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; + info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); let underperformed_validator_session_count = get_underperformed_validator_session_count(&root_connection, validator_to_disable); @@ -74,13 +84,18 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { assert!(validator_to_disable_kick_out_reason.is_none()); - let validator_key_to_disable = validator_keys.non_reserved[0].clone(); + let validator_seed = get_validator_seed(VALIDATOR_TO_DISABLE_OVERALL_INDEX); + let stash_controller = NodeKeys::from(validator_seed); + let controller_key_to_disable = stash_controller.controller; + // This connection has to be set up with the controller key. let connection_to_disable = - SignedConnection::new(NODE_TO_DISABLE_ADDRESS, validator_key_to_disable); + SignedConnection::new(NODE_TO_DISABLE_ADDRESS, controller_key_to_disable); + set_invalid_keys_for_validator(&connection_to_disable)?; let current_session = get_current_session(&root_connection); + wait_for_at_least_session( &root_connection, current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, @@ -93,7 +108,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { let validator_to_disable_kick_out_reason = get_kick_out_reason_for_validator(&root_connection, validator_to_disable) - .expect("Cannot obtain kick out reason for validator!"); + .expect("Cannot obtain kick-out reason for validator!"); let expected_kick_out_reason = KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); @@ -111,7 +126,10 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { &root_connection, ("Elections", "KickOutValidators"), |e: KickOutEvent| { - info!("Received KickOutValidators event: {:?}", e); + info!( + "Received KickOutValidators event: {:?}", + e.kicked_out_validators + ); true }, )?; @@ -122,7 +140,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { assert_eq!(next_era_reserved_validators, reserved_validators); assert_eq!( next_era_non_reserved_validators, - non_reserved_validators[1..] + non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..] ); let current_era_validators = get_current_era_validators(&root_connection); @@ -133,7 +151,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { ); assert_eq!( current_era_validators.non_reserved, - start_era_validators.non_reserved[1..] + start_era_validators.non_reserved[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..] ); Ok(()) From 259f1e55eac3c05bf3864a41885d6a2246625025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Mon, 24 Oct 2022 16:22:59 +0200 Subject: [PATCH 05/42] Reworked automatic test for greater modularity --- Cargo.lock | 6 +- aleph-client/src/elections.rs | 46 +++++- aleph-client/src/lib.rs | 3 +- e2e-tests/src/test/kick_out.rs | 255 +++++++++++++++++++++++++-------- primitives/src/lib.rs | 2 +- 5 files changed, 247 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c186149454..a00bab5732 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2513,7 +2513,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -5358,7 +5358,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -8559,7 +8559,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", - "sha2 0.10.2", + "sha2 0.10.6", "thiserror", "unicode-normalization", "wasm-bindgen", diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 4bee09c540..325aa23f8d 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -2,9 +2,13 @@ use primitives::{ CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount, SessionIndex, }; -use sp_core::H256; +use sp_core::{Pair, H256}; +use substrate_api_client::{compose_call, compose_extrinsic, ExtrinsicParams}; -use crate::{get_session_first_block, AccountId, ReadStorage}; +use crate::{ + get_session_first_block, send_xt, AccountId, AnyConnection, ReadStorage, RootConnection, + XtStatus, +}; const PALLET: &str = "Elections"; @@ -47,6 +51,17 @@ pub fn get_next_era_non_reserved_validators(connection: &C) -> V connection.read_storage_value(PALLET, "NextEraNonReservedValidators") } +pub fn get_next_era_validators(connection: &C) -> EraValidators { + let reserved: Vec = + connection.read_storage_value(PALLET, "NextEraReservedValidators"); + let non_reserved: Vec = + connection.read_storage_value(PALLET, "NextEraNonReservedValidators"); + EraValidators { + reserved, + non_reserved, + } +} + pub fn get_era_validators( connection: &C, session: SessionIndex, @@ -79,3 +94,30 @@ pub fn get_kick_out_reason_for_validator( ) -> Option { connection.read_storage_map(PALLET, "ToBeKickedOutFromCommittee", account_id, None) } + +pub fn kick_out_from_committee( + connection: &RootConnection, + to_be_kicked_out: &AccountId, + reason: KickOutReason, + status: XtStatus, +) { + let call_name = "kick_out_from_committee"; + + let kick_out_from_committee_call = compose_call!( + connection.as_connection().metadata, + PALLET, + call_name, + to_be_kicked_out, + reason + ); + + let xt = compose_extrinsic!( + connection.as_connection(), + "Sudo", + "sudo_unchecked_weight", + kick_out_from_committee_call, + 0_u64 + ); + + send_xt(connection, xt, Some(call_name), status); +} diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index c62fabc1c4..04efdba48f 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -10,7 +10,8 @@ pub use elections::{ get_current_era_reserved_validators, get_current_era_validators, get_era_validators, get_kick_out_reason_for_validator, get_next_era_committee_seats, get_next_era_non_reserved_validators, get_next_era_reserved_validators, - get_underperformed_validator_session_count, get_validator_block_count, + get_next_era_validators, get_underperformed_validator_session_count, get_validator_block_count, + kick_out_from_committee, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 4f0fd1507e..b20ef20cf4 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,16 +1,19 @@ use aleph_client::{ change_validators, get_committee_kick_out_config, get_current_era_validators, get_current_session, get_kick_out_reason_for_validator, get_next_era_non_reserved_validators, - get_next_era_reserved_validators, get_underperformed_validator_session_count, - wait_for_at_least_session, wait_for_event, wait_for_full_era_completion, AccountId, + get_next_era_reserved_validators, get_next_era_validators, + get_underperformed_validator_session_count, kick_out_from_committee, wait_for_at_least_session, + wait_for_event, wait_for_full_era_completion, AccountId, AnyConnection, RootConnection, SignedConnection, XtStatus, }; use codec::Decode; use log::info; use primitives::{ - CommitteeSeats, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + BoundedVec, CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY, DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, }; +use sp_runtime::Perbill; use crate::{ accounts::{account_ids_from_keys, get_validator_seed, NodeKeys}, @@ -24,11 +27,88 @@ const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; +const VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX: u32 = 1; +const VALIDATOR_TO_MANUALLY_KICK_OUT_OVERALL_INDEX: u32 = 3; +const MANUAL_KICK_OUT_REASON: &str = "Manual kick out reason"; + /// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the /// validators. Waits for the offending validator to hit the kick-out threshold of sessions without /// producing blocks. Verifies that the offending validator has in fact been kicked out for the /// appropriate reason. pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { + let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + + // Check current era validators. + let start_era_validators = check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators, + get_current_era_validators, + ); + + check_committee_kick_out_config( + &root_connection, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + ); + + let validator_to_disable = + &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; + info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); + + check_underperformed_validator_session_count(&root_connection, validator_to_disable, 0); + check_underperformed_validator_reason(&root_connection, validator_to_disable, &None); + + let validator_seed = get_validator_seed(VALIDATOR_TO_DISABLE_OVERALL_INDEX); + let stash_controller = NodeKeys::from(validator_seed); + let controller_key_to_disable = stash_controller.controller; + + // This connection has to be set up with the controller key. + let connection_to_disable = + SignedConnection::new(NODE_TO_DISABLE_ADDRESS, controller_key_to_disable); + + set_invalid_keys_for_validator(&connection_to_disable)?; + + let current_session = get_current_session(&root_connection); + + wait_for_at_least_session( + &root_connection, + current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, + )?; + + check_underperformed_validator_session_count(&root_connection, validator_to_disable, 0); + let expected_kick_out_reason = + KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); + check_underperformed_validator_reason( + &root_connection, + validator_to_disable, + &Some(expected_kick_out_reason), + ); + + wait_for_kick_out_event(&root_connection)?; + + // Check next era validators. + check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + get_next_era_validators, + ); + + // Check current validators. + check_validators( + &root_connection, + &start_era_validators.reserved, + &start_era_validators.non_reserved + [(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + get_current_era_validators, + ); + + Ok(()) +} + +pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { let root_connection = config.create_root_connection(); let validator_keys = get_test_validators(config); @@ -70,60 +150,139 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { DEFAULT_CLEAN_SESSION_COUNTER_DELAY ); - let validator_to_disable = - &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; - info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); + let validator_to_manually_kick_out = + &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; + info!(target: "aleph-client", "Validator to disable: {}", validator_to_manually_kick_out); - let underperformed_validator_session_count = - get_underperformed_validator_session_count(&root_connection, validator_to_disable); + let underperformed_validator_session_count = get_underperformed_validator_session_count( + &root_connection, + validator_to_manually_kick_out, + ); assert_eq!(underperformed_validator_session_count, 0); let validator_to_disable_kick_out_reason = - get_kick_out_reason_for_validator(&root_connection, validator_to_disable); + get_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out); assert!(validator_to_disable_kick_out_reason.is_none()); - let validator_seed = get_validator_seed(VALIDATOR_TO_DISABLE_OVERALL_INDEX); - let stash_controller = NodeKeys::from(validator_seed); - let controller_key_to_disable = stash_controller.controller; + let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); + let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); + let manual_kick_out_reason = KickOutReason::OtherReason(reason); - // This connection has to be set up with the controller key. - let connection_to_disable = - SignedConnection::new(NODE_TO_DISABLE_ADDRESS, controller_key_to_disable); + kick_out_from_committee( + &root_connection, + validator_to_manually_kick_out, + manual_kick_out_reason, + XtStatus::InBlock, + ); - set_invalid_keys_for_validator(&connection_to_disable)?; + Ok(()) +} - let current_session = get_current_session(&root_connection); +fn setup_test(config: &Config) -> anyhow::Result<(RootConnection, Vec, Vec)> { + let root_connection = config.create_root_connection(); - wait_for_at_least_session( + let validator_keys = get_test_validators(config); + let reserved_validators = account_ids_from_keys(&validator_keys.reserved); + let non_reserved_validators = account_ids_from_keys(&validator_keys.non_reserved); + + let seats = CommitteeSeats { + reserved_seats: 2, + non_reserved_seats: 2, + }; + + change_validators( &root_connection, - current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, - )?; + Some(reserved_validators.clone()), + Some(non_reserved_validators.clone()), + Some(seats), + XtStatus::InBlock, + ); - let underperformed_validator_session_count = - get_underperformed_validator_session_count(&root_connection, validator_to_disable); + wait_for_full_era_completion(&root_connection)?; - assert_eq!(underperformed_validator_session_count, 0); + Ok(( + root_connection, + reserved_validators, + non_reserved_validators, + )) +} - let validator_to_disable_kick_out_reason = - get_kick_out_reason_for_validator(&root_connection, validator_to_disable) - .expect("Cannot obtain kick-out reason for validator!"); - let expected_kick_out_reason = - KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); +fn check_validators( + connection: &C, + expected_reserved: &[AccountId], + expected_non_reserved: &[AccountId], + actual_validators_source: fn(&C) -> EraValidators, +) -> EraValidators { + let era_validators = actual_validators_source(connection); + + assert_eq!(era_validators.reserved, expected_reserved); + assert_eq!(era_validators.non_reserved, expected_non_reserved); + + era_validators +} + +fn check_committee_kick_out_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); assert_eq!( - validator_to_disable_kick_out_reason, - expected_kick_out_reason + committee_kick_out_config.minimal_expected_performance, + expected_minimal_expected_performance + ); + assert_eq!( + committee_kick_out_config.underperformed_session_count_threshold, + expected_session_count_threshold + ); + assert_eq!( + committee_kick_out_config.clean_session_counter_delay, + expected_clean_session_counter_delay ); - #[derive(Debug, Decode, Clone)] - struct KickOutEvent { - kicked_out_validators: Vec<(AccountId, KickOutReason)>, - } + committee_kick_out_config +} - wait_for_event( - &root_connection, +fn check_underperformed_validator_session_count( + connection: &C, + validator: &AccountId, + expected_session_count: SessionCount, +) -> SessionCount { + let underperformed_validator_session_count = + get_underperformed_validator_session_count(connection, validator); + + assert_eq!( + underperformed_validator_session_count, + expected_session_count + ); + + underperformed_validator_session_count +} + +fn check_underperformed_validator_reason( + connection: &C, + validator: &AccountId, + expected_reason: &Option, +) -> Option { + let validator_kick_out_reason = get_kick_out_reason_for_validator(connection, validator); + + assert_eq!(&validator_kick_out_reason, expected_reason); + + validator_kick_out_reason +} + +#[derive(Debug, Decode, Clone)] +struct KickOutEvent { + kicked_out_validators: Vec<(AccountId, KickOutReason)>, +} + +fn wait_for_kick_out_event(connection: &C) -> anyhow::Result { + let event = wait_for_event( + connection, ("Elections", "KickOutValidators"), |e: KickOutEvent| { info!( @@ -134,25 +293,5 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { }, )?; - let next_era_reserved_validators = get_next_era_reserved_validators(&root_connection); - let next_era_non_reserved_validators = get_next_era_non_reserved_validators(&root_connection); - - assert_eq!(next_era_reserved_validators, reserved_validators); - assert_eq!( - next_era_non_reserved_validators, - non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..] - ); - - let current_era_validators = get_current_era_validators(&root_connection); - - assert_eq!( - current_era_validators.reserved, - start_era_validators.reserved - ); - assert_eq!( - current_era_validators.non_reserved, - start_era_validators.non_reserved[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..] - ); - - Ok(()) + Ok(event) } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index c21bd631d8..e3c3892d7e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -5,7 +5,7 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_core::crypto::KeyTypeId; -use sp_runtime::{ +pub use sp_runtime::{ generic::Header as GenericHeader, traits::{BlakeTwo256, ConstU32, Header as HeaderT}, BoundedVec, ConsensusEngineId, Perbill, From b422aa0c0de57f0f4a4d88c53df802839d76fc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 13:00:32 +0200 Subject: [PATCH 06/42] Partial manual kick-out --- e2e-tests/src/cases.rs | 2 +- e2e-tests/src/test/kick_out.rs | 113 +++++++++++++++++---------------- 2 files changed, 61 insertions(+), 54 deletions(-) diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 85b78b051a..a562ccfac1 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -25,6 +25,7 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ + ("kick_out_automatic", test_kick_out_automatic as TestCase), ("finalization", test_finalization as TestCase), ("rewards_disable_node", test_disable_node as TestCase), ("token_transfer", test_token_transfer as TestCase), @@ -55,6 +56,5 @@ pub fn possible_test_cases() -> PossibleTestCases { "authorities_are_staking", test_authorities_are_staking as TestCase, ), - ("kick_out_automatic", test_kick_out_automatic as TestCase), ] } diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index b20ef20cf4..c886d452ff 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -39,7 +39,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; // Check current era validators. - let start_era_validators = check_validators( + check_validators( &root_connection, &reserved_validators, &non_reserved_validators, @@ -86,85 +86,55 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { &Some(expected_kick_out_reason), ); - wait_for_kick_out_event(&root_connection)?; + let expected_non_reserved = &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..]; // Check next era validators. check_validators( &root_connection, &reserved_validators, - &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + expected_non_reserved, get_next_era_validators, ); + wait_for_kick_out_event(&root_connection)?; + // Check current validators. check_validators( &root_connection, - &start_era_validators.reserved, - &start_era_validators.non_reserved - [(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + &reserved_validators, + expected_non_reserved, get_current_era_validators, ); + check_underperformed_validator_reason(&root_connection, validator_to_disable, &None); + Ok(()) } pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { - let root_connection = config.create_root_connection(); - - let validator_keys = get_test_validators(config); - let reserved_validators = account_ids_from_keys(&validator_keys.reserved); - let non_reserved_validators = account_ids_from_keys(&validator_keys.non_reserved); - - let seats = CommitteeSeats { - reserved_seats: 2, - non_reserved_seats: 2, - }; + let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; - change_validators( + // Check current era validators. + let start_era_validators = check_validators( &root_connection, - Some(reserved_validators.clone()), - Some(non_reserved_validators.clone()), - Some(seats), - XtStatus::InBlock, + &reserved_validators, + &non_reserved_validators, + get_current_era_validators, ); - wait_for_full_era_completion(&root_connection)?; - - let start_era_validators = get_current_era_validators(&root_connection); - - assert_eq!(start_era_validators.reserved, reserved_validators); - assert_eq!(start_era_validators.non_reserved, non_reserved_validators); - - let committee_kick_out_config = get_committee_kick_out_config(&root_connection); - - assert_eq!( - committee_kick_out_config.minimal_expected_performance, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE - ); - assert_eq!( - committee_kick_out_config.underperformed_session_count_threshold, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD - ); - assert_eq!( - committee_kick_out_config.clean_session_counter_delay, - DEFAULT_CLEAN_SESSION_COUNTER_DELAY + check_committee_kick_out_config( + &root_connection, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY, ); let validator_to_manually_kick_out = &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; - info!(target: "aleph-client", "Validator to disable: {}", validator_to_manually_kick_out); - - let underperformed_validator_session_count = get_underperformed_validator_session_count( - &root_connection, - validator_to_manually_kick_out, - ); + info!(target: "aleph-client", "Validator to manually kick out: {}", validator_to_manually_kick_out); - assert_eq!(underperformed_validator_session_count, 0); - - let validator_to_disable_kick_out_reason = - get_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out); - - assert!(validator_to_disable_kick_out_reason.is_none()); + check_underperformed_validator_session_count(&root_connection, validator_to_manually_kick_out, 0); + check_underperformed_validator_reason(&root_connection, validator_to_manually_kick_out, &None); let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); @@ -177,6 +147,43 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { XtStatus::InBlock, ); + let current_session = get_current_session(&root_connection); + + wait_for_at_least_session( + &root_connection, + current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, + )?; + + check_underperformed_validator_session_count(&root_connection, validator_to_manually_kick_out, 0); + check_underperformed_validator_reason( + &root_connection, + validator_to_manually_kick_out, + &Some(manual_kick_out_reason), + ); + + let expected_non_reserved = &non_reserved_validators[..VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize] + .iter() + .chain(&non_reserved_validators[(VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX + 1) as usize..].iter()) + .collect(); + + // Check next era validators. + check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + get_next_era_validators, + ); + + wait_for_kick_out_event(&root_connection)?; + + // Check current validators. + check_validators( + &root_connection, + &start_era_validators.reserved, + &start_era_validators.non_reserved + [(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + get_current_era_validators, + ); Ok(()) } From 5ffe7a669ff9226ef434bc6a736dce7e7f273258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:02:53 +0200 Subject: [PATCH 07/42] Modularity; bumped crate versions --- aleph-client/Cargo.toml | 2 +- e2e-tests/Cargo.toml | 2 +- e2e-tests/src/kick_out.rs | 135 +++++++++++++++++++ e2e-tests/src/lib.rs | 1 + e2e-tests/src/test/kick_out.rs | 239 +++------------------------------ 5 files changed, 160 insertions(+), 219 deletions(-) create mode 100644 e2e-tests/src/kick_out.rs diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index 4c07db35f8..f110b0db11 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph_client" -version = "1.9.0" +version = "1.9.1" edition = "2021" license = "Apache 2.0" diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml index d05960eaef..46f2604051 100644 --- a/e2e-tests/Cargo.toml +++ b/e2e-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph-e2e-client" -version = "0.4.0" +version = "0.4.1" edition = "2021" license = "Apache 2.0" diff --git a/e2e-tests/src/kick_out.rs b/e2e-tests/src/kick_out.rs new file mode 100644 index 0000000000..62d644298c --- /dev/null +++ b/e2e-tests/src/kick_out.rs @@ -0,0 +1,135 @@ +use aleph_client::{ + change_validators, get_committee_kick_out_config, get_kick_out_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 sp_runtime::Perbill; + +use crate::{accounts::account_ids_from_keys, validators::get_test_validators, Config}; + +pub fn setup_test( + config: &Config, +) -> anyhow::Result<(RootConnection, Vec, Vec)> { + let root_connection = config.create_root_connection(); + + let validator_keys = get_test_validators(config); + let reserved_validators = account_ids_from_keys(&validator_keys.reserved); + let non_reserved_validators = account_ids_from_keys(&validator_keys.non_reserved); + + let seats = CommitteeSeats { + reserved_seats: 2, + non_reserved_seats: 2, + }; + + change_validators( + &root_connection, + Some(reserved_validators.clone()), + Some(non_reserved_validators.clone()), + Some(seats), + XtStatus::InBlock, + ); + + wait_for_full_era_completion(&root_connection)?; + + Ok(( + root_connection, + reserved_validators, + non_reserved_validators, + )) +} + +pub fn check_validators( + connection: &C, + expected_reserved: &[AccountId], + expected_non_reserved: &[AccountId], + actual_validators_source: fn(&C) -> EraValidators, +) -> EraValidators { + let era_validators = actual_validators_source(connection); + + assert_eq!(era_validators.reserved, expected_reserved); + assert_eq!(era_validators.non_reserved, expected_non_reserved); + + era_validators +} + +pub fn check_committee_kick_out_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); + + assert_eq!( + committee_kick_out_config.minimal_expected_performance, + expected_minimal_expected_performance + ); + assert_eq!( + committee_kick_out_config.underperformed_session_count_threshold, + expected_session_count_threshold + ); + assert_eq!( + committee_kick_out_config.clean_session_counter_delay, + expected_clean_session_counter_delay + ); + + committee_kick_out_config +} + +pub fn check_underperformed_validator_session_count( + connection: &C, + validator: &AccountId, + expected_session_count: &SessionCount, +) -> SessionCount { + let underperformed_validator_session_count = + get_underperformed_validator_session_count(connection, validator); + + assert_eq!( + &underperformed_validator_session_count, + expected_session_count + ); + + underperformed_validator_session_count +} + +pub fn check_underperformed_validator_reason( + connection: &C, + validator: &AccountId, + expected_reason: Option<&KickOutReason>, +) -> Option { + let validator_kick_out_reason = get_kick_out_reason_for_validator(connection, validator); + + assert_eq!(validator_kick_out_reason.as_ref(), expected_reason); + + validator_kick_out_reason +} + +#[derive(Debug, Decode, Clone)] +pub struct KickOutEvent { + kicked_out_validators: Vec<(AccountId, KickOutReason)>, +} + +pub fn check_kick_out_event( + connection: &C, + expected_kicked_out_validators: &[(AccountId, KickOutReason)], +) -> anyhow::Result { + 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 + }, + )?; + + Ok(event) +} diff --git a/e2e-tests/src/lib.rs b/e2e-tests/src/lib.rs index 2ee3b4dc74..86cbb989af 100644 --- a/e2e-tests/src/lib.rs +++ b/e2e-tests/src/lib.rs @@ -5,6 +5,7 @@ mod accounts; mod cases; mod config; mod elections; +mod kick_out; mod rewards; mod test; mod transfer; diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index c886d452ff..1aa5bbd72b 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,36 +1,30 @@ use aleph_client::{ - change_validators, get_committee_kick_out_config, get_current_era_validators, - get_current_session, get_kick_out_reason_for_validator, get_next_era_non_reserved_validators, - get_next_era_reserved_validators, get_next_era_validators, - get_underperformed_validator_session_count, kick_out_from_committee, wait_for_at_least_session, - wait_for_event, wait_for_full_era_completion, AccountId, AnyConnection, RootConnection, - SignedConnection, XtStatus, + get_current_era_validators, get_current_session, get_next_era_validators, + wait_for_at_least_session, SignedConnection, }; -use codec::Decode; use log::info; use primitives::{ - BoundedVec, CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount, - DEFAULT_CLEAN_SESSION_COUNTER_DELAY, DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, }; -use sp_runtime::Perbill; use crate::{ - accounts::{account_ids_from_keys, get_validator_seed, NodeKeys}, + accounts::{get_validator_seed, NodeKeys}, + kick_out::{ + check_committee_kick_out_config, check_kick_out_event, + check_underperformed_validator_reason, check_underperformed_validator_session_count, + check_validators, setup_test, + }, rewards::set_invalid_keys_for_validator, - validators::get_test_validators, Config, }; const VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX: u32 = 0; const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; +// Address for //2 (Node2). Depends on the infrastructure setup. const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; -const VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX: u32 = 1; -const VALIDATOR_TO_MANUALLY_KICK_OUT_OVERALL_INDEX: u32 = 3; -const MANUAL_KICK_OUT_REASON: &str = "Manual kick out reason"; - /// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the /// validators. Waits for the offending validator to hit the kick-out threshold of sessions without /// producing blocks. Verifies that the offending validator has in fact been kicked out for the @@ -57,8 +51,8 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); - check_underperformed_validator_session_count(&root_connection, validator_to_disable, 0); - check_underperformed_validator_reason(&root_connection, validator_to_disable, &None); + check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); + check_underperformed_validator_reason(&root_connection, validator_to_disable, None); let validator_seed = get_validator_seed(VALIDATOR_TO_DISABLE_OVERALL_INDEX); let stash_controller = NodeKeys::from(validator_seed); @@ -77,16 +71,21 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, )?; - check_underperformed_validator_session_count(&root_connection, validator_to_disable, 0); + check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); let expected_kick_out_reason = KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); check_underperformed_validator_reason( &root_connection, validator_to_disable, - &Some(expected_kick_out_reason), + Some(&expected_kick_out_reason), ); - let expected_non_reserved = &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..]; + let expected_non_reserved = + &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..]; + + let expected_kicked_out_validators = + vec![(validator_to_disable.clone(), expected_kick_out_reason)]; + check_kick_out_event(&root_connection, &expected_kicked_out_validators)?; // Check next era validators. check_validators( @@ -96,8 +95,6 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { get_next_era_validators, ); - wait_for_kick_out_event(&root_connection)?; - // Check current validators. check_validators( &root_connection, @@ -106,199 +103,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { get_current_era_validators, ); - check_underperformed_validator_reason(&root_connection, validator_to_disable, &None); - - Ok(()) -} - -pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; - - // Check current era validators. - let start_era_validators = check_validators( - &root_connection, - &reserved_validators, - &non_reserved_validators, - get_current_era_validators, - ); - - check_committee_kick_out_config( - &root_connection, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, - DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - ); - - let validator_to_manually_kick_out = - &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; - info!(target: "aleph-client", "Validator to manually kick out: {}", validator_to_manually_kick_out); - - check_underperformed_validator_session_count(&root_connection, validator_to_manually_kick_out, 0); - check_underperformed_validator_reason(&root_connection, validator_to_manually_kick_out, &None); - - let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); - let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); - let manual_kick_out_reason = KickOutReason::OtherReason(reason); - - kick_out_from_committee( - &root_connection, - validator_to_manually_kick_out, - manual_kick_out_reason, - XtStatus::InBlock, - ); - - let current_session = get_current_session(&root_connection); - - wait_for_at_least_session( - &root_connection, - current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, - )?; - - check_underperformed_validator_session_count(&root_connection, validator_to_manually_kick_out, 0); - check_underperformed_validator_reason( - &root_connection, - validator_to_manually_kick_out, - &Some(manual_kick_out_reason), - ); - - let expected_non_reserved = &non_reserved_validators[..VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize] - .iter() - .chain(&non_reserved_validators[(VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX + 1) as usize..].iter()) - .collect(); - - // Check next era validators. - check_validators( - &root_connection, - &reserved_validators, - &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], - get_next_era_validators, - ); - - wait_for_kick_out_event(&root_connection)?; + check_underperformed_validator_reason(&root_connection, validator_to_disable, None); - // Check current validators. - check_validators( - &root_connection, - &start_era_validators.reserved, - &start_era_validators.non_reserved - [(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], - get_current_era_validators, - ); Ok(()) } - -fn setup_test(config: &Config) -> anyhow::Result<(RootConnection, Vec, Vec)> { - let root_connection = config.create_root_connection(); - - let validator_keys = get_test_validators(config); - let reserved_validators = account_ids_from_keys(&validator_keys.reserved); - let non_reserved_validators = account_ids_from_keys(&validator_keys.non_reserved); - - let seats = CommitteeSeats { - reserved_seats: 2, - non_reserved_seats: 2, - }; - - change_validators( - &root_connection, - Some(reserved_validators.clone()), - Some(non_reserved_validators.clone()), - Some(seats), - XtStatus::InBlock, - ); - - wait_for_full_era_completion(&root_connection)?; - - Ok(( - root_connection, - reserved_validators, - non_reserved_validators, - )) -} - -fn check_validators( - connection: &C, - expected_reserved: &[AccountId], - expected_non_reserved: &[AccountId], - actual_validators_source: fn(&C) -> EraValidators, -) -> EraValidators { - let era_validators = actual_validators_source(connection); - - assert_eq!(era_validators.reserved, expected_reserved); - assert_eq!(era_validators.non_reserved, expected_non_reserved); - - era_validators -} - -fn check_committee_kick_out_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); - - assert_eq!( - committee_kick_out_config.minimal_expected_performance, - expected_minimal_expected_performance - ); - assert_eq!( - committee_kick_out_config.underperformed_session_count_threshold, - expected_session_count_threshold - ); - assert_eq!( - committee_kick_out_config.clean_session_counter_delay, - expected_clean_session_counter_delay - ); - - committee_kick_out_config -} - -fn check_underperformed_validator_session_count( - connection: &C, - validator: &AccountId, - expected_session_count: SessionCount, -) -> SessionCount { - let underperformed_validator_session_count = - get_underperformed_validator_session_count(connection, validator); - - assert_eq!( - underperformed_validator_session_count, - expected_session_count - ); - - underperformed_validator_session_count -} - -fn check_underperformed_validator_reason( - connection: &C, - validator: &AccountId, - expected_reason: &Option, -) -> Option { - let validator_kick_out_reason = get_kick_out_reason_for_validator(connection, validator); - - assert_eq!(&validator_kick_out_reason, expected_reason); - - validator_kick_out_reason -} - -#[derive(Debug, Decode, Clone)] -struct KickOutEvent { - kicked_out_validators: Vec<(AccountId, KickOutReason)>, -} - -fn wait_for_kick_out_event(connection: &C) -> anyhow::Result { - let event = wait_for_event( - connection, - ("Elections", "KickOutValidators"), - |e: KickOutEvent| { - info!( - "Received KickOutValidators event: {:?}", - e.kicked_out_validators - ); - true - }, - )?; - - Ok(event) -} From d3853ddb56933817d84da079d40b559430675fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:21:27 +0200 Subject: [PATCH 08/42] GH workflow --- .github/workflows/e2e-tests-main-devnet.yml | 16 ++++++++++++++++ e2e-tests/Cargo.lock | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-tests-main-devnet.yml b/.github/workflows/e2e-tests-main-devnet.yml index 1701afbf99..50170af483 100644 --- a/.github/workflows/e2e-tests-main-devnet.yml +++ b/.github/workflows/e2e-tests-main-devnet.yml @@ -402,6 +402,21 @@ jobs: follow-up-finalization-check: true timeout-minutes: 15 + run-e2e-kick-out-automatic: + needs: [build-test-docker, build-test-client] + name: Run kick out automatic test + runs-on: ubuntu-20.04 + steps: + - name: Checkout source code + uses: actions/checkout@v2 + + - name: Run e2e test + uses: ./.github/actions/run-e2e-test + with: + test-case: kick_out_automatic + follow-up-finalization-check: true + timeout-minutes: 10 + check-e2e-test-suite-completion: needs: [ run-e2e-finalization-test, @@ -422,6 +437,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, ] name: Check e2e test suite completion runs-on: ubuntu-20.04 diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index 6f0228c566..0e4b5be3d0 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "aleph-e2e-client" -version = "0.4.0" +version = "0.4.1" dependencies = [ "aleph_client", "anyhow", @@ -116,7 +116,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.9.0" +version = "1.9.1" dependencies = [ "ac-node-api", "ac-primitives", From f760c49b8f22bb349f89d52cf282851e39e38d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:21:44 +0200 Subject: [PATCH 09/42] Test case reordering --- e2e-tests/src/cases.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index a562ccfac1..85b78b051a 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -25,7 +25,6 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ - ("kick_out_automatic", test_kick_out_automatic as TestCase), ("finalization", test_finalization as TestCase), ("rewards_disable_node", test_disable_node as TestCase), ("token_transfer", test_token_transfer as TestCase), @@ -56,5 +55,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), ] } From 969006d5f40eef95c01dcfc4a7244d210fdcdfec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:39:17 +0200 Subject: [PATCH 10/42] Initial modules work --- e2e-tests/src/cases.rs | 4 +++- e2e-tests/src/test/mod.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 85b78b051a..8e4366fbf6 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -9,7 +9,8 @@ use crate::{ 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, + kick_out_manual as test_kick_out_manual, points_basic as test_points_basic, + points_stake_change as test_points_stake_change, staking_era_payouts as test_staking_era_payouts, staking_new_validator as test_staking_new_validator, token_transfer as test_token_transfer, treasury_access as test_treasury_access, validators_rotate as test_validators_rotate, @@ -25,6 +26,7 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ + ("kick_out_manual", test_kick_out_manual as TestCase), ("finalization", test_finalization as TestCase), ("rewards_disable_node", test_disable_node as TestCase), ("token_transfer", test_token_transfer as TestCase), diff --git a/e2e-tests/src/test/mod.rs b/e2e-tests/src/test/mod.rs index cf9165fd9c..5c854f3ba3 100644 --- a/e2e-tests/src/test/mod.rs +++ b/e2e-tests/src/test/mod.rs @@ -3,7 +3,7 @@ pub use era_payout::era_payouts_calculated_correctly; pub use era_validators::era_validators; pub use fee::fee_calculation; pub use finalization::finalization; -pub use kick_out::kick_out_automatic; +pub use kick_out::{kick_out_automatic, kick_out_manual}; pub use rewards::{ change_stake_and_force_new_era, disable_node, force_new_era, points_basic, points_stake_change, }; From 01ac2d2ad823f826c0c0bb480e039b8b254a9750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:41:39 +0200 Subject: [PATCH 11/42] Manual kickout case --- e2e-tests/src/test/kick_out.rs | 91 +++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 1aa5bbd72b..c6f095808c 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,6 +1,6 @@ use aleph_client::{ get_current_era_validators, get_current_session, get_next_era_validators, - wait_for_at_least_session, SignedConnection, + wait_for_at_least_session, SignedConnection, XtStatus }; use log::info; use primitives::{ @@ -107,3 +107,92 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { Ok(()) } + +pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { + let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + + // Check current era validators. + let start_era_validators = check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators, + get_current_era_validators, + ); + + check_committee_kick_out_config( + &root_connection, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + ); + + let validator_to_manually_kick_out = + &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; + info!(target: "aleph-client", "Validator to manually kick out: {}", validator_to_manually_kick_out); + + check_underperformed_validator_session_count( + &root_connection, + validator_to_manually_kick_out, + 0, + ); + check_underperformed_validator_reason(&root_connection, validator_to_manually_kick_out, &None); + + let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); + let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); + let manual_kick_out_reason = KickOutReason::OtherReason(reason); + + kick_out_from_committee( + &root_connection, + validator_to_manually_kick_out, + manual_kick_out_reason, + XtStatus::InBlock, + ); + + let current_session = get_current_session(&root_connection); + + wait_for_at_least_session( + &root_connection, + current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, + )?; + + check_underperformed_validator_session_count( + &root_connection, + validator_to_manually_kick_out, + 0, + ); + check_underperformed_validator_reason( + &root_connection, + validator_to_manually_kick_out, + &Some(manual_kick_out_reason), + ); + + let expected_non_reserved = &non_reserved_validators + [..VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize] + .iter() + .chain( + &non_reserved_validators + [(VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX + 1) as usize..] + .iter(), + ) + .collect(); + + // Check next era validators. + check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + get_next_era_validators, + ); + + wait_for_kick_out_event(&root_connection)?; + + // Check current validators. + check_validators( + &root_connection, + &start_era_validators.reserved, + &start_era_validators.non_reserved + [(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + get_current_era_validators, + ); + Ok(()) +} From a3d3d618da3d2ccca05fb5235013a75a0b7a64ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:42:19 +0200 Subject: [PATCH 12/42] Consts --- e2e-tests/src/test/kick_out.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index c6f095808c..b35fb10efd 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -25,6 +25,10 @@ const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; +const VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX: u32 = 1; +const VALIDATOR_TO_MANUALLY_KICK_OUT_OVERALL_INDEX: u32 = 3; +const MANUAL_KICK_OUT_REASON: &str = "Manual kick out reason"; + /// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the /// validators. Waits for the offending validator to hit the kick-out threshold of sessions without /// producing blocks. Verifies that the offending validator has in fact been kicked out for the From 6261a5606bde85bbd4c826dfc7ca169e05b4f66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 25 Oct 2022 15:43:36 +0200 Subject: [PATCH 13/42] Modules --- e2e-tests/src/test/kick_out.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index b35fb10efd..8073f16a3f 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,9 +1,10 @@ use aleph_client::{ get_current_era_validators, get_current_session, get_next_era_validators, - wait_for_at_least_session, SignedConnection, XtStatus + wait_for_at_least_session, SignedConnection, XtStatus, }; use log::info; use primitives::{ + BoundedVec, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, }; From 51ce93751663a5f15e15df494e6121a79cf1eb7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 11:08:37 +0200 Subject: [PATCH 14/42] Checkpoint --- aleph-client/src/elections.rs | 2 +- e2e-tests/src/test/kick_out.rs | 33 +++++++++++++++++---------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 325aa23f8d..e878d27321 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -98,7 +98,7 @@ pub fn get_kick_out_reason_for_validator( pub fn kick_out_from_committee( connection: &RootConnection, to_be_kicked_out: &AccountId, - reason: KickOutReason, + reason: &KickOutReason, status: XtStatus, ) { let call_name = "kick_out_from_committee"; diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 8073f16a3f..4e5f449d43 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,11 +1,10 @@ use aleph_client::{ get_current_era_validators, get_current_session, get_next_era_validators, - wait_for_at_least_session, SignedConnection, XtStatus, + kick_out_from_committee, wait_for_at_least_session, SignedConnection, XtStatus, }; use log::info; use primitives::{ - BoundedVec, - KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + BoundedVec, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, }; @@ -117,7 +116,7 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; // Check current era validators. - let start_era_validators = check_validators( + check_validators( &root_connection, &reserved_validators, &non_reserved_validators, @@ -138,9 +137,9 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { check_underperformed_validator_session_count( &root_connection, validator_to_manually_kick_out, - 0, + &0, ); - check_underperformed_validator_reason(&root_connection, validator_to_manually_kick_out, &None); + check_underperformed_validator_reason(&root_connection, validator_to_manually_kick_out, None); let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); @@ -149,7 +148,7 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { kick_out_from_committee( &root_connection, validator_to_manually_kick_out, - manual_kick_out_reason, + &manual_kick_out_reason, XtStatus::InBlock, ); @@ -163,19 +162,19 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { check_underperformed_validator_session_count( &root_connection, validator_to_manually_kick_out, - 0, + &0, ); check_underperformed_validator_reason( &root_connection, validator_to_manually_kick_out, - &Some(manual_kick_out_reason), + Some(&manual_kick_out_reason), ); - let expected_non_reserved = &non_reserved_validators + let expected_non_reserved: Vec<_> = non_reserved_validators [..VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize] .iter() .chain( - &non_reserved_validators + non_reserved_validators [(VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX + 1) as usize..] .iter(), ) @@ -185,18 +184,20 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { check_validators( &root_connection, &reserved_validators, - &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + &expected_non_reserved, get_next_era_validators, ); - wait_for_kick_out_event(&root_connection)?; + let expected_kicked_out_validators = + vec![(validator_to_manually_kick_out.clone(), manual_kick_out_reason)]; + + check_kick_out_event(&root_connection, &expected_kicked_out_validators)?; // Check current validators. check_validators( &root_connection, - &start_era_validators.reserved, - &start_era_validators.non_reserved - [(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..], + &reserved_validators, + &expected_non_reserved, get_current_era_validators, ); Ok(()) From cd0072a68d387f2b31ac64fee28f090fbe1a042b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 11:11:00 +0200 Subject: [PATCH 15/42] Removed next era validators check --- .github/workflows/e2e-tests-main-devnet.yml | 2 +- e2e-tests/src/test/kick_out.rs | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/e2e-tests-main-devnet.yml b/.github/workflows/e2e-tests-main-devnet.yml index 7d397a1270..aab7fbcf61 100644 --- a/.github/workflows/e2e-tests-main-devnet.yml +++ b/.github/workflows/e2e-tests-main-devnet.yml @@ -415,7 +415,7 @@ jobs: with: test-case: kick_out_automatic follow-up-finalization-check: true - timeout-minutes: 10 + timeout-minutes: 15 check-e2e-test-suite-completion: needs: [ diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 1aa5bbd72b..1de3e46f6f 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,6 +1,5 @@ use aleph_client::{ - get_current_era_validators, get_current_session, get_next_era_validators, - wait_for_at_least_session, SignedConnection, + get_current_era_validators, get_current_session, wait_for_at_least_session, SignedConnection, }; use log::info; use primitives::{ @@ -87,14 +86,6 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { vec![(validator_to_disable.clone(), expected_kick_out_reason)]; check_kick_out_event(&root_connection, &expected_kicked_out_validators)?; - // Check next era validators. - check_validators( - &root_connection, - &reserved_validators, - expected_non_reserved, - get_next_era_validators, - ); - // Check current validators. check_validators( &root_connection, From d02f8fded7afbb67aec83260acf4fd46786e7264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 12:34:41 +0200 Subject: [PATCH 16/42] Checkpoint --- .github/workflows/e2e-tests-main-devnet.yml | 16 +++++ e2e-tests/src/kick_out.rs | 2 +- e2e-tests/src/test/kick_out.rs | 74 +++++++++------------ 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/.github/workflows/e2e-tests-main-devnet.yml b/.github/workflows/e2e-tests-main-devnet.yml index aab7fbcf61..a33ce1b690 100644 --- a/.github/workflows/e2e-tests-main-devnet.yml +++ b/.github/workflows/e2e-tests-main-devnet.yml @@ -417,6 +417,21 @@ jobs: follow-up-finalization-check: true timeout-minutes: 15 + run-e2e-kick-out-manual: + needs: [build-test-docker, build-test-client] + name: Run kick out manual test + runs-on: ubuntu-20.04 + steps: + - name: Checkout source code + uses: actions/checkout@v2 + + - name: Run e2e test + uses: ./.github/actions/run-e2e-test + with: + test-case: kick_out_manual + follow-up-finalization-check: true + timeout-minutes: 15 + check-e2e-test-suite-completion: needs: [ run-e2e-finalization-test, @@ -438,6 +453,7 @@ jobs: run-e2e-rewards-points-basic, run-e2e-authorities-are-staking, run-e2e-kick-out-automatic, + run-e2e-kick-out-manual, ] name: Check e2e test suite completion runs-on: ubuntu-20.04 diff --git a/e2e-tests/src/kick_out.rs b/e2e-tests/src/kick_out.rs index 62d644298c..32b21ff91b 100644 --- a/e2e-tests/src/kick_out.rs +++ b/e2e-tests/src/kick_out.rs @@ -97,7 +97,7 @@ pub fn check_underperformed_validator_session_count( underperformed_validator_session_count } -pub fn check_underperformed_validator_reason( +pub fn check_kick_out_reason_for_validator( connection: &C, validator: &AccountId, expected_reason: Option<&KickOutReason>, diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 83ded4ac96..f8f725a4f8 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,7 +1,6 @@ use aleph_client::{ - get_current_era_validators, get_current_session, get_next_era_validators, - kick_out_from_committee, wait_for_at_least_session, SignedConnection, XtStatus, - get_current_era_validators, get_current_session, wait_for_at_least_session, SignedConnection, + get_current_era_validators, get_current_session, kick_out_from_committee, + wait_for_at_least_session, SignedConnection, XtStatus, }; use log::info; use primitives::{ @@ -12,9 +11,8 @@ use primitives::{ use crate::{ accounts::{get_validator_seed, NodeKeys}, kick_out::{ - check_committee_kick_out_config, check_kick_out_event, - check_underperformed_validator_reason, check_underperformed_validator_session_count, - check_validators, setup_test, + check_committee_kick_out_config, check_kick_out_event, check_kick_out_reason_for_validator, + check_underperformed_validator_session_count, check_validators, setup_test, }, rewards::set_invalid_keys_for_validator, Config, @@ -27,7 +25,6 @@ const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; const VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX: u32 = 1; -const VALIDATOR_TO_MANUALLY_KICK_OUT_OVERALL_INDEX: u32 = 3; const MANUAL_KICK_OUT_REASON: &str = "Manual kick out reason"; /// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the @@ -54,10 +51,11 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { let validator_to_disable = &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; + info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); - check_underperformed_validator_reason(&root_connection, validator_to_disable, None); + check_kick_out_reason_for_validator(&root_connection, validator_to_disable, None); let validator_seed = get_validator_seed(VALIDATOR_TO_DISABLE_OVERALL_INDEX); let stash_controller = NodeKeys::from(validator_seed); @@ -79,7 +77,7 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); let expected_kick_out_reason = KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); - check_underperformed_validator_reason( + check_kick_out_reason_for_validator( &root_connection, validator_to_disable, Some(&expected_kick_out_reason), @@ -100,11 +98,15 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { get_current_era_validators, ); - check_underperformed_validator_reason(&root_connection, validator_to_disable, None); + check_kick_out_reason_for_validator(&root_connection, validator_to_disable, None); Ok(()) } +/// Runs a chain, sets up a committee and validators. Manually kicks out one of the validators +/// from the committee. Waits for the offending validator to hit the kick-out threshold of sessions without +/// producing blocks. Verifies that the offending validator has in fact been kicked out for the +/// appropriate reason. pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; @@ -125,6 +127,7 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { let validator_to_manually_kick_out = &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; + info!(target: "aleph-client", "Validator to manually kick out: {}", validator_to_manually_kick_out); check_underperformed_validator_session_count( @@ -132,60 +135,40 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { validator_to_manually_kick_out, &0, ); - check_underperformed_validator_reason(&root_connection, validator_to_manually_kick_out, None); + check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); let manual_kick_out_reason = KickOutReason::OtherReason(reason); + info!("Before kick out"); kick_out_from_committee( &root_connection, validator_to_manually_kick_out, &manual_kick_out_reason, XtStatus::InBlock, ); + info!("After kick out"); - let current_session = get_current_session(&root_connection); - - wait_for_at_least_session( - &root_connection, - current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, - )?; - - check_underperformed_validator_session_count( - &root_connection, - validator_to_manually_kick_out, - &0, - ); - check_underperformed_validator_reason( + check_kick_out_reason_for_validator( &root_connection, validator_to_manually_kick_out, Some(&manual_kick_out_reason), ); - let expected_non_reserved: Vec<_> = non_reserved_validators - [..VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize] - .iter() - .chain( - non_reserved_validators - [(VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX + 1) as usize..] - .iter(), - ) - .collect(); - - // Check next era validators. - check_validators( - &root_connection, - &reserved_validators, - &expected_non_reserved, - get_next_era_validators, - ); - - let expected_kicked_out_validators = - vec![(validator_to_manually_kick_out.clone(), manual_kick_out_reason)]; + let expected_kicked_out_validators = vec![( + validator_to_manually_kick_out.clone(), + manual_kick_out_reason, + )]; check_kick_out_event(&root_connection, &expected_kicked_out_validators)?; + let expected_non_reserved: Vec<_> = non_reserved_validators + .clone() + .into_iter() + .filter(|account_id| account_id != validator_to_manually_kick_out) + .collect(); + // Check current validators. check_validators( &root_connection, @@ -193,5 +176,8 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { &expected_non_reserved, get_current_era_validators, ); + + check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); + Ok(()) } From 81cb920f784d3499812a93cec942651a62c24b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 12:42:50 +0200 Subject: [PATCH 17/42] Semver consistent versioning --- aleph-client/Cargo.lock | 2 +- aleph-client/Cargo.toml | 2 +- e2e-tests/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index 2bb0e93a5d..f617e7681d 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.9.0" +version = "1.10.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index f110b0db11..c8c3b33799 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph_client" -version = "1.9.1" +version = "1.10.0" edition = "2021" license = "Apache 2.0" diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml index 46f2604051..c2ce0a1a8a 100644 --- a/e2e-tests/Cargo.toml +++ b/e2e-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph-e2e-client" -version = "0.4.1" +version = "0.5.0" edition = "2021" license = "Apache 2.0" From ea4bcf8401c37b2d45ea8e4408d564c49274c5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 13:13:11 +0200 Subject: [PATCH 18/42] Removed superfluous function and imports --- aleph-client/Cargo.lock | 20 ++++++++++---------- aleph-client/src/elections.rs | 35 ++--------------------------------- aleph-client/src/lib.rs | 1 - e2e-tests/Cargo.lock | 34 +++++++++++++++++----------------- 4 files changed, 29 insertions(+), 61 deletions(-) diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index cae9c7a2c8..dc74ac7694 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -1393,7 +1393,7 @@ dependencies = [ "derive_more", "parity-scale-codec", "rand 0.8.5", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "sha2 0.10.6", "sha3", ] @@ -1419,7 +1419,7 @@ dependencies = [ "rand 0.8.5", "rlibc", "scale-info", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "sha2 0.10.6", "sha3", "static_assertions", @@ -1550,9 +1550,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.136" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55edcf6c0bb319052dea84732cf99db461780fd5e8d3eb46ab6ff312ab31f197" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libm" @@ -2305,9 +2305,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" @@ -2689,9 +2689,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7649a0b3ffb32636e60c7ce0d70511eda9c52c658cd0634e194d5a19943aeff" +checksum = "ff55dc09d460954e9ef2fa8a7ced735a964be9981fd50e870b2b3b0705e14964" dependencies = [ "secp256k1-sys 0.6.1", ] @@ -3042,7 +3042,7 @@ dependencies = [ "regex", "scale-info", "schnorrkel", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "secrecy", "serde", "sp-core-hashing 4.0.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", @@ -3194,7 +3194,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "sp-core 6.0.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", "sp-externalities 0.12.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", "sp-keystore 0.12.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 325aa23f8d..282ffde26b 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -2,13 +2,9 @@ use primitives::{ CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount, SessionIndex, }; -use sp_core::{Pair, H256}; -use substrate_api_client::{compose_call, compose_extrinsic, ExtrinsicParams}; +use sp_core::H256; -use crate::{ - get_session_first_block, send_xt, AccountId, AnyConnection, ReadStorage, RootConnection, - XtStatus, -}; +use crate::{get_session_first_block, AccountId, ReadStorage}; const PALLET: &str = "Elections"; @@ -94,30 +90,3 @@ pub fn get_kick_out_reason_for_validator( ) -> Option { connection.read_storage_map(PALLET, "ToBeKickedOutFromCommittee", account_id, None) } - -pub fn kick_out_from_committee( - connection: &RootConnection, - to_be_kicked_out: &AccountId, - reason: KickOutReason, - status: XtStatus, -) { - let call_name = "kick_out_from_committee"; - - let kick_out_from_committee_call = compose_call!( - connection.as_connection().metadata, - PALLET, - call_name, - to_be_kicked_out, - reason - ); - - let xt = compose_extrinsic!( - connection.as_connection(), - "Sudo", - "sudo_unchecked_weight", - kick_out_from_committee_call, - 0_u64 - ); - - send_xt(connection, xt, Some(call_name), status); -} diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index 869f8b684f..40ab6892a2 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -11,7 +11,6 @@ pub use elections::{ get_kick_out_reason_for_validator, 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, - kick_out_from_committee, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index 58e07e49e6..c63549b634 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph-e2e-client" -version = "0.4.1" +version = "0.5.0" dependencies = [ "aleph_client", "anyhow", @@ -121,7 +121,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.9.1" +version = "1.10.0" dependencies = [ "ac-node-api", "ac-primitives", @@ -427,9 +427,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.21" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed5341b2301a26ab80be5cbdced622e80ed808483c52e45e3310a877d3b37d7" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", "bitflags", @@ -1474,7 +1474,7 @@ dependencies = [ "derive_more", "parity-scale-codec", "rand 0.8.5", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "sha2 0.10.6", "sha3", ] @@ -1500,7 +1500,7 @@ dependencies = [ "rand 0.8.5", "rlibc", "scale-info", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "sha2 0.10.6", "sha3", "static_assertions", @@ -1631,9 +1631,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.135" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libm" @@ -2392,9 +2392,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" @@ -2800,9 +2800,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7649a0b3ffb32636e60c7ce0d70511eda9c52c658cd0634e194d5a19943aeff" +checksum = "ff55dc09d460954e9ef2fa8a7ced735a964be9981fd50e870b2b3b0705e14964" dependencies = [ "secp256k1-sys 0.6.1", ] @@ -3153,7 +3153,7 @@ dependencies = [ "regex", "scale-info", "schnorrkel", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "secrecy", "serde", "sp-core-hashing 4.0.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", @@ -3305,7 +3305,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot", - "secp256k1 0.24.0", + "secp256k1 0.24.1", "sp-core 6.0.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", "sp-externalities 0.12.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", "sp-keystore 0.12.0 (git+https://github.com/Cardinal-Cryptography/substrate.git?branch=aleph-v0.9.28)", @@ -3867,9 +3867,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" @@ -4062,7 +4062,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.5", "rand 0.8.5", "static_assertions", From 502bef5098d43f63b9629b299a9714dc94ed0d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 13:43:09 +0200 Subject: [PATCH 19/42] Checkpoint --- aleph-client/src/elections.rs | 6 +++++- aleph-client/src/lib.rs | 1 + e2e-tests/src/test/kick_out.rs | 5 ++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 684869f4ff..be0858378a 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -3,8 +3,12 @@ use primitives::{ SessionIndex, }; use sp_core::H256; +use substrate_api_client::{compose_call, compose_extrinsic}; -use crate::{get_session_first_block, AccountId, ReadStorage}; +use crate::{ + get_session_first_block, send_xt, AccountId, AnyConnection, ReadStorage, RootConnection, + XtStatus, +}; const PALLET: &str = "Elections"; diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index 40ab6892a2..869f8b684f 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -11,6 +11,7 @@ pub use elections::{ get_kick_out_reason_for_validator, 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, + kick_out_from_committee, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index f8f725a4f8..5819ca4dae 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -104,9 +104,8 @@ pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { } /// Runs a chain, sets up a committee and validators. Manually kicks out one of the validators -/// from the committee. Waits for the offending validator to hit the kick-out threshold of sessions without -/// producing blocks. Verifies that the offending validator has in fact been kicked out for the -/// appropriate reason. +/// from the committee with a specific reason. Verifies that validator marked for kick out has in +/// fact been kicked out for the given reason. pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; From 2e2244f3f69edebbb542f433e1ee9dc5556fa9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 22:47:01 +0200 Subject: [PATCH 20/42] Explicit params for bounded vec --- e2e-tests/src/test/kick_out.rs | 9 ++++++--- primitives/src/lib.rs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 5819ca4dae..5c7c8eb571 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -4,8 +4,9 @@ use aleph_client::{ }; use log::info; use primitives::{ - BoundedVec, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + BoundedVec, ConstU32, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_REASON_LENGTH, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, }; use crate::{ @@ -137,7 +138,9 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); - let reason = BoundedVec::try_from(manual_reason).expect("Incorrect manual kick out reason!"); + let reason = + BoundedVec::>::try_from(manual_reason) + .expect("Incorrect manual kick out reason!"); let manual_kick_out_reason = KickOutReason::OtherReason(reason); info!("Before kick out"); diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index e3c3892d7e..9d61ff2b3e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -245,4 +245,4 @@ pub mod staking { )* }; } -} +} \ No newline at end of file From 16a89e92417982246f4a376a1effff2614e0a775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 26 Oct 2022 23:09:52 +0200 Subject: [PATCH 21/42] Merge fixes --- aleph-client/src/elections.rs | 3 ++- e2e-tests/src/cases.rs | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 9d5f0878b9..be0858378a 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -7,7 +7,8 @@ use substrate_api_client::{compose_call, compose_extrinsic}; use crate::{ get_session_first_block, send_xt, AccountId, AnyConnection, ReadStorage, RootConnection, - XtStatus}; + XtStatus, +}; const PALLET: &str = "Elections"; diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 2399ada73a..787f8fdc7d 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -11,8 +11,6 @@ use crate::{ force_new_era as test_force_new_era, kick_out_automatic as test_kick_out_automatic, kick_out_manual as test_kick_out_manual, points_basic as test_points_basic, points_stake_change as test_points_stake_change, - 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, 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, From 8275e1be3ddd4669b8ab52532693c3a8640747b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Thu, 27 Oct 2022 15:04:54 +0200 Subject: [PATCH 22/42] Changed bounded vec creation --- e2e-tests/src/test/kick_out.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 07a126b5f8..3d82064b9b 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -4,9 +4,8 @@ use aleph_client::{ }; use log::info; use primitives::{ - BoundedVec, ConstU32, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_REASON_LENGTH, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + BoundedVec, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, }; use crate::{ @@ -143,9 +142,11 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); - let reason = - BoundedVec::>::try_from(manual_reason) - .expect("Incorrect manual kick out reason!"); + let reason: BoundedVec<_, _> = manual_reason + .try_into() + .expect("Incorrect manual kick out reason format!"); + info!("Reason: {:?}", reason); + info!("Reason len: {:?}", reason.len()); let manual_kick_out_reason = KickOutReason::OtherReason(reason); info!("Before kick out"); From 4107329cd7c9c3f1cef6c6650f7009a91737a08c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Thu, 27 Oct 2022 15:15:15 +0200 Subject: [PATCH 23/42] Linter, version --- aleph-client/Cargo.toml | 2 +- e2e-tests/Cargo.lock | 4 ++-- e2e-tests/Cargo.toml | 2 +- primitives/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index f3f0e8b9f6..7f71b82ebe 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph_client" -version = "1.10.0" +version = "1.11.0" edition = "2021" license = "Apache 2.0" diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index c63549b634..b7d7d8d828 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph-e2e-client" -version = "0.5.0" +version = "0.6.0" dependencies = [ "aleph_client", "anyhow", @@ -121,7 +121,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.10.0" +version = "1.11.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml index b42a4b1090..32429f8f96 100644 --- a/e2e-tests/Cargo.toml +++ b/e2e-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph-e2e-client" -version = "0.5.0" +version = "0.6.0" edition = "2021" license = "Apache 2.0" diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 9d61ff2b3e..e3c3892d7e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -245,4 +245,4 @@ pub mod staking { )* }; } -} \ No newline at end of file +} From 2739d036ef67f2f07e32d5eb500257bb322c597e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 28 Oct 2022 11:50:12 +0200 Subject: [PATCH 24/42] Fixed reason passed to extrinsic --- aleph-client/Cargo.lock | 2 +- aleph-client/src/elections.rs | 2 +- e2e-tests/src/test/kick_out.rs | 13 +++++-------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index dc74ac7694..e290c25710 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.10.0" +version = "1.11.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index be0858378a..ecfc2676a6 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -98,7 +98,7 @@ pub fn get_kick_out_reason_for_validator( pub fn kick_out_from_committee( connection: &RootConnection, to_be_kicked_out: &AccountId, - reason: &KickOutReason, + reason: &Vec, status: XtStatus, ) { let call_name = "kick_out_from_committee"; diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index 3d82064b9b..e28ee6eac5 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -141,22 +141,19 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { ); check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); - let manual_reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); - let reason: BoundedVec<_, _> = manual_reason + let reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); + let bounded_reason: BoundedVec<_, _> = reason + .clone() .try_into() .expect("Incorrect manual kick out reason format!"); - info!("Reason: {:?}", reason); - info!("Reason len: {:?}", reason.len()); - let manual_kick_out_reason = KickOutReason::OtherReason(reason); + let manual_kick_out_reason = KickOutReason::OtherReason(bounded_reason); - info!("Before kick out"); kick_out_from_committee( &root_connection, validator_to_manually_kick_out, - &manual_kick_out_reason, + &reason, XtStatus::InBlock, ); - info!("After kick out"); check_kick_out_reason_for_validator( &root_connection, From 08e183c0e142ca006535056d9a791cb6931e8390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 28 Oct 2022 13:56:35 +0200 Subject: [PATCH 25/42] Session count tracking --- aleph-client/src/elections.rs | 36 ++++++++++++++++++++-- aleph-client/src/lib.rs | 2 +- e2e-tests/src/cases.rs | 7 +++-- e2e-tests/src/test/kick_out.rs | 55 ++++++++++++++++++++++++++++++++-- e2e-tests/src/test/mod.rs | 2 +- 5 files changed, 92 insertions(+), 10 deletions(-) diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index ecfc2676a6..06778142d1 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -1,3 +1,4 @@ +use log::info; use primitives::{ CommitteeKickOutConfig, CommitteeSeats, EraValidators, KickOutReason, SessionCount, SessionIndex, @@ -101,9 +102,10 @@ pub fn kick_out_from_committee( reason: &Vec, status: XtStatus, ) { + info!(target: "aleph-client", "Validator being kicked out from committee: {}", to_be_kicked_out); let call_name = "kick_out_from_committee"; - let kick_out_from_committee_call = compose_call!( + let call = compose_call!( connection.as_connection().metadata, PALLET, call_name, @@ -115,7 +117,37 @@ pub fn kick_out_from_committee( connection.as_connection(), "Sudo", "sudo_unchecked_weight", - kick_out_from_committee_call, + call, + 0_u64 + ); + + send_xt(connection, xt, Some(call_name), status); +} + +pub fn set_kick_out_config( + connection: &RootConnection, + minimal_expected_performance: Option, + underperformed_session_count_threshold: Option, + clean_session_counter_delay: Option, + status: XtStatus, +) { + info!(target: "aleph-client", "Setting kick out config | min expected performance: {:#?} | session threshold: {:#?} | counter delay: {:#?}", minimal_expected_performance, underperformed_session_count_threshold, clean_session_counter_delay); + let call_name = "set_kick_out_config"; + + let call = compose_call!( + connection.as_connection().metadata, + PALLET, + call_name, + minimal_expected_performance, + underperformed_session_count_threshold, + clean_session_counter_delay + ); + + let xt = compose_extrinsic!( + connection.as_connection(), + "Sudo", + "sudo_unchecked_weight", + call, 0_u64 ); diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index 32500c66e9..87a0981b97 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -11,7 +11,7 @@ pub use elections::{ get_kick_out_reason_for_validator, 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, - kick_out_from_committee, + kick_out_from_committee, set_kick_out_config, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 787f8fdc7d..196af132d2 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -9,8 +9,8 @@ use crate::{ 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, - kick_out_manual as test_kick_out_manual, points_basic as test_points_basic, - points_stake_change as test_points_stake_change, + kick_out_manual as test_kick_out_manual, kick_out_threshold as test_kick_out_threshold, + 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, @@ -27,7 +27,7 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ - ("kick_out_manual", test_kick_out_manual as TestCase), + ("kick_out_threshold", test_kick_out_threshold as TestCase), ("finalization", test_finalization as TestCase), ("version_upgrade", test_schedule_version_change), ("rewards_disable_node", test_disable_node as TestCase), @@ -60,5 +60,6 @@ pub fn possible_test_cases() -> PossibleTestCases { test_authorities_are_staking as TestCase, ), ("kick_out_automatic", test_kick_out_automatic as TestCase), + ("kick_out_manual", test_kick_out_manual as TestCase), ] } diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs index e28ee6eac5..e2d5aeba23 100644 --- a/e2e-tests/src/test/kick_out.rs +++ b/e2e-tests/src/test/kick_out.rs @@ -1,5 +1,5 @@ use aleph_client::{ - get_current_era_validators, get_current_session, kick_out_from_committee, + get_current_era_validators, get_current_session, kick_out_from_committee, set_kick_out_config, wait_for_at_least_session, SignedConnection, XtStatus, }; use log::info; @@ -27,6 +27,8 @@ const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; const VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX: u32 = 1; const MANUAL_KICK_OUT_REASON: &str = "Manual kick out reason"; +const MIN_EXPECTED_PERFORMANCE: u8 = 100; + /// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the /// validators. Waits for the offending validator to hit the kick-out threshold of sessions without /// producing blocks. Verifies that the offending validator has in fact been kicked out for the @@ -132,8 +134,6 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { let validator_to_manually_kick_out = &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; - info!(target: "aleph-client", "Validator to manually kick out: {}", validator_to_manually_kick_out); - check_underperformed_validator_session_count( &root_connection, validator_to_manually_kick_out, @@ -186,3 +186,52 @@ pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { Ok(()) } + +pub fn kick_out_threshold(config: &Config) -> anyhow::Result<()> { + let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + + // Check current era validators. + check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators, + get_current_era_validators, + ); + + check_committee_kick_out_config( + &root_connection, + DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, + DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + ); + + set_kick_out_config( + &root_connection, + Some(MIN_EXPECTED_PERFORMANCE), + None, + None, + XtStatus::InBlock, + ); + + let current_session = get_current_session(&root_connection); + + wait_for_at_least_session(&root_connection, current_session + 1)?; + + let validators: Vec<_> = reserved_validators + .iter() + .chain(non_reserved_validators.iter()) + .collect(); + + let check_start_session = get_current_session(&root_connection); + + for session in check_start_session..check_start_session + 5 { + wait_for_at_least_session(&root_connection, session)?; + let expected_session_count = session - check_start_session + 1; + validators.iter().for_each(|&val| { + info!(target: "aleph-client", "Checking session count | session {} | validator {}", session, val); + check_underperformed_validator_session_count(&root_connection, val, &expected_session_count); + }); + } + + Ok(()) +} diff --git a/e2e-tests/src/test/mod.rs b/e2e-tests/src/test/mod.rs index 20cb3e9383..7e68c38f77 100644 --- a/e2e-tests/src/test/mod.rs +++ b/e2e-tests/src/test/mod.rs @@ -3,7 +3,7 @@ pub use era_payout::era_payouts_calculated_correctly; pub use era_validators::era_validators; pub use fee::fee_calculation; pub use finalization::finalization; -pub use kick_out::{kick_out_automatic, kick_out_manual}; +pub use kick_out::{kick_out_automatic, kick_out_manual, kick_out_threshold}; pub use rewards::{ change_stake_and_force_new_era, disable_node, force_new_era, points_basic, points_stake_change, }; From f0397738e8650153b9166c20baecba3973400c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 12:30:26 +0100 Subject: [PATCH 26/42] Welcome to the ban world! --- aleph-client/src/elections.rs | 36 +---- aleph-client/src/lib.rs | 3 +- e2e-tests/src/ban.rs | 6 +- e2e-tests/src/cases.rs | 9 +- e2e-tests/src/test/ban.rs | 58 +++++++- e2e-tests/src/test/kick_out.rs | 237 --------------------------------- e2e-tests/src/test/mod.rs | 2 +- 7 files changed, 67 insertions(+), 284 deletions(-) delete mode 100644 e2e-tests/src/test/kick_out.rs diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 80e2403360..5af1e0091c 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -1,11 +1,9 @@ use log::info; - -use sp_core::H256; -use substrate_api_client::{compose_call, compose_extrinsic, XtStatus}; - use primitives::{ BanConfig, BanInfo, CommitteeSeats, EraIndex, EraValidators, SessionCount, SessionIndex, }; +use sp_core::H256; +use substrate_api_client::{compose_call, compose_extrinsic}; use crate::{ get_session_first_block, send_xt, AccountId, AnyConnection, ReadStorage, RootConnection, @@ -90,7 +88,7 @@ pub fn get_underperformed_validator_session_count( .unwrap_or(0) } -pub fn get_ban_reason_for_validator( +pub fn get_ban_info_for_validator( connection: &C, account_id: &AccountId, ) -> Option { @@ -128,31 +126,3 @@ pub fn change_ban_config( send_xt(sudo_connection, xt, Some(call_name), status); } - -pub fn ban_from_committee( - connection: &RootConnection, - banned: &AccountId, - reason: &Vec, - status: XtStatus, -) { - info!(target: "aleph-client", "Validator being banned from committee: {}", banned); - let call_name = "ban_from_committee"; - - let call = compose_call!( - connection.as_connection().metadata, - PALLET, - call_name, - banned, - reason - ); - - let xt = compose_extrinsic!( - connection.as_connection(), - "Sudo", - "sudo_unchecked_weight", - call, - 0_u64 - ); - - send_xt(connection, xt, Some(call_name), status); -} diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index 10d48fa115..fd53ddd47f 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -6,12 +6,11 @@ pub use balances::total_issuance; use codec::{Decode, Encode}; pub use debug::print_storages; pub use elections::{ - change_ban_config, get_ban_config, get_ban_reason_for_validator, get_committee_seats, + change_ban_config, get_ban_config, get_ban_info_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, - kick_out_from_committee, set_kick_out_config, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index eac29c3bb1..44e95d991e 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -1,5 +1,5 @@ use aleph_client::{ - change_validators, get_ban_config, get_ban_reason_for_validator, + change_validators, get_ban_config, get_ban_info_for_validator, get_underperformed_validator_session_count, wait_for_event, wait_for_full_era_completion, AccountId, AnyConnection, RootConnection, XtStatus, }; @@ -95,12 +95,12 @@ pub fn check_underperformed_validator_session_count( underperformed_validator_session_count } -pub fn check_kick_out_reason_for_validator( +pub fn check_ban_info_for_validator( connection: &C, validator: &AccountId, expected_info: Option<&BanInfo>, ) -> Option { - let validator_ban_info = get_ban_reason_for_validator(connection, validator); + let validator_ban_info = get_ban_info_for_validator(connection, validator); assert_eq!(validator_ban_info.as_ref(), expected_info); diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 24bb26c8df..a8e74ea406 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -2,7 +2,8 @@ use crate::{ config::Config, test::{ authorities_are_staking as test_authorities_are_staking, - ban_automatic as test_ban_automatic, batch_transactions as test_batch_transactions, + ban_automatic as test_ban_automatic, ban_threshold as test_ban_threshold, + 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, @@ -11,7 +12,6 @@ use crate::{ fee_calculation as test_fee_calculation, finalization as test_finalization, force_new_era as test_force_new_era, points_basic as test_points_basic, points_stake_change as test_points_stake_change, - 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, @@ -28,7 +28,7 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ - ("ban_threshold", test_kick_out_threshold as TestCase), + ("ban_threshold", test_ban_threshold as TestCase), ("finalization", test_finalization as TestCase), ("version_upgrade", test_schedule_version_change), ("rewards_disable_node", test_disable_node as TestCase), @@ -60,11 +60,10 @@ pub fn possible_test_cases() -> PossibleTestCases { "authorities_are_staking", test_authorities_are_staking as TestCase, ), + ("ban_automatic", test_ban_automatic as TestCase), ( "clearing_session_count", test_clearing_session_count as TestCase, ), - ("ban_automatic", test_ban_automatic as TestCase), - ("ban_manual", test_kick_out_manual as TestCase), ] } diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index 698ed08d20..d9c0f7c4b1 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -13,7 +13,7 @@ use primitives::{ use crate::{ accounts::{get_validator_seed, NodeKeys}, ban::{ - check_ban_config, check_ban_event, check_underperformed_validator_reason, + check_ban_config, check_ban_event, check_ban_info_for_validator, check_underperformed_validator_session_count, check_validators, setup_test, }, rewards::set_invalid_keys_for_validator, @@ -26,6 +26,8 @@ const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; const SESSIONS_TO_MEET_BAN_THRESHOLD: SessionCount = 4; +const MIN_EXPECTED_PERFORMANCE: u8 = 100; + fn disable_validator(validator_address: &str, validator_seed: u32) -> anyhow::Result<()> { let validator_seed = get_validator_seed(validator_seed); let stash_controller = NodeKeys::from(validator_seed); @@ -65,7 +67,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); - check_underperformed_validator_reason(&root_connection, validator_to_disable, None); + check_ban_info_for_validator(&root_connection, validator_to_disable, None); disable_validator(NODE_TO_DISABLE_ADDRESS, VALIDATOR_TO_DISABLE_OVERALL_INDEX)?; @@ -84,7 +86,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { let start = get_current_era(&root_connection) + 1; let expected_ban_info = BanInfo { reason, start }; - check_underperformed_validator_reason( + check_ban_info_for_validator( &root_connection, validator_to_disable, Some(&expected_ban_info), @@ -148,3 +150,53 @@ pub fn clearing_session_count(config: &Config) -> anyhow::Result<()> { Ok(()) } + +pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { + let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + + // Check current era validators. + check_validators( + &root_connection, + &reserved_validators, + &non_reserved_validators, + get_current_era_validators, + ); + + check_ban_config( + &root_connection, + DEFAULT_BAN_MINIMAL_EXPECTED_PERFORMANCE, + DEFAULT_BAN_SESSION_COUNT_THRESHOLD, + DEFAULT_CLEAN_SESSION_COUNTER_DELAY, + ); + + change_ban_config( + &root_connection, + Some(MIN_EXPECTED_PERFORMANCE), + None, + None, + None, + XtStatus::InBlock, + ); + + let current_session = get_current_session(&root_connection); + + wait_for_at_least_session(&root_connection, current_session + 1)?; + + let validators: Vec<_> = reserved_validators + .iter() + .chain(non_reserved_validators.iter()) + .collect(); + + let check_start_session = get_current_session(&root_connection); + + for session in check_start_session..check_start_session + 5 { + wait_for_at_least_session(&root_connection, session)?; + let expected_session_count = session - check_start_session + 1; + validators.iter().for_each(|&val| { + info!(target: "aleph-client", "Checking session count | session {} | validator {}", session, val); + check_underperformed_validator_session_count(&root_connection, val, &expected_session_count); + }); + } + + Ok(()) +} diff --git a/e2e-tests/src/test/kick_out.rs b/e2e-tests/src/test/kick_out.rs deleted file mode 100644 index e2d5aeba23..0000000000 --- a/e2e-tests/src/test/kick_out.rs +++ /dev/null @@ -1,237 +0,0 @@ -use aleph_client::{ - get_current_era_validators, get_current_session, kick_out_from_committee, set_kick_out_config, - wait_for_at_least_session, SignedConnection, XtStatus, -}; -use log::info; -use primitives::{ - BoundedVec, KickOutReason, SessionCount, DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, -}; - -use crate::{ - accounts::{get_validator_seed, NodeKeys}, - kick_out::{ - check_committee_kick_out_config, check_kick_out_event, check_kick_out_reason_for_validator, - check_underperformed_validator_session_count, check_validators, setup_test, - }, - rewards::set_invalid_keys_for_validator, - Config, -}; - -const VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX: u32 = 0; -const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; -// Address for //2 (Node2). Depends on the infrastructure setup. -const NODE_TO_DISABLE_ADDRESS: &str = "127.0.0.1:9945"; -const SESSIONS_TO_MEET_KICK_OUT_THRESHOLD: SessionCount = 4; - -const VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX: u32 = 1; -const MANUAL_KICK_OUT_REASON: &str = "Manual kick out reason"; - -const MIN_EXPECTED_PERFORMANCE: u8 = 100; - -/// Runs a chain, sets up a committee and validators. Sets an incorrect key for one of the -/// validators. Waits for the offending validator to hit the kick-out threshold of sessions without -/// producing blocks. Verifies that the offending validator has in fact been kicked out for the -/// appropriate reason. -pub fn kick_out_automatic(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; - - // Check current era validators. - check_validators( - &root_connection, - &reserved_validators, - &non_reserved_validators, - get_current_era_validators, - ); - - check_committee_kick_out_config( - &root_connection, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, - DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - ); - - let validator_to_disable = - &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; - - info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); - - check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); - check_kick_out_reason_for_validator(&root_connection, validator_to_disable, None); - - let validator_seed = get_validator_seed(VALIDATOR_TO_DISABLE_OVERALL_INDEX); - let stash_controller = NodeKeys::from(validator_seed); - let controller_key_to_disable = stash_controller.controller; - - // This connection has to be set up with the controller key. - let connection_to_disable = - SignedConnection::new(NODE_TO_DISABLE_ADDRESS, controller_key_to_disable); - - set_invalid_keys_for_validator(&connection_to_disable)?; - - let current_session = get_current_session(&root_connection); - - wait_for_at_least_session( - &root_connection, - current_session + SESSIONS_TO_MEET_KICK_OUT_THRESHOLD, - )?; - - // The session count for underperforming validators is reset to 0 immediately on reaching the - // threshold. - check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); - - let expected_kick_out_reason = - KickOutReason::InsufficientUptime(DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD); - - check_kick_out_reason_for_validator( - &root_connection, - validator_to_disable, - Some(&expected_kick_out_reason), - ); - - let expected_non_reserved = - &non_reserved_validators[(VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX + 1) as usize..]; - - let expected_kicked_out_validators = - vec![(validator_to_disable.clone(), expected_kick_out_reason)]; - - check_kick_out_event(&root_connection, &expected_kicked_out_validators)?; - - // Check current validators. - check_validators( - &root_connection, - &reserved_validators, - expected_non_reserved, - get_current_era_validators, - ); - - check_kick_out_reason_for_validator(&root_connection, validator_to_disable, None); - - Ok(()) -} - -/// Runs a chain, sets up a committee and validators. Manually kicks out one of the validators -/// from the committee with a specific reason. Verifies that validator marked for kick out has in -/// fact been kicked out for the given reason. -pub fn kick_out_manual(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; - - // Check current era validators. - check_validators( - &root_connection, - &reserved_validators, - &non_reserved_validators, - get_current_era_validators, - ); - - check_committee_kick_out_config( - &root_connection, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, - DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - ); - - let validator_to_manually_kick_out = - &non_reserved_validators[VALIDATOR_TO_MANUALLY_KICK_OUT_NON_RESERVED_INDEX as usize]; - - check_underperformed_validator_session_count( - &root_connection, - validator_to_manually_kick_out, - &0, - ); - check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); - - let reason = MANUAL_KICK_OUT_REASON.as_bytes().to_vec(); - let bounded_reason: BoundedVec<_, _> = reason - .clone() - .try_into() - .expect("Incorrect manual kick out reason format!"); - let manual_kick_out_reason = KickOutReason::OtherReason(bounded_reason); - - kick_out_from_committee( - &root_connection, - validator_to_manually_kick_out, - &reason, - XtStatus::InBlock, - ); - - check_kick_out_reason_for_validator( - &root_connection, - validator_to_manually_kick_out, - Some(&manual_kick_out_reason), - ); - - let expected_kicked_out_validators = vec![( - validator_to_manually_kick_out.clone(), - manual_kick_out_reason, - )]; - - check_kick_out_event(&root_connection, &expected_kicked_out_validators)?; - - let expected_non_reserved: Vec<_> = non_reserved_validators - .clone() - .into_iter() - .filter(|account_id| account_id != validator_to_manually_kick_out) - .collect(); - - // Check current validators. - check_validators( - &root_connection, - &reserved_validators, - &expected_non_reserved, - get_current_era_validators, - ); - - check_kick_out_reason_for_validator(&root_connection, validator_to_manually_kick_out, None); - - Ok(()) -} - -pub fn kick_out_threshold(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; - - // Check current era validators. - check_validators( - &root_connection, - &reserved_validators, - &non_reserved_validators, - get_current_era_validators, - ); - - check_committee_kick_out_config( - &root_connection, - DEFAULT_KICK_OUT_MINIMAL_EXPECTED_PERFORMANCE, - DEFAULT_KICK_OUT_SESSION_COUNT_THRESHOLD, - DEFAULT_CLEAN_SESSION_COUNTER_DELAY, - ); - - set_kick_out_config( - &root_connection, - Some(MIN_EXPECTED_PERFORMANCE), - None, - None, - XtStatus::InBlock, - ); - - let current_session = get_current_session(&root_connection); - - wait_for_at_least_session(&root_connection, current_session + 1)?; - - let validators: Vec<_> = reserved_validators - .iter() - .chain(non_reserved_validators.iter()) - .collect(); - - let check_start_session = get_current_session(&root_connection); - - for session in check_start_session..check_start_session + 5 { - wait_for_at_least_session(&root_connection, session)?; - let expected_session_count = session - check_start_session + 1; - validators.iter().for_each(|&val| { - info!(target: "aleph-client", "Checking session count | session {} | validator {}", session, val); - check_underperformed_validator_session_count(&root_connection, val, &expected_session_count); - }); - } - - Ok(()) -} diff --git a/e2e-tests/src/test/mod.rs b/e2e-tests/src/test/mod.rs index 3af19b1ba7..4eff344cf7 100644 --- a/e2e-tests/src/test/mod.rs +++ b/e2e-tests/src/test/mod.rs @@ -1,4 +1,4 @@ -pub use ban::{ban_automatic, ban_manual, clearing_session_count, ban_threshold}; +pub use ban::{ban_automatic, ban_threshold, clearing_session_count}; pub use electing_validators::authorities_are_staking; pub use era_payout::era_payouts_calculated_correctly; pub use era_validators::era_validators; From d1541a2adacd3d629a84dd268c39a587a1d921d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 12:36:44 +0100 Subject: [PATCH 27/42] GH workflow --- .github/workflows/e2e-tests-main-devnet.yml | 14 +++++++------- e2e-tests/src/test/ban.rs | 16 +++++++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/e2e-tests-main-devnet.yml b/.github/workflows/e2e-tests-main-devnet.yml index 51460f5c8b..fc2ae128c3 100644 --- a/.github/workflows/e2e-tests-main-devnet.yml +++ b/.github/workflows/e2e-tests-main-devnet.yml @@ -417,9 +417,9 @@ jobs: follow-up-finalization-check: true timeout-minutes: 15 - run-e2e-ban-manual: + run-e2e-ban-counter-clearing: needs: [build-test-docker, build-test-client] - name: Run ban manual test + name: Run ban counter clearing test runs-on: ubuntu-20.04 steps: - name: Checkout source code @@ -428,13 +428,13 @@ jobs: - name: Run e2e test uses: ./.github/actions/run-e2e-test with: - test-case: ban_manual + test-case: clearing_session_count follow-up-finalization-check: true timeout-minutes: 15 - run-e2e-ban-counter-clearing: + run-e2e-ban-threshold: needs: [build-test-docker, build-test-client] - name: Run ban counter clearing test + name: Run ban threshold test runs-on: ubuntu-20.04 steps: - name: Checkout source code @@ -443,7 +443,7 @@ jobs: - name: Run e2e test uses: ./.github/actions/run-e2e-test with: - test-case: clearing_session_count + test-case: ban_threshold follow-up-finalization-check: true timeout-minutes: 15 @@ -486,8 +486,8 @@ jobs: run-e2e-rewards-points-basic, run-e2e-authorities-are-staking, run-e2e-ban-automatic, - run-e2e-ban-manual, run-e2e-ban-counter-clearing, + run-e2e-ban-threshold, run-e2e-version-upgrade, ] name: Check e2e test suite completion diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index d9c0f7c4b1..aca98cc30a 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -64,7 +64,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { let validator_to_disable = &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; - info!(target: "aleph-client", "Validator to disable: {}", validator_to_disable); + info!("Validator to disable: {}", validator_to_disable); check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); check_ban_info_for_validator(&root_connection, validator_to_disable, None); @@ -116,7 +116,6 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { pub fn clearing_session_count(config: &Config) -> anyhow::Result<()> { let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; - info!(target: "aleph-client", "changing ban config"); change_ban_config( &root_connection, None, @@ -130,7 +129,7 @@ pub fn clearing_session_count(config: &Config) -> anyhow::Result<()> { &non_reserved_validators[VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX as usize]; disable_validator(NODE_TO_DISABLE_ADDRESS, VALIDATOR_TO_DISABLE_OVERALL_INDEX)?; - info!(target: "aleph-client", "Disabling validator {}", validator_to_disable); + info!("Disabling validator {}", validator_to_disable); let current_session = get_current_session(&root_connection); wait_for_at_least_session(&root_connection, current_session + 5)?; @@ -193,8 +192,15 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { wait_for_at_least_session(&root_connection, session)?; let expected_session_count = session - check_start_session + 1; validators.iter().for_each(|&val| { - info!(target: "aleph-client", "Checking session count | session {} | validator {}", session, val); - check_underperformed_validator_session_count(&root_connection, val, &expected_session_count); + info!( + "Checking session count | session {} | validator {}", + session, val + ); + check_underperformed_validator_session_count( + &root_connection, + val, + &expected_session_count, + ); }); } From 9f35a41aedd23f378c3dcef47122601692473be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 21:28:55 +0100 Subject: [PATCH 28/42] Changed params to refs; cases reorder --- e2e-tests/src/ban.rs | 87 +++++++++++++++++++++++++++++++++++---- e2e-tests/src/cases.rs | 2 +- e2e-tests/src/test/ban.rs | 43 +++++++++---------- 3 files changed, 98 insertions(+), 34 deletions(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 44e95d991e..3e2ab34c1f 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -1,18 +1,31 @@ +use std::collections::HashMap; + use aleph_client::{ change_validators, get_ban_config, get_ban_info_for_validator, - get_underperformed_validator_session_count, wait_for_event, wait_for_full_era_completion, - AccountId, AnyConnection, RootConnection, XtStatus, + get_underperformed_validator_session_count, wait_for_at_least_session, wait_for_event, + wait_for_full_era_completion, AccountId, AnyConnection, RootConnection, XtStatus, }; use codec::Decode; use log::info; -use primitives::{BanConfig, BanInfo, CommitteeSeats, EraValidators, SessionCount}; +use primitives::{BanConfig, BanInfo, CommitteeSeats, EraValidators, SessionCount, SessionIndex}; use sp_runtime::Perbill; -use crate::{accounts::account_ids_from_keys, validators::get_test_validators, Config}; +use crate::{ + accounts::account_ids_from_keys, elections::get_members_subset_for_session, + validators::get_test_validators, Config, +}; + +const RESERVED_SEATS: u32 = 2; +const NON_RESERVED_SEATS: u32 = 2; + +type BanTestSetup = ( + RootConnection, + Vec, + Vec, + CommitteeSeats, +); -pub fn setup_test( - config: &Config, -) -> anyhow::Result<(RootConnection, Vec, Vec)> { +pub fn setup_test(config: &Config) -> anyhow::Result { let root_connection = config.create_root_connection(); let validator_keys = get_test_validators(config); @@ -20,8 +33,8 @@ pub fn setup_test( let non_reserved_validators = account_ids_from_keys(&validator_keys.non_reserved); let seats = CommitteeSeats { - reserved_seats: 2, - non_reserved_seats: 2, + reserved_seats: RESERVED_SEATS, + non_reserved_seats: NON_RESERVED_SEATS, }; change_validators( @@ -38,6 +51,7 @@ pub fn setup_test( root_connection, reserved_validators, non_reserved_validators, + seats, )) } @@ -124,3 +138,58 @@ pub fn check_ban_event( Ok(event) } + +pub fn check_session_count( + connection: &C, + seats: &CommitteeSeats, + reserved_validators: &[AccountId], + non_reserved_validators: &[AccountId], + start_session: &SessionIndex, + sessions_to_check: &SessionCount, + ban_session_threshold: &SessionCount, +) -> anyhow::Result<()> { + let validators: Vec<_> = reserved_validators + .iter() + .chain(non_reserved_validators.iter()) + .collect(); + + let mut expected_validator_session_count = HashMap::new(); + + for session in *start_session..*start_session + *sessions_to_check { + wait_for_at_least_session(connection, session)?; + + let reserved_members_for_session = + get_members_subset_for_session(seats.reserved_seats, reserved_validators, session - 1); + let non_reserved_members_for_session = get_members_subset_for_session( + seats.non_reserved_seats, + non_reserved_validators, + session - 1, + ); + let members_for_session: Vec<_> = reserved_members_for_session + .iter() + .chain(non_reserved_members_for_session.iter()) + .collect(); + + validators.iter().for_each(|&val| { + info!( + "Checking session count | session {} | validator {}", + session - 1, + val + ); + let session_count = expected_validator_session_count.entry(val).or_insert(0); + + if members_for_session.contains(&val) { + *session_count += 1; + *session_count %= ban_session_threshold; + } + + let expected_session_count = expected_validator_session_count.get(&val).expect( + &format!("Missing expected session count for validator {}", val), + ); + + check_underperformed_validator_session_count(connection, val, &expected_session_count); + }); + } + + Ok(()) +} diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index a8e74ea406..024ffe4223 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -28,7 +28,6 @@ pub type PossibleTestCases = Vec<(&'static str, TestCase)>; /// This comes up in local tests. pub fn possible_test_cases() -> PossibleTestCases { vec![ - ("ban_threshold", test_ban_threshold as TestCase), ("finalization", test_finalization as TestCase), ("version_upgrade", test_schedule_version_change), ("rewards_disable_node", test_disable_node as TestCase), @@ -65,5 +64,6 @@ pub fn possible_test_cases() -> PossibleTestCases { "clearing_session_count", test_clearing_session_count as TestCase, ), + ("ban_threshold", test_ban_threshold as TestCase), ] } diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index aca98cc30a..a713c30397 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -13,13 +13,15 @@ use primitives::{ use crate::{ accounts::{get_validator_seed, NodeKeys}, ban::{ - check_ban_config, check_ban_event, check_ban_info_for_validator, + check_ban_config, check_ban_event, check_ban_info_for_validator, check_session_count, check_underperformed_validator_session_count, check_validators, setup_test, }, rewards::set_invalid_keys_for_validator, Config, }; +const SESSIONS_TO_CHECK: SessionCount = 5; + const VALIDATOR_TO_DISABLE_NON_RESERVED_INDEX: u32 = 0; const VALIDATOR_TO_DISABLE_OVERALL_INDEX: u32 = 2; // Address for //2 (Node2). Depends on the infrastructure setup. @@ -44,7 +46,7 @@ fn disable_validator(validator_address: &str, validator_seed: u32) -> anyhow::Re /// producing blocks. Verifies that the offending validator has in fact been banned out for the /// appropriate reason. pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + let (root_connection, reserved_validators, non_reserved_validators, _) = setup_test(config)?; // Check current era validators. check_validators( @@ -114,7 +116,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { /// Disable one non_reserved validator. Check if the disabled validator is still in the committee /// and his underperformed session count is less or equal to 2. pub fn clearing_session_count(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + let (root_connection, reserved_validators, non_reserved_validators, _) = setup_test(config)?; change_ban_config( &root_connection, @@ -150,8 +152,12 @@ pub fn clearing_session_count(config: &Config) -> anyhow::Result<()> { Ok(()) } +/// Runs a chain, sets up a committee and validators. Changes the ban config to require 100% +/// performance. Checks that each validator has all the sessions in which they were chosen for the +/// committee marked as ones in which they underperformed. pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + let (root_connection, reserved_validators, non_reserved_validators, seats) = + setup_test(config)?; // Check current era validators. check_validators( @@ -181,28 +187,17 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { wait_for_at_least_session(&root_connection, current_session + 1)?; - let validators: Vec<_> = reserved_validators - .iter() - .chain(non_reserved_validators.iter()) - .collect(); - let check_start_session = get_current_session(&root_connection); - for session in check_start_session..check_start_session + 5 { - wait_for_at_least_session(&root_connection, session)?; - let expected_session_count = session - check_start_session + 1; - validators.iter().for_each(|&val| { - info!( - "Checking session count | session {} | validator {}", - session, val - ); - check_underperformed_validator_session_count( - &root_connection, - val, - &expected_session_count, - ); - }); - } + check_session_count( + &root_connection, + &seats, + &reserved_validators, + &non_reserved_validators, + &check_start_session, + &SESSIONS_TO_CHECK, + &DEFAULT_BAN_SESSION_COUNT_THRESHOLD, + )?; Ok(()) } From 8bcc43a9aa39d3ffd12129d5c96d418ed67f63f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 21:39:51 +0100 Subject: [PATCH 29/42] Housekeeping --- aleph-client/src/lib.rs | 12 ++++++------ e2e-tests/src/cases.rs | 4 ++-- e2e-tests/src/test/ban.rs | 2 +- e2e-tests/src/test/mod.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/aleph-client/src/lib.rs b/aleph-client/src/lib.rs index 4edaa8aa4b..27403626e5 100644 --- a/aleph-client/src/lib.rs +++ b/aleph-client/src/lib.rs @@ -6,12 +6,12 @@ pub use balances::total_issuance; use codec::{Decode, Encode}; pub use debug::print_storages; pub use elections::{ - change_ban_config, get_ban_config, get_ban_info_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, - ban_from_committee, get_ban_reason_for_validator, + ban_from_committee, change_ban_config, get_ban_config, get_ban_info_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, }; pub use fee::get_next_fee_multiplier; pub use finalization::set_emergency_finalizer as finalization_set_emergency_finalizer; diff --git a/e2e-tests/src/cases.rs b/e2e-tests/src/cases.rs index 4f24096f0e..571f326ebf 100644 --- a/e2e-tests/src/cases.rs +++ b/e2e-tests/src/cases.rs @@ -2,8 +2,8 @@ use crate::{ config::Config, test::{ authorities_are_staking as test_authorities_are_staking, - ban_automatic as test_ban_automatic, ban_manual as test_ban_manual, ban_threshold as test_ban_threshold, - batch_transactions as test_batch_transactions, + ban_automatic as test_ban_automatic, ban_manual as test_ban_manual, + ban_threshold as test_ban_threshold, 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, diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index ca4325ee06..350d1a6c9f 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -118,7 +118,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { /// from the committee with a specific reason. Verifies that validator marked for ban has in /// fact been banned for the given reason. pub fn ban_manual(config: &Config) -> anyhow::Result<()> { - let (root_connection, reserved_validators, non_reserved_validators) = setup_test(config)?; + let (root_connection, reserved_validators, non_reserved_validators, _) = setup_test(config)?; // Check current era validators. check_validators( diff --git a/e2e-tests/src/test/mod.rs b/e2e-tests/src/test/mod.rs index 3af19b1ba7..ad1ba2923d 100644 --- a/e2e-tests/src/test/mod.rs +++ b/e2e-tests/src/test/mod.rs @@ -1,4 +1,4 @@ -pub use ban::{ban_automatic, ban_manual, clearing_session_count, ban_threshold}; +pub use ban::{ban_automatic, ban_manual, ban_threshold, clearing_session_count}; pub use electing_validators::authorities_are_staking; pub use era_payout::era_payouts_calculated_correctly; pub use era_validators::era_validators; From d792c3ad1c28871dac6373a237b66c9aff59b383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 21:41:40 +0100 Subject: [PATCH 30/42] Version bumps --- aleph-client/Cargo.toml | 2 +- e2e-tests/Cargo.lock | 4 ++-- e2e-tests/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index 7f71b82ebe..9439f1960a 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph_client" -version = "1.11.0" +version = "1.12.0" edition = "2021" license = "Apache 2.0" diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index a5f686c588..e2cb7f60ad 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph-e2e-client" -version = "0.7.0" +version = "0.8.0" dependencies = [ "aleph_client", "anyhow", @@ -121,7 +121,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml index 0a14771af6..64e3bb1d6d 100644 --- a/e2e-tests/Cargo.toml +++ b/e2e-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph-e2e-client" -version = "0.7.0" +version = "0.8.0" edition = "2021" license = "Apache 2.0" From c98e3069debfe296f4b3180c62bae1c4747176be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 21:54:21 +0100 Subject: [PATCH 31/42] Changed option unwrapping --- e2e-tests/src/ban.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 3e2ab34c1f..e9e2f8f083 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -183,9 +183,9 @@ pub fn check_session_count( *session_count %= ban_session_threshold; } - let expected_session_count = expected_validator_session_count.get(&val).expect( - &format!("Missing expected session count for validator {}", val), - ); + let expected_session_count = expected_validator_session_count + .get(&val) + .unwrap_or_else(|| panic!("Missing expected session count for validator {}", val)); check_underperformed_validator_session_count(connection, val, &expected_session_count); }); From c857d6f2ca6e19c48a6fce3184873aafb38686b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Wed, 2 Nov 2022 22:01:55 +0100 Subject: [PATCH 32/42] Removed needless borrow --- aleph-client/Cargo.lock | 2 +- e2e-tests/src/ban.rs | 2 +- flooder/Cargo.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index e290c25710..b1d80b1dd6 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index e9e2f8f083..9b22407c4b 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -187,7 +187,7 @@ pub fn check_session_count( .get(&val) .unwrap_or_else(|| panic!("Missing expected session count for validator {}", val)); - check_underperformed_validator_session_count(connection, val, &expected_session_count); + check_underperformed_validator_session_count(connection, val, expected_session_count); }); } diff --git a/flooder/Cargo.lock b/flooder/Cargo.lock index 39ec0dda25..d71dccc95b 100644 --- a/flooder/Cargo.lock +++ b/flooder/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ac-node-api", "ac-primitives", From 71e731dfdb8ffe71b69397a3352d3e5c2d8bc4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Thu, 3 Nov 2022 09:26:30 +0100 Subject: [PATCH 33/42] Added ban event call --- pallets/elections/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pallets/elections/src/lib.rs b/pallets/elections/src/lib.rs index a8b96b8f82..b9dadb3521 100644 --- a/pallets/elections/src/lib.rs +++ b/pallets/elections/src/lib.rs @@ -539,6 +539,8 @@ pub mod pallet { } } + Self::emit_fresh_bans_event(); + Ok(supports.into_iter().collect()) } } From d7cc2700e042bcb8eb0c2c461f6ba4cafe941b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Thu, 3 Nov 2022 09:29:00 +0100 Subject: [PATCH 34/42] Removed borrows --- e2e-tests/src/ban.rs | 8 ++++---- e2e-tests/src/test/ban.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 9b22407c4b..498b23a492 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -144,9 +144,9 @@ pub fn check_session_count( seats: &CommitteeSeats, reserved_validators: &[AccountId], non_reserved_validators: &[AccountId], - start_session: &SessionIndex, - sessions_to_check: &SessionCount, - ban_session_threshold: &SessionCount, + start_session: SessionIndex, + sessions_to_check: SessionCount, + ban_session_threshold: SessionCount, ) -> anyhow::Result<()> { let validators: Vec<_> = reserved_validators .iter() @@ -155,7 +155,7 @@ pub fn check_session_count( let mut expected_validator_session_count = HashMap::new(); - for session in *start_session..*start_session + *sessions_to_check { + for session in start_session..start_session + sessions_to_check { wait_for_at_least_session(connection, session)?; let reserved_members_for_session = diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index 350d1a6c9f..6d7c7833bd 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -269,9 +269,9 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { &seats, &reserved_validators, &non_reserved_validators, - &check_start_session, - &SESSIONS_TO_CHECK, - &DEFAULT_BAN_SESSION_COUNT_THRESHOLD, + check_start_session, + SESSIONS_TO_CHECK, + DEFAULT_BAN_SESSION_COUNT_THRESHOLD, )?; Ok(()) From 95075824c3449230cea7dad46a7e7f8b8e615565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Thu, 3 Nov 2022 09:56:53 +0100 Subject: [PATCH 35/42] Removed ban event call from initial place --- pallets/elections/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pallets/elections/src/lib.rs b/pallets/elections/src/lib.rs index b9dadb3521..902a4b62f4 100644 --- a/pallets/elections/src/lib.rs +++ b/pallets/elections/src/lib.rs @@ -472,7 +472,6 @@ pub mod pallet { /// 1) "`NextEraNonReservedValidators` that are staking and are not banned" in case of Permissioned ElectionOpenness /// 2) "All staking and not banned validators" in case of Permissionless ElectionOpenness fn elect() -> Result, Self::Error> { - Self::emit_fresh_bans_event(); let active_era = ::EraInfoProvider::active_era().unwrap_or(0); let ban_period = BanConfig::::get().ban_period; From d4296ae10af17a0e4c99bfedd5c833bf3ec783c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Thu, 3 Nov 2022 21:38:35 +0100 Subject: [PATCH 36/42] Changed test logic to post factum --- aleph-client/src/elections.rs | 3 +- benches/payout-stakers/Cargo.lock | 2 +- bin/cliain/Cargo.lock | 2 +- e2e-tests/src/ban.rs | 68 ++++++++++++++++++++----------- e2e-tests/src/test/ban.rs | 29 +++++++------ 5 files changed, 66 insertions(+), 38 deletions(-) diff --git a/aleph-client/src/elections.rs b/aleph-client/src/elections.rs index 391076a7b1..1a98a9cca9 100644 --- a/aleph-client/src/elections.rs +++ b/aleph-client/src/elections.rs @@ -77,13 +77,14 @@ pub fn get_ban_config(connection: &C) -> BanConfig { pub fn get_underperformed_validator_session_count( connection: &C, account_id: &AccountId, + block_hash: Option, ) -> SessionCount { connection .read_storage_map( PALLET, "UnderperformedValidatorSessionCount", account_id, - None, + block_hash, ) .unwrap_or(0) } diff --git a/benches/payout-stakers/Cargo.lock b/benches/payout-stakers/Cargo.lock index 8d216c22b4..6f5ea1f226 100644 --- a/benches/payout-stakers/Cargo.lock +++ b/benches/payout-stakers/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/bin/cliain/Cargo.lock b/bin/cliain/Cargo.lock index a32dca162d..9b6ec5cad9 100644 --- a/bin/cliain/Cargo.lock +++ b/bin/cliain/Cargo.lock @@ -98,7 +98,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ac-node-api", "ac-primitives", diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 498b23a492..06bc2eab12 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -1,13 +1,12 @@ -use std::collections::HashMap; - use aleph_client::{ - change_validators, get_ban_config, get_ban_info_for_validator, - get_underperformed_validator_session_count, wait_for_at_least_session, wait_for_event, + change_validators, get_ban_config, get_ban_info_for_validator, get_block_hash, + get_session_period, 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::{BanConfig, BanInfo, CommitteeSeats, EraValidators, SessionCount, SessionIndex}; +use sp_core::H256; use sp_runtime::Perbill; use crate::{ @@ -97,9 +96,10 @@ pub fn check_underperformed_validator_session_count( connection: &C, validator: &AccountId, expected_session_count: &SessionCount, + block_hash: Option, ) -> SessionCount { let underperformed_validator_session_count = - get_underperformed_validator_session_count(connection, validator); + get_underperformed_validator_session_count(connection, validator, block_hash); assert_eq!( &underperformed_validator_session_count, @@ -139,31 +139,36 @@ pub fn check_ban_event( Ok(event) } -pub fn check_session_count( +pub fn check_underperformed_count_for_sessions( connection: &C, seats: &CommitteeSeats, reserved_validators: &[AccountId], non_reserved_validators: &[AccountId], start_session: SessionIndex, - sessions_to_check: SessionCount, + end_session: SessionIndex, ban_session_threshold: SessionCount, ) -> anyhow::Result<()> { + let session_period = get_session_period(connection); + let validators: Vec<_> = reserved_validators .iter() .chain(non_reserved_validators.iter()) .collect(); - let mut expected_validator_session_count = HashMap::new(); + for session in start_session..end_session { + let session_start_block = session * session_period; + let session_start_block_hash = get_block_hash(connection, session_start_block); - for session in start_session..start_session + sessions_to_check { - wait_for_at_least_session(connection, session)?; + let previous_session_start_block = session_start_block - session_period; + let previous_session_start_block_hash = + get_block_hash(connection, previous_session_start_block); let reserved_members_for_session = - get_members_subset_for_session(seats.reserved_seats, reserved_validators, session - 1); + get_members_subset_for_session(seats.reserved_seats, reserved_validators, session); let non_reserved_members_for_session = get_members_subset_for_session( seats.non_reserved_seats, non_reserved_validators, - session - 1, + session, ); let members_for_session: Vec<_> = reserved_members_for_session .iter() @@ -173,21 +178,38 @@ pub fn check_session_count( validators.iter().for_each(|&val| { info!( "Checking session count | session {} | validator {}", - session - 1, - val + session, val + ); + let session_underperformed_count = get_underperformed_validator_session_count( + connection, + val, + Some(session_start_block_hash), + ); + let previous_session_underperformed_count = get_underperformed_validator_session_count( + connection, + val, + Some(previous_session_start_block_hash), ); - let session_count = expected_validator_session_count.entry(val).or_insert(0); + + let underperformed_diff = + session_underperformed_count - previous_session_underperformed_count; if members_for_session.contains(&val) { - *session_count += 1; - *session_count %= ban_session_threshold; + // Counter for committee members legally incremented by 1 or reset to 0 (decremented + // by ban_session_threshold - 1). + if underperformed_diff != 1 && underperformed_diff != (ban_session_threshold - 1) { + panic!( + "Underperformed session count for committee validator {} changed from {} to {}.", + val, session_underperformed_count, previous_session_underperformed_count + ); + } + } else if underperformed_diff != 0 { + // Counter for validators on the bench should stay the same. + panic!( + "Underperformed session count for non-committee validator {} changed from {} to {}.", + val, session_underperformed_count, previous_session_underperformed_count + ); } - - let expected_session_count = expected_validator_session_count - .get(&val) - .unwrap_or_else(|| panic!("Missing expected session count for validator {}", val)); - - check_underperformed_validator_session_count(connection, val, expected_session_count); }); } diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index 6d7c7833bd..21ae3a9f6e 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -13,8 +13,9 @@ use primitives::{ use crate::{ accounts::{get_validator_seed, NodeKeys}, ban::{ - check_ban_config, check_ban_event, check_ban_info_for_validator, check_session_count, - check_underperformed_validator_session_count, check_validators, setup_test, + check_ban_config, check_ban_event, check_ban_info_for_validator, + check_underperformed_count_for_sessions, check_underperformed_validator_session_count, + check_validators, setup_test, }, rewards::set_invalid_keys_for_validator, Config, @@ -71,7 +72,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { info!("Validator to disable: {}", validator_to_disable); - check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); + check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0, None); check_ban_info_for_validator(&root_connection, validator_to_disable, None); disable_validator(NODE_TO_DISABLE_ADDRESS, VALIDATOR_TO_DISABLE_OVERALL_INDEX)?; @@ -85,7 +86,7 @@ pub fn ban_automatic(config: &Config) -> anyhow::Result<()> { // The session count for underperforming validators is reset to 0 immediately on reaching the // threshold. - check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0); + check_underperformed_validator_session_count(&root_connection, validator_to_disable, &0, None); let reason = BanReason::InsufficientUptime(DEFAULT_BAN_SESSION_COUNT_THRESHOLD); let start = get_current_era(&root_connection) + 1; @@ -140,7 +141,12 @@ pub fn ban_manual(config: &Config) -> anyhow::Result<()> { info!("Validator to manually ban: {}", validator_to_manually_ban); - check_underperformed_validator_session_count(&root_connection, validator_to_manually_ban, &0); + check_underperformed_validator_session_count( + &root_connection, + validator_to_manually_ban, + &0, + None, + ); check_ban_info_for_validator(&root_connection, validator_to_manually_ban, None); let bounded_reason: BoundedVec<_, _> = MANUAL_BAN_REASON @@ -212,7 +218,7 @@ pub fn clearing_session_count(config: &Config) -> anyhow::Result<()> { wait_for_at_least_session(&root_connection, current_session + 5)?; let underperformed_validator_session_count = - get_underperformed_validator_session_count(&root_connection, validator_to_disable); + get_underperformed_validator_session_count(&root_connection, validator_to_disable, None); // it only has to be ge than 0 and should be cleared before reaching values larger than 3. assert!(underperformed_validator_session_count <= 2); @@ -258,19 +264,18 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { XtStatus::InBlock, ); - let current_session = get_current_session(&root_connection); - - wait_for_at_least_session(&root_connection, current_session + 1)?; - let check_start_session = get_current_session(&root_connection); + let check_end_session = check_start_session + SESSIONS_TO_CHECK; + + wait_for_at_least_session(&root_connection, check_end_session + 1)?; - check_session_count( + check_underperformed_count_for_sessions( &root_connection, &seats, &reserved_validators, &non_reserved_validators, check_start_session, - SESSIONS_TO_CHECK, + check_end_session, DEFAULT_BAN_SESSION_COUNT_THRESHOLD, )?; From 2202e1af2b84205fd7520ccb3bcb99430bac817d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 4 Nov 2022 09:24:01 +0100 Subject: [PATCH 37/42] Changed logic to test only sessions after ban config change comes in --- e2e-tests/src/ban.rs | 3 +++ e2e-tests/src/test/ban.rs | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 06bc2eab12..35635c8a90 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -139,6 +139,9 @@ pub fn check_ban_event( Ok(event) } +/// Checks whether underperformed counts for validators change predictably. Assumes: (a) that the +/// sessions checked are in the past, (b) that all the checked validators are underperforming in +/// those sessions (e.g. due to a prohibitively high performance threshold). pub fn check_underperformed_count_for_sessions( connection: &C, seats: &CommitteeSeats, diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index 21ae3a9f6e..b4907ad054 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -255,6 +255,7 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { DEFAULT_CLEAN_SESSION_COUNTER_DELAY, ); + // Change ban config to require prohibitively high performance from all validators. change_ban_config( &root_connection, Some(MIN_EXPECTED_PERFORMANCE), @@ -264,9 +265,11 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { XtStatus::InBlock, ); - let check_start_session = get_current_session(&root_connection); + let ban_config_change_session = get_current_session(&root_connection); + let check_start_session = ban_config_change_session + 1; let check_end_session = check_start_session + SESSIONS_TO_CHECK; + // Wait until all the sessions to be checked are in the past. wait_for_at_least_session(&root_connection, check_end_session + 1)?; check_underperformed_count_for_sessions( From 49cae48dd5cd85cc42790beda8cb21ac40f1f604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 4 Nov 2022 12:42:53 +0100 Subject: [PATCH 38/42] Test logic fix --- e2e-tests/src/ban.rs | 60 ++++++++++++++++++++++++--------------- e2e-tests/src/test/ban.rs | 4 +-- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 35635c8a90..0073a1f271 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -139,14 +139,30 @@ pub fn check_ban_event( Ok(event) } +pub fn get_members_for_session( + reserved_validators: &[AccountId], + non_reserved_validators: &[AccountId], + seats: &CommitteeSeats, + session: SessionIndex, +) -> Vec { + let reserved_members = + get_members_subset_for_session(seats.reserved_seats, reserved_validators, session); + let non_reserved_members = + get_members_subset_for_session(seats.non_reserved_seats, non_reserved_validators, session); + reserved_members + .into_iter() + .chain(non_reserved_members.into_iter()) + .collect() +} + /// Checks whether underperformed counts for validators change predictably. Assumes: (a) that the /// sessions checked are in the past, (b) that all the checked validators are underperforming in /// those sessions (e.g. due to a prohibitively high performance threshold). pub fn check_underperformed_count_for_sessions( connection: &C, - seats: &CommitteeSeats, reserved_validators: &[AccountId], non_reserved_validators: &[AccountId], + seats: &CommitteeSeats, start_session: SessionIndex, end_session: SessionIndex, ban_session_threshold: SessionCount, @@ -159,24 +175,21 @@ pub fn check_underperformed_count_for_sessions( .collect(); for session in start_session..end_session { - let session_start_block = session * session_period; - let session_start_block_hash = get_block_hash(connection, session_start_block); + let session_end_block = (session + 1) * session_period; + let session_end_block_hash = get_block_hash(connection, session_end_block); - let previous_session_start_block = session_start_block - session_period; - let previous_session_start_block_hash = - get_block_hash(connection, previous_session_start_block); + let previous_session_end_block = session_end_block - session_period; + let previous_session_end_block_hash = + get_block_hash(connection, previous_session_end_block); - let reserved_members_for_session = - get_members_subset_for_session(seats.reserved_seats, reserved_validators, session); - let non_reserved_members_for_session = get_members_subset_for_session( - seats.non_reserved_seats, + let members = + get_members_for_session(reserved_validators, non_reserved_validators, seats, session); + let members_previous_session = get_members_for_session( + reserved_validators, non_reserved_validators, - session, + seats, + session - 1, ); - let members_for_session: Vec<_> = reserved_members_for_session - .iter() - .chain(non_reserved_members_for_session.iter()) - .collect(); validators.iter().for_each(|&val| { info!( @@ -186,31 +199,32 @@ pub fn check_underperformed_count_for_sessions( let session_underperformed_count = get_underperformed_validator_session_count( connection, val, - Some(session_start_block_hash), + Some(session_end_block_hash), ); let previous_session_underperformed_count = get_underperformed_validator_session_count( connection, val, - Some(previous_session_start_block_hash), + Some(previous_session_end_block_hash), ); let underperformed_diff = session_underperformed_count - previous_session_underperformed_count; - - if members_for_session.contains(&val) { + info!("Underperformed diff: {}", underperformed_diff); + + if members.contains(&val) { // Counter for committee members legally incremented by 1 or reset to 0 (decremented // by ban_session_threshold - 1). if underperformed_diff != 1 && underperformed_diff != (ban_session_threshold - 1) { panic!( - "Underperformed session count for committee validator {} changed from {} to {}.", - val, session_underperformed_count, previous_session_underperformed_count + "Underperformed session count for committee validator {} for session {} changed from {} to {}.", + val, session, previous_session_underperformed_count, session_underperformed_count ); } } else if underperformed_diff != 0 { // Counter for validators on the bench should stay the same. panic!( - "Underperformed session count for non-committee validator {} changed from {} to {}.", - val, session_underperformed_count, previous_session_underperformed_count + "Underperformed session count for non-committee validator {} for session {} changed from {} to {}.", + val, session, previous_session_underperformed_count, session_underperformed_count ); } }); diff --git a/e2e-tests/src/test/ban.rs b/e2e-tests/src/test/ban.rs index b4907ad054..ea206ca7a8 100644 --- a/e2e-tests/src/test/ban.rs +++ b/e2e-tests/src/test/ban.rs @@ -267,16 +267,16 @@ pub fn ban_threshold(config: &Config) -> anyhow::Result<()> { let ban_config_change_session = get_current_session(&root_connection); let check_start_session = ban_config_change_session + 1; - let check_end_session = check_start_session + SESSIONS_TO_CHECK; + let check_end_session = check_start_session + SESSIONS_TO_CHECK - 1; // Wait until all the sessions to be checked are in the past. wait_for_at_least_session(&root_connection, check_end_session + 1)?; check_underperformed_count_for_sessions( &root_connection, - &seats, &reserved_validators, &non_reserved_validators, + &seats, check_start_session, check_end_session, DEFAULT_BAN_SESSION_COUNT_THRESHOLD, From a900ff3de3a3c1060313b22b77334c937ca775d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 4 Nov 2022 13:21:10 +0100 Subject: [PATCH 39/42] Typo fix in rewards test --- e2e-tests/src/ban.rs | 11 ++--------- e2e-tests/src/rewards.rs | 10 +++++----- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 0073a1f271..9b6144d5e3 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -184,12 +184,6 @@ pub fn check_underperformed_count_for_sessions( let members = get_members_for_session(reserved_validators, non_reserved_validators, seats, session); - let members_previous_session = get_members_for_session( - reserved_validators, - non_reserved_validators, - seats, - session - 1, - ); validators.iter().for_each(|&val| { info!( @@ -208,9 +202,8 @@ pub fn check_underperformed_count_for_sessions( ); let underperformed_diff = - session_underperformed_count - previous_session_underperformed_count; - info!("Underperformed diff: {}", underperformed_diff); - + session_underperformed_count.abs_diff(previous_session_underperformed_count); + if members.contains(&val) { // Counter for committee members legally incremented by 1 or reset to 0 (decremented // by ban_session_threshold - 1). diff --git a/e2e-tests/src/rewards.rs b/e2e-tests/src/rewards.rs index 132175b169..ea87a52ced 100644 --- a/e2e-tests/src/rewards.rs +++ b/e2e-tests/src/rewards.rs @@ -163,12 +163,12 @@ pub fn check_points( info!("Era: {} | session: {}.", era, session); - let beggining_of_session_block = session * session_period; - let end_of_session_block = beggining_of_session_block + session_period; + let beginning_of_session_block = session * session_period; + let end_of_session_block = beginning_of_session_block + session_period; info!("Waiting for block: {}.", end_of_session_block); wait_for_finalized_block(connection, end_of_session_block)?; - let beggining_of_session_block_hash = get_block_hash(connection, beggining_of_session_block); + let beginning_of_session_block_hash = get_block_hash(connection, beginning_of_session_block); let end_of_session_block_hash = get_block_hash(connection, end_of_session_block); let before_end_of_session_block_hash = get_block_hash(connection, end_of_session_block - 1); info!("End-of-session block hash: {}.", end_of_session_block_hash); @@ -188,7 +188,7 @@ pub fn check_points( .individual; let validator_reward_points_previous_session = - get_era_reward_points(connection, era, Some(beggining_of_session_block_hash)) + get_era_reward_points(connection, era, Some(beginning_of_session_block_hash)) .unwrap_or_default() .individual; @@ -229,7 +229,7 @@ pub fn check_points( let members_count = reward_points.len() as f64; for (account_id, reward_points) in reward_points.iter_mut() { let exposure = - download_exposure(connection, era, account_id, beggining_of_session_block_hash); + download_exposure(connection, era, account_id, beginning_of_session_block_hash); *reward_points *= exposure as f64 / members_count; } From 7454ce2e17913a6addc3600cb5e019f7b32648f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 4 Nov 2022 13:28:45 +0100 Subject: [PATCH 40/42] Removed unnecessary reference --- e2e-tests/src/ban.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/src/ban.rs b/e2e-tests/src/ban.rs index 9b6144d5e3..227a252e53 100644 --- a/e2e-tests/src/ban.rs +++ b/e2e-tests/src/ban.rs @@ -204,7 +204,7 @@ pub fn check_underperformed_count_for_sessions( let underperformed_diff = session_underperformed_count.abs_diff(previous_session_underperformed_count); - if members.contains(&val) { + if members.contains(val) { // Counter for committee members legally incremented by 1 or reset to 0 (decremented // by ban_session_threshold - 1). if underperformed_diff != 1 && underperformed_diff != (ban_session_threshold - 1) { From 86cad43f7c72a5d9efdfba7408105f76299c5216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Fri, 4 Nov 2022 14:18:00 +0100 Subject: [PATCH 41/42] Rolled back pallet change --- pallets/elections/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pallets/elections/src/lib.rs b/pallets/elections/src/lib.rs index 902a4b62f4..a8b96b8f82 100644 --- a/pallets/elections/src/lib.rs +++ b/pallets/elections/src/lib.rs @@ -472,6 +472,7 @@ pub mod pallet { /// 1) "`NextEraNonReservedValidators` that are staking and are not banned" in case of Permissioned ElectionOpenness /// 2) "All staking and not banned validators" in case of Permissionless ElectionOpenness fn elect() -> Result, Self::Error> { + Self::emit_fresh_bans_event(); let active_era = ::EraInfoProvider::active_era().unwrap_or(0); let ban_period = BanConfig::::get().ban_period; @@ -538,8 +539,6 @@ pub mod pallet { } } - Self::emit_fresh_bans_event(); - Ok(supports.into_iter().collect()) } } From 53343d52bbb9769e1bfb52f78f48c44b42641265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBelaszczyk?= Date: Tue, 8 Nov 2022 13:51:00 +0100 Subject: [PATCH 42/42] aleph-client version bump --- aleph-client/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index 9439f1960a..b066ee4c15 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aleph_client" -version = "1.12.0" +version = "1.13.0" edition = "2021" license = "Apache 2.0"