pallet_election_provider_multi_block/verifier/
benchmarking.rs1use crate::{
19	verifier::{Config, Event, FeasibilityError, Pallet, Status, StatusStorage},
20	CurrentPhase, Phase,
21};
22use frame_benchmarking::v2::*;
23use frame_election_provider_support::{ElectionProvider, NposSolution};
24use frame_support::pallet_prelude::*;
25use sp_std::prelude::*;
26
27#[benchmarks(where
28	T: crate::Config + crate::signed::Config + crate::unsigned::Config,
29	<T as frame_system::Config>::RuntimeEvent: TryInto<crate::verifier::Event<T>>
30)]
31mod benchmarks {
32	use super::*;
33
34	fn events_for<T: Config>() -> Vec<Event<T>>
35	where
36		<T as frame_system::Config>::RuntimeEvent: TryInto<Event<T>>,
37	{
38		frame_system::Pallet::<T>::read_events_for_pallet::<Event<T>>()
39	}
40
41	#[benchmark(pov_mode = Measured)]
42	fn on_initialize_valid_non_terminal() -> Result<(), BenchmarkError> {
43		#[cfg(test)]
44		crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
45		crate::Pallet::<T>::start().unwrap();
46
47		crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
49
50		crate::Pallet::<T>::roll_until_matches(|| {
52			matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
53		});
54		crate::Pallet::<T>::roll_next(true, false);
56
57		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
59
60		#[block]
61		{
62			crate::Pallet::<T>::roll_next(true, false);
63		}
64		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp() - 1));
65
66		Ok(())
67	}
68
69	#[benchmark(pov_mode = Measured)]
70	fn on_initialize_valid_terminal() -> Result<(), BenchmarkError> {
71		#[cfg(test)]
72		crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
73		crate::Pallet::<T>::start().unwrap();
74
75		assert!(
77			T::SignedValidationPhase::get() >= T::Pages::get().into(),
78			"Signed validation phase must be larger than the number of pages"
79		);
80
81		crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
82		crate::Pallet::<T>::roll_until_matches(|| {
84			matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
85		});
86		crate::Pallet::<T>::roll_next(true, false);
88
89		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
91		for _ in 0..(T::Pages::get() - 1) {
92			crate::Pallet::<T>::roll_next(true, false);
93		}
94
95		assert!(matches!(
97			&events_for::<T>()[..],
98			[Event::Verified(_, _), .., Event::Verified(1, _)]
99		));
100
101		#[block]
103		{
104			crate::Pallet::<T>::roll_next(true, false);
105		}
106
107		assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
109		assert!(matches!(
111			&events_for::<T>()[..],
112			[Event::Verified(_, _), .., Event::Verified(0, _), Event::Queued(_, None)]
113		));
114
115		Ok(())
116	}
117
118	#[benchmark(pov_mode = Measured)]
119	fn on_initialize_invalid_terminal() -> Result<(), BenchmarkError> {
120		assert!(T::Pages::get() >= 2, "benchmark only works if we have more than 2 pages");
124
125		#[cfg(test)]
126		crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
127		crate::Pallet::<T>::start().unwrap();
128
129		let mut paged_solution = crate::Pallet::<T>::roll_to_signed_and_mine_full_solution();
133		paged_solution.score.minimal_stake -= 1;
134		crate::Pallet::<T>::submit_full_solution(paged_solution)?;
135
136		crate::Pallet::<T>::roll_until_matches(|| {
138			matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
139		});
140		crate::Pallet::<T>::roll_next(true, false);
142
143		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
144		for i in 0..T::Pages::get() - 1 {
146			crate::Pallet::<T>::roll_next(true, false);
147			assert_eq!(
148				StatusStorage::<T>::get(),
149				Status::Ongoing(crate::Pallet::<T>::msp() - 1 - i)
150			);
151		}
152
153		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::lsp()));
155		assert!(matches!(
156			&events_for::<T>()[..],
157			[Event::Verified(_, _), .., Event::Verified(1, _)]
158		));
159
160		#[block]
161		{
162			crate::Pallet::<T>::roll_next(true, false);
163		}
164
165		assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
167		assert!(matches!(
168			&events_for::<T>()[..],
169			[
170				..,
171				Event::Verified(0, _),
172				Event::VerificationFailed(0, FeasibilityError::InvalidScore)
173			]
174		));
175
176		Ok(())
177	}
178
179	#[benchmark(pov_mode = Measured)]
180	fn on_initialize_invalid_non_terminal(
181		v: Linear<0, { T::Pages::get() - 1 }>,
184	) -> Result<(), BenchmarkError> {
185		assert!(T::Pages::get() >= 2, "benchmark only works if we have more than 2 pages");
186
187		#[cfg(test)]
188		crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
189		crate::Pallet::<T>::start().unwrap();
190
191		let mut paged_solution = crate::Pallet::<T>::roll_to_signed_and_mine_full_solution();
194		let page_to_corrupt = crate::Pallet::<T>::msp() - v;
195		crate::log!(
196			info,
197			"pages of solution: {:?}, to corrupt {}, v {}",
198			paged_solution.solution_pages.len(),
199			page_to_corrupt,
200			v
201		);
202		paged_solution.solution_pages[page_to_corrupt as usize].corrupt();
203		crate::Pallet::<T>::submit_full_solution(paged_solution)?;
204
205		crate::Pallet::<T>::roll_until_matches(|| {
207			matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
208		});
209		crate::Pallet::<T>::roll_next(true, false);
211
212		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
214
215		for _ in 0..v {
217			crate::Pallet::<T>::roll_next(true, false);
218		}
219
220		assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp() - v));
222
223		#[block]
225		{
226			crate::Pallet::<T>::roll_next(true, false);
227		}
228
229		assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
231
232		assert!(matches!(
233			&events_for::<T>()[..],
234			[.., Event::VerificationFailed(_, FeasibilityError::NposElection(_))]
235		));
236
237		Ok(())
238	}
239
240	impl_benchmark_test_suite!(
241		Pallet,
242		crate::mock::ExtBuilder::full().build_unchecked(),
243		crate::mock::Runtime
244	);
245}