From 0a291dc3202769086429365e9df95080670f1b3b Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 26 Jun 2024 17:31:46 +0300 Subject: [PATCH] Deduplicate construct_partials!() and construct_async_run!() --- Cargo.lock | 2 + cumulus/polkadot-parachain/Cargo.toml | 3 + cumulus/polkadot-parachain/src/command.rs | 233 ++++++------------ .../polkadot-parachain/src/common/command.rs | 136 ++++++++++ cumulus/polkadot-parachain/src/common/mod.rs | 1 + 5 files changed, 215 insertions(+), 160 deletions(-) create mode 100644 cumulus/polkadot-parachain/src/common/command.rs diff --git a/Cargo.lock b/Cargo.lock index 91d604d6fa3cb..bb01746308122 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13952,9 +13952,11 @@ dependencies = [ "polkadot-service", "rococo-parachain-runtime", "sc-basic-authorship", + "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", + "sc-client-db", "sc-consensus", "sc-executor", "sc-network", diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index ae5abdcfab6a3..63e1dfd6950fb 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -56,11 +56,13 @@ sp-io = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-session = { workspace = true, default-features = true } frame-try-runtime = { optional = true, workspace = true, default-features = true } +sc-block-builder = { workspace = true, default-features = true } sc-consensus = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } frame-support = { workspace = true, default-features = true } sc-cli = { workspace = true, default-features = true } sc-client-api = { workspace = true, default-features = true } +sc-client-db = { workspace = true, default-features = true } sc-executor = { workspace = true, default-features = true } sc-service = { workspace = true, default-features = true } sc-telemetry = { workspace = true, default-features = true } @@ -147,6 +149,7 @@ runtime-benchmarks = [ "polkadot-primitives/runtime-benchmarks", "polkadot-service/runtime-benchmarks", "rococo-parachain-runtime/runtime-benchmarks", + "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index d7c4a14c1de05..a06f125500906 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -18,6 +18,7 @@ use crate::{ chain_spec, chain_spec::GenericChainSpec, cli::{Cli, RelayChainCli, Subcommand}, + common::command::CmdRunner, fake_runtime_api::{ asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, aura::RuntimeApi, }, @@ -382,146 +383,47 @@ impl SubstrateCli for RelayChainCli { } } -/// Creates partial components for the runtimes that are supported by the benchmarks. -macro_rules! construct_partials { - ($config:expr, |$partials:ident| $code:expr) => { - match $config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => { - let $partials = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, - )?; - $code - }, - Runtime::AssetHub | - Runtime::BridgeHub(_) | - Runtime::Collectives | - Runtime::Coretime(_) | - Runtime::People(_) => { - let $partials = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AuraId>, - )?; - $code - }, - Runtime::Glutton | Runtime::Shell | Runtime::Seedling => { - let $partials = new_partial::( - &$config, - crate::service::build_shell_import_queue, - )?; - $code - }, - Runtime::ContractsRococo | Runtime::Penpal(_) => { - let $partials = new_partial::( - &$config, - crate::service::build_aura_import_queue, - )?; - $code - }, - Runtime::Omni(consensus) => match consensus { - Consensus::Aura => { - let $partials = new_partial::( - &$config, - crate::service::build_aura_import_queue, - )?; - $code - }, - Consensus::Relay => { - let $partials = new_partial::( - &$config, - crate::service::build_shell_import_queue, - )?; - $code - }, - }, - } - }; -} - -macro_rules! construct_async_run { - (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ - let runner = $cli.create_runner($cmd)?; - match runner.config().chain_spec.runtime()? { - Runtime::AssetHubPolkadot => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::AssetHub | - Runtime::BridgeHub(_) | - Runtime::Collectives | - Runtime::Coretime(_) | - Runtime::People(_) => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AuraId>, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::Shell | - Runtime::Seedling | - Runtime::Glutton => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::build_shell_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - } - Runtime::ContractsRococo | Runtime::Penpal(_) => { - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _, - >( - &$config, - crate::service::build_aura_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::Omni(consensus) => match consensus { - Consensus::Aura => { - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _, - >( - &$config, - crate::service::build_aura_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Consensus::Relay - => { - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _, - >( - &$config, - crate::service::build_shell_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - } - } - }} +fn new_partial_from_config( + config: &sc_service::Configuration, +) -> std::result::Result>, sc_cli::Error> { + Ok(match config.chain_spec.runtime()? { + Runtime::AssetHubPolkadot => Box::new( + new_partial::( + config, + crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, + ) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::AssetHub | + Runtime::BridgeHub(_) | + Runtime::Collectives | + Runtime::Coretime(_) | + Runtime::People(_) => Box::new( + new_partial::( + config, + crate::service::build_relay_to_aura_import_queue::<_, AuraId>, + ) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::Glutton | Runtime::Shell | Runtime::Seedling => Box::new( + new_partial::(config, crate::service::build_shell_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::ContractsRococo | Runtime::Penpal(_) => Box::new( + new_partial::(config, crate::service::build_aura_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::Omni(consensus) => match consensus { + Consensus::Aura => Box::new( + new_partial::(config, crate::service::build_aura_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + Consensus::Relay => Box::new( + new_partial::(config, crate::service::build_shell_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + }, + }) } /// Parse command line arguments into service configuration. @@ -534,28 +436,40 @@ pub fn run() -> Result<()> { runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) }, Some(Subcommand::CheckBlock(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.import_queue)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_check_block_cmd(cmd)) }) }, Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, config.database)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_export_blocks_cmd(cmd, config)) }) }, Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, config.chain_spec)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_export_state_cmd(cmd, config)) }) }, Some(Subcommand::ImportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.import_queue)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_import_blocks_cmd(cmd)) + }) + }, + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_revert_cmd(cmd)) }) }, - Some(Subcommand::Revert(cmd)) => construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.backend, None)) - }), Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; let polkadot_cli = RelayChainCli::new(runner.config(), cli.relay_chain_args.iter()); @@ -573,8 +487,10 @@ pub fn run() -> Result<()> { }, Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; - runner - .sync_run(|config| construct_partials!(config, |partials| cmd.run(partials.client))) + runner.sync_run(|config| { + let partials = new_partial_from_config(&config)?; + partials.run_export_genesis_head_cmd(cmd) + }) }, Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -595,16 +511,13 @@ pub fn run() -> Result<()> { )) }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { - construct_partials!(config, |partials| cmd.run(partials.client)) + let partials = new_partial_from_config(&config)?; + partials.run_benchmark_block_cmd(cmd) }), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - construct_partials!(config, |partials| { - let db = partials.backend.expose_db(); - let storage = partials.backend.expose_storage(); - - cmd.run(config, partials.client.clone(), db, storage) - }) + let partials = new_partial_from_config(&config)?; + partials.run_benchmark_storage_cmd(cmd, config) }), BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), diff --git a/cumulus/polkadot-parachain/src/common/command.rs b/cumulus/polkadot-parachain/src/common/command.rs new file mode 100644 index 0000000000000..57587fd8697f4 --- /dev/null +++ b/cumulus/polkadot-parachain/src/common/command.rs @@ -0,0 +1,136 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Helper trait used to dynamically run parachain node commands. + +use cumulus_client_cli::ExportGenesisHeadCommand; +use cumulus_primitives_core::BlockT; +use frame_benchmarking_cli::BlockCmd; +#[cfg(any(feature = "runtime-benchmarks"))] +use frame_benchmarking_cli::StorageCmd; +use sc_block_builder::BlockBuilderApi; +use sc_cli::{CheckBlockCmd, ExportBlocksCmd, ExportStateCmd, ImportBlocksCmd, RevertCmd}; +use sc_client_api::{BlockBackend, StorageProvider, UsageProvider}; +use sc_client_db::{Backend, DbHash}; +use sc_service::{Configuration, PartialComponents, TaskManager}; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::{traits::Header as HeaderT, OpaqueExtrinsic}; +use std::{fmt::Debug, future::Future, pin::Pin, str::FromStr}; + +type SyncCmdResult = sc_cli::Result<()>; +type AsyncCmdResult<'a> = (Pin + 'a>>, TaskManager); + +pub trait CmdRunner { + fn prepare_check_block_cmd(self: Box, cmd: &CheckBlockCmd) -> AsyncCmdResult<'_>; + + fn prepare_export_blocks_cmd( + self: Box, + cmd: &ExportBlocksCmd, + config: Configuration, + ) -> AsyncCmdResult<'_>; + + fn prepare_export_state_cmd( + self: Box, + cmd: &ExportStateCmd, + config: Configuration, + ) -> AsyncCmdResult<'_>; + + fn prepare_import_blocks_cmd(self: Box, cmd: &ImportBlocksCmd) -> AsyncCmdResult<'_>; + + fn prepare_revert_cmd(self: Box, cmd: &RevertCmd) -> AsyncCmdResult<'_>; + + fn run_export_genesis_head_cmd( + self: Box, + cmd: &ExportGenesisHeadCommand, + ) -> SyncCmdResult; + + fn run_benchmark_block_cmd(self: Box, cmd: &BlockCmd) -> SyncCmdResult; + + #[cfg(any(feature = "runtime-benchmarks"))] + fn run_benchmark_storage_cmd( + self: Box, + cmd: &StorageCmd, + config: Configuration, + ) -> SyncCmdResult; +} + +impl CmdRunner + for PartialComponents, SelectChain, ImportQueue, TransactionPool, Other> +where + Self: Send, + Block: BlockT + for<'de> serde::Deserialize<'de>, + <::Number as FromStr>::Err: Debug, + Client: HeaderBackend + + BlockBackend + + ProvideRuntimeApi + + StorageProvider> + + UsageProvider + + 'static, + Client::Api: BlockBuilderApi, + ImportQueue: sc_service::ImportQueue + 'static, +{ + fn prepare_check_block_cmd(self: Box, cmd: &CheckBlockCmd) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, self.import_queue)), self.task_manager) + } + + fn prepare_export_blocks_cmd( + self: Box, + cmd: &ExportBlocksCmd, + config: Configuration, + ) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, config.database)), self.task_manager) + } + + fn prepare_export_state_cmd( + self: Box, + cmd: &ExportStateCmd, + config: Configuration, + ) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, config.chain_spec)), self.task_manager) + } + + fn prepare_import_blocks_cmd(self: Box, cmd: &ImportBlocksCmd) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, self.import_queue)), self.task_manager) + } + + fn prepare_revert_cmd(self: Box, cmd: &RevertCmd) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, self.backend, None)), self.task_manager) + } + + fn run_export_genesis_head_cmd( + self: Box, + cmd: &ExportGenesisHeadCommand, + ) -> SyncCmdResult { + cmd.run(self.client) + } + + fn run_benchmark_block_cmd(self: Box, cmd: &BlockCmd) -> SyncCmdResult { + cmd.run(self.client) + } + + #[cfg(any(feature = "runtime-benchmarks"))] + fn run_benchmark_storage_cmd( + self: Box, + cmd: &StorageCmd, + config: Configuration, + ) -> SyncCmdResult { + let db = self.backend.expose_db(); + let storage = self.backend.expose_storage(); + + cmd.run(config, self.client, db, storage) + } +} diff --git a/cumulus/polkadot-parachain/src/common/mod.rs b/cumulus/polkadot-parachain/src/common/mod.rs index 5adbb4137cd3d..860980ae9be85 100644 --- a/cumulus/polkadot-parachain/src/common/mod.rs +++ b/cumulus/polkadot-parachain/src/common/mod.rs @@ -19,6 +19,7 @@ #![warn(missing_docs)] pub mod aura; +pub mod command; use cumulus_primitives_core::CollectCollationInfo; use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata};