Skip to content

Commit c468b45

Browse files
committed
chain_spec customization
1 parent 2546063 commit c468b45

File tree

6 files changed

+220
-17
lines changed

6 files changed

+220
-17
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
**/target/
22
**/node_modules/
3+
/src/x.rs

src/generator.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,24 @@ struct Runtime<'a> {
88
code: &'a str,
99
balances: bool,
1010
}
11+
12+
// TODO: This should be coupled with Runtime in the sense that pallets part of a Runtime may need a default genesis config
13+
#[derive(Template)]
14+
#[template(path = "chain_spec.templ", escape = "none")]
15+
struct ChainSpec<'a> {
16+
token_symbol : &'a str,
17+
decimals: u8,
18+
initial_endowment: &'a str,
19+
}
1120
// todo : generate directory structure
1221

1322
pub fn generate() {
14-
let hello = Runtime {
15-
code: r#"fn main() {
16-
println!("Hello, world!");
17-
}"#,
18-
balances: false,
19-
}; // instantiate your struct
20-
let rendered = hello.render().unwrap();
23+
let cs = ChainSpec {
24+
token_symbol: "DOT",
25+
decimals: 10,
26+
initial_endowment: "1u64 << 15"
27+
};
28+
let rendered = cs.render().unwrap();
2129
write_to_file(Path::new("src/x.rs"), &rendered);
2230
}
2331

src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use cli::Cli;
66
use std::path::Path;
77

88
fn main() -> anyhow::Result<()> {
9-
// generator::generate();
10-
// std::process::exit(0);
9+
generator::generate();
10+
std::process::exit(0);
1111

1212
let cli = <Cli as clap::Parser>::parse();
1313
let (app_name, template) = match cli.create {

src/x.rs

-3
This file was deleted.

templates/chain_spec.templ

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
use cumulus_primitives_core::ParaId;
2+
use parachain_template_runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT};
3+
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
4+
use sc_service::ChainType;
5+
use serde::{Deserialize, Serialize};
6+
use sp_core::{sr25519, Pair, Public};
7+
use sp_runtime::traits::{IdentifyAccount, Verify};
8+
9+
/// Specialized `ChainSpec` for the normal parachain runtime.
10+
pub type ChainSpec = sc_service::GenericChainSpec<(), Extensions>;
11+
12+
/// The default XCM version to set in genesis config.
13+
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
14+
15+
/// Helper function to generate a crypto pair from seed
16+
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
17+
TPublic::Pair::from_string(&format!("//{}", seed), None)
18+
.expect("static values are valid; qed")
19+
.public()
20+
}
21+
22+
/// The extensions for the [`ChainSpec`].
23+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
24+
#[serde(deny_unknown_fields)]
25+
pub struct Extensions {
26+
/// The relay chain of the Parachain.
27+
pub relay_chain: String,
28+
/// The id of the Parachain.
29+
pub para_id: u32,
30+
}
31+
32+
impl Extensions {
33+
/// Try to get the extension from the given `ChainSpec`.
34+
pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {
35+
sc_chain_spec::get_extension(chain_spec.extensions())
36+
}
37+
}
38+
39+
type AccountPublic = <Signature as Verify>::Signer;
40+
41+
/// Generate collator keys from seed.
42+
///
43+
/// This function's return type must always match the session keys of the chain in tuple format.
44+
pub fn get_collator_keys_from_seed(seed: &str) -> AuraId {
45+
get_from_seed::<AuraId>(seed)
46+
}
47+
48+
/// Helper function to generate an account ID from seed
49+
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
50+
where
51+
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
52+
{
53+
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
54+
}
55+
56+
/// Generate the session keys from individual elements.
57+
///
58+
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
59+
pub fn template_session_keys(keys: AuraId) -> parachain_template_runtime::SessionKeys {
60+
parachain_template_runtime::SessionKeys { aura: keys }
61+
}
62+
63+
pub fn development_config() -> ChainSpec {
64+
// Give your base currency a unit name and decimal places
65+
let mut properties = sc_chain_spec::Properties::new();
66+
properties.insert("tokenSymbol".into(), "^^token_symbol^^".into());
67+
properties.insert("tokenDecimals".into(), ^^decimals^^.into());
68+
properties.insert("ss58Format".into(), 42.into());
69+
70+
ChainSpec::builder(
71+
parachain_template_runtime::WASM_BINARY
72+
.expect("WASM binary was not built, please build it!"),
73+
Extensions {
74+
relay_chain: "rococo-local".into(),
75+
// You MUST set this to the correct network!
76+
para_id: 1000,
77+
},
78+
)
79+
.with_name("Development")
80+
.with_id("dev")
81+
.with_chain_type(ChainType::Development)
82+
.with_genesis_config_patch(testnet_genesis(
83+
// initial collators.
84+
vec![
85+
(
86+
get_account_id_from_seed::<sr25519::Public>("Alice"),
87+
get_collator_keys_from_seed("Alice"),
88+
),
89+
(
90+
get_account_id_from_seed::<sr25519::Public>("Bob"),
91+
get_collator_keys_from_seed("Bob"),
92+
),
93+
],
94+
vec![
95+
get_account_id_from_seed::<sr25519::Public>("Alice"),
96+
get_account_id_from_seed::<sr25519::Public>("Bob"),
97+
get_account_id_from_seed::<sr25519::Public>("Charlie"),
98+
get_account_id_from_seed::<sr25519::Public>("Dave"),
99+
get_account_id_from_seed::<sr25519::Public>("Eve"),
100+
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
101+
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
102+
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
103+
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
104+
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
105+
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
106+
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
107+
],
108+
get_account_id_from_seed::<sr25519::Public>("Alice"),
109+
1000.into(),
110+
))
111+
.build()
112+
}
113+
114+
pub fn local_testnet_config() -> ChainSpec {
115+
// Give your base currency a unit name and decimal places
116+
let mut properties = sc_chain_spec::Properties::new();
117+
properties.insert("tokenSymbol".into(), "^^token_symbol^^".into());
118+
properties.insert("tokenDecimals".into(), ^^decimals^^.into());
119+
properties.insert("ss58Format".into(), 42.into());
120+
121+
#[allow(deprecated)]
122+
ChainSpec::builder(
123+
parachain_template_runtime::WASM_BINARY
124+
.expect("WASM binary was not built, please build it!"),
125+
Extensions {
126+
relay_chain: "rococo-local".into(),
127+
// You MUST set this to the correct network!
128+
para_id: 1000,
129+
},
130+
)
131+
.with_name("Local Testnet")
132+
.with_id("local_testnet")
133+
.with_chain_type(ChainType::Local)
134+
.with_genesis_config_patch(testnet_genesis(
135+
// initial collators.
136+
vec![
137+
(
138+
get_account_id_from_seed::<sr25519::Public>("Alice"),
139+
get_collator_keys_from_seed("Alice"),
140+
),
141+
(
142+
get_account_id_from_seed::<sr25519::Public>("Bob"),
143+
get_collator_keys_from_seed("Bob"),
144+
),
145+
],
146+
vec![
147+
get_account_id_from_seed::<sr25519::Public>("Alice"),
148+
get_account_id_from_seed::<sr25519::Public>("Bob"),
149+
get_account_id_from_seed::<sr25519::Public>("Charlie"),
150+
get_account_id_from_seed::<sr25519::Public>("Dave"),
151+
get_account_id_from_seed::<sr25519::Public>("Eve"),
152+
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
153+
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
154+
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
155+
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
156+
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
157+
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
158+
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
159+
],
160+
get_account_id_from_seed::<sr25519::Public>("Alice"),
161+
1000.into(),
162+
))
163+
.with_protocol_id("template-local")
164+
.with_properties(properties)
165+
.build()
166+
}
167+
168+
fn testnet_genesis(
169+
invulnerables: Vec<(AccountId, AuraId)>,
170+
endowed_accounts: Vec<AccountId>,
171+
root: AccountId,
172+
id: ParaId,
173+
) -> serde_json::Value {
174+
serde_json::json!({
175+
"balances": {
176+
"balances": endowed_accounts.iter().cloned().map(|k| (k, ^^initial_endowment^^)).collect::<Vec<_>>(),
177+
},
178+
"parachainInfo": {
179+
"parachainId": id,
180+
},
181+
"collatorSelection": {
182+
"invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::<Vec<_>>(),
183+
"candidacyBond": EXISTENTIAL_DEPOSIT * 16,
184+
},
185+
"session": {
186+
"keys": invulnerables
187+
.into_iter()
188+
.map(|(acc, aura)| {
189+
(
190+
acc.clone(), // account id
191+
acc, // validator id
192+
template_session_keys(aura), // session keys
193+
)
194+
})
195+
.collect::<Vec<_>>(),
196+
},
197+
"polkadotXcm": {
198+
"safeXcmVersion": Some(SAFE_XCM_VERSION),
199+
},
200+
"sudo": { "key": Some(root) }
201+
})
202+
}

templates/test.templ

-5
This file was deleted.

0 commit comments

Comments
 (0)