1#![cfg_attr(not(feature = "std"), no_std)]
108
109pub mod disabling;
110#[cfg(feature = "historical")]
111pub mod historical;
112pub mod migrations;
113#[cfg(test)]
114mod mock;
115#[cfg(test)]
116mod tests;
117pub mod weights;
118
119extern crate alloc;
120
121use alloc::{boxed::Box, vec::Vec};
122use codec::{Decode, MaxEncodedLen};
123use core::{
124 marker::PhantomData,
125 ops::{Rem, Sub},
126};
127use disabling::DisablingStrategy;
128use frame_support::{
129 dispatch::DispatchResult,
130 ensure,
131 traits::{
132 Defensive, EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get,
133 OneSessionHandler, ValidatorRegistration, ValidatorSet,
134 },
135 weights::Weight,
136 Parameter,
137};
138use frame_system::pallet_prelude::BlockNumberFor;
139use sp_runtime::{
140 traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero},
141 ConsensusEngineId, DispatchError, KeyTypeId, Permill, RuntimeAppPublic,
142};
143use sp_staking::{offence::OffenceSeverity, SessionIndex};
144
145pub use pallet::*;
146pub use weights::WeightInfo;
147
148#[cfg(any(feature = "try-runtime"))]
149use sp_runtime::TryRuntimeError;
150
151pub(crate) const LOG_TARGET: &str = "runtime::session";
152
153#[macro_export]
155macro_rules! log {
156 ($level:tt, $patter:expr $(, $values:expr)* $(,)?) => {
157 log::$level!(
158 target: crate::LOG_TARGET,
159 concat!("[{:?}] 💸 ", $patter), <frame_system::Pallet<T>>::block_number() $(, $values)*
160 )
161 };
162}
163
164pub trait ShouldEndSession<BlockNumber> {
166 fn should_end_session(now: BlockNumber) -> bool;
168}
169
170pub struct PeriodicSessions<Period, Offset>(PhantomData<(Period, Offset)>);
176
177impl<
178 BlockNumber: Rem<Output = BlockNumber> + Sub<Output = BlockNumber> + Zero + PartialOrd,
179 Period: Get<BlockNumber>,
180 Offset: Get<BlockNumber>,
181 > ShouldEndSession<BlockNumber> for PeriodicSessions<Period, Offset>
182{
183 fn should_end_session(now: BlockNumber) -> bool {
184 let offset = Offset::get();
185 now >= offset && ((now - offset) % Period::get()).is_zero()
186 }
187}
188
189impl<
190 BlockNumber: AtLeast32BitUnsigned + Clone,
191 Period: Get<BlockNumber>,
192 Offset: Get<BlockNumber>,
193 > EstimateNextSessionRotation<BlockNumber> for PeriodicSessions<Period, Offset>
194{
195 fn average_session_length() -> BlockNumber {
196 Period::get()
197 }
198
199 fn estimate_current_session_progress(now: BlockNumber) -> (Option<Permill>, Weight) {
200 let offset = Offset::get();
201 let period = Period::get();
202
203 let progress = if now >= offset {
207 let current = (now - offset) % period.clone() + One::one();
208 Some(Permill::from_rational(current, period))
209 } else {
210 Some(Permill::from_rational(now + One::one(), offset))
211 };
212
213 (progress, Zero::zero())
218 }
219
220 fn estimate_next_session_rotation(now: BlockNumber) -> (Option<BlockNumber>, Weight) {
221 let offset = Offset::get();
222 let period = Period::get();
223
224 let next_session = if now > offset {
225 let block_after_last_session = (now.clone() - offset) % period.clone();
226 if block_after_last_session > Zero::zero() {
227 now.saturating_add(period.saturating_sub(block_after_last_session))
228 } else {
229 now + period
234 }
235 } else {
236 offset
237 };
238
239 (Some(next_session), Zero::zero())
244 }
245}
246
247pub trait SessionManager<ValidatorId> {
249 fn new_session(new_index: SessionIndex) -> Option<Vec<ValidatorId>>;
263 fn new_session_genesis(new_index: SessionIndex) -> Option<Vec<ValidatorId>> {
268 Self::new_session(new_index)
269 }
270 fn end_session(end_index: SessionIndex);
275 fn start_session(start_index: SessionIndex);
279}
280
281impl<A> SessionManager<A> for () {
282 fn new_session(_: SessionIndex) -> Option<Vec<A>> {
283 None
284 }
285 fn start_session(_: SessionIndex) {}
286 fn end_session(_: SessionIndex) {}
287}
288
289pub trait SessionHandler<ValidatorId> {
291 const KEY_TYPE_IDS: &'static [KeyTypeId];
297
298 fn on_genesis_session<Ks: OpaqueKeys>(validators: &[(ValidatorId, Ks)]);
303
304 fn on_new_session<Ks: OpaqueKeys>(
314 changed: bool,
315 validators: &[(ValidatorId, Ks)],
316 queued_validators: &[(ValidatorId, Ks)],
317 );
318
319 fn on_before_session_ending() {}
324
325 fn on_disabled(validator_index: u32);
327}
328
329#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
330#[tuple_types_custom_trait_bound(OneSessionHandler<AId>)]
331impl<AId> SessionHandler<AId> for Tuple {
332 for_tuples!(
333 const KEY_TYPE_IDS: &'static [KeyTypeId] = &[ #( <Tuple::Key as RuntimeAppPublic>::ID ),* ];
334 );
335
336 fn on_genesis_session<Ks: OpaqueKeys>(validators: &[(AId, Ks)]) {
337 for_tuples!(
338 #(
339 let our_keys: Box<dyn Iterator<Item=_>> = Box::new(validators.iter()
340 .filter_map(|k|
341 k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
342 )
343 );
344
345 Tuple::on_genesis_session(our_keys);
346 )*
347 )
348 }
349
350 fn on_new_session<Ks: OpaqueKeys>(
351 changed: bool,
352 validators: &[(AId, Ks)],
353 queued_validators: &[(AId, Ks)],
354 ) {
355 for_tuples!(
356 #(
357 let our_keys: Box<dyn Iterator<Item=_>> = Box::new(validators.iter()
358 .filter_map(|k|
359 k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
360 ));
361 let queued_keys: Box<dyn Iterator<Item=_>> = Box::new(queued_validators.iter()
362 .filter_map(|k|
363 k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
364 ));
365 Tuple::on_new_session(changed, our_keys, queued_keys);
366 )*
367 )
368 }
369
370 fn on_before_session_ending() {
371 for_tuples!( #( Tuple::on_before_session_ending(); )* )
372 }
373
374 fn on_disabled(i: u32) {
375 for_tuples!( #( Tuple::on_disabled(i); )* )
376 }
377}
378
379pub struct TestSessionHandler;
381impl<AId> SessionHandler<AId> for TestSessionHandler {
382 const KEY_TYPE_IDS: &'static [KeyTypeId] = &[sp_runtime::key_types::DUMMY];
383 fn on_genesis_session<Ks: OpaqueKeys>(_: &[(AId, Ks)]) {}
384 fn on_new_session<Ks: OpaqueKeys>(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {}
385 fn on_before_session_ending() {}
386 fn on_disabled(_: u32) {}
387}
388
389#[frame_support::pallet]
390pub mod pallet {
391 use super::*;
392 use frame_support::pallet_prelude::*;
393 use frame_system::pallet_prelude::*;
394
395 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
397
398 #[pallet::pallet]
399 #[pallet::storage_version(STORAGE_VERSION)]
400 #[pallet::without_storage_info]
401 pub struct Pallet<T>(_);
402
403 #[pallet::config]
404 pub trait Config: frame_system::Config {
405 #[allow(deprecated)]
407 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
408
409 type ValidatorId: Member
411 + Parameter
412 + MaybeSerializeDeserialize
413 + MaxEncodedLen
414 + TryFrom<Self::AccountId>;
415
416 type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
420
421 type ShouldEndSession: ShouldEndSession<BlockNumberFor<Self>>;
423
424 type NextSessionRotation: EstimateNextSessionRotation<BlockNumberFor<Self>>;
428
429 type SessionManager: SessionManager<Self::ValidatorId>;
431
432 type SessionHandler: SessionHandler<Self::ValidatorId>;
434
435 type Keys: OpaqueKeys + Member + Parameter + MaybeSerializeDeserialize;
437
438 type DisablingStrategy: DisablingStrategy<Self>;
440
441 type WeightInfo: WeightInfo;
443 }
444
445 #[pallet::genesis_config]
446 #[derive(frame_support::DefaultNoBound)]
447 pub struct GenesisConfig<T: Config> {
448 pub keys: Vec<(T::AccountId, T::ValidatorId, T::Keys)>,
452 pub non_authority_keys: Vec<(T::AccountId, T::ValidatorId, T::Keys)>,
456 }
457
458 #[pallet::genesis_build]
459 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
460 fn build(&self) {
461 if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() {
462 panic!("Number of keys in session handler and session keys does not match");
463 }
464
465 T::SessionHandler::KEY_TYPE_IDS
466 .iter()
467 .zip(T::Keys::key_ids())
468 .enumerate()
469 .for_each(|(i, (sk, kk))| {
470 if sk != kk {
471 panic!(
472 "Session handler and session key expect different key type at index: {}",
473 i,
474 );
475 }
476 });
477
478 for (account, val, keys) in
479 self.keys.iter().chain(self.non_authority_keys.iter()).cloned()
480 {
481 Pallet::<T>::inner_set_keys(&val, keys)
482 .expect("genesis config must not contain duplicates; qed");
483 if frame_system::Pallet::<T>::inc_consumers_without_limit(&account).is_err() {
484 frame_system::Pallet::<T>::inc_providers(&account);
489 }
490 }
491
492 let initial_validators_0 =
493 T::SessionManager::new_session_genesis(0).unwrap_or_else(|| {
494 frame_support::print(
495 "No initial validator provided by `SessionManager`, use \
496 session config keys to generate initial validator set.",
497 );
498 self.keys.iter().map(|x| x.1.clone()).collect()
499 });
500
501 let initial_validators_1 = T::SessionManager::new_session_genesis(1)
502 .unwrap_or_else(|| initial_validators_0.clone());
503
504 let queued_keys: Vec<_> = initial_validators_1
505 .into_iter()
506 .filter_map(|v| Pallet::<T>::load_keys(&v).map(|k| (v, k)))
507 .collect();
508
509 T::SessionHandler::on_genesis_session::<T::Keys>(&queued_keys);
511
512 Validators::<T>::put(initial_validators_0);
513 QueuedKeys::<T>::put(queued_keys);
514
515 T::SessionManager::start_session(0);
516 }
517 }
518
519 #[pallet::storage]
521 pub type Validators<T: Config> = StorageValue<_, Vec<T::ValidatorId>, ValueQuery>;
522
523 #[pallet::storage]
525 pub type CurrentIndex<T> = StorageValue<_, SessionIndex, ValueQuery>;
526
527 #[pallet::storage]
530 pub type QueuedChanged<T> = StorageValue<_, bool, ValueQuery>;
531
532 #[pallet::storage]
535 pub type QueuedKeys<T: Config> = StorageValue<_, Vec<(T::ValidatorId, T::Keys)>, ValueQuery>;
536
537 #[pallet::storage]
543 pub type DisabledValidators<T> = StorageValue<_, Vec<(u32, OffenceSeverity)>, ValueQuery>;
544
545 #[pallet::storage]
547 pub type NextKeys<T: Config> =
548 StorageMap<_, Twox64Concat, T::ValidatorId, T::Keys, OptionQuery>;
549
550 #[pallet::storage]
552 pub type KeyOwner<T: Config> =
553 StorageMap<_, Twox64Concat, (KeyTypeId, Vec<u8>), T::ValidatorId, OptionQuery>;
554
555 #[pallet::event]
556 #[pallet::generate_deposit(pub(super) fn deposit_event)]
557 pub enum Event<T: Config> {
558 NewSession { session_index: SessionIndex },
561 NewQueued,
564 ValidatorDisabled { validator: T::ValidatorId },
566 ValidatorReenabled { validator: T::ValidatorId },
568 }
569
570 #[pallet::error]
572 pub enum Error<T> {
573 InvalidProof,
575 NoAssociatedValidatorId,
577 DuplicatedKey,
579 NoKeys,
581 NoAccount,
583 }
584
585 #[pallet::hooks]
586 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
587 fn on_initialize(n: BlockNumberFor<T>) -> Weight {
590 if T::ShouldEndSession::should_end_session(n) {
591 Self::rotate_session();
592 T::BlockWeights::get().max_block
593 } else {
594 Weight::zero()
598 }
599 }
600
601 #[cfg(feature = "try-runtime")]
602 fn try_state(_n: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
603 Self::do_try_state()
604 }
605 }
606
607 #[pallet::call]
608 impl<T: Config> Pallet<T> {
609 #[pallet::call_index(0)]
619 #[pallet::weight(T::WeightInfo::set_keys())]
620 pub fn set_keys(origin: OriginFor<T>, keys: T::Keys, proof: Vec<u8>) -> DispatchResult {
621 let who = ensure_signed(origin)?;
622 ensure!(keys.ownership_proof_is_valid(&proof), Error::<T>::InvalidProof);
623
624 Self::do_set_keys(&who, keys)?;
625 Ok(())
626 }
627
628 #[pallet::call_index(1)]
641 #[pallet::weight(T::WeightInfo::purge_keys())]
642 pub fn purge_keys(origin: OriginFor<T>) -> DispatchResult {
643 let who = ensure_signed(origin)?;
644 Self::do_purge_keys(&who)?;
645 Ok(())
646 }
647 }
648}
649
650impl<T: Config> Pallet<T> {
651 pub fn validators() -> Vec<T::ValidatorId> {
653 Validators::<T>::get()
654 }
655
656 pub fn current_index() -> SessionIndex {
658 CurrentIndex::<T>::get()
659 }
660
661 pub fn queued_keys() -> Vec<(T::ValidatorId, T::Keys)> {
663 QueuedKeys::<T>::get()
664 }
665
666 pub fn disabled_validators() -> Vec<u32> {
668 DisabledValidators::<T>::get().iter().map(|(i, _)| *i).collect()
669 }
670
671 pub fn rotate_session() {
675 let session_index = CurrentIndex::<T>::get();
676 let changed = QueuedChanged::<T>::get();
677
678 T::SessionHandler::on_before_session_ending();
680 T::SessionManager::end_session(session_index);
681 log!(trace, "ending_session {:?}", session_index);
682
683 let session_keys = QueuedKeys::<T>::get();
685 let validators =
686 session_keys.iter().map(|(validator, _)| validator.clone()).collect::<Vec<_>>();
687 Validators::<T>::put(&validators);
688
689 if changed {
690 log!(trace, "resetting disabled validators");
691 DisabledValidators::<T>::kill();
693 }
694
695 let session_index = session_index + 1;
697 CurrentIndex::<T>::put(session_index);
698 T::SessionManager::start_session(session_index);
699 log!(trace, "starting_session {:?}", session_index);
700
701 let maybe_next_validators = T::SessionManager::new_session(session_index + 1);
703 log!(
704 trace,
705 "planning_session {:?} with {:?} validators",
706 session_index + 1,
707 maybe_next_validators.as_ref().map(|v| v.len())
708 );
709 let (next_validators, next_identities_changed) =
710 if let Some(validators) = maybe_next_validators {
711 Self::deposit_event(Event::<T>::NewQueued);
715 (validators, true)
716 } else {
717 (Validators::<T>::get(), false)
718 };
719
720 let (queued_amalgamated, next_changed) = {
722 let mut changed = next_identities_changed;
725
726 let mut now_session_keys = session_keys.iter();
727 let mut check_next_changed = |keys: &T::Keys| {
728 if changed {
729 return;
730 }
731 if let Some((_, old_keys)) = now_session_keys.next() {
735 if old_keys != keys {
736 changed = true;
737 }
738 }
739 };
740 let queued_amalgamated =
741 next_validators
742 .into_iter()
743 .filter_map(|a| {
744 let k =
745 Self::load_keys(&a).or_else(|| {
746 log!(warn, "failed to load session key for {:?}, skipping for next session, maybe you need to set session keys for them?", a);
747 None
748 })?;
749 check_next_changed(&k);
750 Some((a, k))
751 })
752 .collect::<Vec<_>>();
753
754 (queued_amalgamated, changed)
755 };
756
757 QueuedKeys::<T>::put(queued_amalgamated.clone());
758 QueuedChanged::<T>::put(next_changed);
759
760 Self::deposit_event(Event::NewSession { session_index });
762
763 T::SessionHandler::on_new_session::<T::Keys>(changed, &session_keys, &queued_amalgamated);
765 }
766
767 pub fn upgrade_keys<Old, F>(upgrade: F)
783 where
784 Old: OpaqueKeys + Member + Decode,
785 F: Fn(T::ValidatorId, Old) -> T::Keys,
786 {
787 let old_ids = Old::key_ids();
788 let new_ids = T::Keys::key_ids();
789
790 NextKeys::<T>::translate::<Old, _>(|val, old_keys| {
792 for i in old_ids.iter() {
795 Self::clear_key_owner(*i, old_keys.get_raw(*i));
796 }
797
798 let new_keys = upgrade(val.clone(), old_keys);
799
800 for i in new_ids.iter() {
802 Self::put_key_owner(*i, new_keys.get_raw(*i), &val);
803 }
804
805 Some(new_keys)
806 });
807
808 let _ = QueuedKeys::<T>::translate::<Vec<(T::ValidatorId, Old)>, _>(|k| {
809 k.map(|k| {
810 k.into_iter()
811 .map(|(val, old_keys)| (val.clone(), upgrade(val, old_keys)))
812 .collect::<Vec<_>>()
813 })
814 });
815 }
816
817 fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> DispatchResult {
822 let who = T::ValidatorIdOf::convert(account.clone())
823 .ok_or(Error::<T>::NoAssociatedValidatorId)?;
824
825 ensure!(frame_system::Pallet::<T>::can_inc_consumer(account), Error::<T>::NoAccount);
826 let old_keys = Self::inner_set_keys(&who, keys)?;
827 if old_keys.is_none() {
828 let assertion = frame_system::Pallet::<T>::inc_consumers(account).is_ok();
829 debug_assert!(assertion, "can_inc_consumer() returned true; no change since; qed");
830 }
831
832 Ok(())
833 }
834
835 fn inner_set_keys(
842 who: &T::ValidatorId,
843 keys: T::Keys,
844 ) -> Result<Option<T::Keys>, DispatchError> {
845 let old_keys = Self::load_keys(who);
846
847 for id in T::Keys::key_ids() {
848 let key = keys.get_raw(*id);
849
850 ensure!(
852 Self::key_owner(*id, key).map_or(true, |owner| &owner == who),
853 Error::<T>::DuplicatedKey,
854 );
855 }
856
857 for id in T::Keys::key_ids() {
858 let key = keys.get_raw(*id);
859
860 if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(*id)) {
861 if key == old {
862 continue
863 }
864
865 Self::clear_key_owner(*id, old);
866 }
867
868 Self::put_key_owner(*id, key, who);
869 }
870
871 Self::put_keys(who, &keys);
872 Ok(old_keys)
873 }
874
875 fn do_purge_keys(account: &T::AccountId) -> DispatchResult {
876 let who = T::ValidatorIdOf::convert(account.clone())
877 .or_else(|| T::ValidatorId::try_from(account.clone()).ok())
881 .ok_or(Error::<T>::NoAssociatedValidatorId)?;
882
883 let old_keys = Self::take_keys(&who).ok_or(Error::<T>::NoKeys)?;
884 for id in T::Keys::key_ids() {
885 let key_data = old_keys.get_raw(*id);
886 Self::clear_key_owner(*id, key_data);
887 }
888 frame_system::Pallet::<T>::dec_consumers(account);
889
890 Ok(())
891 }
892
893 pub fn load_keys(v: &T::ValidatorId) -> Option<T::Keys> {
894 NextKeys::<T>::get(v)
895 }
896
897 fn take_keys(v: &T::ValidatorId) -> Option<T::Keys> {
898 NextKeys::<T>::take(v)
899 }
900
901 fn put_keys(v: &T::ValidatorId, keys: &T::Keys) {
902 NextKeys::<T>::insert(v, keys);
903 }
904
905 pub fn key_owner(id: KeyTypeId, key_data: &[u8]) -> Option<T::ValidatorId> {
907 KeyOwner::<T>::get((id, key_data))
908 }
909
910 fn put_key_owner(id: KeyTypeId, key_data: &[u8], v: &T::ValidatorId) {
911 KeyOwner::<T>::insert((id, key_data), v)
912 }
913
914 fn clear_key_owner(id: KeyTypeId, key_data: &[u8]) {
915 KeyOwner::<T>::remove((id, key_data));
916 }
917
918 pub fn disable_index_with_severity(i: u32, severity: OffenceSeverity) -> bool {
924 if i >= Validators::<T>::decode_len().defensive_unwrap_or(0) as u32 {
925 return false;
926 }
927
928 DisabledValidators::<T>::mutate(|disabled| {
929 match disabled.binary_search_by_key(&i, |(index, _)| *index) {
930 Ok(index) => {
932 let current_severity = &mut disabled[index].1;
933 if severity > *current_severity {
934 log!(
935 trace,
936 "updating disablement severity of validator {:?} from {:?} to {:?}",
937 i,
938 *current_severity,
939 severity
940 );
941 *current_severity = severity;
942 }
943 true
944 },
945 Err(index) => {
947 log!(trace, "disabling validator {:?}", i);
948 Self::deposit_event(Event::ValidatorDisabled {
949 validator: Validators::<T>::get()[i as usize].clone(),
950 });
951 disabled.insert(index, (i, severity));
952 T::SessionHandler::on_disabled(i);
953 true
954 },
955 }
956 })
957 }
958
959 pub fn disable_index(i: u32) -> bool {
962 let default_severity = OffenceSeverity::default();
963 Self::disable_index_with_severity(i, default_severity)
964 }
965
966 pub fn reenable_index(i: u32) -> bool {
968 if i >= Validators::<T>::decode_len().defensive_unwrap_or(0) as u32 {
969 return false;
970 }
971
972 DisabledValidators::<T>::mutate(|disabled| {
973 if let Ok(index) = disabled.binary_search_by_key(&i, |(index, _)| *index) {
974 log!(trace, "reenabling validator {:?}", i);
975 Self::deposit_event(Event::ValidatorReenabled {
976 validator: Validators::<T>::get()[i as usize].clone(),
977 });
978 disabled.remove(index);
979 return true;
980 }
981 false
982 })
983 }
984
985 pub fn validator_id_to_index(id: &T::ValidatorId) -> Option<u32> {
988 Validators::<T>::get().iter().position(|i| i == id).map(|i| i as u32)
989 }
990
991 pub fn report_offence(validator: T::ValidatorId, severity: OffenceSeverity) {
994 let decision =
995 T::DisablingStrategy::decision(&validator, severity, &DisabledValidators::<T>::get());
996 log!(
997 debug,
998 "reporting offence for {:?} with {:?}, decision: {:?}",
999 validator,
1000 severity,
1001 decision
1002 );
1003
1004 if let Some(offender_idx) = decision.disable {
1006 Self::disable_index_with_severity(offender_idx, severity);
1007 }
1008
1009 if let Some(reenable_idx) = decision.reenable {
1011 Self::reenable_index(reenable_idx);
1012 }
1013 }
1014
1015 #[cfg(any(test, feature = "try-runtime"))]
1016 pub fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> {
1017 ensure!(
1019 DisabledValidators::<T>::get().windows(2).all(|pair| pair[0].0 <= pair[1].0),
1020 "DisabledValidators is not sorted"
1021 );
1022 Ok(())
1023 }
1024}
1025
1026impl<T: Config> ValidatorRegistration<T::ValidatorId> for Pallet<T> {
1027 fn is_registered(id: &T::ValidatorId) -> bool {
1028 Self::load_keys(id).is_some()
1029 }
1030}
1031
1032impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
1033 type ValidatorId = T::ValidatorId;
1034 type ValidatorIdOf = T::ValidatorIdOf;
1035
1036 fn session_index() -> sp_staking::SessionIndex {
1037 CurrentIndex::<T>::get()
1038 }
1039
1040 fn validators() -> Vec<Self::ValidatorId> {
1041 Validators::<T>::get()
1042 }
1043}
1044
1045impl<T: Config> EstimateNextNewSession<BlockNumberFor<T>> for Pallet<T> {
1046 fn average_session_length() -> BlockNumberFor<T> {
1047 T::NextSessionRotation::average_session_length()
1048 }
1049
1050 fn estimate_next_new_session(now: BlockNumberFor<T>) -> (Option<BlockNumberFor<T>>, Weight) {
1053 T::NextSessionRotation::estimate_next_session_rotation(now)
1054 }
1055}
1056
1057impl<T: Config> frame_support::traits::DisabledValidators for Pallet<T> {
1058 fn is_disabled(index: u32) -> bool {
1059 DisabledValidators::<T>::get().binary_search_by_key(&index, |(i, _)| *i).is_ok()
1060 }
1061
1062 fn disabled_validators() -> Vec<u32> {
1063 Self::disabled_validators()
1064 }
1065}
1066
1067pub struct FindAccountFromAuthorIndex<T, Inner>(core::marker::PhantomData<(T, Inner)>);
1071
1072impl<T: Config, Inner: FindAuthor<u32>> FindAuthor<T::ValidatorId>
1073 for FindAccountFromAuthorIndex<T, Inner>
1074{
1075 fn find_author<'a, I>(digests: I) -> Option<T::ValidatorId>
1076 where
1077 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
1078 {
1079 let i = Inner::find_author(digests)?;
1080
1081 let validators = Validators::<T>::get();
1082 validators.get(i as usize).cloned()
1083 }
1084}