From 56842443297ab959822ffae4c1a2f31a04c3725b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 20 Sep 2023 15:37:14 +0100 Subject: [PATCH 1/5] Adds chain spec generator --- Cargo.lock | 97 +++- Cargo.toml | 1 + chain-spec-generator/Cargo.toml | 29 ++ chain-spec-generator/src/main.rs | 48 ++ chain-spec-generator/src/relay_chain_specs.rs | 474 ++++++++++++++++++ 5 files changed, 643 insertions(+), 6 deletions(-) create mode 100644 chain-spec-generator/Cargo.toml create mode 100644 chain-spec-generator/src/main.rs create mode 100644 chain-spec-generator/src/relay_chain_specs.rs diff --git a/Cargo.lock b/Cargo.lock index c9865981cf..505978728e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1516,6 +1516,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "chain-spec-generator" +version = "1.0.0" +dependencies = [ + "clap", + "hex-literal", + "kusama-runtime-constants 1.0.0", + "pallet-im-online", + "pallet-staking", + "polkadot-primitives", + "polkadot-runtime", + "polkadot-runtime-constants 1.0.0", + "polkadot-runtime-parachains", + "sc-chain-spec", + "sc-consensus-grandpa", + "serde_json", + "sp-authority-discovery", + "sp-consensus-babe", + "sp-consensus-beefy", + "sp-core", + "sp-runtime", + "staging-kusama-runtime", +] + [[package]] name = "chrono" version = "0.4.27" @@ -1594,9 +1618,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.2" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" dependencies = [ "clap_builder", "clap_derive", @@ -1604,9 +1628,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.2" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" dependencies = [ "anstream", "anstyle", @@ -9229,6 +9253,48 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sc-consensus-grandpa" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc9029e051a1ff62dff58219ca654ebecc669e3746cf4a0bc1515f96c2220c9b" +dependencies = [ + "ahash 0.8.3", + "array-bytes", + "async-trait", + "dyn-clone", + "finality-grandpa", + "fork-tree", + "futures", + "futures-timer", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-consensus", + "sc-network", + "sc-network-common", + "sc-network-gossip", + "sc-telemetry", + "sc-transaction-pool-api", + "sc-utils", + "serde_json", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-consensus-grandpa", + "sp-core", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", +] + [[package]] name = "sc-executor" version = "0.27.0" @@ -9396,6 +9462,25 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "sc-network-gossip" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "596fa23e269e218a5cbd9928fa1df30c46fbf9f04cdcf0cbd6549c47e952ad77" +dependencies = [ + "ahash 0.8.3", + "futures", + "futures-timer", + "libp2p", + "log", + "sc-network", + "sc-network-common", + "schnellru", + "sp-runtime", + "substrate-prometheus-endpoint", + "tracing", +] + [[package]] name = "sc-network-light" version = "0.28.0" @@ -10026,9 +10111,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", diff --git a/Cargo.toml b/Cargo.toml index ae60da4073..0403703dd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-only" # TODO Result<(), String> { + let cli = Cli::parse(); + + let supported_chains = + HashMap::<_, Box Result, String>>>::from([ + ( + "polkadot-dev", + Box::new(|| relay_chain_specs::polkadot_development_config()) as Box<_>, + ), + ( + "polkadot-local", + Box::new(|| relay_chain_specs::polkadot_local_testnet_config()) as Box<_>, + ), + ("kusama-dev", Box::new(|| relay_chain_specs::kusama_development_config()) as Box<_>), + ( + "kusama-local", + Box::new(|| relay_chain_specs::kusama_local_testnet_config()) as Box<_>, + ), + ]); + + if let Some(function) = supported_chains.get(&*cli.chain) { + let chain_spec = (*function)()?.as_json(cli.raw)?; + print!("{chain_spec}"); + Ok(()) + } else { + let supported = supported_chains.keys().enumerate().fold(String::new(), |c, (n, k)| { + let extra = (n + 1 < supported_chains.len()).then(|| ", ").unwrap_or(""); + format!("{c}{k}{extra}") + }); + Err(format!("Unknown chain, only supported: {supported}")) + } +} diff --git a/chain-spec-generator/src/relay_chain_specs.rs b/chain-spec-generator/src/relay_chain_specs.rs new file mode 100644 index 0000000000..6ebb8b4ee7 --- /dev/null +++ b/chain-spec-generator/src/relay_chain_specs.rs @@ -0,0 +1,474 @@ +use kusama_runtime_constants::currency::UNITS as KSM; +use pallet_im_online::sr25519::AuthorityId as ImOnlineId; +use pallet_staking::Forcing; +use polkadot_primitives::{AccountId, AccountPublic, AssignmentId, ValidatorId}; +use polkadot_runtime_constants::currency::UNITS as DOT; +use polkadot_runtime_parachains::configuration::HostConfiguration; +use sc_chain_spec::{ChainSpec, ChainType, NoExtension}; +use sc_consensus_grandpa::AuthorityId as GrandpaId; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use sp_consensus_babe::AuthorityId as BabeId; +use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::{traits::IdentifyAccount, Perbill}; + +pub type PolkadotChainSpec = + sc_chain_spec::GenericChainSpec; + +pub type KusamaChainSpec = + sc_chain_spec::GenericChainSpec; + +const DEFAULT_PROTOCOL_ID: &str = "dot"; + +/// Returns the properties for the [`PolkadotChainSpec`]. +pub fn polkadot_chain_spec_properties() -> serde_json::map::Map { + serde_json::json!({ + "tokenDecimals": 10, + }) + .as_object() + .expect("Map given; qed") + .clone() +} + +fn default_parachains_host_configuration() -> HostConfiguration { + use polkadot_primitives::{MAX_CODE_SIZE, MAX_POV_SIZE}; + + polkadot_runtime_parachains::configuration::HostConfiguration { + validation_upgrade_cooldown: 2u32, + validation_upgrade_delay: 2, + code_retention_period: 1200, + max_code_size: MAX_CODE_SIZE, + max_pov_size: MAX_POV_SIZE, + max_head_data_size: 32 * 1024, + group_rotation_frequency: 20, + paras_availability_period: 4, + max_upward_queue_count: 8, + max_upward_queue_size: 1024 * 1024, + max_downward_message_size: 1024 * 1024, + max_upward_message_size: 50 * 1024, + max_upward_message_num_per_candidate: 5, + hrmp_sender_deposit: 0, + hrmp_recipient_deposit: 0, + hrmp_channel_max_capacity: 8, + hrmp_channel_max_total_size: 8 * 1024, + hrmp_max_parachain_inbound_channels: 4, + hrmp_channel_max_message_size: 1024 * 1024, + hrmp_max_parachain_outbound_channels: 4, + hrmp_max_message_num_per_candidate: 5, + dispute_period: 6, + no_show_slots: 2, + n_delay_tranches: 25, + needed_approvals: 2, + relay_vrf_modulo_samples: 2, + zeroth_delay_tranche_width: 0, + minimum_validation_upgrade_delay: 5, + ..Default::default() + } +} + +fn polkadot_session_keys( + babe: BabeId, + grandpa: GrandpaId, + im_online: ImOnlineId, + para_validator: ValidatorId, + para_assignment: AssignmentId, + authority_discovery: AuthorityDiscoveryId, +) -> polkadot_runtime::SessionKeys { + polkadot_runtime::SessionKeys { + babe, + grandpa, + im_online, + para_validator, + para_assignment, + authority_discovery, + } +} + +fn kusama_session_keys( + babe: BabeId, + grandpa: GrandpaId, + im_online: ImOnlineId, + para_validator: ValidatorId, + para_assignment: AssignmentId, + authority_discovery: AuthorityDiscoveryId, + beefy: BeefyId, +) -> kusama_runtime::SessionKeys { + kusama_runtime::SessionKeys { + babe, + grandpa, + im_online, + para_validator, + para_assignment, + authority_discovery, + beefy, + } +} + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate stash, controller and session key from seed +pub fn get_authority_keys_from_seed( + seed: &str, +) -> ( + AccountId, + AccountId, + BabeId, + GrandpaId, + ImOnlineId, + ValidatorId, + AssignmentId, + AuthorityDiscoveryId, + BeefyId, +) { + let keys = get_authority_keys_from_seed_no_beefy(seed); + (keys.0, keys.1, keys.2, keys.3, keys.4, keys.5, keys.6, keys.7, get_from_seed::(seed)) +} + +/// Helper function to generate stash, controller and session key from seed +pub fn get_authority_keys_from_seed_no_beefy( + seed: &str, +) -> ( + AccountId, + AccountId, + BabeId, + GrandpaId, + ImOnlineId, + ValidatorId, + AssignmentId, + AuthorityDiscoveryId, +) { + ( + get_account_id_from_seed::(&format!("{}//stash", seed)), + get_account_id_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + ) +} + +fn testnet_accounts() -> Vec { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ] +} + +pub fn polkadot_testnet_genesis( + wasm_binary: &[u8], + initial_authorities: Vec<( + AccountId, + AccountId, + BabeId, + GrandpaId, + ImOnlineId, + ValidatorId, + AssignmentId, + AuthorityDiscoveryId, + )>, + _root_key: AccountId, + endowed_accounts: Option>, +) -> polkadot_runtime::RuntimeGenesisConfig { + let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(testnet_accounts); + + const ENDOWMENT: u128 = 1_000_000 * DOT; + const STASH: u128 = 100 * DOT; + + polkadot_runtime::RuntimeGenesisConfig { + system: polkadot_runtime::SystemConfig { code: wasm_binary.to_vec(), ..Default::default() }, + indices: polkadot_runtime::IndicesConfig { indices: vec![] }, + balances: polkadot_runtime::BalancesConfig { + balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(), + }, + session: polkadot_runtime::SessionConfig { + keys: initial_authorities + .iter() + .map(|x| { + ( + x.0.clone(), + x.0.clone(), + polkadot_session_keys( + x.2.clone(), + x.3.clone(), + x.4.clone(), + x.5.clone(), + x.6.clone(), + x.7.clone(), + ), + ) + }) + .collect::>(), + }, + staking: polkadot_runtime::StakingConfig { + minimum_validator_count: 1, + validator_count: initial_authorities.len() as u32, + stakers: initial_authorities + .iter() + .map(|x| { + (x.0.clone(), x.0.clone(), STASH, polkadot_runtime::StakerStatus::Validator) + }) + .collect(), + invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), + force_era: Forcing::NotForcing, + slash_reward_fraction: Perbill::from_percent(10), + ..Default::default() + }, + babe: polkadot_runtime::BabeConfig { + authorities: Default::default(), + epoch_config: Some(polkadot_runtime::BABE_GENESIS_EPOCH_CONFIG), + ..Default::default() + }, + grandpa: Default::default(), + im_online: Default::default(), + authority_discovery: polkadot_runtime::AuthorityDiscoveryConfig { + keys: vec![], + ..Default::default() + }, + claims: polkadot_runtime::ClaimsConfig { claims: vec![], vesting: vec![] }, + vesting: polkadot_runtime::VestingConfig { vesting: vec![] }, + treasury: Default::default(), + hrmp: Default::default(), + configuration: polkadot_runtime::ConfigurationConfig { + config: default_parachains_host_configuration(), + }, + paras: Default::default(), + xcm_pallet: Default::default(), + nomination_pools: Default::default(), + } +} + +/// Helper function to create kusama `RuntimeGenesisConfig` for testing +pub fn kusama_testnet_genesis( + wasm_binary: &[u8], + initial_authorities: Vec<( + AccountId, + AccountId, + BabeId, + GrandpaId, + ImOnlineId, + ValidatorId, + AssignmentId, + AuthorityDiscoveryId, + BeefyId, + )>, + _root_key: AccountId, + endowed_accounts: Option>, +) -> kusama_runtime::RuntimeGenesisConfig { + let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(testnet_accounts); + + const ENDOWMENT: u128 = 1_000_000 * KSM; + const STASH: u128 = 100 * KSM; + + kusama_runtime::RuntimeGenesisConfig { + system: kusama_runtime::SystemConfig { code: wasm_binary.to_vec(), ..Default::default() }, + indices: kusama_runtime::IndicesConfig { indices: vec![] }, + balances: kusama_runtime::BalancesConfig { + balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(), + }, + beefy: Default::default(), + session: kusama_runtime::SessionConfig { + keys: initial_authorities + .iter() + .map(|x| { + ( + x.0.clone(), + x.0.clone(), + kusama_session_keys( + x.2.clone(), + x.3.clone(), + x.4.clone(), + x.5.clone(), + x.6.clone(), + x.7.clone(), + x.8.clone(), + ), + ) + }) + .collect::>(), + }, + staking: kusama_runtime::StakingConfig { + minimum_validator_count: 1, + validator_count: initial_authorities.len() as u32, + stakers: initial_authorities + .iter() + .map(|x| (x.0.clone(), x.0.clone(), STASH, kusama_runtime::StakerStatus::Validator)) + .collect(), + invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), + force_era: Forcing::NotForcing, + slash_reward_fraction: Perbill::from_percent(10), + ..Default::default() + }, + babe: kusama_runtime::BabeConfig { + authorities: Default::default(), + epoch_config: Some(kusama_runtime::BABE_GENESIS_EPOCH_CONFIG), + ..Default::default() + }, + grandpa: Default::default(), + im_online: Default::default(), + authority_discovery: kusama_runtime::AuthorityDiscoveryConfig { + keys: vec![], + ..Default::default() + }, + claims: kusama_runtime::ClaimsConfig { claims: vec![], vesting: vec![] }, + vesting: kusama_runtime::VestingConfig { vesting: vec![] }, + treasury: Default::default(), + hrmp: Default::default(), + configuration: kusama_runtime::ConfigurationConfig { + config: default_parachains_host_configuration(), + }, + paras: Default::default(), + xcm_pallet: Default::default(), + nomination_pools: Default::default(), + nis_counterpart_balances: Default::default(), + } +} + +fn polkadot_development_config_genesis( + wasm_binary: &[u8], +) -> polkadot_runtime::RuntimeGenesisConfig { + polkadot_testnet_genesis( + wasm_binary, + vec![get_authority_keys_from_seed_no_beefy("Alice")], + get_account_id_from_seed::("Alice"), + None, + ) +} + +fn kusama_development_config_genesis(wasm_binary: &[u8]) -> kusama_runtime::RuntimeGenesisConfig { + kusama_testnet_genesis( + wasm_binary, + vec![get_authority_keys_from_seed("Alice")], + get_account_id_from_seed::("Alice"), + None, + ) +} + +/// Polkadot development config (single validator Alice) +pub fn polkadot_development_config() -> Result, String> { + let wasm_binary = + polkadot_runtime::WASM_BINARY.ok_or("Polkadot development wasm not available")?; + + Ok(Box::new(PolkadotChainSpec::from_genesis( + "Development", + "polkadot_dev", + ChainType::Development, + move || polkadot_development_config_genesis(wasm_binary), + vec![], + None, + Some(DEFAULT_PROTOCOL_ID), + None, + Some(polkadot_chain_spec_properties()), + Default::default(), + ))) +} + +/// Kusama development config (single validator Alice) +pub fn kusama_development_config() -> Result, String> { + let wasm_binary = kusama_runtime::WASM_BINARY.ok_or("Kusama development wasm not available")?; + + Ok(Box::new(KusamaChainSpec::from_genesis( + "Development", + "kusama_dev", + ChainType::Development, + move || kusama_development_config_genesis(wasm_binary), + vec![], + None, + Some(DEFAULT_PROTOCOL_ID), + None, + None, + Default::default(), + ))) +} + +fn polkadot_local_testnet_genesis(wasm_binary: &[u8]) -> polkadot_runtime::RuntimeGenesisConfig { + polkadot_testnet_genesis( + wasm_binary, + vec![ + get_authority_keys_from_seed_no_beefy("Alice"), + get_authority_keys_from_seed_no_beefy("Bob"), + ], + get_account_id_from_seed::("Alice"), + None, + ) +} + +/// Polkadot local testnet config (multivalidator Alice + Bob) +pub fn polkadot_local_testnet_config() -> Result, String> { + let wasm_binary = + polkadot_runtime::WASM_BINARY.ok_or("Polkadot development wasm not available")?; + + Ok(Box::new(PolkadotChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + ChainType::Local, + move || polkadot_local_testnet_genesis(wasm_binary), + vec![], + None, + Some(DEFAULT_PROTOCOL_ID), + None, + Some(polkadot_chain_spec_properties()), + Default::default(), + ))) +} + +fn kusama_local_testnet_genesis(wasm_binary: &[u8]) -> kusama_runtime::RuntimeGenesisConfig { + kusama_testnet_genesis( + wasm_binary, + vec![get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob")], + get_account_id_from_seed::("Alice"), + None, + ) +} + +/// Kusama local testnet config (multivalidator Alice + Bob) +pub fn kusama_local_testnet_config() -> Result, String> { + let wasm_binary = kusama_runtime::WASM_BINARY.ok_or("Kusama development wasm not available")?; + + Ok(Box::new(KusamaChainSpec::from_genesis( + "Kusama Local Testnet", + "kusama_local_testnet", + ChainType::Local, + move || kusama_local_testnet_genesis(wasm_binary), + vec![], + None, + Some(DEFAULT_PROTOCOL_ID), + None, + None, + Default::default(), + ))) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn default_parachains_host_configuration_is_consistent() { + default_parachains_host_configuration().panic_if_not_consistent(); + } +} From dc17212e5504c9b37707d92c4eafde3a798dbbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 25 Oct 2023 16:03:48 +0200 Subject: [PATCH 2/5] Enable `derive` feature --- chain-spec-generator/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain-spec-generator/Cargo.toml b/chain-spec-generator/Cargo.toml index 66d8e287ee..a627c2ebf7 100644 --- a/chain-spec-generator/Cargo.toml +++ b/chain-spec-generator/Cargo.toml @@ -7,7 +7,7 @@ repository.workspace = true license.workspace = true [dependencies] -clap = "4.4.4" +clap = { version = "4.4.4", features = [ "derive" ] } hex-literal = "0.4.1" serde_json = "1.0.107" From 08d8f9410436c5941d2cecaad6856431d6101949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 25 Oct 2023 16:11:23 +0200 Subject: [PATCH 3/5] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52211be6e2..2e921cbde6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ Changelog for the runtimes governed by the Polkadot Fellowship. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [Unreleased] + +### Added + +- Introduce chain spec generator ([polkadot-fellows/runtimes#78](https://github.com/polkadot-fellows/runtimes/pull/78)) + ## [1.0.0] 22.10.2023 ### Changed From 8e960736c3284638ad8772ca77797f9532f25b77 Mon Sep 17 00:00:00 2001 From: Javier Viola Date: Fri, 27 Oct 2023 15:54:02 -0300 Subject: [PATCH 4/5] chain spec generator, load from json (#79) Hi @bkchr, I know that this is temporary tool but in order to create a workaround for zombienet is useful to allow to pass customized plain spec file and get the `raw` one. Thx! --- chain-spec-generator/src/main.rs | 16 +++++++++++----- chain-spec-generator/src/relay_chain_specs.rs | 10 ++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/chain-spec-generator/src/main.rs b/chain-spec-generator/src/main.rs index 32af258e12..2c949eccb1 100644 --- a/chain-spec-generator/src/main.rs +++ b/chain-spec-generator/src/main.rs @@ -39,10 +39,16 @@ fn main() -> Result<(), String> { print!("{chain_spec}"); Ok(()) } else { - let supported = supported_chains.keys().enumerate().fold(String::new(), |c, (n, k)| { - let extra = (n + 1 < supported_chains.len()).then(|| ", ").unwrap_or(""); - format!("{c}{k}{extra}") - }); - Err(format!("Unknown chain, only supported: {supported}")) + if cli.chain.ends_with(".json") { + let chain_spec = relay_chain_specs::from_json_file(&cli.chain)?.as_json(cli.raw)?; + print!("{chain_spec}"); + Ok(()) + } else { + let supported = supported_chains.keys().enumerate().fold(String::new(), |c, (n, k)| { + let extra = (n + 1 < supported_chains.len()).then(|| ", ").unwrap_or(""); + format!("{c}{k}{extra}") + }); + Err(format!("Unknown chain, only supported: {supported} or a json file")) + } } } diff --git a/chain-spec-generator/src/relay_chain_specs.rs b/chain-spec-generator/src/relay_chain_specs.rs index 6ebb8b4ee7..44c1f0f7d0 100644 --- a/chain-spec-generator/src/relay_chain_specs.rs +++ b/chain-spec-generator/src/relay_chain_specs.rs @@ -463,6 +463,16 @@ pub fn kusama_local_testnet_config() -> Result, String> { ))) } +pub fn from_json_file(filepath: &str) -> Result, String> { + let path = std::path::PathBuf::from(&filepath); + let chain_spec = PolkadotChainSpec::from_json_file(path.clone())?; + match chain_spec.id() { + x if x.starts_with("kusama") | x.starts_with("ksm") => + Ok(Box::new(KusamaChainSpec::from_json_file(path)?)), + _ => Ok(Box::new(chain_spec)), + } +} + #[cfg(test)] mod tests { use super::*; From a6336ed4736891de4fdc4c31c27e6a20641f943b Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 16 Nov 2023 13:02:22 +0100 Subject: [PATCH 5/5] Enable `runtime-benchmarks` feature for chain spec generator (#91) Based on: https://github.com/polkadot-fellows/runtimes/pull/78 Without this fix we cannot run benchmarks for kusama/polkadot. Tested here: https://github.com/polkadot-fellows/runtimes/pull/58#issuecomment-1814123768 --- chain-spec-generator/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chain-spec-generator/Cargo.toml b/chain-spec-generator/Cargo.toml index a627c2ebf7..60c16ca1e0 100644 --- a/chain-spec-generator/Cargo.toml +++ b/chain-spec-generator/Cargo.toml @@ -27,3 +27,9 @@ sc-consensus-grandpa = "0.14.0" pallet-im-online = "22.0.0" sp-runtime = "26.0.0" sp-consensus-beefy = "8.0.0" + +[features] +runtime-benchmarks = [ + "kusama-runtime/runtime-benchmarks", + "polkadot-runtime/runtime-benchmarks", +] \ No newline at end of file