Skip to content

Commit

Permalink
Move remark builders to own file.
Browse files Browse the repository at this point in the history
  • Loading branch information
skunert committed Oct 30, 2024
1 parent 9cab200 commit 52458b8
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 108 deletions.
5 changes: 2 additions & 3 deletions substrate/utils/frame/benchmarking-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ pub use block::BlockCmd;
pub use extrinsic::{ExtrinsicBuilder, ExtrinsicCmd, ExtrinsicFactory};
pub use machine::{MachineCmd, SUBSTRATE_REFERENCE_HARDWARE};
pub use overhead::{
runtime_utilities::{
fetch_latest_metadata_from_code_blob, DynamicRemarkBuilder, SubstrateRemarkBuilder,
},
remark_builder::{DynamicRemarkBuilder, SubstrateRemarkBuilder},
runtime_utilities::fetch_latest_metadata_from_code_blob,
OpaqueBlock, OverheadCmd,
};
pub use pallet::PalletCmd;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::{
overhead::{
command::ChainType::{Parachain, Relaychain, Unknown},
fake_runtime_api,
remark_builder::SubstrateRemarkBuilder,
template::TemplateData,
},
shared::{
Expand Down
4 changes: 3 additions & 1 deletion substrate/utils/frame/benchmarking-cli/src/overhead/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
pub mod command;
pub mod template;

pub use command::{OpaqueBlock, OverheadCmd};
mod fake_runtime_api;
pub mod remark_builder;
pub mod runtime_utilities;

pub use command::{OpaqueBlock, OverheadCmd};
122 changes: 122 additions & 0 deletions substrate/utils/frame/benchmarking-cli/src/overhead/remark_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::extrinsic::ExtrinsicBuilder;
use codec::Decode;
use sc_client_api::UsageProvider;
use sp_api::{ApiExt, Core, Metadata, ProvideRuntimeApi};
use sp_runtime::{traits::Block as BlockT, OpaqueExtrinsic};
use std::sync::Arc;
use subxt::{
client::RuntimeVersion as SubxtRuntimeVersion,
config::substrate::SubstrateExtrinsicParamsBuilder, Config, OfflineClient, SubstrateConfig,
};

pub type SubstrateRemarkBuilder = DynamicRemarkBuilder<SubstrateConfig>;

/// Remark builder that can be used to build simple extrinsics for
/// FRAME-based runtimes.
pub struct DynamicRemarkBuilder<C: Config> {
offline_client: OfflineClient<C>,
}

impl<C: Config<Hash = subxt::utils::H256>> DynamicRemarkBuilder<C> {
/// Initializes a new remark builder from a client.
///
/// This will first fetch metadata and runtime version from the runtime and then
/// construct an offline client that provides the extrinsics.
pub fn new_from_client<Client, Block>(client: Arc<Client>) -> sc_cli::Result<Self>
where
Block: BlockT<Hash = sp_core::H256>,
Client: UsageProvider<Block> + ProvideRuntimeApi<Block>,
Client::Api: Metadata<Block> + Core<Block>,
{
let genesis = client.usage_info().chain.best_hash;
let api = client.runtime_api();

let Ok(Some(metadata_api_version)) = api.api_version::<dyn Metadata<Block>>(genesis) else {
return Err("Unable to fetch metadata runtime API version.".to_string().into());
};

log::debug!("Found metadata API version {}.", metadata_api_version);
let opaque_metadata = if metadata_api_version > 1 {
let Ok(mut supported_metadata_versions) = api.metadata_versions(genesis) else {
return Err("Unable to fetch metadata versions".to_string().into());
};

let latest = supported_metadata_versions
.pop()
.ok_or("No metadata version supported".to_string())?;

api.metadata_at_version(genesis, latest)
.map_err(|e| format!("Unable to fetch metadata: {:?}", e))?
.ok_or("Unable to decode metadata".to_string())?
} else {
// Fall back to using the non-versioned metadata API.
api.metadata(genesis)
.map_err(|e| format!("Unable to fetch metadata: {:?}", e))?
};

let version = api.version(genesis).unwrap();
let runtime_version = SubxtRuntimeVersion {
spec_version: version.spec_version,
transaction_version: version.transaction_version,
};
let metadata = subxt::Metadata::decode(&mut (*opaque_metadata).as_slice())?;
let genesis = subxt::utils::H256::from(genesis.to_fixed_bytes());

Ok(Self { offline_client: OfflineClient::new(genesis, runtime_version, metadata) })
}
}

impl<C: Config> DynamicRemarkBuilder<C> {
/// Constructs a new remark builder.
pub fn new(
metadata: subxt::Metadata,
genesis_hash: C::Hash,
runtime_version: SubxtRuntimeVersion,
) -> Self {
Self { offline_client: OfflineClient::new(genesis_hash, runtime_version, metadata) }
}
}

impl ExtrinsicBuilder for DynamicRemarkBuilder<SubstrateConfig> {
fn pallet(&self) -> &str {
"system"
}

fn extrinsic(&self) -> &str {
"remark"
}

fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let signer = subxt_signer::sr25519::dev::alice();
let dynamic_tx = subxt::dynamic::tx("System", "remark", vec![Vec::<u8>::new()]);

let params = SubstrateExtrinsicParamsBuilder::new().nonce(nonce.into()).build();

// Default transaction parameters assume a nonce of 0.
let transaction = self
.offline_client
.tx()
.create_signed_offline(&dynamic_tx, &signer, params)
.unwrap();
let mut encoded = transaction.into_encoded();

OpaqueExtrinsic::from_bytes(&mut encoded).map_err(|_| "Unable to construct OpaqueExtrinsic")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,118 +15,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::extrinsic::ExtrinsicBuilder;
use codec::{Decode, Encode};
use sc_client_api::UsageProvider;
use sc_executor::WasmExecutor;
use sp_api::{ApiExt, Core, Metadata, ProvideRuntimeApi};
use sp_core::{
traits::{CallContext, CodeExecutor, FetchRuntimeCode, RuntimeCode},
OpaqueMetadata,
};
use sp_runtime::{traits::Block as BlockT, OpaqueExtrinsic};
use sp_state_machine::BasicExternalities;
use sp_wasm_interface::HostFunctions;
use std::{borrow::Cow, sync::Arc};
use subxt::{
client::RuntimeVersion as SubxtRuntimeVersion,
config::substrate::SubstrateExtrinsicParamsBuilder, Config, OfflineClient, SubstrateConfig,
};

pub type SubstrateRemarkBuilder = DynamicRemarkBuilder<SubstrateConfig>;

/// Remark builder that can be used to build simple extrinsics for
/// FRAME-based runtimes.
pub struct DynamicRemarkBuilder<C: Config> {
offline_client: OfflineClient<C>,
}

impl<C: Config<Hash = subxt::utils::H256>> DynamicRemarkBuilder<C> {
/// Initializes a new remark builder from a client.
///
/// This will first fetch metadata and runtime version from the runtime and then
/// construct an offline client that provides the extrinsics.
pub fn new_from_client<Client, Block>(client: Arc<Client>) -> sc_cli::Result<Self>
where
Block: BlockT<Hash = sp_core::H256>,
Client: UsageProvider<Block> + ProvideRuntimeApi<Block>,
Client::Api: Metadata<Block> + Core<Block>,
{
let genesis = client.usage_info().chain.best_hash;
let api = client.runtime_api();

let Ok(Some(metadata_api_version)) = api.api_version::<dyn Metadata<Block>>(genesis) else {
return Err("Unable to fetch metadata runtime API version.".to_string().into());
};

log::debug!("Found metadata API version {}.", metadata_api_version);
let opaque_metadata = if metadata_api_version > 1 {
let Ok(mut supported_metadata_versions) = api.metadata_versions(genesis) else {
return Err("Unable to fetch metadata versions".to_string().into());
};

let latest = supported_metadata_versions
.pop()
.ok_or("No metadata version supported".to_string())?;

api.metadata_at_version(genesis, latest)
.map_err(|e| format!("Unable to fetch metadata: {:?}", e))?
.ok_or("Unable to decode metadata".to_string())?
} else {
// Fall back to using the non-versioned metadata API.
api.metadata(genesis)
.map_err(|e| format!("Unable to fetch metadata: {:?}", e))?
};

let version = api.version(genesis).unwrap();
let runtime_version = SubxtRuntimeVersion {
spec_version: version.spec_version,
transaction_version: version.transaction_version,
};
let metadata = subxt::Metadata::decode(&mut (*opaque_metadata).as_slice())?;
let genesis = subxt::utils::H256::from(genesis.to_fixed_bytes());

Ok(Self { offline_client: OfflineClient::new(genesis, runtime_version, metadata) })
}
}

impl<C: Config> DynamicRemarkBuilder<C> {
/// Constructs a new remark builder.
pub fn new(
metadata: subxt::Metadata,
genesis_hash: C::Hash,
runtime_version: SubxtRuntimeVersion,
) -> Self {
Self { offline_client: OfflineClient::new(genesis_hash, runtime_version, metadata) }
}
}

impl ExtrinsicBuilder for DynamicRemarkBuilder<SubstrateConfig> {
fn pallet(&self) -> &str {
"system"
}

fn extrinsic(&self) -> &str {
"remark"
}

fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let signer = subxt_signer::sr25519::dev::alice();
let dynamic_tx = subxt::dynamic::tx("System", "remark", vec![Vec::<u8>::new()]);

let params = SubstrateExtrinsicParamsBuilder::new().nonce(nonce.into()).build();

// Default transaction parameters assume a nonce of 0.
let transaction = self
.offline_client
.tx()
.create_signed_offline(&dynamic_tx, &signer, params)
.unwrap();
let mut encoded = transaction.into_encoded();

OpaqueExtrinsic::from_bytes(&mut encoded).map_err(|_| "Unable to construct OpaqueExtrinsic")
}
}
use std::borrow::Cow;

/// Fetches the latest metadata from the given runtime blob.
pub fn fetch_latest_metadata_from_code_blob<HF: HostFunctions>(
Expand Down

0 comments on commit 52458b8

Please sign in to comment.