git.delta.rocks / unique-network / refs/commits / a931d82a9899

difftreelog

feat(collator-selection) opal only

Fahrrader2022-10-28parent: #3858e94.patch.diff
in: master

10 files changed

modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
before · node/cli/src/chain_spec.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};18use sc_service::ChainType;19use sp_core::{sr25519, Pair, Public};20use sp_runtime::traits::{IdentifyAccount, Verify};21use std::collections::BTreeMap;2223use serde::{Deserialize, Serialize};24use serde_json::map::Map;2526use up_common::types::opaque::*;27use up_common::constants::EXISTENTIAL_DEPOSIT;2829#[cfg(feature = "unique-runtime")]30pub use unique_runtime as default_runtime;3132#[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))]33pub use quartz_runtime as default_runtime;3435#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]36pub use opal_runtime as default_runtime;3738/// The `ChainSpec` parameterized for the unique runtime.39#[cfg(feature = "unique-runtime")]40pub type UniqueChainSpec = sc_service::GenericChainSpec<unique_runtime::GenesisConfig, Extensions>;4142/// The `ChainSpec` parameterized for the quartz runtime.43#[cfg(feature = "quartz-runtime")]44pub type QuartzChainSpec = sc_service::GenericChainSpec<quartz_runtime::GenesisConfig, Extensions>;4546/// The `ChainSpec` parameterized for the opal runtime.47pub type OpalChainSpec = sc_service::GenericChainSpec<opal_runtime::GenesisConfig, Extensions>;4849#[cfg(feature = "unique-runtime")]50pub type DefaultChainSpec = UniqueChainSpec;5152#[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))]53pub type DefaultChainSpec = QuartzChainSpec;5455#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]56pub type DefaultChainSpec = OpalChainSpec;5758pub enum RuntimeId {59	#[cfg(feature = "unique-runtime")]60	Unique,6162	#[cfg(feature = "quartz-runtime")]63	Quartz,6465	Opal,66	Unknown(String),67}6869#[cfg(not(feature = "unique-runtime"))]70/// PARA_ID for Opal/Quartz71const PARA_ID: u32 = 2095;7273#[cfg(feature = "unique-runtime")]74/// PARA_ID for Unique75const PARA_ID: u32 = 2037;7677pub trait RuntimeIdentification {78	fn runtime_id(&self) -> RuntimeId;79}8081impl RuntimeIdentification for Box<dyn sc_service::ChainSpec> {82	fn runtime_id(&self) -> RuntimeId {83		#[cfg(feature = "unique-runtime")]84		if self.id().starts_with("unique") || self.id().starts_with("unq") {85			return RuntimeId::Unique;86		}8788		#[cfg(feature = "quartz-runtime")]89		if self.id().starts_with("quartz") || self.id().starts_with("qtz") {90			return RuntimeId::Quartz;91		}9293		if self.id().starts_with("opal") || self.id() == "dev" || self.id() == "local_testnet" {94			return RuntimeId::Opal;95		}9697		RuntimeId::Unknown(self.id().into())98	}99}100101pub enum ServiceId {102	Prod,103	Dev,104}105106pub trait ServiceIdentification {107	fn service_id(&self) -> ServiceId;108}109110impl ServiceIdentification for Box<dyn sc_service::ChainSpec> {111	fn service_id(&self) -> ServiceId {112		if self.id().ends_with("dev") {113			ServiceId::Dev114		} else {115			ServiceId::Prod116		}117	}118}119120/// Helper function to generate a crypto pair from seed121pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {122	TPublic::Pair::from_string(&format!("//{}", seed), None)123		.expect("static values are valid; qed")124		.public()125}126127/// The extensions for the [`DefaultChainSpec`].128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]129#[serde(deny_unknown_fields)]130pub struct Extensions {131	/// The relay chain of the Parachain.132	pub relay_chain: String,133	/// The id of the Parachain.134	pub para_id: u32,135}136137impl Extensions {138	/// Try to get the extension from the given `ChainSpec`.139	pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {140		sc_chain_spec::get_extension(chain_spec.extensions())141	}142}143144type AccountPublic = <Signature as Verify>::Signer;145146/// Helper function to generate an account ID from seed147pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId148where149	AccountPublic: From<<TPublic::Pair as Pair>::Public>,150{151	AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()152}153154macro_rules! testnet_genesis {155	(156		$runtime:path,157		$root_key:expr,158		$initial_invulnerables:expr,159		$endowed_accounts:expr,160		$id:expr161	) => {{162		use $runtime::*;163164		GenesisConfig {165			system: SystemConfig {166				code: WASM_BINARY167					.expect("WASM binary was not build, please build it!")168					.to_vec(),169			},170			balances: BalancesConfig {171				balances: $endowed_accounts172					.iter()173					.cloned()174					// 1e13 UNQ175					.map(|k| (k, 1 << 100))176					.collect(),177			},178			treasury: Default::default(),179			tokens: TokensConfig { balances: vec![] },180			sudo: SudoConfig {181				key: Some($root_key),182			},183			vesting: VestingConfig { vesting: vec![] },184			parachain_info: ParachainInfoConfig {185				parachain_id: $id.into(),186			},187			parachain_system: Default::default(),188			collator_selection: CollatorSelectionConfig {189				invulnerables: $initial_invulnerables190					.iter()191					.cloned()192					.map(|(acc, _)| acc)193					.collect(),194				candidacy_bond: EXISTENTIAL_DEPOSIT * 16,195				..Default::default()196			},197			session: SessionConfig {198				keys: $initial_invulnerables199					.into_iter()200					.map(|(acc, aura)| {201						(202							acc.clone(),          // account id203							acc,                  // validator id204							SessionKeys { aura }, // session keys205						)206					})207					.collect(),208			},209			aura: Default::default(),210			/*aura: AuraConfig {211				authorities: $initial_authorities,212			},*/213			aura_ext: Default::default(),214			evm: EVMConfig {215				accounts: BTreeMap::new(),216			},217			ethereum: EthereumConfig {},218		}219	}};220}221222pub fn development_config() -> DefaultChainSpec {223	let mut properties = Map::new();224	properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());225	properties.insert("tokenDecimals".into(), 18.into());226	properties.insert(227		"ss58Format".into(),228		default_runtime::SS58Prefix::get().into(),229	);230231	DefaultChainSpec::from_genesis(232		// Name233		format!(234			"{}{}",235			default_runtime::RUNTIME_NAME.to_uppercase(),236			if cfg!(feature = "unique-runtime") {237				""238			} else {239				" by UNIQUE"240			}241		)242		.as_str(),243		// ID244		format!("{}_dev", default_runtime::RUNTIME_NAME).as_str(),245		ChainType::Local,246		move || {247			testnet_genesis!(248				default_runtime,249				// Sudo account250				get_account_id_from_seed::<sr25519::Public>("Alice"),251				vec![252					(253						get_account_id_from_seed::<sr25519::Public>("Alice"),254						get_from_seed::<AuraId>("Alice"),255					),256					(257						get_account_id_from_seed::<sr25519::Public>("Bob"),258						get_from_seed::<AuraId>("Bob"),259					),260				],261				// Pre-funded accounts262				vec![263					get_account_id_from_seed::<sr25519::Public>("Alice"),264					get_account_id_from_seed::<sr25519::Public>("Bob"),265					get_account_id_from_seed::<sr25519::Public>("Charlie"),266					get_account_id_from_seed::<sr25519::Public>("Dave"),267					get_account_id_from_seed::<sr25519::Public>("Eve"),268					get_account_id_from_seed::<sr25519::Public>("Ferdie"),269					get_account_id_from_seed::<sr25519::Public>("Alice//stash"),270					get_account_id_from_seed::<sr25519::Public>("Bob//stash"),271					get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),272					get_account_id_from_seed::<sr25519::Public>("Dave//stash"),273					get_account_id_from_seed::<sr25519::Public>("Eve//stash"),274					get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),275				],276				PARA_ID277			)278		},279		// Bootnodes280		vec![],281		// Telemetry282		None,283		// Protocol ID284		None,285		None,286		// Properties287		Some(properties),288		// Extensions289		Extensions {290			relay_chain: "rococo-dev".into(),291			para_id: PARA_ID,292		},293	)294}295296pub fn local_testnet_config() -> DefaultChainSpec {297	let mut properties = Map::new();298	properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());299	properties.insert("tokenDecimals".into(), 18.into());300	properties.insert(301		"ss58Format".into(),302		default_runtime::SS58Prefix::get().into(),303	);304305	DefaultChainSpec::from_genesis(306		// Name307		format!(308			"{}{}",309			default_runtime::RUNTIME_NAME.to_uppercase(),310			if cfg!(feature = "unique-runtime") {311				""312			} else {313				" by UNIQUE"314			}315		)316		.as_str(),317		// ID318		format!("{}_local", default_runtime::RUNTIME_NAME).as_str(),319		ChainType::Local,320		move || {321			testnet_genesis!(322				default_runtime,323				// Sudo account324				get_account_id_from_seed::<sr25519::Public>("Alice"),325				vec![326					(327						get_account_id_from_seed::<sr25519::Public>("Alice"),328						get_from_seed::<AuraId>("Alice"),329					),330					(331						get_account_id_from_seed::<sr25519::Public>("Bob"),332						get_from_seed::<AuraId>("Bob"),333					),334				],335				// Pre-funded accounts336				vec![337					get_account_id_from_seed::<sr25519::Public>("Alice"),338					get_account_id_from_seed::<sr25519::Public>("Bob"),339					get_account_id_from_seed::<sr25519::Public>("Charlie"),340					get_account_id_from_seed::<sr25519::Public>("Dave"),341					get_account_id_from_seed::<sr25519::Public>("Eve"),342					get_account_id_from_seed::<sr25519::Public>("Ferdie"),343					get_account_id_from_seed::<sr25519::Public>("Alice//stash"),344					get_account_id_from_seed::<sr25519::Public>("Bob//stash"),345					get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),346					get_account_id_from_seed::<sr25519::Public>("Dave//stash"),347					get_account_id_from_seed::<sr25519::Public>("Eve//stash"),348					get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),349				],350				PARA_ID351			)352		},353		// Bootnodes354		vec![],355		// Telemetry356		None,357		// Protocol ID358		None,359		None,360		// Properties361		Some(properties),362		// Extensions363		Extensions {364			relay_chain: "westend-local".into(),365			para_id: PARA_ID,366		},367	)368}
after · node/cli/src/chain_spec.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};18use sc_service::ChainType;19use sp_core::{sr25519, Pair, Public};20use sp_runtime::traits::{IdentifyAccount, Verify};21use std::collections::BTreeMap;2223use serde::{Deserialize, Serialize};24use serde_json::map::Map;2526use up_common::types::opaque::*;27use up_common::constants::CANDIDACY_BOND;2829#[cfg(feature = "unique-runtime")]30pub use unique_runtime as default_runtime;3132#[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))]33pub use quartz_runtime as default_runtime;3435#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]36pub use opal_runtime as default_runtime;3738/// The `ChainSpec` parameterized for the unique runtime.39#[cfg(feature = "unique-runtime")]40pub type UniqueChainSpec = sc_service::GenericChainSpec<unique_runtime::GenesisConfig, Extensions>;4142/// The `ChainSpec` parameterized for the quartz runtime.43#[cfg(feature = "quartz-runtime")]44pub type QuartzChainSpec = sc_service::GenericChainSpec<quartz_runtime::GenesisConfig, Extensions>;4546/// The `ChainSpec` parameterized for the opal runtime.47pub type OpalChainSpec = sc_service::GenericChainSpec<opal_runtime::GenesisConfig, Extensions>;4849#[cfg(feature = "unique-runtime")]50pub type DefaultChainSpec = UniqueChainSpec;5152#[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))]53pub type DefaultChainSpec = QuartzChainSpec;5455#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]56pub type DefaultChainSpec = OpalChainSpec;5758pub enum RuntimeId {59	#[cfg(feature = "unique-runtime")]60	Unique,6162	#[cfg(feature = "quartz-runtime")]63	Quartz,6465	Opal,66	Unknown(String),67}6869#[cfg(not(feature = "unique-runtime"))]70/// PARA_ID for Opal/Quartz71const PARA_ID: u32 = 2095;7273#[cfg(feature = "unique-runtime")]74/// PARA_ID for Unique75const PARA_ID: u32 = 2037;7677pub trait RuntimeIdentification {78	fn runtime_id(&self) -> RuntimeId;79}8081impl RuntimeIdentification for Box<dyn sc_service::ChainSpec> {82	fn runtime_id(&self) -> RuntimeId {83		#[cfg(feature = "unique-runtime")]84		if self.id().starts_with("unique") || self.id().starts_with("unq") {85			return RuntimeId::Unique;86		}8788		#[cfg(feature = "quartz-runtime")]89		if self.id().starts_with("quartz") || self.id().starts_with("qtz") {90			return RuntimeId::Quartz;91		}9293		if self.id().starts_with("opal") || self.id() == "dev" || self.id() == "local_testnet" {94			return RuntimeId::Opal;95		}9697		RuntimeId::Unknown(self.id().into())98	}99}100101pub enum ServiceId {102	Prod,103	Dev,104}105106pub trait ServiceIdentification {107	fn service_id(&self) -> ServiceId;108}109110impl ServiceIdentification for Box<dyn sc_service::ChainSpec> {111	fn service_id(&self) -> ServiceId {112		if self.id().ends_with("dev") {113			ServiceId::Dev114		} else {115			ServiceId::Prod116		}117	}118}119120/// Helper function to generate a crypto pair from seed121pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {122	TPublic::Pair::from_string(&format!("//{}", seed), None)123		.expect("static values are valid; qed")124		.public()125}126127/// The extensions for the [`DefaultChainSpec`].128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]129#[serde(deny_unknown_fields)]130pub struct Extensions {131	/// The relay chain of the Parachain.132	pub relay_chain: String,133	/// The id of the Parachain.134	pub para_id: u32,135}136137impl Extensions {138	/// Try to get the extension from the given `ChainSpec`.139	pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {140		sc_chain_spec::get_extension(chain_spec.extensions())141	}142}143144type AccountPublic = <Signature as Verify>::Signer;145146/// Helper function to generate an account ID from seed147pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId148where149	AccountPublic: From<<TPublic::Pair as Pair>::Public>,150{151	AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()152}153154#[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]155macro_rules! testnet_genesis {156	(157		$runtime:path,158		$root_key:expr,159		$initial_invulnerables:expr,160		$endowed_accounts:expr,161		$id:expr162	) => {{163		use $runtime::*;164165		GenesisConfig {166			system: SystemConfig {167				code: WASM_BINARY168					.expect("WASM binary was not build, please build it!")169					.to_vec(),170			},171			balances: BalancesConfig {172				balances: $endowed_accounts173					.iter()174					.cloned()175					// 1e13 UNQ176					.map(|k| (k, 1 << 100))177					.collect(),178			},179			treasury: Default::default(),180			tokens: TokensConfig { balances: vec![] },181			sudo: SudoConfig {182				key: Some($root_key),183			},184			vesting: VestingConfig { vesting: vec![] },185			parachain_info: ParachainInfoConfig {186				parachain_id: $id.into(),187			},188			parachain_system: Default::default(),189			collator_selection: CollatorSelectionConfig {190				invulnerables: $initial_invulnerables191					.iter()192					.cloned()193					.map(|(acc, _)| acc)194					.collect(),195				candidacy_bond: CANDIDACY_BOND,196				..Default::default()197			},198			session: SessionConfig {199				keys: $initial_invulnerables200					.into_iter()201					.map(|(acc, aura)| {202						(203							acc.clone(),          // account id204							acc,                  // validator id205							SessionKeys { aura }, // session keys206						)207					})208					.collect(),209			},210			aura: Default::default(),211			aura_ext: Default::default(),212			evm: EVMConfig {213				accounts: BTreeMap::new(),214			},215			ethereum: EthereumConfig {},216		}217	}};218}219220#[cfg(any(feature = "unique-runtime", feature = "quartz-runtime"))]221macro_rules! testnet_genesis {222	(223		$runtime:path,224		$root_key:expr,225		$initial_invulnerables:expr,226		$endowed_accounts:expr,227		$id:expr228	) => {{229		use $runtime::*;230231		GenesisConfig {232			system: SystemConfig {233				code: WASM_BINARY234					.expect("WASM binary was not build, please build it!")235					.to_vec(),236			},237			balances: BalancesConfig {238				balances: $endowed_accounts239					.iter()240					.cloned()241					// 1e13 UNQ242					.map(|k| (k, 1 << 100))243					.collect(),244			},245			treasury: Default::default(),246			tokens: TokensConfig { balances: vec![] },247			sudo: SudoConfig {248				key: Some($root_key),249			},250			vesting: VestingConfig { vesting: vec![] },251			parachain_info: ParachainInfoConfig {252				parachain_id: $id.into(),253			},254			parachain_system: Default::default(),255			aura: AuraConfig {256				authorities: $initial_invulnerables257					.into_iter()258					.map(|(_, aura)| aura)259					.collect(),260			},261			aura_ext: Default::default(),262			evm: EVMConfig {263				accounts: BTreeMap::new(),264			},265			ethereum: EthereumConfig {},266		}267	}};268}269270pub fn development_config() -> DefaultChainSpec {271	let mut properties = Map::new();272	properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());273	properties.insert("tokenDecimals".into(), 18.into());274	properties.insert(275		"ss58Format".into(),276		default_runtime::SS58Prefix::get().into(),277	);278279	DefaultChainSpec::from_genesis(280		// Name281		format!(282			"{}{}",283			default_runtime::RUNTIME_NAME.to_uppercase(),284			if cfg!(feature = "unique-runtime") {285				""286			} else {287				" by UNIQUE"288			}289		)290		.as_str(),291		// ID292		format!("{}_dev", default_runtime::RUNTIME_NAME).as_str(),293		ChainType::Local,294		move || {295			testnet_genesis!(296				default_runtime,297				// Sudo account298				get_account_id_from_seed::<sr25519::Public>("Alice"),299				vec![300					(301						get_account_id_from_seed::<sr25519::Public>("Alice"),302						get_from_seed::<AuraId>("Alice"),303					),304					(305						get_account_id_from_seed::<sr25519::Public>("Bob"),306						get_from_seed::<AuraId>("Bob"),307					),308				],309				// Pre-funded accounts310				vec![311					get_account_id_from_seed::<sr25519::Public>("Alice"),312					get_account_id_from_seed::<sr25519::Public>("Bob"),313					get_account_id_from_seed::<sr25519::Public>("Charlie"),314					get_account_id_from_seed::<sr25519::Public>("Dave"),315					get_account_id_from_seed::<sr25519::Public>("Eve"),316					get_account_id_from_seed::<sr25519::Public>("Ferdie"),317					get_account_id_from_seed::<sr25519::Public>("Alice//stash"),318					get_account_id_from_seed::<sr25519::Public>("Bob//stash"),319					get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),320					get_account_id_from_seed::<sr25519::Public>("Dave//stash"),321					get_account_id_from_seed::<sr25519::Public>("Eve//stash"),322					get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),323				],324				PARA_ID325			)326		},327		// Bootnodes328		vec![],329		// Telemetry330		None,331		// Protocol ID332		None,333		None,334		// Properties335		Some(properties),336		// Extensions337		Extensions {338			relay_chain: "rococo-dev".into(),339			para_id: PARA_ID,340		},341	)342}343344pub fn local_testnet_config() -> DefaultChainSpec {345	let mut properties = Map::new();346	properties.insert("tokenSymbol".into(), default_runtime::TOKEN_SYMBOL.into());347	properties.insert("tokenDecimals".into(), 18.into());348	properties.insert(349		"ss58Format".into(),350		default_runtime::SS58Prefix::get().into(),351	);352353	DefaultChainSpec::from_genesis(354		// Name355		format!(356			"{}{}",357			default_runtime::RUNTIME_NAME.to_uppercase(),358			if cfg!(feature = "unique-runtime") {359				""360			} else {361				" by UNIQUE"362			}363		)364		.as_str(),365		// ID366		format!("{}_local", default_runtime::RUNTIME_NAME).as_str(),367		ChainType::Local,368		move || {369			testnet_genesis!(370				default_runtime,371				// Sudo account372				get_account_id_from_seed::<sr25519::Public>("Alice"),373				vec![374					(375						get_account_id_from_seed::<sr25519::Public>("Alice"),376						get_from_seed::<AuraId>("Alice"),377					),378					(379						get_account_id_from_seed::<sr25519::Public>("Bob"),380						get_from_seed::<AuraId>("Bob"),381					),382				],383				// Pre-funded accounts384				vec![385					get_account_id_from_seed::<sr25519::Public>("Alice"),386					get_account_id_from_seed::<sr25519::Public>("Bob"),387					get_account_id_from_seed::<sr25519::Public>("Charlie"),388					get_account_id_from_seed::<sr25519::Public>("Dave"),389					get_account_id_from_seed::<sr25519::Public>("Eve"),390					get_account_id_from_seed::<sr25519::Public>("Ferdie"),391					get_account_id_from_seed::<sr25519::Public>("Alice//stash"),392					get_account_id_from_seed::<sr25519::Public>("Bob//stash"),393					get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),394					get_account_id_from_seed::<sr25519::Public>("Dave//stash"),395					get_account_id_from_seed::<sr25519::Public>("Eve//stash"),396					get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),397				],398				PARA_ID399			)400		},401		// Bootnodes402		vec![],403		// Telemetry404		None,405		// Protocol ID406		None,407		None,408		// Properties409		Some(properties),410		// Extensions411		Extensions {412			relay_chain: "westend-local".into(),413			para_id: PARA_ID,414		},415	)416}
modifiedprimitives/common/src/constants.rsdiffbeforeafterboth
--- a/primitives/common/src/constants.rs
+++ b/primitives/common/src/constants.rs
@@ -41,7 +41,10 @@
 pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;
 pub const UNIQUE: Balance = 100 * CENTIUNIQUE;
 
+/// Minimum balance required to create or keep an account open.
 pub const EXISTENTIAL_DEPOSIT: u128 = 0;
+/// Amount of Balance reserved for candidate registration.
+pub const CANDIDACY_BOND: u128 = EXISTENTIAL_DEPOSIT;
 
 // Targeting 0.1 UNQ per transfer
 pub const WEIGHT_TO_FEE_COEFF: u32 = /*<weight2fee>*/207_163_598/*</weight2fee>*/;
addedruntime/common/config/pallets/collator_selection.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/common/config/pallets/collator_selection.rs
@@ -0,0 +1,78 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network 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.
+
+// Unique Network 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 Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+use frame_support::{parameter_types, PalletId};
+use frame_system::EnsureRoot;
+use crate::{
+	AccountId, BlockNumber, Runtime, RuntimeEvent, Balances, Aura, Session, SessionKeys,
+	CollatorSelection,
+};
+use up_common::constants::*;
+
+parameter_types! {
+	pub const SessionPeriod: BlockNumber = HOURS;
+	pub const SessionOffset: BlockNumber = 0;
+}
+
+impl pallet_session::Config for Runtime {
+	type RuntimeEvent = RuntimeEvent;
+	type ValidatorId = <Self as frame_system::Config>::AccountId;
+	// we don't have stash and controller, thus we don't need the convert as well.
+	type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
+	type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
+	type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
+	type SessionManager = CollatorSelection;
+	// Essentially just Aura, but lets be pedantic.
+	type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
+	type Keys = SessionKeys;
+	type WeightInfo = pallet_session::weights::SubstrateWeight<Self>; // ();
+}
+
+parameter_types! {
+	pub const UncleGenerations: u32 = 0;
+}
+
+impl pallet_authorship::Config for Runtime {
+	type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
+	type UncleGenerations = UncleGenerations;
+	type FilterUncle = ();
+	type EventHandler = CollatorSelection;
+}
+
+parameter_types! {
+	pub const PotId: PalletId = PalletId(*b"PotStake");
+	pub const MaxCandidates: u32 = 1000;
+	pub const MinCandidates: u32 = 5;
+	pub const MaxInvulnerables: u32 = 100;
+}
+
+impl pallet_collator_selection::Config for Runtime {
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	// We allow root only to execute privileged collator selection operations.
+	type UpdateOrigin = EnsureRoot<AccountId>;
+	type PotId = PotId;
+	type MaxCandidates = MaxCandidates;
+	type MinCandidates = MinCandidates;
+	type MaxInvulnerables = MaxInvulnerables;
+	// todo:collator kick threshold should be in storage and configured only by root -- or rather UpdateOrigin
+	// Should be a multiple of session or things will get inconsistent.
+	type KickThreshold = SessionPeriod;
+	type ValidatorId = <Self as frame_system::Config>::AccountId;
+	type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
+	type ValidatorRegistration = Session;
+	type WeightInfo = ();
+}
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -46,6 +46,9 @@
 #[cfg(feature = "app-promotion")]
 pub mod app_promotion;
 
+#[cfg(feature = "collator-selection")]
+pub mod collator_selection;
+
 parameter_types! {
 	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
 	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
modifiedruntime/common/config/substrate.rsdiffbeforeafterboth
--- a/runtime/common/config/substrate.rs
+++ b/runtime/common/config/substrate.rs
@@ -34,7 +34,7 @@
 };
 use crate::{
 	runtime_common::DealWithFees, Runtime, RuntimeEvent, RuntimeCall, RuntimeOrigin, PalletInfo,
-	System, Balances, Treasury, SS58Prefix, Aura, Session, SessionKeys, CollatorSelection, Version,
+	System, Balances, Treasury, SS58Prefix, Version,
 };
 use up_common::{types::*, constants::*};
 
@@ -215,58 +215,4 @@
 	type AuthorityId = AuraId;
 	type DisabledValidators = ();
 	type MaxAuthorities = MaxAuthorities;
-}
-
-parameter_types! {
-	pub const SessionPeriod: BlockNumber = HOURS;
-	pub const SessionOffset: BlockNumber = 0;
-}
-
-impl pallet_session::Config for Runtime {
-	type RuntimeEvent = RuntimeEvent;
-	type ValidatorId = <Self as frame_system::Config>::AccountId;
-	// we don't have stash and controller, thus we don't need the convert as well.
-	type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
-	type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
-	type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
-	type SessionManager = CollatorSelection;
-	// Essentially just Aura, but lets be pedantic.
-	type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
-	type Keys = SessionKeys;
-	type WeightInfo = pallet_session::weights::SubstrateWeight<Self>; // ();
-}
-
-parameter_types! {
-	pub const UncleGenerations: u32 = 0;
-}
-
-impl pallet_authorship::Config for Runtime {
-	type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
-	type UncleGenerations = UncleGenerations;
-	type FilterUncle = ();
-	type EventHandler = CollatorSelection;
-}
-
-parameter_types! {
-	pub const PotId: PalletId = PalletId(*b"PotStake");
-	pub const MaxCandidates: u32 = 1000;
-	pub const MinCandidates: u32 = 5;
-	pub const MaxInvulnerables: u32 = 100;
-}
-
-impl pallet_collator_selection::Config for Runtime {
-	type RuntimeEvent = RuntimeEvent;
-	type Currency = Balances;
-	// We allow root only to execute privileged collator selection operations.
-	type UpdateOrigin = EnsureRoot<AccountId>;
-	type PotId = PotId;
-	type MaxCandidates = MaxCandidates;
-	type MinCandidates = MinCandidates;
-	type MaxInvulnerables = MaxInvulnerables;
-	// Should be a multiple of session or things will get inconsistent.
-	type KickThreshold = SessionPeriod;
-	type ValidatorId = <Self as frame_system::Config>::AccountId;
-	type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
-	type ValidatorRegistration = Session;
-	type WeightInfo = ();
 }
modifiedruntime/common/construct_runtime/mod.rsdiffbeforeafterboth
--- a/runtime/common/construct_runtime/mod.rs
+++ b/runtime/common/construct_runtime/mod.rs
@@ -32,9 +32,15 @@
                 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
                 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
 
+                #[runtimes(opal)]
                 Authorship: pallet_authorship::{Pallet, Call, Storage} = 22,
+
+                #[runtimes(opal)]
                 CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event<T>, Config<T>} = 23,
+
+                #[runtimes(opal)]
                 Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 24,
+
                 Aura: pallet_aura::{Pallet, Config<T>} = 25,
                 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 26,
 
modifiedruntime/common/mod.rsdiffbeforeafterboth
--- a/runtime/common/mod.rs
+++ b/runtime/common/mod.rs
@@ -180,154 +180,166 @@
 pub struct AuraToCollatorSelection;
 impl frame_support::traits::OnRuntimeUpgrade for AuraToCollatorSelection {
 	fn on_runtime_upgrade() -> Weight {
-		use frame_support::{BoundedVec, storage::migration};
-		use sp_runtime::{
-			traits::{OpaqueKeys, Saturating},
-			RuntimeAppPublic,
-		};
-		use pallet_session::SessionManager;
-		use up_common::constants::EXISTENTIAL_DEPOSIT;
-		use crate::config::substrate::MaxInvulnerables;
-
-		let mut weight = <Runtime as frame_system::Config>::DbWeight::get().reads(1);
+		#[cfg(feature = "collator-selection")]
+		{
+			use frame_support::{BoundedVec, storage::migration};
+			use sp_runtime::{
+				traits::{OpaqueKeys, Saturating},
+				RuntimeAppPublic,
+			};
+			use pallet_session::SessionManager;
+			use up_common::constants::CANDIDACY_BOND;
+			use crate::config::pallets::collator_selection::MaxInvulnerables;
 
-		let version =
-			migration::get_storage_value::<()>(b"AuraToCollatorSelection", b"StorageVersion", &[]);
-
-		let should_upgrade = match version {
-			None => true,
-			Some(_) => false,
-		};
+			let mut weight = <Runtime as frame_system::Config>::DbWeight::get().reads(1);
 
-		if should_upgrade {
-			log::info!(
-				target: "runtime::aura_to_collator_selection",
-				"Running migration of Aura authorities to Collator Selection invulnerables"
+			let version = migration::get_storage_value::<()>(
+				b"AuraToCollatorSelection",
+				b"StorageVersion",
+				&[],
 			);
 
-			let invulnerables = pallet_aura::Pallet::<Runtime>::authorities()
-				.iter()
-				.cloned()
-				.filter_map(|authority_id| {
-					weight.saturating_accrue(<Runtime as frame_system::Config>::DbWeight::get().reads_writes(1, 1));
-					let vec = authority_id.clone().to_raw_vec();
-					let slice = vec.as_slice();
-					let array: Option<[u8; 32]> = match slice.try_into() {
-						Ok(a) => Some(a),
-						Err(_) => {
-							log::error!("Failed to convert an Aura authority to a Collator Selection invulnerable: {:?}", authority_id);
-							None
-						},
-					};
-					array.map(|a| (AccountId::from(a), authority_id))
-				})
-				.collect::<Vec<_>>();
+			let should_upgrade = match version {
+				None => true,
+				Some(_) => false,
+			};
+
+			if should_upgrade {
+				log::info!(
+					target: "runtime::aura_to_collator_selection",
+					"Running migration of Aura authorities to Collator Selection invulnerables"
+				);
 
-			let bounded_invulnerables = BoundedVec::<_, MaxInvulnerables>::try_from(
-				invulnerables
+				let invulnerables = pallet_aura::Pallet::<Runtime>::authorities()
 					.iter()
 					.cloned()
-					.map(|(acc, _)| acc)
-					.collect::<Vec<_>>(),
-			)
-			.expect("Existing collators/invulnerables are more than MaxInvulnerables");
+					.filter_map(|authority_id| {
+						weight.saturating_accrue(<Runtime as frame_system::Config>::DbWeight::get().reads_writes(1, 1));
+						let vec = authority_id.clone().to_raw_vec();
+						let slice = vec.as_slice();
+						let array: Option<[u8; 32]> = match slice.try_into() {
+							Ok(a) => Some(a),
+							Err(_) => {
+								log::error!("Failed to convert an Aura authority to a Collator Selection invulnerable: {:?}", authority_id);
+								None
+							},
+						};
+						array.map(|a| (AccountId::from(a), authority_id))
+					})
+					.collect::<Vec<_>>();
 
-			<pallet_collator_selection::Invulnerables<Runtime>>::put(bounded_invulnerables);
-			<pallet_collator_selection::DesiredCandidates<Runtime>>::put(0);
-			<pallet_collator_selection::CandidacyBond<Runtime>>::put(EXISTENTIAL_DEPOSIT * 16);
+				let bounded_invulnerables = BoundedVec::<_, MaxInvulnerables>::try_from(
+					invulnerables
+						.iter()
+						.cloned()
+						.map(|(acc, _)| acc)
+						.collect::<Vec<_>>(),
+				)
+				.expect("Existing collators/invulnerables are more than MaxInvulnerables");
+
+				<pallet_collator_selection::Invulnerables<Runtime>>::put(bounded_invulnerables);
+				<pallet_collator_selection::DesiredCandidates<Runtime>>::put(0);
+				<pallet_collator_selection::CandidacyBond<Runtime>>::put(CANDIDACY_BOND);
 
-			let keys = invulnerables
-				.into_iter()
-				.map(|(acc, aura)| {
-					(
-						acc.clone(),                        // account id
-						acc,                                // validator id
-						SessionKeys { aura: aura.clone() }, // session keys
-					)
-				})
-				.collect::<Vec<_>>();
+				let keys = invulnerables
+					.into_iter()
+					.map(|(acc, aura)| {
+						(
+							acc.clone(),                        // account id
+							acc,                                // validator id
+							SessionKeys { aura: aura.clone() }, // session keys
+						)
+					})
+					.collect::<Vec<_>>();
 
-			for (account, val, keys) in keys.iter().cloned() {
-				for id in <Runtime as pallet_session::Config>::Keys::key_ids() {
-					<pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), &val)
-				}
-				<pallet_session::NextKeys<Runtime>>::insert(&val, &keys);
-				// todo exercise caution, the following is taken from genesis
-				if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(&account).is_err() {
-					log::warn!(
-						"We have entered an error with incrementing consumers without limit during the migration"
-					);
-					// This will leak a provider reference, however it only happens once (at
-					// genesis) so it's really not a big deal and we assume that the user wants to
-					// do this since it's the only way a non-endowed account can contain a session
-					// key.
-					frame_system::Pallet::<Runtime>::inc_providers(&account);
+				for (account, val, keys) in keys.iter().cloned() {
+					for id in <Runtime as pallet_session::Config>::Keys::key_ids() {
+						<pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), &val)
+					}
+					<pallet_session::NextKeys<Runtime>>::insert(&val, &keys);
+					// todo exercise caution, the following is taken from genesis
+					if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(&account)
+						.is_err()
+					{
+						log::warn!(
+							"We have entered an error with incrementing consumers without limit during the migration"
+						);
+						// This will leak a provider reference, however it only happens once (at
+						// genesis) so it's really not a big deal and we assume that the user wants to
+						// do this since it's the only way a non-endowed account can contain a session
+						// key.
+						frame_system::Pallet::<Runtime>::inc_providers(&account);
+					}
 				}
-			}
 
-			let initial_validators_0 =
-				<Runtime as pallet_session::Config>::SessionManager::new_session(0).unwrap_or_else(
-					|| {
-						frame_support::print(
-							"No initial validator provided by `SessionManager`, use \
-						session config keys to generate initial validator set.",
-						);
-						keys.iter().map(|x| x.1.clone()).collect()
-					},
-				);
-			/*assert!(
-				!initial_validators_0.is_empty(),
-				"Empty validator set for session 0 in (pseudo) genesis block!"
-			);*/
+				let initial_validators_0 =
+					<Runtime as pallet_session::Config>::SessionManager::new_session(0)
+						.unwrap_or_else(|| {
+							frame_support::print(
+								"No initial validator provided by `SessionManager`, use \
+							session config keys to generate initial validator set.",
+							);
+							keys.iter().map(|x| x.1.clone()).collect()
+						});
+				/*assert!(
+					!initial_validators_0.is_empty(),
+					"Empty validator set for session 0 in (pseudo) genesis block!"
+				);*/
 
-			let initial_validators_1 =
-				<Runtime as pallet_session::Config>::SessionManager::new_session(1)
-					.unwrap_or_else(|| initial_validators_0.clone());
-			/*assert!(
-				!initial_validators_1.is_empty(),
-				"Empty validator set for session 1 in (pseudo) genesis block!"
-			);*/
+				let initial_validators_1 =
+					<Runtime as pallet_session::Config>::SessionManager::new_session(1)
+						.unwrap_or_else(|| initial_validators_0.clone());
+				/*assert!(
+					!initial_validators_1.is_empty(),
+					"Empty validator set for session 1 in (pseudo) genesis block!"
+				);*/
 
-			let queued_keys: Vec<_> = initial_validators_1
-				.iter()
-				.cloned()
-				.map(|v| {
-					(
-						v.clone(),
-						<pallet_session::NextKeys<Runtime>>::get(&v)
-							.expect("Validator in session 1 missing keys!"),
-					)
-				})
-				.collect();
+				let queued_keys: Vec<_> = initial_validators_1
+					.iter()
+					.cloned()
+					.map(|v| {
+						(
+							v.clone(),
+							<pallet_session::NextKeys<Runtime>>::get(&v)
+								.expect("Validator in session 1 missing keys!"),
+						)
+					})
+					.collect();
 
-			// Tell everyone about the genesis session keys -- Aura must've already initialized it
-			//<Runtime as pallet_session::Config>::SessionHandler::on_genesis_session::<<Runtime as pallet_session::Config>::Keys>(&queued_keys);
+				// Tell everyone about the genesis session keys -- Aura must've already initialized it
+				//<Runtime as pallet_session::Config>::SessionHandler::on_genesis_session::<<Runtime as pallet_session::Config>::Keys>(&queued_keys);
+
+				<pallet_session::Validators<Runtime>>::put(initial_validators_0);
+				<pallet_session::QueuedKeys<Runtime>>::put(queued_keys);
 
-			<pallet_session::Validators<Runtime>>::put(initial_validators_0);
-			<pallet_session::QueuedKeys<Runtime>>::put(queued_keys);
+				<Runtime as pallet_session::Config>::SessionManager::start_session(0);
 
-			<Runtime as pallet_session::Config>::SessionManager::start_session(0);
+				log::info!(
+					target: "runtime::aura_to_collator_selection",
+					"Migration of Aura authorities to Collator Selection invulnerables is complete."
+				);
 
-			log::info!(
-				target: "runtime::aura_to_collator_selection",
-				"Migration of Aura authorities to Collator Selection invulnerables is complete."
-			);
+				migration::put_storage_value::<()>(
+					b"AuraToCollatorSelection",
+					b"StorageVersion",
+					&[],
+					(),
+				);
 
-			migration::put_storage_value::<()>(
-				b"AuraToCollatorSelection",
-				b"StorageVersion",
-				&[],
-				(),
-			);
+				weight += <Runtime as frame_system::Config>::DbWeight::get().writes(1)
+			} else {
+				log::info!(
+					target: "runtime::aura_to_collator_selection",
+					"The storage migration has already been flagged as complete. No migration needs to be done.",
+				);
+			}
 
-			weight += <Runtime as frame_system::Config>::DbWeight::get().writes(1)
-		} else {
-			log::info!(
-				target: "runtime::aura_to_collator_selection",
-				"The storage migration has already been flagged as complete. No migration needs to be done.",
-			);
+			weight
 		}
 
-		weight
+		#[cfg(not(feature = "collator-selection"))]
+		{
+			Weight::zero()
+		}
 	}
 }
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -173,13 +173,14 @@
     "pallet-foreign-assets/std",
 ]
 limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
-opal-runtime = ['refungible', 'rmrk', 'app-promotion', 'foreign-assets']
+opal-runtime = ['refungible', 'rmrk', 'app-promotion', 'foreign-assets', 'collator-selection']
 
 refungible = []
 scheduler = []
 rmrk = []
 foreign-assets = []
 app-promotion = []
+collator-selection = []
 
 ################################################################################
 # Substrate Dependencies
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -177,6 +177,7 @@
 scheduler = []
 rmrk = []
 foreign-assets = []
+collator-selection = []
 
 ################################################################################
 # Substrate Dependencies
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -178,6 +178,7 @@
 scheduler = []
 rmrk = []
 foreign-assets = []
+collator-selection = []
 
 ################################################################################
 # Substrate Dependencies