diff --git a/substrate-node/pallets/substrate-validator-set/src/benchmarking.rs b/substrate-node/pallets/substrate-validator-set/src/benchmarking.rs index 8ef18905a..8b8014466 100644 --- a/substrate-node/pallets/substrate-validator-set/src/benchmarking.rs +++ b/substrate-node/pallets/substrate-validator-set/src/benchmarking.rs @@ -1,7 +1,7 @@ #![cfg(feature = "runtime-benchmarks")] -use super::*; use crate::Pallet as ValidatorSet; +use crate::{Call, Config, Event, Pallet}; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::assert_ok; use frame_system::{EventRecord, Pallet as System, RawOrigin}; diff --git a/substrate-node/pallets/substrate-validator-set/src/lib.rs b/substrate-node/pallets/substrate-validator-set/src/lib.rs index 2c5258d35..73547359d 100644 --- a/substrate-node/pallets/substrate-validator-set/src/lib.rs +++ b/substrate-node/pallets/substrate-validator-set/src/lib.rs @@ -13,23 +13,14 @@ #![cfg_attr(not(feature = "std"), no_std)] -use frame_support::{ - ensure, - pallet_prelude::*, - traits::{EstimateNextSessionRotation, Get, ValidatorSet, ValidatorSetWithIdentification}, -}; -use log; pub use pallet::*; -use sp_runtime::traits::{Convert, Zero}; -use sp_staking::offence::{Offence, OffenceError, ReportOffence}; -use sp_std::convert::TryInto; -use sp_std::{collections::btree_set::BTreeSet, prelude::*}; mod mock; mod tests; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; +mod validator_set; pub mod weights; @@ -39,7 +30,17 @@ pub const LOG_TARGET: &'static str = "runtime::validator-set"; pub mod pallet { use super::weights::WeightInfo; use super::*; + use frame_support::{ + ensure, + pallet_prelude::*, + traits::{EstimateNextSessionRotation, Get, ValidatorSet, ValidatorSetWithIdentification}, + }; use frame_system::pallet_prelude::*; + use log; + use sp_runtime::traits::{Convert, Zero}; + use sp_staking::offence::{Offence, OffenceError, ReportOffence}; + use sp_std::convert::TryInto; + use sp_std::{collections::btree_set::BTreeSet, prelude::*}; /// Configure the pallet by specifying the parameters and types on which it /// depends. @@ -182,185 +183,93 @@ pub mod pallet { Ok(()) } } -} - -impl Pallet { - fn initialize_validators(validators: &[T::AccountId]) { - assert!( - validators.len() as u32 >= T::MinAuthorities::get(), - "Initial set of validators must be at least T::MinAuthorities" - ); - assert!( - >::get().is_empty(), - "Validators are already initialized!" - ); - - >::put(validators); - >::put(validators); - } - - fn do_add_validator(validator_id: T::AccountId) -> DispatchResult { - let validator_set: BTreeSet<_> = >::get().into_iter().collect(); - ensure!( - !validator_set.contains(&validator_id), - Error::::Duplicate - ); - >::mutate(|v| v.push(validator_id.clone())); - - Self::deposit_event(Event::ValidatorAdditionInitiated(validator_id.clone())); - log::debug!(target: LOG_TARGET, "Validator addition initiated."); - - Ok(()) - } - - fn do_remove_validator(validator_id: T::AccountId) -> DispatchResult { - let mut validators = >::get(); - - // Ensuring that the post removal, target validator count doesn't go - // below the minimum. - ensure!( - validators.len().saturating_sub(1) as u32 >= T::MinAuthorities::get(), - Error::::TooLowValidatorCount - ); - - validators.retain(|v| *v != validator_id); - - >::put(validators); - Self::deposit_event(Event::ValidatorRemovalInitiated(validator_id.clone())); - log::debug!(target: LOG_TARGET, "Validator removal initiated."); - - Ok(()) - } - - fn approve_validator(validator_id: T::AccountId) -> DispatchResult { - let approved_set: BTreeSet<_> = >::get().into_iter().collect(); - ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); - >::mutate(|v| v.push(validator_id.clone())); - Ok(()) - } - - fn unapprove_validator(validator_id: T::AccountId) -> DispatchResult { - let mut approved_set = >::get(); - approved_set.retain(|v| *v != validator_id); - Ok(()) - } + // Provides the new set of validators to the session module when session is + // being rotated. + impl pallet_session::SessionManager for Pallet { + // Plan a new session and provide new validator set. + fn new_session(_new_index: u32) -> Option> { + // Remove any offline validators. This will only work when the runtime + // also has the im-online pallet. + Self::remove_offline_validators(); + + log::debug!( + target: LOG_TARGET, + "New session called; updated validator set provided." + ); - // Adds offline validators to a local cache for removal at new session. - fn mark_for_removal(validator_id: T::AccountId) { - >::mutate(|v| v.push(validator_id)); - log::debug!( - target: LOG_TARGET, - "Offline validator marked for auto removal." - ); - } + Some(Self::validators()) + } - // Removes offline validators from the validator set and clears the offline - // cache. It is called in the session change hook and removes the validators - // who were reported offline during the session that is ending. We do not - // check for `MinAuthorities` here, because the offline validators will not - // produce blocks and will have the same overall effect on the runtime. - fn remove_offline_validators() { - let validators_to_remove: BTreeSet<_> = >::get().into_iter().collect(); - - // Delete from active validator set. - >::mutate(|vs| vs.retain(|v| !validators_to_remove.contains(v))); - log::debug!( - target: LOG_TARGET, - "Initiated removal of {:?} offline validators.", - validators_to_remove.len() - ); - - // Clear the offline validator list to avoid repeated deletion. - >::put(Vec::::new()); - } -} + fn end_session(_end_index: u32) {} -// Provides the new set of validators to the session module when session is -// being rotated. -impl pallet_session::SessionManager for Pallet { - // Plan a new session and provide new validator set. - fn new_session(_new_index: u32) -> Option> { - // Remove any offline validators. This will only work when the runtime - // also has the im-online pallet. - Self::remove_offline_validators(); - - log::debug!( - target: LOG_TARGET, - "New session called; updated validator set provided." - ); - - Some(Self::validators()) + fn start_session(_start_index: u32) {} } - fn end_session(_end_index: u32) {} + impl EstimateNextSessionRotation for Pallet { + fn average_session_length() -> T::BlockNumber { + Zero::zero() + } - fn start_session(_start_index: u32) {} -} + fn estimate_current_session_progress( + _now: T::BlockNumber, + ) -> (Option, frame_support::dispatch::Weight) { + (None, Zero::zero()) + } -impl EstimateNextSessionRotation for Pallet { - fn average_session_length() -> T::BlockNumber { - Zero::zero() + fn estimate_next_session_rotation( + _now: T::BlockNumber, + ) -> (Option, frame_support::dispatch::Weight) { + (None, Zero::zero()) + } } - fn estimate_current_session_progress( - _now: T::BlockNumber, - ) -> (Option, frame_support::dispatch::Weight) { - (None, Zero::zero()) - } + // Implementation of Convert trait for mapping ValidatorId with AccountId. + pub struct ValidatorOf(sp_std::marker::PhantomData); - fn estimate_next_session_rotation( - _now: T::BlockNumber, - ) -> (Option, frame_support::dispatch::Weight) { - (None, Zero::zero()) + impl Convert> for ValidatorOf { + fn convert(account: T::ValidatorId) -> Option { + Some(account) + } } -} - -// Implementation of Convert trait for mapping ValidatorId with AccountId. -pub struct ValidatorOf(sp_std::marker::PhantomData); -impl Convert> for ValidatorOf { - fn convert(account: T::ValidatorId) -> Option { - Some(account) - } -} + impl ValidatorSet for Pallet { + type ValidatorId = T::ValidatorId; + type ValidatorIdOf = T::ValidatorIdOf; -impl ValidatorSet for Pallet { - type ValidatorId = T::ValidatorId; - type ValidatorIdOf = T::ValidatorIdOf; + fn session_index() -> sp_staking::SessionIndex { + pallet_session::Pallet::::current_index() + } - fn session_index() -> sp_staking::SessionIndex { - pallet_session::Pallet::::current_index() + fn validators() -> Vec { + pallet_session::Pallet::::validators() + } } - fn validators() -> Vec { - pallet_session::Pallet::::validators() + impl ValidatorSetWithIdentification for Pallet { + type Identification = T::ValidatorId; + type IdentificationOf = ValidatorOf; } -} -impl ValidatorSetWithIdentification for Pallet { - type Identification = T::ValidatorId; - type IdentificationOf = ValidatorOf; -} + // Offence reporting and unresponsiveness management. + impl> + ReportOffence for Pallet + { + fn report_offence(_reporters: Vec, offence: O) -> Result<(), OffenceError> { + let offenders = offence.offenders(); -// Offence reporting and unresponsiveness management. -impl> - ReportOffence for Pallet -{ - fn report_offence(_reporters: Vec, offence: O) -> Result<(), OffenceError> { - let offenders = offence.offenders(); + for (v, _) in offenders.into_iter() { + Self::mark_for_removal(v); + } - for (v, _) in offenders.into_iter() { - Self::mark_for_removal(v); + Ok(()) } - Ok(()) - } - - fn is_known_offence( - _offenders: &[(T::AccountId, T::AccountId)], - _time_slot: &O::TimeSlot, - ) -> bool { - false + fn is_known_offence( + _offenders: &[(T::AccountId, T::AccountId)], + _time_slot: &O::TimeSlot, + ) -> bool { + false + } } -} \ No newline at end of file +} diff --git a/substrate-node/pallets/substrate-validator-set/src/mock.rs b/substrate-node/pallets/substrate-validator-set/src/mock.rs index c1b460bc2..59baa0ea3 100644 --- a/substrate-node/pallets/substrate-validator-set/src/mock.rs +++ b/substrate-node/pallets/substrate-validator-set/src/mock.rs @@ -2,11 +2,11 @@ #![cfg(test)] -use super::*; use crate as validator_set; use frame_support::{parameter_types, traits::ConstU32, traits::GenesisBuild, BasicExternalities}; use frame_system::EnsureRoot; use pallet_session::*; +use parity_scale_codec::{Decode, Encode}; use sp_core::{crypto::key_types::DUMMY, H256}; use sp_runtime::{ impl_opaque_keys, @@ -16,7 +16,6 @@ use sp_runtime::{ }; use sp_std::convert::{TryFrom, TryInto}; use std::cell::RefCell; -use parity_scale_codec::{Decode, Encode}; impl_opaque_keys! { pub struct MockSessionKeys { diff --git a/substrate-node/pallets/substrate-validator-set/src/tests.rs b/substrate-node/pallets/substrate-validator-set/src/tests.rs index d5eb37188..d138abd1d 100644 --- a/substrate-node/pallets/substrate-validator-set/src/tests.rs +++ b/substrate-node/pallets/substrate-validator-set/src/tests.rs @@ -2,12 +2,13 @@ #![cfg(test)] -use super::*; use crate::mock::*; use crate::mock::{authorities, new_test_ext, Session, TestRuntime, ValidatorSet}; +use crate::Error; use frame_support::{assert_noop, assert_ok}; use frame_system::RawOrigin; use sp_runtime::testing::UintAuthorityId; +use sp_runtime::DispatchError; #[test] fn simple_setup_should_work() { diff --git a/substrate-node/pallets/substrate-validator-set/src/validator_set.rs b/substrate-node/pallets/substrate-validator-set/src/validator_set.rs new file mode 100644 index 000000000..d101a4710 --- /dev/null +++ b/substrate-node/pallets/substrate-validator-set/src/validator_set.rs @@ -0,0 +1,102 @@ +use crate::pallet::{Error, Event}; +use crate::ApprovedValidators; +use crate::Config; +use crate::Pallet; +use crate::Validators; +use crate::{OfflineValidators, LOG_TARGET}; +use frame_support::traits::Get; +use frame_support::{dispatch::DispatchResult, ensure}; +use log; +use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; + +impl Pallet { + pub(crate) fn initialize_validators(validators: &[T::AccountId]) { + assert!( + validators.len() as u32 >= T::MinAuthorities::get(), + "Initial set of validators must be at least T::MinAuthorities" + ); + assert!( + >::get().is_empty(), + "Validators are already initialized!" + ); + + >::put(validators); + >::put(validators); + } + + pub(crate) fn do_add_validator(validator_id: T::AccountId) -> DispatchResult { + let validator_set: BTreeSet<_> = >::get().into_iter().collect(); + ensure!( + !validator_set.contains(&validator_id), + Error::::Duplicate + ); + >::mutate(|v| v.push(validator_id.clone())); + + Self::deposit_event(Event::ValidatorAdditionInitiated(validator_id.clone())); + log::debug!(target: LOG_TARGET, "Validator addition initiated."); + + Ok(()) + } + + pub(crate) fn do_remove_validator(validator_id: T::AccountId) -> DispatchResult { + let mut validators = >::get(); + + // Ensuring that the post removal, target validator count doesn't go + // below the minimum. + ensure!( + validators.len().saturating_sub(1) as u32 >= T::MinAuthorities::get(), + Error::::TooLowValidatorCount + ); + + validators.retain(|v| *v != validator_id); + + >::put(validators); + + Self::deposit_event(Event::ValidatorRemovalInitiated(validator_id.clone())); + log::debug!(target: LOG_TARGET, "Validator removal initiated."); + + Ok(()) + } + + pub(crate) fn approve_validator(validator_id: T::AccountId) -> DispatchResult { + let approved_set: BTreeSet<_> = >::get().into_iter().collect(); + ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); + >::mutate(|v| v.push(validator_id.clone())); + Ok(()) + } + + pub(crate) fn unapprove_validator(validator_id: T::AccountId) -> DispatchResult { + let mut approved_set = >::get(); + approved_set.retain(|v| *v != validator_id); + Ok(()) + } + + // Adds offline validators to a local cache for removal at new session. + pub(crate) fn mark_for_removal(validator_id: T::AccountId) { + >::mutate(|v| v.push(validator_id)); + log::debug!( + target: LOG_TARGET, + "Offline validator marked for auto removal." + ); + } + + // Removes offline validators from the validator set and clears the offline + // cache. It is called in the session change hook and removes the validators + // who were reported offline during the session that is ending. We do not + // check for `MinAuthorities` here, because the offline validators will not + // produce blocks and will have the same overall effect on the runtime. + pub(crate) fn remove_offline_validators() { + let validators_to_remove: BTreeSet<_> = >::get().into_iter().collect(); + + // Delete from active validator set. + >::mutate(|vs| vs.retain(|v| !validators_to_remove.contains(v))); + log::debug!( + target: LOG_TARGET, + "Initiated removal of {:?} offline validators.", + validators_to_remove.len() + ); + + // Clear the offline validator list to avoid repeated deletion. + >::put(Vec::::new()); + } +}