pallet_session_validator_management/
pallet_session_support.rs1use crate::CommitteeMember;
5use core::marker::PhantomData;
6use derive_new::new;
7use frame_system::pallet_prelude::BlockNumberFor;
8use log::{debug, warn};
9use pallet_partner_chains_session::SessionIndex;
10use sp_std::vec::Vec;
11
12#[allow(dead_code)]
16#[derive(new)]
17pub struct PalletSessionSupport<T> {
18 _phantom: PhantomData<T>,
19}
20
21impl<T: crate::Config + pallet_session::Config> pallet_session::SessionManager<T::AccountId>
22 for PalletSessionSupport<T>
23{
24 fn new_session_genesis(_new_index: SessionIndex) -> Option<Vec<T::AccountId>> {
26 Some(
27 crate::Pallet::<T>::current_committee_storage()
28 .committee
29 .into_iter()
30 .map(|member| member.authority_id().into())
31 .collect::<Vec<_>>(),
32 )
33 }
34
35 fn new_session(new_index: SessionIndex) -> Option<Vec<T::AccountId>> {
39 debug!("PalletSessionSupport: New session {new_index}");
40 pallet_session::pallet::CurrentIndex::<T>::put(new_index);
41 Some(
42 crate::Pallet::<T>::rotate_committee_to_next_epoch()
43 .expect(
44 "PalletSessionSupport: Session should never end without current epoch validators defined. This may be caused by ShouldEndSession invalid behavior or being called before starting new session",
45 ).into_iter().map(|member| member.authority_id().into()).collect::<Vec<_>>(),
46 )
47 }
48
49 fn end_session(end_index: SessionIndex) {
50 debug!("PalletSessionSupport: End session {end_index}");
51 }
52
53 fn start_session(start_index: SessionIndex) {
55 let epoch_number = T::current_epoch_number();
56 debug!("PalletSessionSupport: Start session {start_index}, epoch {epoch_number}");
57 }
58}
59
60impl<T, EpochNumber> pallet_session::ShouldEndSession<BlockNumberFor<T>> for PalletSessionSupport<T>
62where
63 T: crate::Config<ScEpochNumber = EpochNumber>,
64 EpochNumber: Clone + PartialOrd,
65{
66 fn should_end_session(n: BlockNumberFor<T>) -> bool {
67 let current_epoch_number = T::current_epoch_number();
68 let current_committee_epoch = crate::Pallet::<T>::current_committee_storage().epoch;
69 let next_committee_is_defined = crate::Pallet::<T>::next_committee().is_some();
70 if current_epoch_number > current_committee_epoch {
71 if next_committee_is_defined {
72 debug!("PalletSessionSupport: should_end_session({n:?}) = true");
73 true
74 } else {
75 warn!(
76 "PalletSessionSupport: should_end_session({n:?}) 'current epoch' > 'committee epoch' but the next committee is not defined"
77 );
78 false
79 }
80 } else {
81 debug!("PalletSessionSupport: should_end_session({n:?}) = false");
82 false
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::{
91 CommitteeInfo, CurrentCommittee, NextCommittee, mock::mock_pallet::CurrentEpoch, mock::*,
92 };
93 use pallet_session::ShouldEndSession;
94 pub const IRRELEVANT: u64 = 2;
95
96 type Manager = PalletSessionSupport<Test>;
97
98 #[test]
99 fn should_end_session_if_last_one_ended_late_and_new_committee_is_defined() {
100 let current_committee_epoch = 100;
101 let current_committee = ids_and_keys_fn(&[ALICE]);
102 let next_committee_epoch = 102;
103 let next_committee = ids_and_keys_fn(&[BOB]);
104
105 new_test_ext().execute_with(|| {
106 CurrentCommittee::<Test>::put(CommitteeInfo {
107 epoch: current_committee_epoch,
108 committee: current_committee,
109 });
110 CurrentEpoch::<Test>::set(current_committee_epoch + 2);
111 assert!(!Manager::should_end_session(IRRELEVANT));
112 NextCommittee::<Test>::put(CommitteeInfo {
113 epoch: next_committee_epoch,
114 committee: next_committee,
115 });
116 assert!(Manager::should_end_session(IRRELEVANT));
117 });
118 }
119}