mirror of
https://git.ghostchain.io/proxmio/ghost-node.git
synced 2026-02-10 23:50:23 +00:00
inital commit, which is clearly not initial
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
21
utils/chain-spec-builder/Cargo.toml
Normal file
21
utils/chain-spec-builder/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "ghost-staging-chain-spec-builder"
|
||||
description = "Utility for building chain-specification files for Ghost and Casper runtimes on `sp-genesis-builder`"
|
||||
version = "1.6.1"
|
||||
build = "build.rs"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
[[bin]]
|
||||
path = "bin/main.rs"
|
||||
name = "chain-spec-builder"
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
log = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sc-chain-spec = { workspace = true }
|
||||
sp-tracing = { workspace = true, features = ["std"] }
|
||||
103
utils/chain-spec-builder/bin/main.rs
Normal file
103
utils/chain-spec-builder/bin/main.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use chain_spec_builder::{
|
||||
generate_chain_spec_for_runtime, ChainSpecBuilder, ChainSpecBuilderCmd,
|
||||
ConvertToRawCmd, DisplayPresetCmd, ListPresetsCmd, UpdateCodeCmd,
|
||||
VerifyCmd,
|
||||
};
|
||||
use clap::Parser;
|
||||
use sc_chain_spec::{
|
||||
update_code_in_json_chain_spec, GenericChainSpec,
|
||||
GenesisConfigBuilderRuntimeCaller,
|
||||
};
|
||||
use ghost_staging_chain_spec_builder as chain_spec_builder;
|
||||
use std::fs;
|
||||
|
||||
fn main() {
|
||||
match inner_main() {
|
||||
Err(e) => eprintln!("{}", format!("{e}")),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_main() -> Result<(), String> {
|
||||
sp_tracing::try_init_simple();
|
||||
|
||||
let builder = ChainSpecBuilder::parse();
|
||||
let chain_spec_path = builder.chain_spec_path.to_path_buf();
|
||||
|
||||
match builder.command {
|
||||
ChainSpecBuilderCmd::Create(cmd) => {
|
||||
let chain_spec_json = generate_chain_spec_for_runtime(&cmd)?;
|
||||
fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?;
|
||||
},
|
||||
ChainSpecBuilderCmd::UpdateCode(UpdateCodeCmd {
|
||||
ref input_chain_spec,
|
||||
ref runtime_wasm_path,
|
||||
}) => {
|
||||
let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?;
|
||||
|
||||
let mut chain_spec_json = serde_json::from_str::<serde_json::Value>(
|
||||
&chain_spec.as_json(false)?
|
||||
).map_err(|e| format!("Conversion to json failed: {e}"))?;
|
||||
update_code_in_json_chain_spec(
|
||||
&mut chain_spec_json,
|
||||
&fs::read(runtime_wasm_path.as_path())
|
||||
.map_err(|e| format!("Wasm blob file could not be read: {e}"))?[..],
|
||||
);
|
||||
|
||||
let chain_spec_json = serde_json::to_string_pretty(&chain_spec_json)
|
||||
.map_err(|e| format!("to pretty failed: {e}"))?;
|
||||
fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?;
|
||||
},
|
||||
ChainSpecBuilderCmd::ConvertToRaw(ConvertToRawCmd { ref input_chain_spec }) => {
|
||||
let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?;
|
||||
|
||||
let chain_spec_json = serde_json::from_str::<serde_json::Value>(
|
||||
&chain_spec.as_json(false)?
|
||||
).map_err(|e| format!("Conversion to json failed: {e}"))?;
|
||||
|
||||
let chain_spec_json = serde_json::to_string_pretty(&chain_spec_json)
|
||||
.map_err(|e| format!("to pretty failed: {e}"))?;
|
||||
fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?;
|
||||
},
|
||||
ChainSpecBuilderCmd::Verify(VerifyCmd { ref input_chain_spec }) => {
|
||||
let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?;
|
||||
let _ = serde_json::from_str::<serde_json::Value>(&chain_spec.as_json(true)?)
|
||||
.map_err(|e| format!("Conversion to json failed: {e}"))?;
|
||||
},
|
||||
ChainSpecBuilderCmd::ListPresets(ListPresetsCmd { runtime_wasm_path }) => {
|
||||
let code = fs::read(runtime_wasm_path.as_path())
|
||||
.map_err(|e| format!("wasm blob shall be readable {e}"))?;
|
||||
let caller: GenesisConfigBuilderRuntimeCaller =
|
||||
GenesisConfigBuilderRuntimeCaller::new(&code[..]);
|
||||
let presets = caller
|
||||
.preset_names()
|
||||
.map_err(|e| format!("getting default config from runtime should work: {e}"))?;
|
||||
let presets: Vec<String> = presets
|
||||
.into_iter()
|
||||
.map(|preset| {
|
||||
String::from(
|
||||
TryInto::<&str>::try_into(&preset)
|
||||
.unwrap_or_else(|_| "cannot display preset id")
|
||||
.to_string(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
println!("{}", serde_json::json!({"presets": presets}).to_string());
|
||||
},
|
||||
ChainSpecBuilderCmd::DisplayPreset(DisplayPresetCmd {
|
||||
runtime_wasm_path,
|
||||
preset_name,
|
||||
}) => {
|
||||
let code = fs::read(runtime_wasm_path.as_path())
|
||||
.map_err(|e| format!("wasm blob shall be readable {e}"))?;
|
||||
let caller: GenesisConfigBuilderRuntimeCaller =
|
||||
GenesisConfigBuilderRuntimeCaller::new(&code[..]);
|
||||
let presets = caller
|
||||
.get_named_preset(preset_name.as_ref())
|
||||
.map_err(|e| format!("getting default config from runtime should work: {e}"))?;
|
||||
println!("{presets}");
|
||||
},
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
7
utils/chain-spec-builder/build.rs
Normal file
7
utils/chain-spec-builder/build.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
if let Ok(profile) = env::var("PROFILE") {
|
||||
println!("cargo:rustc-cfg=build_type=\"{}\"", profile);
|
||||
}
|
||||
}
|
||||
196
utils/chain-spec-builder/src/lib.rs
Normal file
196
utils/chain-spec-builder/src/lib.rs
Normal file
@@ -0,0 +1,196 @@
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use serde_json::Value;
|
||||
use sc_chain_spec::{
|
||||
ChainType, GenericChainSpec, GenesisConfigBuilderRuntimeCaller,
|
||||
};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(rename_all = "kebab-case", version, about)]
|
||||
pub struct ChainSpecBuilder {
|
||||
#[command(subcommand)]
|
||||
pub command: ChainSpecBuilderCmd,
|
||||
/// The path where the chain should be saved.
|
||||
#[arg(long, short, default_value = "./chain_spec.json")]
|
||||
pub chain_spec_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
pub enum ChainSpecBuilderCmd {
|
||||
Create(CreateCmd),
|
||||
Verify(VerifyCmd),
|
||||
UpdateCode(UpdateCodeCmd),
|
||||
ConvertToRaw(ConvertToRawCmd),
|
||||
ListPresets(ListPresetsCmd),
|
||||
DisplayPreset(DisplayPresetCmd),
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct CreateCmd {
|
||||
/// The name of chain.
|
||||
#[arg(long, short = 'n', default_value = "Casper")]
|
||||
chain_name: String,
|
||||
|
||||
/// The chain id.
|
||||
#[arg(long, short = 'i', default_value = "casper")]
|
||||
chain_id: String,
|
||||
|
||||
/// The path to runtime wasm blob.
|
||||
#[arg(long, short)]
|
||||
runtime_wasm_path: PathBuf,
|
||||
|
||||
/// Export chainspec as raw storage.
|
||||
#[arg(long, short = 's')]
|
||||
raw_storage: bool,
|
||||
|
||||
/// Verify the genesis config. This silently generates the raw storage from
|
||||
/// genesis config. Any errors will be reported.
|
||||
#[arg(long, short = 'v')]
|
||||
verify: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
action: GenesisBuildAction,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug, Clone)]
|
||||
enum GenesisBuildAction {
|
||||
Patch(PatchCmd),
|
||||
Full(FullCmd),
|
||||
Default(DefaultCmd),
|
||||
NamedPreset(NamedPresetCmd),
|
||||
}
|
||||
|
||||
/// Pathches the runtime's default genesis config with provided patch.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
struct PatchCmd {
|
||||
/// The path to the full runtime genesis config json file.
|
||||
patch_path: PathBuf,
|
||||
}
|
||||
|
||||
/// Build the genesis config for runtime using provided json file.
|
||||
/// No defaults will be used.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
struct FullCmd {
|
||||
/// The path to the full runtime genesis config json file.
|
||||
config_path: PathBuf,
|
||||
}
|
||||
|
||||
/// Gets the default genesis config for the runtime and uses it in ChainSpec.
|
||||
/// Please note that default genesis config may not be valid. For some runtimes
|
||||
/// initial values should be added there (e.g. session keys, babe epoch).
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
struct DefaultCmd {}
|
||||
|
||||
/// Uses named preset provided by runtime to build the chain spec.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
struct NamedPresetCmd {
|
||||
preset_name: String,
|
||||
}
|
||||
|
||||
/// Updates the coe on the provided input chain spec.
|
||||
///
|
||||
/// The code field of the chain spec will be updated with the runtime provided
|
||||
/// in the command line. The operation supports both plain and raw formats.
|
||||
///
|
||||
/// This command does not update chain-spec file in-place. The result of this
|
||||
/// command will be stored in a file given as `-c/--chain-spec-path` command
|
||||
/// line argument.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
pub struct UpdateCodeCmd {
|
||||
/// Chain spec to be updated.
|
||||
///
|
||||
/// Please note that the file will not be updated in-place.
|
||||
pub input_chain_spec: PathBuf,
|
||||
/// The path to new runtime wasm blob to be stored into chain-spec.
|
||||
pub runtime_wasm_path: PathBuf,
|
||||
}
|
||||
|
||||
/// Converts the given chain spec into raw format.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
pub struct ConvertToRawCmd {
|
||||
/// Chain spec to be converted.
|
||||
pub input_chain_spec: PathBuf,
|
||||
}
|
||||
|
||||
/// Lists avaiable presets.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
pub struct ListPresetsCmd {
|
||||
/// The path to runtime wasm blob.
|
||||
#[arg(long, short)]
|
||||
pub runtime_wasm_path: PathBuf,
|
||||
}
|
||||
|
||||
/// Displays given preset.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
pub struct DisplayPresetCmd {
|
||||
/// The path to runtime wasm blob.
|
||||
#[arg(long, short)]
|
||||
pub runtime_wasm_path: PathBuf,
|
||||
|
||||
/// Preset to be displayed. If none if given default will be displayed.
|
||||
#[arg(long, short)]
|
||||
pub preset_name: Option<String>,
|
||||
}
|
||||
|
||||
/// Verifies the provided input chain spec.
|
||||
///
|
||||
/// Silently checks if given input chain spec can be converted to raw. It allows
|
||||
/// to check if all `RuntimeGenesisConfig` fields are properly initialized and
|
||||
/// if the json does not contain invalid fields.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
pub struct VerifyCmd {
|
||||
/// Chain spec to be verified.
|
||||
pub input_chain_spec: PathBuf,
|
||||
}
|
||||
|
||||
/// Processes `CreateCmd` and returns JSON version of `ChainSpec`.
|
||||
pub fn generate_chain_spec_for_runtime(cmd: &CreateCmd) -> Result<String, String> {
|
||||
let code = fs::read(cmd.runtime_wasm_path.as_path())
|
||||
.map_err(|e| format!("wasm blob shall be readable {e}"))?;
|
||||
|
||||
let builder = GenericChainSpec::<()>::builder(&code[..], Default::default())
|
||||
.with_name(&cmd.chain_name[..])
|
||||
.with_id(&cmd.chain_id[..])
|
||||
.with_chain_type(ChainType::Live);
|
||||
|
||||
let builder = match cmd.action {
|
||||
GenesisBuildAction::NamedPreset(NamedPresetCmd { ref preset_name }) =>
|
||||
builder.with_genesis_config_preset_name(&preset_name),
|
||||
GenesisBuildAction::Patch(PatchCmd { ref patch_path }) => {
|
||||
let patch = fs::read(patch_path.as_path())
|
||||
.map_err(|e| format!("patch file {patch_path:?} shall be readable: {e}"))?;
|
||||
builder.with_genesis_config_patch(serde_json::from_slice::<Value>(&patch[..]).map_err(
|
||||
|e| format!("patch file {patch_path:?} shall contain a valid json: {e}"),
|
||||
)?)
|
||||
},
|
||||
GenesisBuildAction::Full(FullCmd { ref config_path }) => {
|
||||
let config = fs::read(config_path.as_path())
|
||||
.map_err(|e| format!("config file {config_path:?} shall be readable: {e}"))?;
|
||||
builder.with_genesis_config(serde_json::from_slice::<Value>(&config[..]).map_err(
|
||||
|e| format!("config file {config_path:?} shall contain a valid json: {e}"),
|
||||
)?)
|
||||
},
|
||||
GenesisBuildAction::Default(DefaultCmd {}) => {
|
||||
let caller: GenesisConfigBuilderRuntimeCaller =
|
||||
GenesisConfigBuilderRuntimeCaller::new(&code[..]);
|
||||
let default_config = caller
|
||||
.get_default_config()
|
||||
.map_err(|e| format!("getting default config from runtime should work: {e}"))?;
|
||||
builder.with_genesis_config(default_config)
|
||||
},
|
||||
};
|
||||
|
||||
let chain_spec = builder.build();
|
||||
|
||||
match (cmd.verify, cmd.raw_storage) {
|
||||
(_, true) => chain_spec.as_json(true),
|
||||
(true, false) => {
|
||||
chain_spec.as_json(true)?;
|
||||
println!("Genesis config verification: OK");
|
||||
chain_spec.as_json(false)
|
||||
},
|
||||
(false, false) => chain_spec.as_json(false),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user