pallet_election_provider_multi_block/verifier/
benchmarking.rs1use crate::{
19 signed::RewardSource,
20 verifier::{Config, Event, FeasibilityError, Pallet, Status, StatusStorage},
21 CurrentPhase, Phase,
22};
23use frame_benchmarking::v2::*;
24use frame_election_provider_support::{ElectionProvider, NposSolution};
25use frame_support::{
26 pallet_prelude::*,
27 traits::fungible::{Inspect, Mutate},
28};
29use sp_runtime::traits::Saturating;
30use sp_std::prelude::*;
31
32type SignedCurrencyOf<T> = <T as crate::signed::Config>::Currency;
34
35#[benchmarks(where
36 T: crate::Config + crate::signed::Config + crate::unsigned::Config,
37 <T as frame_system::Config>::RuntimeEvent: TryInto<crate::verifier::Event<T>>
38)]
39mod benchmarks {
40 use super::*;
41
42 fn events_for<T: Config>() -> Vec<Event<T>>
43 where
44 <T as frame_system::Config>::RuntimeEvent: TryInto<Event<T>>,
45 {
46 frame_system::Pallet::<T>::read_events_for_pallet::<Event<T>>()
47 }
48
49 #[benchmark(pov_mode = Measured)]
50 fn verification_valid_non_terminal() -> Result<(), BenchmarkError> {
51 #[cfg(test)]
52 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
53 crate::Pallet::<T>::start().unwrap();
54
55 crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
57
58 crate::Pallet::<T>::roll_until_matches(|| {
60 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
61 });
62
63 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
65
66 #[block]
67 {
68 crate::Pallet::<T>::roll_next(false);
69 }
70 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp() - 1));
71
72 Ok(())
73 }
74
75 #[benchmark(pov_mode = Measured)]
76 fn verification_valid_terminal() -> Result<(), BenchmarkError> {
77 #[cfg(test)]
78 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
79 crate::Pallet::<T>::start().unwrap();
80
81 assert!(
83 T::SignedValidationPhase::get() >= T::Pages::get().into(),
84 "Signed validation phase must be larger than the number of pages"
85 );
86
87 crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
88
89 if let Some(source) = <T as crate::signed::Config>::RewardSource::account() {
95 let funds = <T as crate::signed::Config>::RewardBase::get()
96 .saturating_mul(2u32.into())
97 .saturating_add(SignedCurrencyOf::<T>::minimum_balance());
98 SignedCurrencyOf::<T>::mint_into(&source, funds)?;
99 }
100
101 crate::Pallet::<T>::roll_until_matches(|| {
103 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
104 });
105
106 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
108 for _ in 0..(T::Pages::get() - 1) {
109 crate::Pallet::<T>::roll_next(false);
110 }
111
112 assert!(matches!(
114 &events_for::<T>()[..],
115 [Event::Verified(_, _), .., Event::Verified(1, _)]
116 ));
117
118 #[block]
120 {
121 crate::Pallet::<T>::roll_next(false);
122 }
123
124 assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
126 assert!(matches!(
128 &events_for::<T>()[..],
129 [Event::Verified(_, _), .., Event::Verified(0, _), Event::Queued(_, None)]
130 ));
131
132 Ok(())
133 }
134
135 #[benchmark(pov_mode = Measured)]
136 fn verification_invalid_terminal() -> Result<(), BenchmarkError> {
137 assert!(T::Pages::get() >= 2, "benchmark only works if we have more than 2 pages");
141
142 #[cfg(test)]
143 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
144 crate::Pallet::<T>::start().unwrap();
145
146 let mut paged_solution = crate::Pallet::<T>::roll_to_signed_and_mine_full_solution();
150 paged_solution.score.minimal_stake -= 1;
151 crate::Pallet::<T>::submit_full_solution(paged_solution)?;
152
153 crate::Pallet::<T>::roll_until_matches(|| {
155 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
156 });
157
158 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
159 for i in 0..T::Pages::get() - 1 {
161 crate::Pallet::<T>::roll_next(false);
162 assert_eq!(
163 StatusStorage::<T>::get(),
164 Status::Ongoing(crate::Pallet::<T>::msp() - 1 - i)
165 );
166 }
167
168 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::lsp()));
170 assert!(matches!(
171 &events_for::<T>()[..],
172 [Event::Verified(_, _), .., Event::Verified(1, _)]
173 ));
174
175 #[block]
176 {
177 crate::Pallet::<T>::roll_next(false);
178 }
179
180 assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
182 assert!(matches!(
183 &events_for::<T>()[..],
184 [
185 ..,
186 Event::Verified(0, _),
187 Event::VerificationFailed(0, FeasibilityError::InvalidScore)
188 ]
189 ));
190
191 Ok(())
192 }
193
194 #[benchmark(pov_mode = Measured)]
195 fn verification_invalid_non_terminal(
196 v: Linear<0, { T::Pages::get() - 1 }>,
199 ) -> Result<(), BenchmarkError> {
200 assert!(T::Pages::get() >= 2, "benchmark only works if we have more than 2 pages");
201
202 #[cfg(test)]
203 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
204 crate::Pallet::<T>::start().unwrap();
205
206 let mut paged_solution = crate::Pallet::<T>::roll_to_signed_and_mine_full_solution();
209 let page_to_corrupt = crate::Pallet::<T>::msp() - v;
210 crate::log!(
211 info,
212 "pages of solution: {:?}, to corrupt {}, v {}",
213 paged_solution.solution_pages.len(),
214 page_to_corrupt,
215 v
216 );
217 paged_solution.solution_pages[page_to_corrupt as usize].corrupt();
218 crate::Pallet::<T>::submit_full_solution(paged_solution)?;
219
220 crate::Pallet::<T>::roll_until_matches(|| {
222 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
223 });
224
225 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
227
228 for _ in 0..v {
230 crate::Pallet::<T>::roll_next(false);
231 }
232
233 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp() - v));
235
236 #[block]
238 {
239 crate::Pallet::<T>::roll_next(false);
240 }
241
242 assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
244
245 assert!(matches!(
246 &events_for::<T>()[..],
247 [.., Event::VerificationFailed(_, FeasibilityError::NposElection(_))]
248 ));
249
250 Ok(())
251 }
252
253 impl_benchmark_test_suite!(
254 Pallet,
255 crate::mock::ExtBuilder::full().build_unchecked(),
256 crate::mock::Runtime
257 );
258}