From c550fee01f74de4b9af41c284883aef760b118bb Mon Sep 17 00:00:00 2001 From: koushiro Date: Thu, 2 Jun 2022 12:09:47 +0800 Subject: [PATCH 1/3] Move ExportGenesisStateCommand and ExportGenesisWasmCommand to cumulus-client-cli Signed-off-by: koushiro --- Cargo.lock | 4 + client/cli/Cargo.toml | 4 + client/cli/src/lib.rs | 194 ++++++++++++++++++++++--- client/service/src/lib.rs | 2 - parachain-template/node/src/cli.rs | 112 +++++--------- parachain-template/node/src/command.rs | 93 ++++-------- polkadot-parachain/src/cli.rs | 119 ++++++--------- polkadot-parachain/src/command.rs | 101 ++++--------- test/service/src/cli.rs | 101 ++++++------- test/service/src/genesis.rs | 7 +- test/service/src/main.rs | 84 +++-------- 11 files changed, 393 insertions(+), 428 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 956474ce51f..ed60a22aabd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1575,8 +1575,12 @@ name = "cumulus-client-cli" version = "0.1.0" dependencies = [ "clap 3.1.18", + "parity-scale-codec", + "sc-chain-spec", "sc-cli", "sc-service", + "sp-core", + "sp-runtime", "url", ] diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index f9ea950d170..7d7ac2d6448 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -6,8 +6,12 @@ edition = "2021" [dependencies] clap = { version = "3.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0" } # Substrate sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } url = "2.2.2" diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index a30ef306c10..d1c0e8a3deb 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -18,20 +18,28 @@ #![warn(missing_docs)] -use clap::Parser; -use sc_service::{ - config::{PrometheusConfig, TelemetryEndpoints}, - BasePath, TransactionPoolOptions, -}; use std::{ fs, io::{self, Write}, net::SocketAddr, + path::PathBuf, +}; + +use codec::Encode; +use sc_chain_spec::ChainSpec; +use sc_service::{ + config::{PrometheusConfig, TelemetryEndpoints}, + BasePath, TransactionPoolOptions, +}; +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::{ + traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero}, + StateVersion, }; use url::Url; /// The `purge-chain` command used to remove the whole chain: the parachain and the relay chain. -#[derive(Debug, Parser)] +#[derive(Debug, clap::Parser)] pub struct PurgeChainCmd { /// The base struct of the purge-chain command. #[clap(flatten)] @@ -119,6 +127,148 @@ impl sc_cli::CliConfiguration for PurgeChainCmd { } } +/// Command for exporting the genesis state of the parachain +#[derive(Debug, clap::Parser)] +pub struct ExportGenesisStateCommand { + /// Output file name or stdout if unspecified. + #[clap(parse(from_os_str))] + pub output: Option, + + /// Write output in binary. Default is to write in hex. + #[clap(short, long)] + pub raw: bool, + + /// The name of the chain for that the genesis state should be exported. + #[clap(long)] + pub chain: Option, + + #[allow(missing_docs)] + #[clap(flatten)] + pub shared_params: sc_cli::SharedParams, +} + +impl ExportGenesisStateCommand { + /// Run the export-genesis-state command + pub fn run( + &self, + chain_spec: &dyn ChainSpec, + genesis_state_version: StateVersion, + ) -> sc_cli::Result<()> { + let block: Block = generate_genesis_block(chain_spec, genesis_state_version)?; + let raw_header = block.header().encode(); + let output_buf = if self.raw { + raw_header + } else { + format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() + }; + + if let Some(output) = &self.output { + fs::write(output, output_buf)?; + } else { + io::stdout().write_all(&output_buf)?; + } + + Ok(()) + } +} + +/// Generate the genesis block from a given ChainSpec. +pub fn generate_genesis_block( + chain_spec: &dyn ChainSpec, + genesis_state_version: StateVersion, +) -> Result { + let storage = chain_spec.build_storage()?; + + let child_roots = storage.children_default.iter().map(|(sk, child_content)| { + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + child_content.data.clone().into_iter().collect(), + genesis_state_version, + ); + (sk.clone(), state_root.encode()) + }); + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + storage.top.clone().into_iter().chain(child_roots).collect(), + genesis_state_version, + ); + + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + Vec::new(), + sp_runtime::StateVersion::V0, + ); + + Ok(Block::new( + <::Header as HeaderT>::new( + Zero::zero(), + extrinsics_root, + state_root, + Default::default(), + Default::default(), + ), + Default::default(), + )) +} + +impl sc_cli::CliConfiguration for ExportGenesisStateCommand { + fn shared_params(&self) -> &sc_cli::SharedParams { + &self.shared_params + } +} + +/// Command for exporting the genesis wasm file. +#[derive(Debug, clap::Parser)] +pub struct ExportGenesisWasmCommand { + /// Output file name or stdout if unspecified. + #[clap(parse(from_os_str))] + pub output: Option, + + /// Write output in binary. Default is to write in hex. + #[clap(short, long)] + pub raw: bool, + + /// The name of the chain for that the genesis wasm file should be exported. + #[clap(long)] + pub chain: Option, + + #[allow(missing_docs)] + #[clap(flatten)] + pub shared_params: sc_cli::SharedParams, +} + +impl ExportGenesisWasmCommand { + /// Run the export-genesis-state command + pub fn run(&self, chain_spec: &dyn ChainSpec) -> sc_cli::Result<()> { + let raw_wasm_blob = extract_genesis_wasm(chain_spec)?; + let output_buf = if self.raw { + raw_wasm_blob + } else { + format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() + }; + + if let Some(output) = &self.output { + fs::write(output, output_buf)?; + } else { + io::stdout().write_all(&output_buf)?; + } + + Ok(()) + } +} + +/// Extract the genesis code from a given ChainSpec. +pub fn extract_genesis_wasm(chain_spec: &dyn ChainSpec) -> sc_cli::Result> { + let mut storage = chain_spec.build_storage()?; + storage + .top + .remove(sp_core::storage::well_known_keys::CODE) + .ok_or_else(|| "Could not find wasm file in genesis state!".into()) +} + +impl sc_cli::CliConfiguration for ExportGenesisWasmCommand { + fn shared_params(&self) -> &sc_cli::SharedParams { + &self.shared_params + } +} + fn validate_relay_chain_url(arg: &str) -> Result<(), String> { let url = Url::parse(arg).map_err(|e| e.to_string())?; @@ -133,7 +283,7 @@ fn validate_relay_chain_url(arg: &str) -> Result<(), String> { } /// The `run` command used to run a node. -#[derive(Debug, Parser)] +#[derive(Debug, clap::Parser)] pub struct RunCmd { /// The cumulus RunCmd inherents from sc_cli's #[clap(flatten)] @@ -155,21 +305,6 @@ pub struct RunCmd { pub relay_chain_rpc_url: Option, } -/// Options only relevant for collator nodes -#[derive(Clone, Debug)] -pub struct CollatorOptions { - /// Location of relay chain full node - pub relay_chain_rpc_url: Option, -} - -/// A non-redundant version of the `RunCmd` that sets the `validator` field when the -/// original `RunCmd` had the `collator` field. -/// This is how we make `--collator` imply `--validator`. -pub struct NormalizedRunCmd { - /// The cumulus RunCmd inherents from sc_cli's - pub base: sc_cli::RunCmd, -} - impl RunCmd { /// Create a [`NormalizedRunCmd`] which merges the `collator` cli argument into `validator` to have only one. pub fn normalize(&self) -> NormalizedRunCmd { @@ -186,6 +321,21 @@ impl RunCmd { } } +/// Options only relevant for collator nodes +#[derive(Clone, Debug)] +pub struct CollatorOptions { + /// Location of relay chain full node + pub relay_chain_rpc_url: Option, +} + +/// A non-redundant version of the `RunCmd` that sets the `validator` field when the +/// original `RunCmd` had the `collator` field. +/// This is how we make `--collator` imply `--validator`. +pub struct NormalizedRunCmd { + /// The cumulus RunCmd inherents from sc_cli's + pub base: sc_cli::RunCmd, +} + impl sc_cli::CliConfiguration for NormalizedRunCmd { fn shared_params(&self) -> &sc_cli::SharedParams { self.base.shared_params() diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 63ac6894297..77adcb5c41a 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -41,8 +41,6 @@ use sp_runtime::{ }; use std::{sync::Arc, time::Duration}; -pub mod genesis; - /// Parameters given to [`start_collator`]. pub struct StartCollatorParams<'a, Block: BlockT, BS, Client, RCInterface, Spawner, IQ> { pub block_status: Arc, diff --git a/parachain-template/node/src/cli.rs b/parachain-template/node/src/cli.rs index 0d36120a479..89af616ad5e 100644 --- a/parachain-template/node/src/cli.rs +++ b/parachain-template/node/src/cli.rs @@ -1,18 +1,36 @@ -use crate::chain_spec; -use clap::Parser; use std::path::PathBuf; +#[derive(Debug, clap::Parser)] +#[clap( + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] +pub struct Cli { + #[clap(subcommand)] + pub subcommand: Option, + + #[clap(flatten)] + pub run: cumulus_client_cli::RunCmd, + + /// Disable automatic hardware benchmarks. + /// + /// By default these benchmarks are automatically ran at startup and measure + /// the CPU speed, the memory bandwidth and the disk speed. + /// + /// The results are then printed out in the logs, and also sent as part of + /// telemetry, if telemetry is enabled. + #[clap(long)] + pub no_hardware_benchmarks: bool, + + /// Relay chain arguments + #[clap(raw = true)] + pub relay_chain_args: Vec, +} + /// Sub-commands supported by the collator. #[derive(Debug, clap::Subcommand)] pub enum Subcommand { - /// Export the genesis state of the parachain. - #[clap(name = "export-genesis-state")] - ExportGenesisState(ExportGenesisStateCommand), - - /// Export the genesis wasm of the parachain. - #[clap(name = "export-genesis-wasm")] - ExportGenesisWasm(ExportGenesisWasmCommand), - /// Build a chain specification. BuildSpec(sc_cli::BuildSpecCmd), @@ -28,11 +46,17 @@ pub enum Subcommand { /// Import blocks. ImportBlocks(sc_cli::ImportBlocksCmd), + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + /// Remove the whole chain. PurgeChain(cumulus_client_cli::PurgeChainCmd), - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), + /// Export the genesis state of the parachain. + ExportGenesisState(cumulus_client_cli::ExportGenesisStateCommand), + + /// Export the genesis wasm of the parachain. + ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand), /// Sub-commands concerned with benchmarking. /// The pallet benchmarking moved to the `pallet` sub-command. @@ -43,66 +67,6 @@ pub enum Subcommand { TryRuntime(try_runtime_cli::TryRuntimeCmd), } -/// Command for exporting the genesis state of the parachain -#[derive(Debug, Parser)] -pub struct ExportGenesisStateCommand { - /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis state should be exported. - #[clap(long)] - pub chain: Option, -} - -/// Command for exporting the genesis wasm file. -#[derive(Debug, Parser)] -pub struct ExportGenesisWasmCommand { - /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis wasm file should be exported. - #[clap(long)] - pub chain: Option, -} - -#[derive(Debug, Parser)] -#[clap( - propagate_version = true, - args_conflicts_with_subcommands = true, - subcommand_negates_reqs = true -)] -pub struct Cli { - #[clap(subcommand)] - pub subcommand: Option, - - #[clap(flatten)] - pub run: cumulus_client_cli::RunCmd, - - /// Disable automatic hardware benchmarks. - /// - /// By default these benchmarks are automatically ran at startup and measure - /// the CPU speed, the memory bandwidth and the disk speed. - /// - /// The results are then printed out in the logs, and also sent as part of - /// telemetry, if telemetry is enabled. - #[clap(long)] - pub no_hardware_benchmarks: bool, - - /// Relay chain arguments - #[clap(raw = true)] - pub relay_chain_args: Vec, -} - #[derive(Debug)] pub struct RelayChainCli { /// The actual relay chain cli object. @@ -121,9 +85,9 @@ impl RelayChainCli { para_config: &sc_service::Configuration, relay_chain_args: impl Iterator, ) -> Self { - let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); + let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } + Self { base_path, chain_id, base: clap::Parser::parse_from(relay_chain_args) } } } diff --git a/parachain-template/node/src/command.rs b/parachain-template/node/src/command.rs index 47691d41e04..f1a6168a8d0 100644 --- a/parachain-template/node/src/command.rs +++ b/parachain-template/node/src/command.rs @@ -1,10 +1,7 @@ -use crate::{ - chain_spec, - cli::{Cli, RelayChainCli, Subcommand}, - service::{new_partial, TemplateRuntimeExecutor}, -}; +use std::net::SocketAddr; + use codec::Encode; -use cumulus_client_service::genesis::generate_genesis_block; +use cumulus_client_cli::generate_genesis_block; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; use log::info; @@ -19,9 +16,14 @@ use sc_service::{ }; use sp_core::hexdisplay::HexDisplay; use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; -use std::{io::Write, net::SocketAddr}; -fn load_spec(id: &str) -> std::result::Result, String> { +use crate::{ + chain_spec, + cli::{Cli, RelayChainCli, Subcommand}, + service::{new_partial, TemplateRuntimeExecutor}, +}; + +fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { "dev" => Box::new(chain_spec::development_config()), "template-rococo" => Box::new(chain_spec::local_testnet_config()), @@ -106,16 +108,6 @@ impl SubstrateCli for RelayChainCli { } } -#[allow(clippy::borrowed_box)] -fn extract_genesis_wasm(chain_spec: &Box) -> Result> { - let mut storage = chain_spec.build_storage()?; - - storage - .top - .remove(sp_core::storage::well_known_keys::CODE) - .ok_or_else(|| "Could not find wasm file in genesis state!".into()) -} - macro_rules! construct_async_run { (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ let runner = $cli.create_runner($cmd)?; @@ -163,6 +155,11 @@ pub fn run() -> Result<()> { Ok(cmd.run(components.client, components.import_queue)) }) }, + 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)?; @@ -182,54 +179,20 @@ pub fn run() -> Result<()> { cmd.run(config, polkadot_config) }) }, - Some(Subcommand::Revert(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.backend, None)) + Some(Subcommand::ExportGenesisState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + let state_version = Cli::native_runtime_version(&spec).state_version(); + cmd.run::(&*spec, state_version) }) }, - Some(Subcommand::ExportGenesisState(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let spec = load_spec(¶ms.chain.clone().unwrap_or_default())?; - let state_version = Cli::native_runtime_version(&spec).state_version(); - let block: Block = generate_genesis_block(&spec, state_version)?; - let raw_header = block.header().encode(); - let output_buf = if params.raw { - raw_header - } else { - format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) - }, - Some(Subcommand::ExportGenesisWasm(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let raw_wasm_blob = - extract_genesis_wasm(&cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; - let output_buf = if params.raw { - raw_wasm_blob - } else { - format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) + Some(Subcommand::ExportGenesisWasm(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + cmd.run(&*spec) + }) }, Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -311,7 +274,7 @@ pub fn run() -> Result<()> { AccountIdConversion::::into_account_truncating(&id); let state_version = Cli::native_runtime_version(&config.chain_spec).state_version(); - let block: Block = generate_genesis_block(&config.chain_spec, state_version) + let block: Block = generate_genesis_block(&*config.chain_spec, state_version) .map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); diff --git a/polkadot-parachain/src/cli.rs b/polkadot-parachain/src/cli.rs index 31ecb8a5aa0..291c3faa7b4 100644 --- a/polkadot-parachain/src/cli.rs +++ b/polkadot-parachain/src/cli.rs @@ -14,21 +14,42 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use crate::chain_spec; -use clap::Parser; -use sc_cli; use std::path::PathBuf; +#[derive(Debug, clap::Parser)] +#[clap( + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] +pub struct Cli { + #[clap(subcommand)] + pub subcommand: Option, + + #[clap(flatten)] + pub run: cumulus_client_cli::RunCmd, + + /// Disable automatic hardware benchmarks. + /// + /// By default these benchmarks are automatically ran at startup and measure + /// the CPU speed, the memory bandwidth and the disk speed. + /// + /// The results are then printed out in the logs, and also sent as part of + /// telemetry, if telemetry is enabled. + #[clap(long)] + pub no_hardware_benchmarks: bool, + + /// Relay chain arguments + #[clap(raw = true, conflicts_with = "relay-chain-rpc-url")] + pub relaychain_args: Vec, +} + /// Sub-commands supported by the collator. #[derive(Debug, clap::Subcommand)] pub enum Subcommand { - /// Export the genesis state of the parachain. - #[clap(name = "export-genesis-state")] - ExportGenesisState(ExportGenesisStateCommand), - - /// Export the genesis wasm of the parachain. - #[clap(name = "export-genesis-wasm")] - ExportGenesisWasm(ExportGenesisWasmCommand), + /// Key management CLI utilities + #[clap(subcommand)] + Key(sc_cli::KeySubcommand), /// Build a chain specification. BuildSpec(sc_cli::BuildSpecCmd), @@ -45,11 +66,17 @@ pub enum Subcommand { /// Import blocks. ImportBlocks(sc_cli::ImportBlocksCmd), + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + /// Remove the whole chain. PurgeChain(cumulus_client_cli::PurgeChainCmd), - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), + /// Export the genesis state of the parachain. + ExportGenesisState(cumulus_client_cli::ExportGenesisStateCommand), + + /// Export the genesis wasm of the parachain. + ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand), /// Sub-commands concerned with benchmarking. /// The pallet benchmarking moved to the `pallet` sub-command. @@ -58,70 +85,6 @@ pub enum Subcommand { /// Try some testing command against a specified runtime state. TryRuntime(try_runtime_cli::TryRuntimeCmd), - - /// Key management CLI utilities - #[clap(subcommand)] - Key(sc_cli::KeySubcommand), -} - -/// Command for exporting the genesis state of the parachain -#[derive(Debug, Parser)] -pub struct ExportGenesisStateCommand { - /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis state should be exported. - #[clap(long)] - pub chain: Option, -} - -/// Command for exporting the genesis wasm file. -#[derive(Debug, Parser)] -pub struct ExportGenesisWasmCommand { - /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis wasm file should be exported. - #[clap(long)] - pub chain: Option, -} - -#[derive(Debug, Parser)] -#[clap( - propagate_version = true, - args_conflicts_with_subcommands = true, - subcommand_negates_reqs = true -)] -pub struct Cli { - #[clap(subcommand)] - pub subcommand: Option, - - #[clap(flatten)] - pub run: cumulus_client_cli::RunCmd, - - /// Disable automatic hardware benchmarks. - /// - /// By default these benchmarks are automatically ran at startup and measure - /// the CPU speed, the memory bandwidth and the disk speed. - /// - /// The results are then printed out in the logs, and also sent as part of - /// telemetry, if telemetry is enabled. - #[clap(long)] - pub no_hardware_benchmarks: bool, - - /// Relay chain arguments - #[clap(raw = true, conflicts_with = "relay-chain-rpc-url")] - pub relaychain_args: Vec, } #[derive(Debug)] @@ -142,9 +105,9 @@ impl RelayChainCli { para_config: &sc_service::Configuration, relay_chain_args: impl Iterator, ) -> Self { - let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); + let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } + Self { base_path, chain_id, base: clap::Parser::parse_from(relay_chain_args) } } } diff --git a/polkadot-parachain/src/command.rs b/polkadot-parachain/src/command.rs index daf24797b55..3d5abc2a3e7 100644 --- a/polkadot-parachain/src/command.rs +++ b/polkadot-parachain/src/command.rs @@ -14,16 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use crate::{ - chain_spec, - cli::{Cli, RelayChainCli, Subcommand}, - service::{ - new_partial, Block, ShellRuntimeExecutor, StatemineRuntimeExecutor, - StatemintRuntimeExecutor, WestmintRuntimeExecutor, - }, -}; +use std::net::SocketAddr; + use codec::Encode; -use cumulus_client_service::genesis::generate_genesis_block; +use cumulus_client_cli::generate_genesis_block; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; use log::info; @@ -38,7 +32,15 @@ use sc_service::{ }; use sp_core::hexdisplay::HexDisplay; use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; -use std::{io::Write, net::SocketAddr}; + +use crate::{ + chain_spec, + cli::{Cli, RelayChainCli, Subcommand}, + service::{ + new_partial, Block, ShellRuntimeExecutor, StatemineRuntimeExecutor, + StatemintRuntimeExecutor, WestmintRuntimeExecutor, + }, +}; trait IdentifyChain { fn is_shell(&self) -> bool; @@ -49,7 +51,7 @@ trait IdentifyChain { fn is_contracts_rococo(&self) -> bool; } -impl IdentifyChain for dyn sc_service::ChainSpec { +impl IdentifyChain for dyn ChainSpec { fn is_shell(&self) -> bool { self.id().starts_with("shell") } @@ -70,7 +72,7 @@ impl IdentifyChain for dyn sc_service::ChainSpec { } } -impl IdentifyChain for T { +impl IdentifyChain for T { fn is_shell(&self) -> bool { ::is_shell(self) } @@ -91,7 +93,7 @@ impl IdentifyChain for T { } } -fn load_spec(id: &str) -> std::result::Result, String> { +fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { "staging" => Box::new(chain_spec::staging_test_net()), "tick" => Box::new(chain_spec::ChainSpec::from_json_bytes( @@ -258,15 +260,6 @@ impl SubstrateCli for RelayChainCli { } } -fn extract_genesis_wasm(chain_spec: &Box) -> Result> { - let mut storage = chain_spec.build_storage()?; - - storage - .top - .remove(sp_core::storage::well_known_keys::CODE) - .ok_or_else(|| "Could not find wasm file in genesis state!".into()) -} - /// Creates partial components for the runtimes that are supported by the benchmarks. macro_rules! construct_benchmark_partials { ($config:expr, |$partials:ident| $code:expr) => { @@ -396,6 +389,9 @@ pub fn run() -> Result<()> { Ok(cmd.run(components.client, components.import_queue)) }) }, + 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)?; @@ -417,53 +413,20 @@ pub fn run() -> Result<()> { cmd.run(config, polkadot_config) }) }, - Some(Subcommand::Revert(cmd)) => construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.backend, None)) - }), - Some(Subcommand::ExportGenesisState(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let spec = load_spec(¶ms.chain.clone().unwrap_or_default())?; - let state_version = Cli::native_runtime_version(&spec).state_version(); - - let block: crate::service::Block = generate_genesis_block(&spec, state_version)?; - let raw_header = block.header().encode(); - let output_buf = if params.raw { - raw_header - } else { - format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) + Some(Subcommand::ExportGenesisState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + let state_version = Cli::native_runtime_version(&spec).state_version(); + cmd.run::(&*spec, state_version) + }) }, - Some(Subcommand::ExportGenesisWasm(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let raw_wasm_blob = - extract_genesis_wasm(&cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; - let output_buf = if params.raw { - raw_wasm_blob - } else { - format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) + Some(Subcommand::ExportGenesisWasm(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + cmd.run(&*spec) + }) }, Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -570,7 +533,7 @@ pub fn run() -> Result<()> { let state_version = Cli::native_runtime_version(&config.chain_spec).state_version(); let block: crate::service::Block = - generate_genesis_block(&config.chain_spec, state_version) + generate_genesis_block(&*config.chain_spec, state_version) .map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); diff --git a/test/service/src/cli.rs b/test/service/src/cli.rs index 13995d6ed30..b6bd2568511 100644 --- a/test/service/src/cli.rs +++ b/test/service/src/cli.rs @@ -14,64 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use clap::{Parser, Subcommand}; +use std::{net::SocketAddr, path::PathBuf}; + use polkadot_service::{ChainSpec, ParaId, PrometheusConfig}; use sc_cli::{ CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result as CliResult, RuntimeVersion, SharedParams, SubstrateCli, }; use sc_service::BasePath; -use std::{net::SocketAddr, path::PathBuf}; - -#[derive(Debug, Parser)] -pub struct ExportGenesisStateCommand { - #[clap(default_value_t = 2000u32)] - pub parachain_id: u32, - - /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis state should be exported. - #[clap(long)] - pub chain: Option, -} - -/// Command for exporting the genesis wasm file. -#[derive(Debug, Parser)] -pub struct ExportGenesisWasmCommand { - #[clap(default_value_t = 2000u32)] - pub parachain_id: u32, - - /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis wasm file should be exported. - #[clap(long)] - pub chain: Option, -} -#[derive(Subcommand, Debug)] -pub enum Commands { - #[clap(name = "export-genesis-wasm")] - ExportGenesisWasm(ExportGenesisWasmCommand), - #[clap(name = "export-genesis-state")] - ExportGenesisState(ExportGenesisStateCommand), - - /// Build a chain specification. - BuildSpec(sc_cli::BuildSpecCmd), -} - -#[derive(Debug, Parser)] +#[derive(Debug, clap::Parser)] #[clap( version, propagate_version = true, @@ -80,7 +32,7 @@ pub enum Commands { )] pub struct TestCollatorCli { #[clap(subcommand)] - pub subcommand: Option, + pub subcommand: Option, #[clap(flatten)] pub run: cumulus_client_cli::RunCmd, @@ -99,6 +51,49 @@ pub struct TestCollatorCli { pub disable_block_announcements: bool, } +#[derive(Debug, clap::Subcommand)] +pub enum Subcommand { + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Export the genesis state of the parachain. + ExportGenesisState(ExportGenesisStateCommand), + + /// Export the genesis wasm of the parachain. + ExportGenesisWasm(ExportGenesisWasmCommand), +} + +#[derive(Debug, clap::Parser)] +pub struct ExportGenesisStateCommand { + #[clap(default_value_t = 2000u32)] + pub parachain_id: u32, + + #[clap(flatten)] + pub base: cumulus_client_cli::ExportGenesisStateCommand, +} + +impl CliConfiguration for ExportGenesisStateCommand { + fn shared_params(&self) -> &SharedParams { + &self.base.shared_params + } +} + +/// Command for exporting the genesis wasm file. +#[derive(Debug, clap::Parser)] +pub struct ExportGenesisWasmCommand { + #[clap(default_value_t = 2000u32)] + pub parachain_id: u32, + + #[clap(flatten)] + pub base: cumulus_client_cli::ExportGenesisWasmCommand, +} + +impl CliConfiguration for ExportGenesisWasmCommand { + fn shared_params(&self) -> &SharedParams { + &self.base.shared_params + } +} + #[derive(Debug)] pub struct RelayChainCli { /// The actual relay chain cli object. @@ -118,7 +113,7 @@ impl RelayChainCli { relay_chain_args: impl Iterator, ) -> Self { let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { base_path, chain_id: None, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } + Self { base_path, chain_id: None, base: clap::Parser::parse_from(relay_chain_args) } } } diff --git a/test/service/src/genesis.rs b/test/service/src/genesis.rs index c3e0147882f..b472c98a7ae 100644 --- a/test/service/src/genesis.rs +++ b/test/service/src/genesis.rs @@ -15,7 +15,7 @@ // along with Cumulus. If not, see . use codec::Encode; -use cumulus_client_service::genesis::generate_genesis_block; +use cumulus_client_cli::generate_genesis_block; use cumulus_primitives_core::ParaId; use cumulus_test_runtime::Block; use polkadot_primitives::v2::HeadData; @@ -23,9 +23,8 @@ use sp_runtime::traits::Block as BlockT; /// Returns the initial head data for a parachain ID. pub fn initial_head_data(para_id: ParaId) -> HeadData { - let spec = Box::new(crate::chain_spec::get_chain_spec(para_id)); - let block: Block = - generate_genesis_block(&(spec as Box<_>), sp_runtime::StateVersion::V1).unwrap(); + let spec = crate::chain_spec::get_chain_spec(para_id); + let block: Block = generate_genesis_block(&spec, sp_runtime::StateVersion::V1).unwrap(); let genesis_state = block.header().encode(); genesis_state.into() } diff --git a/test/service/src/main.rs b/test/service/src/main.rs index 6bb0a3dc9bf..2b9ad48f9fe 100644 --- a/test/service/src/main.rs +++ b/test/service/src/main.rs @@ -13,27 +13,19 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . + mod cli; -use clap::Parser; -use cli::{Commands, RelayChainCli, TestCollatorCli}; -use cumulus_client_service::genesis::generate_genesis_block; +use std::sync::Arc; + +use cli::{RelayChainCli, Subcommand, TestCollatorCli}; +use cumulus_client_cli::generate_genesis_block; use cumulus_primitives_core::{relay_chain::v2::CollatorPair, ParaId}; use cumulus_test_service::AnnounceBlockFn; use polkadot_service::runtime_traits::AccountIdConversion; use sc_cli::{CliConfiguration, SubstrateCli}; use sp_core::{hexdisplay::HexDisplay, Encode, Pair}; use sp_runtime::traits::Block; -use std::{io::Write, sync::Arc}; - -fn extract_genesis_wasm(chain_spec: &Box) -> Result, String> { - let mut storage = chain_spec.build_storage()?; - - storage - .top - .remove(sp_core::storage::well_known_keys::CODE) - .ok_or_else(|| "Could not find wasm file in genesis state!".into()) -} pub fn wrap_announce_block() -> Box AnnounceBlockFn> { tracing::info!("Block announcements disabled."); @@ -44,59 +36,29 @@ pub fn wrap_announce_block() -> Box AnnounceBlock } fn main() -> Result<(), sc_cli::Error> { - let cli = TestCollatorCli::parse(); + let cli = TestCollatorCli::from_args(); match &cli.subcommand { - Some(Commands::BuildSpec(cmd)) => { + Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) }, - Some(Commands::ExportGenesisState(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let parachain_id = ParaId::from(params.parachain_id); - let spec = Box::new(cumulus_test_service::get_chain_spec(parachain_id)) as Box<_>; - let state_version = cumulus_test_service::runtime::VERSION.state_version(); - - let block: parachains_common::Block = generate_genesis_block(&spec, state_version)?; - let raw_header = block.header().encode(); - let output_buf = if params.raw { - raw_header - } else { - format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) + Some(Subcommand::ExportGenesisState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let parachain_id = ParaId::from(cmd.parachain_id); + let spec = cumulus_test_service::get_chain_spec(parachain_id); + let state_version = cumulus_test_service::runtime::VERSION.state_version(); + cmd.base.run::(&spec, state_version) + }) }, - Some(Commands::ExportGenesisWasm(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let parachain_id = ParaId::from(params.parachain_id); - let spec = Box::new(cumulus_test_service::get_chain_spec(parachain_id)) as Box<_>; - let raw_wasm_blob = extract_genesis_wasm(&spec)?; - let output_buf = if params.raw { - raw_wasm_blob - } else { - format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) + Some(Subcommand::ExportGenesisWasm(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let parachain_id = ParaId::from(cmd.parachain_id); + let spec = cumulus_test_service::get_chain_spec(parachain_id); + cmd.base.run(&spec) + }) }, None => { let mut builder = sc_cli::LoggerBuilder::new(""); @@ -129,7 +91,7 @@ fn main() -> Result<(), sc_cli::Error> { RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); let block: parachains_common::Block = - generate_genesis_block(&config.chain_spec, state_version) + generate_genesis_block(&*config.chain_spec, state_version) .map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); From 87b173548cf3872e4eaca605bef1591b1b56c612 Mon Sep 17 00:00:00 2001 From: koushiro Date: Thu, 2 Jun 2022 12:31:00 +0800 Subject: [PATCH 2/3] Remove useless Signed-off-by: koushiro --- Cargo.lock | 2 -- client/service/Cargo.toml | 2 -- client/service/src/genesis.rs | 55 ----------------------------------- 3 files changed, 59 deletions(-) delete mode 100644 client/service/src/genesis.rs diff --git a/Cargo.lock b/Cargo.lock index ed60a22aabd..963841b0ce6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1764,11 +1764,9 @@ dependencies = [ "cumulus-client-pov-recovery", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "parity-scale-codec", "parking_lot 0.12.1", "polkadot-overseer", "polkadot-primitives", - "sc-chain-spec", "sc-client-api", "sc-consensus", "sc-consensus-babe", diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 2d7eba613ea..687aa0f95ac 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -5,12 +5,10 @@ authors = ["Parity Technologies "] edition = "2021" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } parking_lot = "0.12.1" tracing = "0.1.34" # Substrate -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/client/service/src/genesis.rs b/client/service/src/genesis.rs deleted file mode 100644 index b2d1686f51a..00000000000 --- a/client/service/src/genesis.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020-2021 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 . - -use codec::Encode; -use sc_chain_spec::ChainSpec; -use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero}; - -/// Generate the genesis block from a given ChainSpec. -pub fn generate_genesis_block( - chain_spec: &Box, - genesis_state_version: sp_runtime::StateVersion, -) -> Result { - let storage = chain_spec.build_storage()?; - - let child_roots = storage.children_default.iter().map(|(sk, child_content)| { - let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - child_content.data.clone().into_iter().collect(), - genesis_state_version, - ); - (sk.clone(), state_root.encode()) - }); - let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - storage.top.clone().into_iter().chain(child_roots).collect(), - genesis_state_version, - ); - - let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - Vec::new(), - sp_runtime::StateVersion::V0, - ); - - Ok(Block::new( - <::Header as HeaderT>::new( - Zero::zero(), - extrinsics_root, - state_root, - Default::default(), - Default::default(), - ), - Default::default(), - )) -} From 8ef14009522e72547dbdeb609a7f8dcc79a7bf36 Mon Sep 17 00:00:00 2001 From: koushiro Date: Fri, 10 Jun 2022 21:40:30 +0800 Subject: [PATCH 3/3] Use shared_params.chain Signed-off-by: koushiro --- client/cli/src/lib.rs | 8 -------- parachain-template/node/src/command.rs | 4 ++-- polkadot-parachain/src/command.rs | 4 ++-- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index d1c0e8a3deb..39f4935dc74 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -138,10 +138,6 @@ pub struct ExportGenesisStateCommand { #[clap(short, long)] pub raw: bool, - /// The name of the chain for that the genesis state should be exported. - #[clap(long)] - pub chain: Option, - #[allow(missing_docs)] #[clap(flatten)] pub shared_params: sc_cli::SharedParams, @@ -225,10 +221,6 @@ pub struct ExportGenesisWasmCommand { #[clap(short, long)] pub raw: bool, - /// The name of the chain for that the genesis wasm file should be exported. - #[clap(long)] - pub chain: Option, - #[allow(missing_docs)] #[clap(flatten)] pub shared_params: sc_cli::SharedParams, diff --git a/parachain-template/node/src/command.rs b/parachain-template/node/src/command.rs index f1a6168a8d0..eedc6e952f7 100644 --- a/parachain-template/node/src/command.rs +++ b/parachain-template/node/src/command.rs @@ -182,7 +182,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { - let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; let state_version = Cli::native_runtime_version(&spec).state_version(); cmd.run::(&*spec, state_version) }) @@ -190,7 +190,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { - let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; cmd.run(&*spec) }) }, diff --git a/polkadot-parachain/src/command.rs b/polkadot-parachain/src/command.rs index 3d5abc2a3e7..be727a0d0db 100644 --- a/polkadot-parachain/src/command.rs +++ b/polkadot-parachain/src/command.rs @@ -416,7 +416,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { - let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; let state_version = Cli::native_runtime_version(&spec).state_version(); cmd.run::(&*spec, state_version) }) @@ -424,7 +424,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { - let spec = cli.load_spec(&cmd.chain.clone().unwrap_or_default())?; + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; cmd.run(&*spec) }) },