1use polkadot_sdk::*;
21
22use crate::{
23 constants::currency::*, frame_support::build_struct_json_patch, AccountId, AssetsConfig,
24 BabeConfig, Balance, BalancesConfig, ElectionsConfig, NominationPoolsConfig, ReviveConfig,
25 RuntimeGenesisConfig, SessionConfig, SessionKeys, SocietyConfig, StakerStatus, StakingConfig,
26 SudoConfig, TechnicalCommitteeConfig, BABE_GENESIS_EPOCH_CONFIG,
27};
28use alloc::{vec, vec::Vec};
29use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
30use pallet_revive::is_eth_derived;
31use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
32use sp_consensus_babe::AuthorityId as BabeId;
33use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
34use sp_consensus_grandpa::AuthorityId as GrandpaId;
35use sp_core::{crypto::get_public_from_string_or_panic, sr25519};
36use sp_genesis_builder::PresetId;
37use sp_keyring::Sr25519Keyring;
38use sp_mixnet::types::AuthorityId as MixnetId;
39use sp_runtime::Perbill;
40
41pub const ENDOWMENT: Balance = 10_000_000 * DOLLARS;
42pub const STASH: Balance = ENDOWMENT / 1000;
43
44pub type Staker = (AccountId, AccountId, Balance, StakerStatus<AccountId>);
46
47pub fn kitchensink_genesis(
49 initial_authorities: Vec<(AccountId, AccountId, SessionKeys)>,
50 root_key: AccountId,
51 endowed_accounts: Vec<AccountId>,
52 stakers: Vec<Staker>,
53) -> serde_json::Value {
54 let validator_count = initial_authorities.len() as u32;
55 let minimum_validator_count = validator_count;
56
57 let collective = collective(&endowed_accounts);
58
59 build_struct_json_patch!(RuntimeGenesisConfig {
60 balances: BalancesConfig {
61 balances: endowed_accounts.iter().cloned().map(|x| (x, ENDOWMENT)).collect(),
62 ..Default::default()
63 },
64 session: SessionConfig {
65 keys: initial_authorities
66 .iter()
67 .map(|x| { (x.0.clone(), x.1.clone(), x.2.clone()) })
68 .collect(),
69 },
70 staking: StakingConfig {
71 validator_count,
72 minimum_validator_count,
73 invulnerables: initial_authorities
74 .iter()
75 .map(|x| x.0.clone())
76 .collect::<Vec<_>>()
77 .try_into()
78 .expect("Too many invulnerable validators: upper limit is MaxInvulnerables from pallet staking config"),
79 slash_reward_fraction: Perbill::from_percent(10),
80 stakers,
81 },
82 elections: ElectionsConfig {
83 members: collective.iter().cloned().map(|member| (member, STASH)).collect(),
84 },
85 technical_committee: TechnicalCommitteeConfig { members: collective },
86 sudo: SudoConfig { key: Some(root_key) },
87 babe: BabeConfig { epoch_config: BABE_GENESIS_EPOCH_CONFIG },
88 society: SocietyConfig { pot: 0 },
89 assets: AssetsConfig {
90 assets: vec![(9, Sr25519Keyring::Alice.to_account_id(), true, 1)],
92 ..Default::default()
93 },
94 nomination_pools: NominationPoolsConfig {
95 min_create_bond: 10 * DOLLARS,
96 min_join_bond: 1 * DOLLARS,
97 },
98 revive: ReviveConfig {
99 mapped_accounts: endowed_accounts.iter().filter(|x| ! is_eth_derived(x)).cloned().collect(),
100 },
101 })
102}
103
104pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
106 let (alice_stash, alice, alice_session_keys) = authority_keys_from_seed("Alice");
108 let (bob_stash, _bob, bob_session_keys) = authority_keys_from_seed("Bob");
109
110 let endowed = well_known_including_eth_accounts();
111
112 let patch = match id.as_ref() {
113 sp_genesis_builder::DEV_RUNTIME_PRESET => kitchensink_genesis(
114 vec![(alice_stash.clone(), alice_stash.clone(), alice_session_keys)],
117 alice.clone(),
118 endowed,
119 vec![validator(alice_stash.clone())],
120 ),
121 sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => kitchensink_genesis(
122 vec![
123 (alice_stash.clone(), alice_stash.clone(), alice_session_keys),
126 (bob_stash.clone(), bob_stash.clone(), bob_session_keys),
127 ],
128 alice,
129 endowed,
130 vec![validator(alice_stash), validator(bob_stash)],
131 ),
132 _ => return None,
133 };
134
135 Some(
136 serde_json::to_string(&patch)
137 .expect("serialization to json is expected to work. qed.")
138 .into_bytes(),
139 )
140}
141
142pub fn preset_names() -> Vec<PresetId> {
144 vec![
145 PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
146 PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
147 ]
148}
149
150pub fn validator(account: AccountId) -> Staker {
153 (account.clone(), account, STASH, StakerStatus::Validator)
155}
156
157fn collective(endowed: &[AccountId]) -> Vec<AccountId> {
159 const MAX_COLLECTIVE_SIZE: usize = 50;
160 let endowed_accounts_count = endowed.len();
161 endowed
162 .iter()
163 .take((endowed_accounts_count.div_ceil(2)).min(MAX_COLLECTIVE_SIZE))
164 .cloned()
165 .collect()
166}
167
168pub fn well_known_including_eth_accounts() -> Vec<AccountId> {
172 Sr25519Keyring::well_known()
173 .map(|k| k.to_account_id())
174 .chain([
175 array_bytes::hex_n_into_unchecked(
177 "f24ff3a9cf04c71dbc94d0b566f7a27b94566caceeeeeeeeeeeeeeeeeeeeeeee",
178 ),
179 array_bytes::hex_n_into_unchecked(
181 "3cd0a705a2dc65e5b1e1205896baa2be8a07c6e0eeeeeeeeeeeeeeeeeeeeeeee",
182 ),
183 ])
184 .collect::<Vec<_>>()
185}
186
187pub fn authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, SessionKeys) {
191 (
192 get_public_from_string_or_panic::<sr25519::Public>(&alloc::format!("{seed}//stash")).into(),
193 get_public_from_string_or_panic::<sr25519::Public>(seed).into(),
194 session_keys_from_seed(seed),
195 )
196}
197
198pub fn session_keys(
199 grandpa: GrandpaId,
200 babe: BabeId,
201 im_online: ImOnlineId,
202 authority_discovery: AuthorityDiscoveryId,
203 mixnet: MixnetId,
204 beefy: BeefyId,
205) -> SessionKeys {
206 SessionKeys { grandpa, babe, im_online, authority_discovery, mixnet, beefy }
207}
208
209pub fn session_keys_from_seed(seed: &str) -> SessionKeys {
214 session_keys(
215 get_public_from_string_or_panic::<GrandpaId>(seed),
216 get_public_from_string_or_panic::<BabeId>(seed),
217 get_public_from_string_or_panic::<ImOnlineId>(seed),
218 get_public_from_string_or_panic::<AuthorityDiscoveryId>(seed),
219 get_public_from_string_or_panic::<MixnetId>(seed),
220 get_public_from_string_or_panic::<BeefyId>(seed),
221 )
222}