polkadot_runtime_parachains/disputes/slashing/
benchmarking.rs1use super::*;
18
19use crate::{disputes::SlashingHandler, initializer, shared};
20use frame_benchmarking::v2::*;
21use frame_support::traits::{OnFinalize, OnInitialize};
22use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
23use pallet_staking::testing_utils::create_validators;
24use polkadot_primitives::{Hash, PARACHAIN_KEY_TYPE_ID};
25use sp_runtime::traits::{One, StaticLookup};
26use sp_session::MembershipProof;
27
28const CANDIDATE_HASH: CandidateHash = CandidateHash(Hash::zero());
30
31pub const fn max_validators_for<T: super::Config>() -> u32 {
33 <<T>::BenchmarkingConfig as BenchmarkingConfiguration>::MAX_VALIDATORS
34}
35
36pub trait Config:
37 pallet_session::Config
38 + pallet_session_benchmarking::Config
39 + pallet_session::historical::Config
40 + pallet_staking::Config
41 + super::Config
42 + shared::Config
43 + initializer::Config
44{
45}
46
47fn setup_validator_set<T>(n: u32) -> (SessionIndex, MembershipProof, ValidatorId)
48where
49 T: Config,
50{
51 pallet_staking::ValidatorCount::<T>::put(n);
52
53 let balance_factor = 1000;
54 for who in create_validators::<T>(n, balance_factor).unwrap().into_iter() {
56 let validator = T::Lookup::lookup(who).unwrap();
57 let controller = pallet_staking::Pallet::<T>::bonded(&validator).unwrap();
58
59 let (keys, proof) = T::generate_session_keys_and_proof(controller.clone());
60
61 whitelist_account!(controller);
62 pallet_session::Pallet::<T>::ensure_can_pay_key_deposit(&controller).unwrap();
63 pallet_session::Pallet::<T>::set_keys(RawOrigin::Signed(controller).into(), keys, proof)
64 .expect("session::set_keys should work");
65 }
66
67 pallet_session::Pallet::<T>::on_initialize(BlockNumberFor::<T>::one());
68 initializer::Pallet::<T>::on_initialize(BlockNumberFor::<T>::one());
69
70 use frame_election_provider_support::ElectionProvider;
72 <<T as pallet_staking::Config>::ElectionProvider as ElectionProvider>::asap();
73
74 while pallet_session::Pallet::<T>::validators().len() < n as usize {
76 pallet_session::Pallet::<T>::rotate_session();
77 }
78 initializer::Pallet::<T>::on_finalize(BlockNumberFor::<T>::one());
79
80 let session_index = crate::shared::CurrentSessionIndex::<T>::get();
81 let session_info = crate::session_info::Sessions::<T>::get(session_index);
82 let session_info = session_info.unwrap();
83 let validator_id = session_info.validators.get(ValidatorIndex::from(0)).unwrap().clone();
84 let key = (PARACHAIN_KEY_TYPE_ID, validator_id.clone());
85 let key_owner_proof = pallet_session::historical::Pallet::<T>::prove(key).unwrap();
86
87 initializer::Pallet::<T>::on_initialize(BlockNumberFor::<T>::one());
89 pallet_session::Pallet::<T>::rotate_session();
90 initializer::Pallet::<T>::on_finalize(BlockNumberFor::<T>::one());
91
92 let idx = crate::shared::CurrentSessionIndex::<T>::get();
93 assert!(
94 idx > session_index,
95 "session rotation should work for parachain pallets: {} <= {}",
96 idx,
97 session_index,
98 );
99
100 (session_index, key_owner_proof, validator_id)
101}
102
103fn setup_dispute<T>(session_index: SessionIndex, validator_id: ValidatorId) -> DisputeProof
105where
106 T: Config,
107{
108 let current_session = T::ValidatorSet::session_index();
109 assert_ne!(session_index, current_session);
110
111 let validator_index = ValidatorIndex(0);
112 let losers = [validator_index].into_iter();
113 let backers = losers.clone();
114
115 T::SlashingHandler::punish_for_invalid(session_index, CANDIDATE_HASH, losers, backers);
116
117 let unapplied = <UnappliedSlashes<T>>::get(session_index, CANDIDATE_HASH);
118 assert_eq!(unapplied.unwrap().keys.len(), 1);
119
120 dispute_proof(session_index, validator_id, validator_index)
121}
122
123fn dispute_proof(
125 session_index: SessionIndex,
126 validator_id: ValidatorId,
127 validator_index: ValidatorIndex,
128) -> DisputeProof {
129 let kind = DisputeOffenceKind::ForInvalidBacked;
130 let time_slot = DisputesTimeSlot::new(session_index, CANDIDATE_HASH);
131
132 DisputeProof { time_slot, kind, validator_index, validator_id }
133}
134
135#[benchmarks(where T: Config<KeyOwnerProof = MembershipProof>)]
136mod benchmarks {
137 use super::*;
138
139 #[benchmark]
140 fn report_dispute_lost_unsigned(n: Linear<4, { max_validators_for::<T>() }>) {
141 let (session_index, key_owner_proof, validator_id) = setup_validator_set::<T>(n);
142
143 let dispute_proof = setup_dispute::<T>(session_index, validator_id);
145
146 #[extrinsic_call]
147 _(RawOrigin::None, Box::new(dispute_proof), key_owner_proof);
148
149 let unapplied = <UnappliedSlashes<T>>::get(session_index, CANDIDATE_HASH);
150 assert!(unapplied.is_none());
151 }
152}