polkadot_parachain/chain_spec/
mod.rs1use cumulus_primitives_core::ParaId;
18use polkadot_omni_node_lib::{
19 chain_spec::{GenericChainSpec, LoadSpec},
20 runtime::{
21 AuraConsensusId, BlockNumber, Consensus, Runtime, RuntimeResolver as RuntimeResolverT,
22 },
23};
24use sc_chain_spec::{ChainSpec, ChainType};
25use yet_another_parachain::yet_another_parachain_config;
26
27pub mod asset_hubs;
28pub mod bridge_hubs;
29pub mod collectives;
30pub mod coretime;
31pub mod glutton;
32pub mod penpal;
33pub mod people;
34pub mod rococo_parachain;
35pub mod yet_another_parachain;
36
37fn extract_parachain_id<'a>(
41 id: &'a str,
42 para_prefixes: &[&str],
43) -> (&'a str, &'a str, Option<ParaId>) {
44 for para_prefix in para_prefixes {
45 if let Some(suffix) = id.strip_prefix(para_prefix) {
46 let para_id: u32 = suffix.parse().expect("Invalid parachain-id suffix");
47 return (&id[..para_prefix.len() - 1], id, Some(para_id.into()));
48 }
49 }
50
51 (id, id, None)
52}
53
54#[derive(Debug)]
55pub(crate) struct ChainSpecLoader;
56
57impl LoadSpec for ChainSpecLoader {
58 fn load_spec(&self, id: &str) -> Result<Box<dyn ChainSpec>, String> {
59 Ok(match id {
60 "staging" => Box::new(rococo_parachain::staging_rococo_parachain_local_config()),
62 "tick" => Box::new(GenericChainSpec::from_json_bytes(
63 &include_bytes!("../../chain-specs/tick.json")[..],
64 )?),
65 "trick" => Box::new(GenericChainSpec::from_json_bytes(
66 &include_bytes!("../../chain-specs/trick.json")[..],
67 )?),
68 "track" => Box::new(GenericChainSpec::from_json_bytes(
69 &include_bytes!("../../chain-specs/track.json")[..],
70 )?),
71
72 "asset-hub-polkadot" | "statemint" => Box::new(GenericChainSpec::from_json_bytes(
74 &include_bytes!("../../chain-specs/asset-hub-polkadot.json")[..],
75 )?),
76
77 "asset-hub-kusama" | "statemine" => Box::new(GenericChainSpec::from_json_bytes(
79 &include_bytes!("../../chain-specs/asset-hub-kusama.json")[..],
80 )?),
81
82 "asset-hub-rococo-dev" => Box::new(asset_hubs::asset_hub_rococo_development_config()),
84 "asset-hub-rococo-local" => Box::new(asset_hubs::asset_hub_rococo_local_config()),
85 "asset-hub-rococo-genesis" => Box::new(asset_hubs::asset_hub_rococo_genesis_config()),
87 "asset-hub-rococo" => Box::new(GenericChainSpec::from_json_bytes(
88 &include_bytes!("../../chain-specs/asset-hub-rococo.json")[..],
89 )?),
90
91 "asset-hub-westend-dev" | "westmint-dev" =>
93 Box::new(asset_hubs::asset_hub_westend_development_config()),
94 "asset-hub-westend-local" | "westmint-local" =>
95 Box::new(asset_hubs::asset_hub_westend_local_config()),
96 "asset-hub-westend-genesis" | "westmint-genesis" =>
98 Box::new(asset_hubs::asset_hub_westend_config()),
99 "asset-hub-westend" | "westmint" => Box::new(GenericChainSpec::from_json_bytes(
101 &include_bytes!("../../chain-specs/asset-hub-westend.json")[..],
102 )?),
103
104 "collectives-polkadot" => Box::new(GenericChainSpec::from_json_bytes(
106 &include_bytes!("../../chain-specs/collectives-polkadot.json")[..],
107 )?),
108
109 "collectives-westend-dev" =>
111 Box::new(collectives::collectives_westend_development_config()),
112 "collectives-westend-local" =>
113 Box::new(collectives::collectives_westend_local_config()),
114 "collectives-westend" => Box::new(GenericChainSpec::from_json_bytes(
115 &include_bytes!("../../chain-specs/collectives-westend.json")[..],
116 )?),
117
118 bridge_like_id
120 if bridge_like_id.starts_with(bridge_hubs::BridgeHubRuntimeType::ID_PREFIX) =>
121 bridge_like_id
122 .parse::<bridge_hubs::BridgeHubRuntimeType>()
123 .expect("invalid value")
124 .load_config()?,
125
126 coretime_like_id
128 if coretime_like_id.starts_with(coretime::CoretimeRuntimeType::ID_PREFIX) =>
129 coretime_like_id
130 .parse::<coretime::CoretimeRuntimeType>()
131 .expect("invalid value")
132 .load_config()?,
133
134 id if id.starts_with("penpal-rococo") => {
136 let (_, _, para_id) = extract_parachain_id(&id, &["penpal-rococo-"]);
137 Box::new(penpal::get_penpal_chain_spec(
138 para_id.expect("Must specify parachain id"),
139 "rococo-local",
140 ))
141 },
142 id if id.starts_with("penpal-westend") => {
143 let (_, _, para_id) = extract_parachain_id(&id, &["penpal-westend-"]);
144 Box::new(penpal::get_penpal_chain_spec(
145 para_id.expect("Must specify parachain id"),
146 "westend-local",
147 ))
148 },
149
150 id if id.starts_with("glutton-westend-dev") => {
152 let (_, _, para_id) = extract_parachain_id(&id, &["glutton-westend-dev-"]);
153 Box::new(glutton::glutton_westend_config(
154 para_id.expect("Must specify parachain id"),
155 ChainType::Development,
156 "westend-dev",
157 ))
158 },
159 id if id.starts_with("glutton-westend-local") => {
160 let (_, _, para_id) = extract_parachain_id(&id, &["glutton-westend-local-"]);
161 Box::new(glutton::glutton_westend_config(
162 para_id.expect("Must specify parachain id"),
163 ChainType::Local,
164 "westend-local",
165 ))
166 },
167 id if id.starts_with("glutton-westend-genesis") => {
169 let (_, _, para_id) = extract_parachain_id(&id, &["glutton-westend-genesis-"]);
170 Box::new(glutton::glutton_westend_config(
171 para_id.expect("Must specify parachain id"),
172 ChainType::Live,
173 "westend",
174 ))
175 },
176
177 id if id.starts_with("yap-") => {
178 let tok: Vec<String> = id.split('-').map(|s| s.to_owned()).collect();
179 assert!(
180 tok.len() == 4,
181 "Invalid YAP chain id, should be 'yap-<relay>-<chaintype>-<para-id>'"
182 );
183 let relay = if &tok[2] == "live" { tok[1].clone() } else { tok[1..=2].join("-") };
184 let chain_type = match tok[2].as_str() {
185 "local" => ChainType::Local,
186 "dev" => ChainType::Development,
187 "live" => ChainType::Live,
188 _ => unimplemented!("Unknown chain type {}", tok[2]),
189 };
190 let para_id: u32 =
191 tok[3].parse().expect(&format!("Illegal para id '{}' provided", tok[3]));
192
193 Box::new(yet_another_parachain_config(relay, chain_type, para_id))
194 },
195
196 people_like_id if people_like_id.starts_with(people::PeopleRuntimeType::ID_PREFIX) =>
198 people_like_id
199 .parse::<people::PeopleRuntimeType>()
200 .expect("invalid value")
201 .load_config()?,
202
203 "" => {
205 log::warn!("No ChainSpec.id specified, so using default one, based on rococo-parachain runtime");
206 Box::new(rococo_parachain::rococo_parachain_local_config())
207 },
208
209 path => Box::new(GenericChainSpec::from_json_file(path.into())?),
211 })
212 }
213}
214
215#[derive(Debug, PartialEq)]
218enum LegacyRuntime {
219 Omni,
220 AssetHubPolkadot,
221 AssetHub,
222 Penpal,
223 Collectives,
224 Glutton,
225 BridgeHub(bridge_hubs::BridgeHubRuntimeType),
226 Coretime(coretime::CoretimeRuntimeType),
227 People(people::PeopleRuntimeType),
228}
229
230impl LegacyRuntime {
231 fn from_id(id: &str) -> LegacyRuntime {
232 let id = id.replace('_', "-");
233
234 if id.starts_with("asset-hub-polkadot") | id.starts_with("statemint") {
235 LegacyRuntime::AssetHubPolkadot
236 } else if id.starts_with("asset-hub-kusama") |
237 id.starts_with("statemine") |
238 id.starts_with("asset-hub-rococo") |
239 id.starts_with("rockmine") |
240 id.starts_with("asset-hub-westend") |
241 id.starts_with("westmint")
242 {
243 LegacyRuntime::AssetHub
244 } else if id.starts_with("penpal") {
245 LegacyRuntime::Penpal
246 } else if id.starts_with("collectives-polkadot") || id.starts_with("collectives-westend") {
247 LegacyRuntime::Collectives
248 } else if id.starts_with(bridge_hubs::BridgeHubRuntimeType::ID_PREFIX) {
249 LegacyRuntime::BridgeHub(
250 id.parse::<bridge_hubs::BridgeHubRuntimeType>().expect("Invalid value"),
251 )
252 } else if id.starts_with(coretime::CoretimeRuntimeType::ID_PREFIX) {
253 LegacyRuntime::Coretime(
254 id.parse::<coretime::CoretimeRuntimeType>().expect("Invalid value"),
255 )
256 } else if id.starts_with("glutton") {
257 LegacyRuntime::Glutton
258 } else if id.starts_with(people::PeopleRuntimeType::ID_PREFIX) {
259 LegacyRuntime::People(id.parse::<people::PeopleRuntimeType>().expect("Invalid value"))
260 } else {
261 log::warn!(
262 "No specific runtime was recognized for ChainSpec's id: '{}', \
263 so Runtime::Omni(Consensus::Aura) will be used",
264 id
265 );
266 LegacyRuntime::Omni
267 }
268 }
269}
270
271#[derive(Debug)]
272pub(crate) struct RuntimeResolver;
273
274impl RuntimeResolverT for RuntimeResolver {
275 fn runtime(&self, chain_spec: &dyn ChainSpec) -> sc_cli::Result<Runtime> {
276 let legacy_runtime = LegacyRuntime::from_id(chain_spec.id());
277 Ok(match legacy_runtime {
278 LegacyRuntime::AssetHubPolkadot =>
279 Runtime::Omni(BlockNumber::U32, Consensus::Aura(AuraConsensusId::Ed25519)),
280 LegacyRuntime::AssetHub |
281 LegacyRuntime::BridgeHub(_) |
282 LegacyRuntime::Collectives |
283 LegacyRuntime::Coretime(_) |
284 LegacyRuntime::People(_) |
285 LegacyRuntime::Glutton |
286 LegacyRuntime::Penpal |
287 LegacyRuntime::Omni =>
288 Runtime::Omni(BlockNumber::U32, Consensus::Aura(AuraConsensusId::Sr25519)),
289 })
290 }
291}
292
293#[cfg(test)]
294mod tests {
295 use super::*;
296 use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup, ChainType, Extension};
297 use serde::{Deserialize, Serialize};
298
299 #[derive(
300 Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, Default,
301 )]
302 #[serde(deny_unknown_fields)]
303 pub struct Extensions1 {
304 pub attribute1: String,
305 pub attribute2: u32,
306 }
307
308 #[derive(
309 Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, Default,
310 )]
311 #[serde(deny_unknown_fields)]
312 pub struct Extensions2 {
313 pub attribute_x: String,
314 pub attribute_y: String,
315 pub attribute_z: u32,
316 }
317
318 pub type DummyChainSpec<E> = sc_service::GenericChainSpec<E>;
319
320 pub fn create_default_with_extensions<E: Extension>(
321 id: &str,
322 extension: E,
323 ) -> DummyChainSpec<E> {
324 DummyChainSpec::builder(
325 rococo_parachain_runtime::WASM_BINARY
326 .expect("WASM binary was not built, please build it!"),
327 extension,
328 )
329 .with_name("Dummy local testnet")
330 .with_id(id)
331 .with_chain_type(ChainType::Local)
332 .with_genesis_config_preset_name(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET)
333 .build()
334 }
335
336 #[test]
337 fn test_legacy_runtime_for_different_chain_specs() {
338 let chain_spec =
339 create_default_with_extensions("penpal-rococo-1000", Extensions2::default());
340 assert_eq!(LegacyRuntime::Penpal, LegacyRuntime::from_id(chain_spec.id()));
341
342 let chain_spec = crate::chain_spec::rococo_parachain::rococo_parachain_local_config();
343 assert_eq!(LegacyRuntime::Omni, LegacyRuntime::from_id(chain_spec.id()));
344 }
345}