use cumulus_primitives_core::ParaId; use parachain_template_runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; /// The default XCM version to set in genesis config. const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// 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() } /// The extensions for the [`ChainSpec`]. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] #[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. pub relay_chain: String, /// The id of the Parachain. pub para_id: u32, } impl Extensions { /// Try to get the extension from the given `ChainSpec`. pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> { sc_chain_spec::get_extension(chain_spec.extensions()) } } type AccountPublic = ::Signer; /// Generate collator keys from seed. /// /// This function's return type must always match the session keys of the chain /// in tuple format. pub fn get_collator_keys_from_seed(seed: &str) -> AuraId { get_from_seed::(seed) } /// 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() } /// Generate the session keys from individual elements. /// /// The input must be a tuple of individual keys (a single arg for now since we /// have just one key). pub fn template_session_keys(keys: AuraId) -> parachain_template_runtime::SessionKeys { parachain_template_runtime::SessionKeys { aura: keys } } pub fn development_config() -> ChainSpec { // Give your base currency a unit name and decimal places let mut properties = sc_chain_spec::Properties::new(); properties.insert("tokenSymbol".into(), "UNIT".into()); properties.insert("tokenDecimals".into(), 12.into()); properties.insert("ss58Format".into(), 42.into()); ChainSpec::from_genesis( // Name "Development", // ID "dev", ChainType::Development, move || { testnet_genesis( // initial collators. vec![ ( get_account_id_from_seed::("Alice"), get_collator_keys_from_seed("Alice"), ), ( get_account_id_from_seed::("Bob"), get_collator_keys_from_seed("Bob"), ), ], 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"), ], get_account_id_from_seed::("Alice"), 1000.into(), ) }, Vec::new(), None, None, None, None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! para_id: 1000, }, ) } pub fn local_testnet_config() -> ChainSpec { // Give your base currency a unit name and decimal places let mut properties = sc_chain_spec::Properties::new(); properties.insert("tokenSymbol".into(), "UNIT".into()); properties.insert("tokenDecimals".into(), 12.into()); properties.insert("ss58Format".into(), 42.into()); ChainSpec::from_genesis( // Name "Local Testnet", // ID "local_testnet", ChainType::Local, move || { testnet_genesis( // initial collators. vec![ ( get_account_id_from_seed::("Alice"), get_collator_keys_from_seed("Alice"), ), ( get_account_id_from_seed::("Bob"), get_collator_keys_from_seed("Bob"), ), ], 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"), ], get_account_id_from_seed::("Alice"), 1000.into(), ) }, // Bootnodes Vec::new(), // Telemetry None, // Protocol ID Some("template-local"), // Fork ID None, // Properties Some(properties), // Extensions Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! para_id: 1000, }, ) } fn testnet_genesis( invulnerables: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, root: AccountId, id: ParaId, ) -> parachain_template_runtime::RuntimeGenesisConfig { parachain_template_runtime::RuntimeGenesisConfig { system: parachain_template_runtime::SystemConfig { code: parachain_template_runtime::WASM_BINARY .expect("WASM binary was not build, please build it!") .to_vec(), ..Default::default() }, balances: parachain_template_runtime::BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }, parachain_info: parachain_template_runtime::ParachainInfoConfig { parachain_id: id, ..Default::default() }, collator_selection: parachain_template_runtime::CollatorSelectionConfig { invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), candidacy_bond: EXISTENTIAL_DEPOSIT * 16, ..Default::default() }, session: parachain_template_runtime::SessionConfig { keys: invulnerables .into_iter() .map(|(acc, aura)| { ( acc.clone(), // account id acc, // validator id template_session_keys(aura), // session keys ) }) .collect(), }, // no need to pass anything to aura, in fact it will panic if we do. Session will take care // of this. aura: Default::default(), aura_ext: Default::default(), parachain_system: Default::default(), polkadot_xcm: parachain_template_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, transaction_payment: Default::default(), sudo: parachain_template_runtime::SudoConfig { key: Some(root) }, } }