referrerpolicy=no-referrer-when-downgrade

pallet_registrar_para/
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 `pallet-registrar-para`.
19
20use super::*;
21use frame_benchmarking::v2::*;
22use frame_support::traits::Get;
23use frame_system::RawOrigin;
24use registrar_primitives::{MessageToPara, MessageToParaV1};
25
26/// An account able to pay every consideration this pallet can ask for.
27fn funded_manager<T: Config>() -> T::AccountId {
28	let who: T::AccountId = account("manager", 0, 0);
29	T::ReservationConsideration::ensure_successful(&who, Footprint::from_parts(1, 0));
30	T::RegistrationConsideration::ensure_successful(
31		&who,
32		Pallet::<T>::registration_footprint(T::MaxHeadDataSize::get(), T::MaxCodeSize::get()),
33	);
34	who
35}
36
37/// Reserve a para id for `who` and return it.
38fn reserve_for<T: Config>(who: &T::AccountId) -> Result<ParaId, BenchmarkError> {
39	Pallet::<T>::reserve(RawOrigin::Signed(who.clone()).into())?;
40	Ok(NextFreeParaId::<T>::get().saturating_sub(1))
41}
42
43/// Reserve a para id and put it into `Pending`.
44fn make_pending<T: Config>(who: &T::AccountId) -> Result<ParaId, BenchmarkError> {
45	let para_id = reserve_for::<T>(who)?;
46	Pallet::<T>::register(
47		RawOrigin::Signed(who.clone()).into(),
48		para_id,
49		alloc::vec![2u8; T::MaxHeadDataSize::get() as usize],
50		T::MaxCodeSize::get(),
51		sp_core::H256::repeat_byte(1),
52	)?;
53	Ok(para_id)
54}
55
56/// Reserve a para id and put it into `Registered`.
57fn make_registered<T: Config>(who: &T::AccountId) -> Result<ParaId, BenchmarkError> {
58	let para_id = make_pending::<T>(who)?;
59	Pallet::<T>::receive(
60		RawOrigin::Root.into(),
61		MessageToPara::V1(MessageToParaV1::RegisterResponse {
62			para_id,
63			message_id: 0,
64			outcome: Ok(()),
65		}),
66	)?;
67	Ok(para_id)
68}
69
70/// Reserve a para id, register it and lock it.
71fn make_locked<T: Config>(who: &T::AccountId) -> Result<ParaId, BenchmarkError> {
72	let para_id = make_registered::<T>(who)?;
73	Pallet::<T>::add_lock(RawOrigin::Signed(who.clone()).into(), para_id)?;
74	Ok(para_id)
75}
76
77#[benchmarks]
78mod benchmarks {
79	use super::*;
80
81	#[benchmark]
82	fn reserve() -> Result<(), BenchmarkError> {
83		let who = funded_manager::<T>();
84
85		#[extrinsic_call]
86		_(RawOrigin::Signed(who.clone()));
87
88		let para_id = NextFreeParaId::<T>::get().saturating_sub(1);
89		assert_eq!(Paras::<T>::get(para_id).map(|i| i.manager), Some(who));
90		Ok(())
91	}
92
93	/// Requesting a registration. Dominated by shipping the head data to the relay chain.
94	#[benchmark]
95	fn register(h: Linear<0, { T::MaxHeadDataSize::get() }>) -> Result<(), BenchmarkError> {
96		let who = funded_manager::<T>();
97		let para_id = reserve_for::<T>(&who)?;
98
99		#[extrinsic_call]
100		_(
101			RawOrigin::Signed(who),
102			para_id,
103			alloc::vec![2u8; h as usize],
104			T::MaxCodeSize::get(),
105			sp_core::H256::repeat_byte(1),
106		);
107
108		assert!(matches!(
109			Paras::<T>::get(para_id).map(|i| i.state),
110			Some(RegistrationState::Pending { .. })
111		));
112		Ok(())
113	}
114
115	/// Asking the relay chain to drop an authorization. The deposit stays held, so this is the
116	/// state write plus the message.
117	#[benchmark]
118	fn cancel_registration() -> Result<(), BenchmarkError> {
119		let who = funded_manager::<T>();
120		let para_id = make_pending::<T>(&who)?;
121		T::BlockNumberProvider::set_block_number(
122			T::BlockNumberProvider::current_block_number()
123				.saturating_add(T::PendingDeadline::get())
124				.saturating_add(1u32.into()),
125		);
126
127		#[extrinsic_call]
128		_(RawOrigin::Signed(who), para_id);
129
130		assert!(matches!(
131			Paras::<T>::get(para_id).map(|i| i.state),
132			Some(RegistrationState::Pending { .. })
133		));
134		Ok(())
135	}
136
137	/// The worst case of the messages this call serves is a confirmed cancellation, which releases
138	/// the deposit on top of writing the new state.
139	#[benchmark]
140	fn receive() -> Result<(), BenchmarkError> {
141		let who = funded_manager::<T>();
142		let para_id = make_pending::<T>(&who)?;
143		let message = MessageToPara::V1(MessageToParaV1::CancelResponse {
144			para_id,
145			message_id: 0,
146			outcome: Ok(()),
147		});
148
149		#[extrinsic_call]
150		_(RawOrigin::Root, message);
151
152		assert_eq!(Paras::<T>::get(para_id).map(|i| i.state), Some(RegistrationState::Reserved));
153		Ok(())
154	}
155
156	/// Locking a registered para: one state read and write.
157	#[benchmark]
158	fn add_lock() -> Result<(), BenchmarkError> {
159		let who = funded_manager::<T>();
160		let para_id = make_registered::<T>(&who)?;
161
162		#[extrinsic_call]
163		_(RawOrigin::Signed(who), para_id);
164
165		assert!(Paras::<T>::get(para_id).map(|i| i.is_locked()).unwrap_or(false));
166		Ok(())
167	}
168
169	/// Unlocking, with root standing in for the para itself: both do the same read and write.
170	#[benchmark]
171	fn remove_lock() -> Result<(), BenchmarkError> {
172		let who = funded_manager::<T>();
173		let para_id = make_locked::<T>(&who)?;
174
175		#[extrinsic_call]
176		_(RawOrigin::Root, para_id);
177
178		assert!(!Paras::<T>::get(para_id).map(|i| i.is_locked()).unwrap_or(true));
179		Ok(())
180	}
181
182	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
183}