referrerpolicy=no-referrer-when-downgrade

pallet_registrar_relay/
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-relay`.
19
20use super::*;
21use frame_benchmarking::v2::*;
22use frame_support::traits::Get;
23use frame_system::RawOrigin;
24use registrar_primitives::{MessageToRelay, MessageToRelayV1};
25use sp_runtime::traits::{BlakeTwo256, Hash};
26
27/// A para id no benchmark setup will collide on.
28const PARA_ID: ParaId = 4_242;
29
30fn code_of(len: u32) -> Vec<u8> {
31	alloc::vec![1u8; len as usize]
32}
33
34/// Park a pending registration for `PARA_ID` expecting exactly `code`.
35///
36/// Written straight to storage rather than pushed through [`Pallet::authorize_code`]: going
37/// through the call would put the whole range at the mercy of whatever minimum code size the
38/// configured [`ParachainRegistrar`] enforces, and `c = 0` would fail setup instead of measuring
39/// anything.
40fn park<T: Config>(code: &[u8]) -> Result<(), BenchmarkError> {
41	let genesis_head = alloc::vec![2u8; T::MaxHeadDataSize::get() as usize];
42	let pending = PendingRegistration {
43		message_id: 0,
44		manager: account("manager", 0, 0),
45		genesis_head: genesis_head.try_into().map_err(|_| "head data exceeds its own bound")?,
46		code_hash: BlakeTwo256::hash(code),
47		code_len: code.len() as u32,
48	};
49
50	PendingRegistrations::<T>::insert(PARA_ID, pending);
51	Ok(())
52}
53
54#[benchmarks]
55mod benchmarks {
56	use super::*;
57
58	/// Accepting a registration request. Dominated by writing the head data.
59	#[benchmark]
60	fn authorize_code(h: Linear<0, { T::MaxHeadDataSize::get() }>) -> Result<(), BenchmarkError> {
61		let manager: T::AccountId = account("manager", 0, 0);
62		let code = code_of(T::MaxCodeSize::get());
63		let message = MessageToRelay::V1(MessageToRelayV1::Register {
64			para_id: PARA_ID,
65			message_id: 0,
66			manager,
67			genesis_head: alloc::vec![2u8; h as usize],
68			code_hash: BlakeTwo256::hash(&code),
69			code_len: code.len() as u32,
70		});
71
72		#[extrinsic_call]
73		authorize_code(RawOrigin::Root, message);
74
75		assert!(PendingRegistrations::<T>::contains_key(PARA_ID));
76		Ok(())
77	}
78
79	/// Uploading the validation code. Dominated by hashing and onboarding the blob.
80	#[benchmark]
81	fn apply_authorized_code(
82		c: Linear<0, { T::MaxCodeSize::get() }>,
83	) -> Result<(), BenchmarkError> {
84		let code = code_of(c);
85		park::<T>(&code)?;
86
87		#[extrinsic_call]
88		_(RawOrigin::Authorized, PARA_ID, code);
89
90		assert!(!PendingRegistrations::<T>::contains_key(PARA_ID));
91		Ok(())
92	}
93
94	/// Deciding whether an unsigned `apply_authorized_code` may enter the pool.
95	///
96	/// This runs on every node for every candidate transaction, so it is the number that keeps
97	/// the free call from being a cheap way to make everyone hash megabytes.
98	#[benchmark]
99	fn authorize_apply_authorized_code(
100		c: Linear<0, { T::MaxCodeSize::get() }>,
101	) -> Result<(), BenchmarkError> {
102		let code = code_of(c);
103		park::<T>(&code)?;
104		let call = Call::<T>::apply_authorized_code { para_id: PARA_ID, validation_code: code };
105
106		#[block]
107		{
108			use frame_support::pallet_prelude::Authorize;
109			call.authorize(sp_runtime::transaction_validity::TransactionSource::External)
110				.ok_or("call must give some authorization")??;
111		}
112
113		Ok(())
114	}
115
116	/// Dropping an authorization. The worst case carries the largest head data, since that is what
117	/// the entry being removed holds.
118	#[benchmark]
119	fn cancel_authorization() -> Result<(), BenchmarkError> {
120		park::<T>(&code_of(T::MaxCodeSize::get()))?;
121		let message = MessageToRelay::V1(MessageToRelayV1::CancelRegistration {
122			para_id: PARA_ID,
123			message_id: 0,
124		});
125
126		#[extrinsic_call]
127		_(RawOrigin::Root, message);
128
129		assert!(!PendingRegistrations::<T>::contains_key(PARA_ID));
130		Ok(())
131	}
132
133	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
134}