referrerpolicy=no-referrer-when-downgrade

pallet_election_provider_multi_block/signed/
benchmarking.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{
19	signed::{Config, Pallet, Submissions},
20	types::PagedRawSolution,
21	unsigned::miner::OffchainWorkerMiner,
22	CurrentPhase, Phase, Round,
23};
24use frame_benchmarking::v2::*;
25use frame_election_provider_support::ElectionProvider;
26use frame_support::pallet_prelude::*;
27use frame_system::RawOrigin;
28use sp_npos_elections::ElectionScore;
29use sp_runtime::traits::One;
30use sp_std::boxed::Box;
31
32#[benchmarks(where T: crate::Config + crate::verifier::Config + crate::unsigned::Config)]
33mod benchmarks {
34	use super::*;
35
36	#[benchmark(pov_mode = Measured)]
37	fn register_not_full() -> Result<(), BenchmarkError> {
38		CurrentPhase::<T>::put(Phase::Signed(T::SignedPhase::get() - One::one()));
39		let round = Round::<T>::get();
40		let alice = crate::Pallet::<T>::funded_account("alice", 0);
41		let score = ElectionScore::default();
42
43		assert_eq!(Submissions::<T>::sorted_submitters(round).len(), 0);
44		#[block]
45		{
46			Pallet::<T>::register(RawOrigin::Signed(alice).into(), score)?;
47		}
48
49		assert_eq!(Submissions::<T>::sorted_submitters(round).len(), 1);
50		Ok(())
51	}
52
53	#[benchmark(pov_mode = Measured)]
54	fn register_eject() -> Result<(), BenchmarkError> {
55		CurrentPhase::<T>::put(Phase::Signed(T::SignedPhase::get() - One::one()));
56		let round = Round::<T>::get();
57
58		for i in 0..T::MaxSubmissions::get() {
59			let submitter = crate::Pallet::<T>::funded_account("submitter", i);
60			let score = ElectionScore { minimal_stake: i.into(), ..Default::default() };
61			Pallet::<T>::register(RawOrigin::Signed(submitter.clone()).into(), score)?;
62
63			// The first one, which will be ejected, has also submitted all pages
64			if i == 0 {
65				for p in 0..T::Pages::get() {
66					let page = Some(Default::default());
67					Pallet::<T>::submit_page(RawOrigin::Signed(submitter.clone()).into(), p, page)?;
68				}
69			}
70		}
71
72		let who = crate::Pallet::<T>::funded_account("who", 0);
73		let score =
74			ElectionScore { minimal_stake: T::MaxSubmissions::get().into(), ..Default::default() };
75
76		assert_eq!(
77			Submissions::<T>::sorted_submitters(round).len(),
78			T::MaxSubmissions::get() as usize
79		);
80
81		#[block]
82		{
83			Pallet::<T>::register(RawOrigin::Signed(who).into(), score)?;
84		}
85
86		assert_eq!(
87			Submissions::<T>::sorted_submitters(round).len(),
88			T::MaxSubmissions::get() as usize
89		);
90		Ok(())
91	}
92
93	#[benchmark(pov_mode = Measured)]
94	fn submit_page() -> Result<(), BenchmarkError> {
95		#[cfg(test)]
96		crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
97		crate::Pallet::<T>::start().unwrap();
98
99		crate::Pallet::<T>::roll_until_matches(|| {
100			matches!(CurrentPhase::<T>::get(), Phase::Signed(_))
101		});
102
103		// mine a full solution
104		let PagedRawSolution { score, solution_pages, .. } =
105			OffchainWorkerMiner::<T>::mine_solution(T::Pages::get(), false).unwrap();
106		let page = Some(Box::new(solution_pages[0].clone()));
107
108		// register alice
109		let alice = crate::Pallet::<T>::funded_account("alice", 0);
110		Pallet::<T>::register(RawOrigin::Signed(alice.clone()).into(), score)?;
111
112		#[block]
113		{
114			Pallet::<T>::submit_page(RawOrigin::Signed(alice).into(), 0, page)?;
115		}
116
117		Ok(())
118	}
119
120	#[benchmark(pov_mode = Measured)]
121	fn unset_page() -> Result<(), BenchmarkError> {
122		#[cfg(test)]
123		crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
124		crate::Pallet::<T>::start().unwrap();
125
126		crate::Pallet::<T>::roll_until_matches(|| {
127			matches!(CurrentPhase::<T>::get(), Phase::Signed(_))
128		});
129
130		// mine a full solution
131		let PagedRawSolution { score, solution_pages, .. } =
132			OffchainWorkerMiner::<T>::mine_solution(T::Pages::get(), false).unwrap();
133		let page = Some(Box::new(solution_pages[0].clone()));
134
135		// register alice
136		let alice = crate::Pallet::<T>::funded_account("alice", 0);
137		Pallet::<T>::register(RawOrigin::Signed(alice.clone()).into(), score)?;
138
139		// submit page
140		Pallet::<T>::submit_page(RawOrigin::Signed(alice.clone()).into(), 0, page)?;
141
142		#[block]
143		{
144			Pallet::<T>::submit_page(RawOrigin::Signed(alice).into(), 0, None)?;
145		}
146
147		Ok(())
148	}
149
150	#[benchmark(pov_mode = Measured)]
151	fn bail() -> Result<(), BenchmarkError> {
152		CurrentPhase::<T>::put(Phase::Signed(T::SignedPhase::get() - One::one()));
153		let alice = crate::Pallet::<T>::funded_account("alice", 0);
154
155		// register alice
156		let score = ElectionScore::default();
157		Pallet::<T>::register(RawOrigin::Signed(alice.clone()).into(), score)?;
158
159		// submit all pages
160		for p in 0..T::Pages::get() {
161			let page = Some(Default::default());
162			Pallet::<T>::submit_page(RawOrigin::Signed(alice.clone()).into(), p, page)?;
163		}
164
165		#[block]
166		{
167			Pallet::<T>::bail(RawOrigin::Signed(alice).into())?;
168		}
169
170		Ok(())
171	}
172
173	#[benchmark(pov_mode = Measured)]
174	fn clear_old_round_data(p: Linear<1, { T::Pages::get() }>) -> Result<(), BenchmarkError> {
175		// set signed phase and alice ready to submit
176		CurrentPhase::<T>::put(Phase::Signed(T::SignedPhase::get() - One::one()));
177		let alice = crate::Pallet::<T>::funded_account("alice", 0);
178
179		// register alice
180		let score = ElectionScore::default();
181		Pallet::<T>::register(RawOrigin::Signed(alice.clone()).into(), score)?;
182
183		// submit a solution with p pages.
184		for pp in 0..p {
185			let page = Some(Default::default());
186			Pallet::<T>::submit_page(RawOrigin::Signed(alice.clone()).into(), pp, page)?;
187		}
188
189		// force rotate to the next round.
190		let prev_round = Round::<T>::get();
191		crate::Pallet::<T>::rotate_round();
192
193		#[block]
194		{
195			Pallet::<T>::clear_old_round_data(RawOrigin::Signed(alice).into(), prev_round, p)?;
196		}
197
198		Ok(())
199	}
200
201	impl_benchmark_test_suite!(
202		Pallet,
203		crate::mock::ExtBuilder::signed().build_unchecked(),
204		crate::mock::Runtime
205	);
206}