Skip to content

Commit

Permalink
node/cli: export genesis metadata
Browse files Browse the repository at this point in the history
This commit adds a new subcommand to the CLI that exports metadata from
the compiled-in runtime, similar to the existing subcommands like
`export-genesis-state` and `export-genesis-wasm`.

A typical usage would be

```bash
sugondat-node export-genesis-metadata --raw binary_metadata.scale
subxt codegen --file binary_metadata.scale | \
	rustfmt --edition=2021 --emit=stdout > src/metadata.rs
```

Ideally, it would be solved by [paritytech/polkadot-sdk#2745] and thus we could
just take the wasm blob (either exported by `export-genesis-wasm`) and just get
it from there via simple of the shelf tools. Until then, we will have this command.

[paritytech/polkadot-sdk#2745]: paritytech/polkadot-sdk#2745
  • Loading branch information
pepyakin committed Dec 21, 2023
1 parent b7fe237 commit cd327db
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
5 changes: 5 additions & 0 deletions sugondat-chain/node/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::command::export_genesis_metadata;
use std::path::PathBuf;

/// Sub-commands supported by the collator.
Expand Down Expand Up @@ -28,6 +29,10 @@ pub enum Subcommand {
/// Remove the whole chain.
PurgeChain(cumulus_client_cli::PurgeChainCmd),

// intentianally left out: the docs will be generated from the subcommand rustdoc.
#[allow(missing_docs)]
ExportGenesisMetadata(export_genesis_metadata::ExportGenesisMetadataCmd),

/// Export the genesis state of the parachain.
ExportGenesisState(cumulus_client_cli::ExportGenesisStateCommand),

Expand Down
9 changes: 9 additions & 0 deletions sugondat-chain/node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use crate::{
service::new_partial,
};

pub(crate) mod export_genesis_metadata;

fn load_spec(id: &str) -> std::result::Result<Box<dyn ChainSpec>, String> {
Ok(match id {
"dev" => Box::new(chain_spec::development_config()),
Expand Down Expand Up @@ -168,6 +170,13 @@ pub fn run() -> Result<()> {
cmd.run(config, polkadot_config)
})
},
Some(Subcommand::ExportGenesisMetadata(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
cmd.run(&config)?;
Ok(())
})
},
Some(Subcommand::ExportGenesisState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
Expand Down
69 changes: 69 additions & 0 deletions sugondat-chain/node/src/command/export_genesis_metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::command::new_partial;
use sc_client_api::HeaderBackend;
use sc_service::Configuration;
use sp_api::{Metadata, ProvideRuntimeApi};
use sp_core::hexdisplay::HexDisplay;
use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;

/// Export the genesis metadata of the parachain.
///
/// This will print the metadata into the specified file or stdout if no file is specified. By
/// default, the metadata is printed in hex format. Use the `--raw` flag to print the metadata in
/// binary format.
///
/// To use it with subxt, you can use the following commands:
///
/// sugondat-node export-genesis-metadata --raw > metadata.bin
///
/// subxt codegen --file metadata.bin | rustfmt --edition=2021 --emit=stdout > src/metadata.rs
#[derive(Debug, clap::Parser)]
pub struct ExportGenesisMetadataCmd {
#[allow(missing_docs)]
#[command(flatten)]
pub shared_params: sc_cli::SharedParams,

/// Output file name or stdout if unspecified.
#[arg()]
pub output: Option<PathBuf>,

/// Write output in binary. Default is to write in hex.
#[arg(short, long)]
pub raw: bool,
}

impl ExportGenesisMetadataCmd {
/// Exports the metadata for the genesis block.
///
/// Basically, this returns the metadata returned from the compiled-in runtime.
pub fn run(&self, config: &Configuration) -> sc_cli::Result<()> {
let partials = new_partial(&config)?;
let client = partials.client.clone();
let hash = client.info().genesis_hash;
let metadata: sp_core::OpaqueMetadata = client
.runtime_api()
.metadata(hash)
.map_err(|e| format!("Failed to fetch metadata from client: {:?}", e))?;

let output_buf: Vec<u8> = if self.raw {
metadata.to_vec()
} else {
format!("0x{:?}", HexDisplay::from(&*metadata)).into_bytes()
};

if let Some(output) = &self.output {
fs::write(output, output_buf)?;
} else {
io::stdout().write_all(&output_buf)?;
}

Ok(())
}
}

impl sc_cli::CliConfiguration for ExportGenesisMetadataCmd {
fn shared_params(&self) -> &sc_cli::SharedParams {
&self.shared_params
}
}

0 comments on commit cd327db

Please sign in to comment.