referrerpolicy=no-referrer-when-downgrade

pallet_nis/
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
18//! Benchmarks for NIS Pallet
19
20#![cfg(feature = "runtime-benchmarks")]
21
22use frame::benchmarking::prelude::*;
23
24use crate::*;
25
26const SEED: u32 = 0;
27
28type BalanceOf<T> =
29	<<T as Config>::Currency as FunInspect<<T as frame_system::Config>::AccountId>>::Balance;
30
31fn fill_queues<T: Config>() -> Result<(), DispatchError> {
32	// filling queues involves filling the first queue entirely and placing a single item in all
33	// other queues.
34
35	let queues = T::QueueCount::get();
36	let bids = T::MaxQueueLen::get();
37
38	let caller: T::AccountId = whitelisted_caller();
39	T::Currency::set_balance(&caller, T::MinBid::get() * BalanceOf::<T>::from(queues + bids));
40
41	for _ in 0..bids {
42		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
43	}
44	for d in 1..queues {
45		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1 + d)?;
46	}
47	Ok(())
48}
49
50#[benchmarks]
51mod benchmarks {
52	use super::*;
53
54	#[benchmark]
55	fn place_bid(l: Linear<0, { T::MaxQueueLen::get() - 1 }>) -> Result<(), BenchmarkError> {
56		let caller: T::AccountId = whitelisted_caller();
57		let ed = T::Currency::minimum_balance();
58		let bid = T::MinBid::get();
59		T::Currency::set_balance(&caller, (ed + bid) * BalanceOf::<T>::from(l + 1) + bid);
60		for _ in 0..l {
61			Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
62		}
63
64		#[extrinsic_call]
65		_(RawOrigin::Signed(caller.clone()), T::MinBid::get() * BalanceOf::<T>::from(2_u32), 1);
66
67		assert_eq!(
68			QueueTotals::<T>::get()[0],
69			(l + 1, T::MinBid::get() * BalanceOf::<T>::from(l + 2))
70		);
71
72		Ok(())
73	}
74
75	#[benchmark]
76	fn place_bid_max() -> Result<(), BenchmarkError> {
77		let caller: T::AccountId = whitelisted_caller();
78		let origin = RawOrigin::Signed(caller.clone());
79		let ed = T::Currency::minimum_balance();
80		let bid = T::MinBid::get();
81		let ql = T::MaxQueueLen::get();
82		T::Currency::set_balance(&caller, (ed + bid) * BalanceOf::<T>::from(ql + 1) + bid);
83		for _ in 0..T::MaxQueueLen::get() {
84			Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
85		}
86
87		#[extrinsic_call]
88		place_bid(origin, T::MinBid::get() * BalanceOf::<T>::from(2_u32), 1);
89
90		assert_eq!(
91			QueueTotals::<T>::get()[0],
92			(
93				T::MaxQueueLen::get(),
94				T::MinBid::get() * BalanceOf::<T>::from(T::MaxQueueLen::get() + 1),
95			)
96		);
97
98		Ok(())
99	}
100
101	#[benchmark]
102	fn retract_bid(l: Linear<1, { T::MaxQueueLen::get() }>) -> Result<(), BenchmarkError> {
103		let caller: T::AccountId = whitelisted_caller();
104		let ed = T::Currency::minimum_balance();
105		let bid = T::MinBid::get();
106		T::Currency::set_balance(&caller, (ed + bid) * BalanceOf::<T>::from(l + 1) + bid);
107		for _ in 0..l {
108			Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
109		}
110
111		#[extrinsic_call]
112		_(RawOrigin::Signed(caller.clone()), T::MinBid::get(), 1);
113
114		assert_eq!(
115			QueueTotals::<T>::get()[0],
116			(l - 1, T::MinBid::get() * BalanceOf::<T>::from(l - 1))
117		);
118
119		Ok(())
120	}
121
122	#[benchmark]
123	fn fund_deficit() -> Result<(), BenchmarkError> {
124		T::BenchmarkSetup::create_counterpart_asset();
125		let origin =
126			T::FundOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
127		let caller: T::AccountId = whitelisted_caller();
128		let bid = T::MinBid::get().max(One::one());
129		let ed = T::Currency::minimum_balance();
130		T::Currency::set_balance(&caller, ed + bid);
131		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
132		Pallet::<T>::process_queues(Perquintill::one(), 1, 1, &mut WeightCounter::unlimited());
133		Pallet::<T>::communify(RawOrigin::Signed(caller.clone()).into(), 0)?;
134		let original = T::Currency::balance(&Pallet::<T>::account_id());
135		T::Currency::set_balance(&Pallet::<T>::account_id(), BalanceOf::<T>::min_value());
136
137		#[extrinsic_call]
138		_(origin as T::RuntimeOrigin);
139
140		// Must fund at least 99.999% of the required amount.
141		let missing =
142			Perquintill::from_rational(T::Currency::balance(&Pallet::<T>::account_id()), original)
143				.left_from_one();
144		assert!(missing <= Perquintill::one() / 100_000);
145
146		Ok(())
147	}
148
149	#[benchmark]
150	fn communify() -> Result<(), BenchmarkError> {
151		T::BenchmarkSetup::create_counterpart_asset();
152		let caller: T::AccountId = whitelisted_caller();
153		let bid = T::MinBid::get().max(One::one()) * 100u32.into();
154		let ed = T::Currency::minimum_balance();
155		T::Currency::set_balance(&caller, ed + bid + bid);
156		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
157		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
158		Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
159
160		#[extrinsic_call]
161		_(RawOrigin::Signed(caller.clone()), 0);
162
163		assert_eq!(Pallet::<T>::owner(&0), None);
164
165		Ok(())
166	}
167
168	#[benchmark]
169	fn privatize() -> Result<(), BenchmarkError> {
170		T::BenchmarkSetup::create_counterpart_asset();
171		let caller: T::AccountId = whitelisted_caller();
172		let bid = T::MinBid::get().max(One::one());
173		let ed = T::Currency::minimum_balance();
174		T::Currency::set_balance(&caller, ed + bid + bid);
175		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
176		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
177		Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
178		Pallet::<T>::communify(RawOrigin::Signed(caller.clone()).into(), 0)?;
179
180		#[extrinsic_call]
181		_(RawOrigin::Signed(caller.clone()), 0);
182
183		assert_eq!(Pallet::<T>::owner(&0), Some(caller));
184
185		Ok(())
186	}
187
188	#[benchmark]
189	fn thaw_private() -> Result<(), BenchmarkError> {
190		T::BenchmarkSetup::create_counterpart_asset();
191		let whale: T::AccountId = account("whale", 0, SEED);
192		let caller: T::AccountId = whitelisted_caller();
193		let bid = T::MinBid::get().max(One::one());
194		let ed = T::Currency::minimum_balance();
195		T::Currency::set_balance(&caller, ed + bid + bid);
196		// Ensure we don't get throttled.
197		T::Currency::set_balance(
198			&whale,
199			T::ThawThrottle::get()
200				.0
201				.saturating_reciprocal_mul_ceil(T::Currency::balance(&caller)),
202		);
203		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
204		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
205		Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
206		frame_system::Pallet::<T>::set_block_number(Receipts::<T>::get(0).unwrap().expiry);
207
208		#[extrinsic_call]
209		_(RawOrigin::Signed(caller.clone()), 0, None);
210
211		assert!(Receipts::<T>::get(0).is_none());
212
213		Ok(())
214	}
215
216	#[benchmark]
217	fn thaw_communal() -> Result<(), BenchmarkError> {
218		T::BenchmarkSetup::create_counterpart_asset();
219		let whale: T::AccountId = account("whale", 0, SEED);
220		let caller: T::AccountId = whitelisted_caller();
221		let bid = T::MinBid::get().max(One::one());
222		let ed = T::Currency::minimum_balance();
223		T::Currency::set_balance(&caller, ed + bid + bid);
224		// Ensure we don't get throttled.
225		T::Currency::set_balance(
226			&whale,
227			T::ThawThrottle::get()
228				.0
229				.saturating_reciprocal_mul_ceil(T::Currency::balance(&caller)),
230		);
231		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
232		Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
233		Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
234		frame_system::Pallet::<T>::set_block_number(Receipts::<T>::get(0).unwrap().expiry);
235		Pallet::<T>::communify(RawOrigin::Signed(caller.clone()).into(), 0)?;
236
237		#[extrinsic_call]
238		_(RawOrigin::Signed(caller.clone()), 0);
239
240		assert!(Receipts::<T>::get(0).is_none());
241
242		Ok(())
243	}
244
245	#[benchmark]
246	fn process_queues() -> Result<(), BenchmarkError> {
247		fill_queues::<T>()?;
248
249		#[block]
250		{
251			Pallet::<T>::process_queues(
252				Perquintill::one(),
253				Zero::zero(),
254				u32::max_value(),
255				&mut WeightCounter::unlimited(),
256			);
257		}
258
259		Ok(())
260	}
261
262	#[benchmark]
263	fn process_queue() {
264		let our_account = Pallet::<T>::account_id();
265		let issuance = Pallet::<T>::issuance();
266		let mut summary = Summary::<T>::get();
267
268		#[block]
269		{
270			Pallet::<T>::process_queue(
271				1_u32,
272				1_u32.into(),
273				&our_account,
274				&issuance,
275				0,
276				&mut Bounded::max_value(),
277				&mut (T::MaxQueueLen::get(), Bounded::max_value()),
278				&mut summary,
279				&mut WeightCounter::unlimited(),
280			);
281		}
282	}
283
284	#[benchmark]
285	fn process_bid() {
286		let who = account::<T::AccountId>("bidder", 0, SEED);
287		let min_bid = T::MinBid::get().max(One::one());
288		let ed = T::Currency::minimum_balance();
289		T::Currency::set_balance(&who, ed + min_bid);
290		let bid = Bid { amount: T::MinBid::get(), who };
291		let our_account = Pallet::<T>::account_id();
292		let issuance = Pallet::<T>::issuance();
293		let mut summary = Summary::<T>::get();
294
295		#[block]
296		{
297			Pallet::<T>::process_bid(
298				bid,
299				2_u32.into(),
300				&our_account,
301				&issuance,
302				&mut Bounded::max_value(),
303				&mut Bounded::max_value(),
304				&mut summary,
305			);
306		}
307	}
308
309	impl_benchmark_test_suite! {
310		Pallet,
311		mock::new_test_ext_empty(),
312		mock::Test
313	}
314}