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}