#![cfg(test)] use frame_support::{ derive_impl, parameter_types, traits::{ConstU32, ConstU64}, weights::Weight, }; use frame_system::EnsureRoot; use pallet_session::historical as pallet_session_historical; use sp_runtime::{ testing::{TestXt, UintAuthorityId}, traits::ConvertInto, curve::PiecewiseLinear, Permill, }; use sp_staking::{ offence::{OffenceError, ReportOffence}, SessionIndex, }; use sp_runtime::BuildStorage; use crate as slow_clap; use crate::Config; type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( pub enum Runtime { System: frame_system, Session: pallet_session, Historical: pallet_session_historical, Balances: pallet_balances, Networks: ghost_networks, SlowClap: slow_clap, } ); parameter_types! { pub static Validators: Option> = Some(vec![ 1, 2, 3, ]); } pub struct TestSessionManager; impl pallet_session::SessionManager for TestSessionManager { fn new_session(_new_index: SessionIndex) -> Option> { Validators::mutate(|l| l.take()) } fn end_session(_: SessionIndex) {} fn start_session(_: SessionIndex) {} } impl pallet_session::historical::SessionManager for TestSessionManager { fn new_session(_new_index: SessionIndex) -> Option> { Validators::mutate(|l| l .take() .map(|validators| validators .iter() .map(|v| (*v, *v)) .collect()) ) } fn end_session(_: SessionIndex) {} fn start_session(_: SessionIndex) {} } type IdentificationTuple = (u64, u64); type Offence = crate::ThrottlingOffence; parameter_types! { pub static Offences: Vec<(Vec, Offence)> = vec![]; } pub struct OffenceHandler; impl ReportOffence for OffenceHandler { fn report_offence(reporters: Vec, offence: Offence) -> Result<(), OffenceError> { Offences::mutate(|l| l.push((reporters, offence))); Ok(()) } fn is_known_offence(_offenders: &[IdentificationTuple], _time_slot: &SessionIndex) -> bool { false } } pub fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::::default() .build_storage() .unwrap(); let mut result = sp_io::TestExternalities::new(t); result.execute_with(|| { for i in 1..=3 { System::inc_providers(&i); assert_eq!(Session::set_keys( RuntimeOrigin::signed(i), i.into(), vec![], ), Ok(())); } }); result } #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; type AccountData = pallet_balances::AccountData; } parameter_types! { pub const Period: u64 = 1; pub const Offset: u64 = 0; } impl pallet_session::Config for Runtime { type ShouldEndSession = pallet_session::PeriodicSessions; type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = (SlowClap,); type ValidatorId = u64; type ValidatorIdOf = ConvertInto; type Keys = UintAuthorityId; type RuntimeEvent = RuntimeEvent; type NextSessionRotation = pallet_session::PeriodicSessions; type WeightInfo = (); } impl pallet_session::historical::Config for Runtime { type FullIdentification = u64; type FullIdentificationOf = ConvertInto; } parameter_types! { pub static MockCurrentSessionProgress: Option> = None; } parameter_types! { pub static MockAverageSessionLength: Option = None; } pub struct TestNextSessionRotation; impl frame_support::traits::EstimateNextSessionRotation for TestNextSessionRotation { fn average_session_length() -> u64 { let mock = MockAverageSessionLength::mutate(|p| p.take()); mock.unwrap_or(pallet_session::PeriodicSessions::::average_session_length()) } fn estimate_current_session_progress(now: u64) -> (Option, Weight) { let (estimate, weight) = pallet_session::PeriodicSessions::::estimate_current_session_progress( now, ); let mock = MockCurrentSessionProgress::mutate(|p| p.take()); (mock.unwrap_or(estimate), weight) } fn estimate_next_session_rotation(now: u64) -> (Option, Weight) { pallet_session::PeriodicSessions::::estimate_next_session_rotation(now) } } impl ghost_networks::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type NetworkId = u32; type RegisterOrigin = EnsureRoot; type UpdateOrigin = EnsureRoot; type RemoveOrigin = EnsureRoot; type WeightInfo = (); } pallet_staking_reward_curve::build! { const REWARD_CURVE: PiecewiseLinear<'static> = curve!( min_inflation: 0_006_000, max_inflation: 1_000_000, ideal_stake: 0_690_000, falloff: 0_050_000, max_piece_count: 100, test_precision: 0_005_000, ); } parameter_types! { pub static ExistentialDeposit: u64 = 2; pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; } #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type MaxReserves = ConstU32<2>; type AccountStore = System; type WeightInfo = (); } impl Config for Runtime { type RuntimeEvent = RuntimeEvent; type AuthorityId = UintAuthorityId; type NextSessionRotation = TestNextSessionRotation; type ValidatorSet = Historical; type Currency = Balances; type NetworkDataHandler = Networks; type BlockNumberProvider = System; type ReportUnresponsiveness = OffenceHandler; type MaxAuthorities = ConstU32<5>; type ApplauseThreshold = ConstU32<50>; type OffenceThreshold = ConstU32<75>; type UnsignedPriority = ConstU64<{ 1 << 20 }>; type WeightInfo = (); } pub type Extrinsic = TestXt; impl frame_system::offchain::SendTransactionTypes for Runtime where RuntimeCall: From, { type OverarchingCall = RuntimeCall; type Extrinsic = Extrinsic; } pub fn advance_session() { let now = System::block_number().max(1); System::set_block_number(now + 1); Session::rotate_session(); let session_index = Session::current_index(); let authorities = Session::validators() .into_iter() .map(UintAuthorityId) .collect(); SlowClap::set_test_authorities(session_index, authorities); assert_eq!(session_index, (now / Period::get()) as u32); } pub fn advance_session_with_authority(authority: u64) { let now = System::block_number().max(1); System::set_block_number(now + 1); Session::rotate_session(); let session_index = Session::current_index(); SlowClap::set_test_authorities( session_index, vec![ UintAuthorityId::from(authority), UintAuthorityId::from(69), UintAuthorityId::from(420), UintAuthorityId::from(1337), ] ); assert_eq!(session_index, (now / Period::get()) as u32); }