From 4d1aea29b1f234580055c86e096ba6039f7fb0a5 Mon Sep 17 00:00:00 2001
From: Seemant Aggarwal <seemant.aggarwal@parity.io>
Date: Wed, 26 Feb 2025 00:05:42 +0530
Subject: [PATCH] adding command export_chain_spec

---
 cumulus/polkadot-omni-node/lib/src/cli.rs     |  8 ++--
 cumulus/polkadot-omni-node/lib/src/command.rs |  7 +++
 .../cli/src/commands/export_chain_spec_cmd.rs | 45 +++++++++++++++++++
 substrate/client/cli/src/commands/mod.rs      |  3 +-
 4 files changed, 58 insertions(+), 5 deletions(-)
 create mode 100644 substrate/client/cli/src/commands/export_chain_spec_cmd.rs

diff --git a/cumulus/polkadot-omni-node/lib/src/cli.rs b/cumulus/polkadot-omni-node/lib/src/cli.rs
index 995a50b2e48..564ee2a4ba6 100644
--- a/cumulus/polkadot-omni-node/lib/src/cli.rs
+++ b/cumulus/polkadot-omni-node/lib/src/cli.rs
@@ -26,10 +26,7 @@ use crate::{
 use chain_spec_builder::ChainSpecBuilder;
 use clap::{Command, CommandFactory, FromArgMatches};
 use sc_chain_spec::ChainSpec;
-use sc_cli::{
-	CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams,
-	RpcEndpoint, SharedParams, SubstrateCli,
-};
+use sc_cli::{CliConfiguration, DefaultConfigurationValues, ExportChainSpecCmd, ImportParams, KeystoreParams, NetworkParams, RpcEndpoint, SharedParams, SubstrateCli};
 use sc_service::{config::PrometheusConfig, BasePath};
 use std::{fmt::Debug, marker::PhantomData, path::PathBuf};
 /// Trait that can be used to customize some of the customer-facing info related to the node binary
@@ -106,6 +103,9 @@ pub enum Subcommand {
 	/// Export the genesis wasm of the parachain.
 	ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand),
 
+	/// Export the chain specification.
+	ExportChainSpec(ExportChainSpecCmd),
+
 	/// Sub-commands concerned with benchmarking.
 	/// The pallet benchmarking moved to the `pallet` sub-command.
 	#[command(subcommand)]
diff --git a/cumulus/polkadot-omni-node/lib/src/command.rs b/cumulus/polkadot-omni-node/lib/src/command.rs
index b4d89b151bf..6f259f7a29b 100644
--- a/cumulus/polkadot-omni-node/lib/src/command.rs
+++ b/cumulus/polkadot-omni-node/lib/src/command.rs
@@ -167,6 +167,13 @@ pub fn run<CliConfig: crate::cli::CliConfig>(cmd_config: RunConfig) -> Result<()
 				cmd.run(config, polkadot_config)
 			})
 		},
+		Some(Subcommand::ExportChainSpec(cmd)) => {
+			// Directly load the embedded chain spec using the CLI’s load_spec method.
+			let spec = cli.load_spec(&cmd.chain)
+				.map_err(|err| format!("{}", err))?;
+			cmd.run(spec)
+		},
+
 		Some(Subcommand::ExportGenesisHead(cmd)) => {
 			let runner = cli.create_runner(cmd)?;
 			runner.sync_run(|config| {
diff --git a/substrate/client/cli/src/commands/export_chain_spec_cmd.rs b/substrate/client/cli/src/commands/export_chain_spec_cmd.rs
new file mode 100644
index 00000000000..ec8dbb4e5b5
--- /dev/null
+++ b/substrate/client/cli/src/commands/export_chain_spec_cmd.rs
@@ -0,0 +1,45 @@
+use clap::Parser;
+use sc_service::{chain_ops, ChainSpec};
+use std::{
+    fs,
+    io::{self, Write},
+    path::PathBuf,
+};
+
+use crate::error::{Error, Result};
+
+/// Export the embedded chain-spec to a JSON file.
+///
+/// This command loads the embedded chain-spec (for example, when you pass
+/// `--chain /full/path/to/asset-hub-rococo`) and exports it to a JSON file. If `--output`
+/// is not provided, the JSON is printed to stdout.
+#[derive(Debug, Clone, Parser)]
+pub struct ExportChainSpecCmd {
+    /// The chain spec identifier to export.
+    #[arg(long, default_value = "local")]
+    pub chain: String,
+
+    /// Output file path. If omitted, prints to stdout.
+    #[arg(long)]
+    pub output: Option<PathBuf>,
+
+    /// Export in raw genesis storage format.
+    #[arg(long)]
+    pub raw: bool,
+}
+
+impl ExportChainSpecCmd {
+    pub fn run(&self, spec: Box<dyn ChainSpec>) -> Result<()> {
+        let json = chain_ops::build_spec(&*spec, self.raw)
+            .map_err(|e| format!("{}", e))?;
+        if let Some(ref path) = self.output {
+            fs::write(path, json).map_err(|e| format!("{}", e))?;
+            eprintln!("Exported chain spec to {}", path.display());
+        } else {
+            io::stdout()
+                .write_all(json.as_bytes())
+                .map_err(|e| format!("{}", e))?;
+        }
+        Ok(())
+    }
+}
diff --git a/substrate/client/cli/src/commands/mod.rs b/substrate/client/cli/src/commands/mod.rs
index 2d7a0dc72ff..55b2d51aace 100644
--- a/substrate/client/cli/src/commands/mod.rs
+++ b/substrate/client/cli/src/commands/mod.rs
@@ -38,6 +38,7 @@ mod test;
 pub mod utils;
 mod vanity;
 mod verify;
+mod export_chain_spec_cmd;
 
 pub use self::{
 	build_spec_cmd::BuildSpecCmd, chain_info_cmd::ChainInfoCmd, check_block_cmd::CheckBlockCmd,
@@ -45,5 +46,5 @@ pub use self::{
 	generate_node_key::GenerateKeyCmdCommon, import_blocks_cmd::ImportBlocksCmd,
 	insert_key::InsertKeyCmd, inspect_key::InspectKeyCmd, inspect_node_key::InspectNodeKeyCmd,
 	key::KeySubcommand, purge_chain_cmd::PurgeChainCmd, revert_cmd::RevertCmd, run_cmd::RunCmd,
-	sign::SignCmd, vanity::VanityCmd, verify::VerifyCmd,
+	sign::SignCmd, vanity::VanityCmd, verify::VerifyCmd, export_chain_spec_cmd::ExportChainSpecCmd,
 };
-- 
GitLab