frequency_cli/
benchmarking.rs

1//! Setup code for [`super::command`] which would otherwise bloat that module.
2//!
3//! Should only be used for benchmarking as it may break in other contexts.
4#![allow(clippy::unwrap_used, clippy::expect_used)]
5
6use common_primitives::node::{AccountId, Balance, Signature};
7use frame_support::pallet_prelude::InherentData;
8use frame_system::{Call as SystemCall, Config};
9use frequency_service::service::{frequency_runtime as runtime, ParachainClient as FullClient};
10use sc_cli::Result;
11use sc_client_api::BlockBackend;
12use sp_core::{Encode, Pair};
13use sp_keyring::Sr25519Keyring;
14use sp_runtime::{OpaqueExtrinsic, SaturatedConversion};
15
16use pallet_balances::Call as BalancesCall;
17use sp_inherents::InherentDataProvider;
18use std::{sync::Arc, time::Duration};
19
20/// Generates extrinsics for the `benchmark overhead` command.
21///
22/// Note: Should only be used for benchmarking.
23pub struct RemarkBuilder {
24	client: Arc<FullClient>,
25}
26
27impl RemarkBuilder {
28	/// Creates a new [`Self`] from the given client.
29	pub fn new(client: Arc<FullClient>) -> Self {
30		Self { client }
31	}
32}
33
34impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
35	fn pallet(&self) -> &str {
36		"system"
37	}
38
39	fn extrinsic(&self) -> &str {
40		"remark"
41	}
42
43	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
44		let acc = Sr25519Keyring::Bob.pair();
45		let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
46			self.client.as_ref(),
47			acc,
48			SystemCall::remark { remark: vec![] }.into(),
49			nonce,
50		)
51		.into();
52
53		Ok(extrinsic)
54	}
55}
56
57/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks.
58///
59/// Note: Should only be used for benchmarking.
60pub struct TransferKeepAliveBuilder {
61	client: Arc<FullClient>,
62	dest: AccountId,
63	value: Balance,
64}
65
66impl TransferKeepAliveBuilder {
67	/// Creates a new [`Self`] from the given client.
68	pub fn new(client: Arc<FullClient>, dest: AccountId, value: Balance) -> Self {
69		Self { client, dest, value }
70	}
71}
72
73impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
74	fn pallet(&self) -> &str {
75		"balances"
76	}
77
78	fn extrinsic(&self) -> &str {
79		"transfer_keep_alive"
80	}
81
82	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
83		let acc = Sr25519Keyring::Bob.pair();
84		let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
85			self.client.as_ref(),
86			acc,
87			BalancesCall::transfer_keep_alive { dest: self.dest.clone().into(), value: self.value }
88				.into(),
89			nonce,
90		)
91		.into();
92
93		Ok(extrinsic)
94	}
95}
96
97/// Create a transaction using the given `call`.
98///
99/// Note: Should only be used for benchmarking.
100pub fn create_benchmark_extrinsic(
101	client: &FullClient,
102	sender: sp_core::sr25519::Pair,
103	call: runtime::RuntimeCall,
104	nonce: u32,
105) -> runtime::UncheckedExtrinsic {
106	let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed");
107	let best_hash = client.chain_info().best_hash;
108	let best_block = client.chain_info().best_number;
109
110	let period = <runtime::Runtime as Config>::BlockHashCount::get()
111		.checked_next_power_of_two()
112		.map(|c| c / 2)
113		.unwrap_or(2) as u64;
114
115	#[allow(deprecated)]
116	let extra: runtime::TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim::<
117		runtime::Runtime,
118		_,
119	>::new((
120		frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
121		(
122			frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
123			frame_system::CheckTxVersion::<runtime::Runtime>::new(),
124		),
125		frame_system::CheckGenesis::<runtime::Runtime>::new(),
126		frame_system::CheckEra::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
127			period,
128			best_block.saturated_into(),
129		)),
130		common_runtime::extensions::check_nonce::CheckNonce::<runtime::Runtime>::from(nonce),
131		pallet_frequency_tx_payment::ChargeFrqTransactionPayment::<runtime::Runtime>::from(0),
132		pallet_msa::CheckFreeExtrinsicUse::<runtime::Runtime>::new(),
133		pallet_handles::handles_signed_extension::HandlesSignedExtension::<runtime::Runtime>::new(),
134		frame_metadata_hash_extension::CheckMetadataHash::<runtime::Runtime>::new(false),
135		frame_system::CheckWeight::<runtime::Runtime>::new(),
136	));
137	let raw_payload = sp_runtime::generic::SignedPayload::from_raw(
138		call.clone(),
139		extra.clone(),
140		(
141			(),
142			(runtime::VERSION.spec_version, runtime::VERSION.transaction_version),
143			genesis_hash,
144			best_hash,
145			(),
146			(),
147			(),
148			(),
149			None,
150			(),
151		),
152	);
153	let signature = raw_payload.using_encoded(|e| sender.sign(e));
154
155	runtime::UncheckedExtrinsic::new_signed(
156		call.clone(),
157		sp_runtime::AccountId32::from(sender.public()).into(),
158		Signature::Sr25519(signature),
159		extra.clone(),
160	)
161}
162
163/// Generates inherent data for the `benchmark overhead` command.
164///
165/// Note: Should only be used for benchmarking.
166pub fn inherent_benchmark_data() -> Result<InherentData> {
167	let mut inherent_data = InherentData::new();
168	let d = Duration::from_millis(0);
169	let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
170	let mock_para_inherent_provider =
171		cumulus_client_parachain_inherent::MockValidationDataInherentDataProvider {
172			para_id: 1000.into(),
173			current_para_block_head: Some(cumulus_primitives_core::relay_chain::HeadData::default()),
174			current_para_block: 0,
175			relay_offset: 1,
176			relay_blocks_per_para_block: 1,
177			xcm_config: Default::default(),
178			raw_downward_messages: Default::default(),
179			raw_horizontal_messages: Default::default(),
180			para_blocks_per_relay_epoch: 2,
181			relay_randomness_config: (),
182			additional_key_values: Some(vec![]),
183			upgrade_go_ahead: None,
184		};
185
186	futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data))
187		.map_err(|e| format!("creating inherent data: {e:?}"))?;
188	futures::executor::block_on(
189		mock_para_inherent_provider.provide_inherent_data(&mut inherent_data),
190	)
191	.map_err(|e| format!("creating cumulus inherent data: {e:?}"))?;
192
193	Ok(inherent_data)
194}