Skip to main content

pezframe_benchmarking_cli/overhead/
remark_builder.rs

1// This file is part of Bizinikiwi.
2
3// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
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::extrinsic::ExtrinsicBuilder;
19use codec::{Decode, Encode};
20use pezkuwi_subxt::{
21	client::RuntimeVersion as SubxtRuntimeVersion,
22	config::{bizinikiwi::BizinikiwiExtrinsicParamsBuilder as ParamsBuilder, HashFor},
23	BizinikiwConfig, Config, OfflineClient,
24};
25use pezsc_client_api::UsageProvider;
26use pezsp_api::{ApiExt, Core, Metadata, ProvideRuntimeApi};
27use pezsp_runtime::{traits::Block as BlockT, OpaqueExtrinsic};
28use std::sync::Arc;
29
30/// Bizinikiwi configuration
31pub type BizinikiwiConfig = BizinikiwConfig;
32/// Bizinikiwi extrinsic params builder
33pub type BizinikiwiExtrinsicParamsBuilder = ParamsBuilder<BizinikiwiConfig>;
34
35pub type BizinikiwiRemarkBuilder = DynamicRemarkBuilder<BizinikiwiConfig>;
36
37/// Remark builder that can be used to build simple extrinsics for
38/// FRAME-based runtimes.
39pub struct DynamicRemarkBuilder<C: Config> {
40	offline_client: OfflineClient<C>,
41}
42
43impl<C: Config> DynamicRemarkBuilder<C> {
44	/// Initializes a new remark builder from a client.
45	///
46	/// This will first fetch metadata and runtime version from the runtime and then
47	/// construct an offline client that provides the extrinsics.
48	pub fn new_from_client<Client, Block>(client: Arc<Client>) -> pezsc_cli::Result<Self>
49	where
50		Block: BlockT,
51		Client: UsageProvider<Block> + ProvideRuntimeApi<Block>,
52		Client::Api: Metadata<Block> + Core<Block>,
53	{
54		let genesis = client.usage_info().chain.best_hash;
55		let api = client.runtime_api();
56
57		let Ok(Some(metadata_api_version)) = api.api_version::<dyn Metadata<Block>>(genesis) else {
58			return Err("Unable to fetch metadata runtime API version.".to_string().into());
59		};
60
61		log::debug!("Found metadata API version {}.", metadata_api_version);
62		let opaque_metadata = if metadata_api_version > 1 {
63			let Ok(supported_metadata_versions) = api.metadata_versions(genesis) else {
64				return Err("Unable to fetch metadata versions".to_string().into());
65			};
66
67			let latest = supported_metadata_versions
68				.into_iter()
69				.max()
70				.ok_or("No stable metadata versions supported".to_string())?;
71
72			api.metadata_at_version(genesis, latest)
73				.map_err(|e| format!("Unable to fetch metadata: {:?}", e))?
74				.ok_or("Unable to decode metadata".to_string())?
75		} else {
76			// Fall back to using the non-versioned metadata API.
77			api.metadata(genesis)
78				.map_err(|e| format!("Unable to fetch metadata: {:?}", e))?
79		};
80
81		let version = api.version(genesis).unwrap();
82		let runtime_version = SubxtRuntimeVersion {
83			spec_version: version.spec_version,
84			transaction_version: version.transaction_version,
85		};
86		let metadata = pezkuwi_subxt::Metadata::decode(&mut (*opaque_metadata).as_slice())?;
87		let genesis = HashFor::<C>::decode(&mut &genesis.encode()[..])
88			.map_err(|_| "Incompatible hash types?")?;
89
90		Ok(Self { offline_client: OfflineClient::new(genesis, runtime_version, metadata) })
91	}
92}
93
94impl<C: Config> DynamicRemarkBuilder<C> {
95	/// Constructs a new remark builder.
96	pub fn new(
97		metadata: pezkuwi_subxt::Metadata,
98		genesis_hash: HashFor<C>,
99		runtime_version: SubxtRuntimeVersion,
100	) -> Self {
101		Self { offline_client: OfflineClient::new(genesis_hash, runtime_version, metadata) }
102	}
103}
104
105impl ExtrinsicBuilder for DynamicRemarkBuilder<BizinikiwiConfig> {
106	fn pezpallet(&self) -> &str {
107		"system"
108	}
109
110	fn extrinsic(&self) -> &str {
111		"remark"
112	}
113
114	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
115		let signer = pezkuwi_subxt_signer::sr25519::dev::alice();
116		let dynamic_tx = pezkuwi_subxt::dynamic::tx("System", "remark", vec![Vec::<u8>::new()]);
117
118		let params = BizinikiwiExtrinsicParamsBuilder::new().nonce(nonce.into()).build();
119
120		// Default transaction parameters assume a nonce of 0.
121		let transaction = self
122			.offline_client
123			.tx()
124			.create_partial_offline(&dynamic_tx, params)
125			.unwrap()
126			.sign(&signer);
127		let mut encoded = transaction.into_encoded();
128
129		OpaqueExtrinsic::try_from_encoded_extrinsic(&mut encoded)
130			.map_err(|_| "Unable to construct OpaqueExtrinsic")
131	}
132}