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 verification_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
55 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
57
58 #[block]
59 {
60 crate::Pallet::<T>::roll_next(false);
61 }
62 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp() - 1));
63
64 Ok(())
65 }
66
67 #[benchmark(pov_mode = Measured)]
68 fn verification_valid_terminal() -> Result<(), BenchmarkError> {
69 #[cfg(test)]
70 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
71 crate::Pallet::<T>::start().unwrap();
72
73 assert!(
75 T::SignedValidationPhase::get() >= T::Pages::get().into(),
76 "Signed validation phase must be larger than the number of pages"
77 );
78
79 crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
80 crate::Pallet::<T>::roll_until_matches(|| {
82 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
83 });
84
85 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
87 for _ in 0..(T::Pages::get() - 1) {
88 crate::Pallet::<T>::roll_next(false);
89 }
90
91 assert!(matches!(
93 &events_for::<T>()[..],
94 [Event::Verified(_, _), .., Event::Verified(1, _)]
95 ));
96
97 #[block]
99 {
100 crate::Pallet::<T>::roll_next(false);
101 }
102
103 assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
105 assert!(matches!(
107 &events_for::<T>()[..],
108 [Event::Verified(_, _), .., Event::Verified(0, _), Event::Queued(_, None)]
109 ));
110
111 Ok(())
112 }
113
114 #[benchmark(pov_mode = Measured)]
115 fn verification_invalid_terminal() -> Result<(), BenchmarkError> {
116 assert!(T::Pages::get() >= 2, "benchmark only works if we have more than 2 pages");
120
121 #[cfg(test)]
122 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
123 crate::Pallet::<T>::start().unwrap();
124
125 let mut paged_solution = crate::Pallet::<T>::roll_to_signed_and_mine_full_solution();
129 paged_solution.score.minimal_stake -= 1;
130 crate::Pallet::<T>::submit_full_solution(paged_solution)?;
131
132 crate::Pallet::<T>::roll_until_matches(|| {
134 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
135 });
136
137 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
138 for i in 0..T::Pages::get() - 1 {
140 crate::Pallet::<T>::roll_next(false);
141 assert_eq!(
142 StatusStorage::<T>::get(),
143 Status::Ongoing(crate::Pallet::<T>::msp() - 1 - i)
144 );
145 }
146
147 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::lsp()));
149 assert!(matches!(
150 &events_for::<T>()[..],
151 [Event::Verified(_, _), .., Event::Verified(1, _)]
152 ));
153
154 #[block]
155 {
156 crate::Pallet::<T>::roll_next(false);
157 }
158
159 assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
161 assert!(matches!(
162 &events_for::<T>()[..],
163 [
164 ..,
165 Event::Verified(0, _),
166 Event::VerificationFailed(0, FeasibilityError::InvalidScore)
167 ]
168 ));
169
170 Ok(())
171 }
172
173 #[benchmark(pov_mode = Measured)]
174 fn verification_invalid_non_terminal(
175 v: Linear<0, { T::Pages::get() - 1 }>,
178 ) -> Result<(), BenchmarkError> {
179 assert!(T::Pages::get() >= 2, "benchmark only works if we have more than 2 pages");
180
181 #[cfg(test)]
182 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
183 crate::Pallet::<T>::start().unwrap();
184
185 let mut paged_solution = crate::Pallet::<T>::roll_to_signed_and_mine_full_solution();
188 let page_to_corrupt = crate::Pallet::<T>::msp() - v;
189 crate::log!(
190 info,
191 "pages of solution: {:?}, to corrupt {}, v {}",
192 paged_solution.solution_pages.len(),
193 page_to_corrupt,
194 v
195 );
196 paged_solution.solution_pages[page_to_corrupt as usize].corrupt();
197 crate::Pallet::<T>::submit_full_solution(paged_solution)?;
198
199 crate::Pallet::<T>::roll_until_matches(|| {
201 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
202 });
203
204 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp()));
206
207 for _ in 0..v {
209 crate::Pallet::<T>::roll_next(false);
210 }
211
212 assert_eq!(StatusStorage::<T>::get(), Status::Ongoing(crate::Pallet::<T>::msp() - v));
214
215 #[block]
217 {
218 crate::Pallet::<T>::roll_next(false);
219 }
220
221 assert_eq!(StatusStorage::<T>::get(), Status::Nothing);
223
224 assert!(matches!(
225 &events_for::<T>()[..],
226 [.., Event::VerificationFailed(_, FeasibilityError::NposElection(_))]
227 ));
228
229 Ok(())
230 }
231
232 impl_benchmark_test_suite!(
233 Pallet,
234 crate::mock::ExtBuilder::full().build_unchecked(),
235 crate::mock::Runtime
236 );
237}