// This file is part of Substrate. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 // This program 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. // This program 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 this program. If not, see . use chain_spec_builder::{ generate_chain_spec_for_runtime, AddCodeSubstituteCmd, ChainSpecBuilder, ChainSpecBuilderCmd, ConvertToRawCmd, DisplayPresetCmd, ListPresetsCmd, UpdateCodeCmd, VerifyCmd, }; use clap::Parser; use sc_chain_spec::{ set_code_substitute_in_json_chain_spec, update_code_in_json_chain_spec, GenericChainSpec, GenesisConfigBuilderRuntimeCaller, }; use staging_chain_spec_builder as chain_spec_builder; use std::fs; type ChainSpec = GenericChainSpec<(), ()>; //avoid error message escaping 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 = ChainSpec::from_json_file(input_chain_spec.clone())?; let mut chain_spec_json = serde_json::from_str::(&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::AddCodeSubstitute(AddCodeSubstituteCmd { ref input_chain_spec, ref runtime_wasm_path, block_height, }) => { let chain_spec = ChainSpec::from_json_file(input_chain_spec.clone())?; let mut chain_spec_json = serde_json::from_str::(&chain_spec.as_json(false)?) .map_err(|e| format!("Conversion to json failed: {e}"))?; set_code_substitute_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}"))?[..], block_height, ); 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 = ChainSpec::from_json_file(input_chain_spec.clone())?; let chain_spec_json = serde_json::from_str::(&chain_spec.as_json(true)?) .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!("Conversion 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 = ChainSpec::from_json_file(input_chain_spec.clone())?; let _ = serde_json::from_str::(&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 = 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 preset = caller .get_named_preset(preset_name.as_ref()) .map_err(|e| format!("getting default config from runtime should work: {e}"))?; println!("{preset}"); }, }; Ok(()) }