1use domain_runtime_primitives::{AccountId20Converter, MultiAccountId};
2use evm_domain_runtime::{AccountId as AccountId20, EVMChainIdConfig, EVMConfig, Precompiles};
3use hex_literal::hex;
4use parity_scale_codec::Encode;
5use sc_chain_spec::GenericChainSpec;
6use sc_service::ChainType;
7use sp_core::crypto::AccountId32;
8use sp_core::{Pair, Public, sr25519};
9use sp_domains::storage::RawGenesis;
10use sp_domains::{
11 DomainRuntimeConfig, OperatorAllowList, OperatorPublicKey, PermissionedActionAllowedBy,
12 RuntimeType,
13};
14use sp_runtime::traits::{Convert, IdentifyAccount};
15use sp_runtime::{BuildStorage, MultiSigner, Percent};
16use std::marker::PhantomData;
17use std::num::NonZeroU32;
18use subspace_runtime::{
19 AllowAuthoringBy, CouncilConfig, DemocracyConfig, DomainsConfig, EnableRewardsAt,
20 RewardsConfig, RuntimeConfigsConfig, SubspaceConfig,
21};
22use subspace_runtime_primitives::{
23 AI3, AccountId, Balance, BlockNumber, CouncilDemocracyConfigParams, GenesisConfigParams,
24};
25
26fn endowed_accounts() -> Vec<(MultiAccountId, Balance)> {
27 [
28 AccountId20::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")),
30 AccountId20::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0")),
32 AccountId20::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc")),
34 AccountId20::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9")),
36 ]
37 .into_iter()
38 .map(|k| (AccountId20Converter::convert(k), 1_000_000 * AI3))
39 .collect()
40}
41
42pub fn domain_dev_config() -> Result<GenericChainSpec, String> {
43 Ok(GenericChainSpec::builder(
44 evm_domain_runtime::WASM_BINARY.expect("WASM binary was not build, please build it!"),
45 None,
46 )
47 .with_name("Development")
48 .with_id("evm_domain_dev")
49 .with_chain_type(ChainType::Development)
50 .with_genesis_config({
51 let revert_bytecode = vec![0x60, 0x00, 0x60, 0x00, 0xFD];
56
57 serde_json::to_value(evm_domain_runtime::RuntimeGenesisConfig {
58 system: evm_domain_runtime::SystemConfig::default(),
59 balances: evm_domain_runtime::BalancesConfig::default(),
60 evm_chain_id: EVMChainIdConfig::default(),
63 evm: EVMConfig {
64 accounts: Precompiles::used_addresses()
67 .into_iter()
68 .map(|addr| {
69 (
70 addr,
71 fp_evm::GenesisAccount {
72 nonce: Default::default(),
73 balance: Default::default(),
74 storage: Default::default(),
75 code: revert_bytecode.clone(),
76 },
77 )
78 })
79 .collect(),
80 ..Default::default()
81 },
82 ..Default::default()
83 })
84 .map_err(|error| format!("Failed to serialize genesis config: {error}"))?
85 })
86 .build())
87}
88
89pub(crate) fn consensus_dev_sudo_account() -> AccountId32 {
90 get_account_id_from_seed("Alice")
91}
92
93pub fn create_domain_spec(chain_id: &str) -> Result<Box<dyn sc_cli::ChainSpec>, String> {
94 let chain_spec = match chain_id {
95 "dev" => domain_dev_config()?,
96 path => GenericChainSpec::from_json_file(std::path::PathBuf::from(path))?,
97 };
98 Ok(Box::new(chain_spec))
99}
100
101pub fn load_domain_chain_spec(spec_id: &str) -> Result<Box<dyn sc_cli::ChainSpec>, String> {
102 let chain_spec = match spec_id {
103 "dev" => domain_dev_config()?,
104 path => GenericChainSpec::from_json_file(std::path::PathBuf::from(path))?,
105 };
106 Ok(Box::new(chain_spec))
107}
108
109fn get_public_key_from_seed<TPublic: Public>(
111 seed: &'static str,
112) -> <TPublic::Pair as Pair>::Public {
113 TPublic::Pair::from_string(&format!("//{seed}"), None)
114 .expect("Static values are valid; qed")
115 .public()
116}
117
118fn get_account_id_from_seed(seed: &'static str) -> AccountId32 {
120 MultiSigner::from(get_public_key_from_seed::<sr25519::Public>(seed)).into_account()
121}
122
123struct GenesisParams {
125 enable_rewards_at: EnableRewardsAt<BlockNumber>,
126 allow_authoring_by: AllowAuthoringBy,
127 pot_slot_iterations: NonZeroU32,
128 enable_domains: bool,
129 enable_dynamic_cost_of_storage: bool,
130 enable_balance_transfers: bool,
131 confirmation_depth_k: u32,
132 rewards_config: RewardsConfig,
133 domain_block_pruning_depth: u32,
134 staking_withdrawal_period: u32,
135}
136
137struct GenesisDomainParams {
138 domain_name: String,
139 operator_allow_list: OperatorAllowList<AccountId>,
140 operator_signing_key: OperatorPublicKey,
141 raw_genesis_storage: Vec<u8>,
142 initial_balances: Vec<(MultiAccountId, Balance)>,
143 permissioned_action_allowed_by: PermissionedActionAllowedBy<AccountId>,
144 domain_runtime_config: DomainRuntimeConfig,
145}
146
147pub fn dev_config() -> Result<GenericChainSpec, String> {
148 let wasm_binary = subspace_runtime::WASM_BINARY
149 .ok_or_else(|| "Development wasm not available".to_string())?;
150
151 let raw_genesis_storage = {
152 let domain_genesis_config = domain_dev_config()?;
153 let storage = domain_genesis_config
154 .build_storage()
155 .expect("Failed to build genesis storage from genesis runtime config");
156 let raw_genesis = RawGenesis::from_storage(storage);
157 raw_genesis.encode()
158 };
159
160 let GenesisConfigParams {
161 confirmation_depth_k,
162 domain_block_pruning_depth,
163 staking_withdrawal_period,
164 } = GenesisConfigParams::dev_params();
165
166 Ok(GenericChainSpec::builder(wasm_binary, None)
167 .with_name("Subspace development")
168 .with_id("subspace_dev")
169 .with_chain_type(ChainType::Development)
170 .with_genesis_config(
171 serde_json::to_value(subspace_genesis_config(
172 get_account_id_from_seed("Alice"),
174 vec![
176 (get_account_id_from_seed("Alice"), Balance::MAX / 2),
177 (get_account_id_from_seed("Bob"), 1_000 * AI3),
178 (get_account_id_from_seed("Alice//stash"), 1_000 * AI3),
179 (get_account_id_from_seed("Bob//stash"), 1_000 * AI3),
180 ],
181 GenesisParams {
182 enable_rewards_at: EnableRewardsAt::Manually,
183 allow_authoring_by: AllowAuthoringBy::Anyone,
184 pot_slot_iterations: NonZeroU32::new(100_000_000).expect("Not zero; qed"),
185 enable_domains: true,
186 enable_dynamic_cost_of_storage: false,
187 enable_balance_transfers: true,
188 confirmation_depth_k,
189 rewards_config: RewardsConfig {
190 remaining_issuance: 1_000_000 * AI3,
191 proposer_subsidy_points: Default::default(),
192 voter_subsidy_points: Default::default(),
193 },
194 domain_block_pruning_depth,
195 staking_withdrawal_period,
196 },
197 GenesisDomainParams {
198 domain_name: "evm-domain".to_owned(),
199 operator_allow_list: OperatorAllowList::Anyone,
200 operator_signing_key: get_public_key_from_seed::<OperatorPublicKey>("Alice"),
201 raw_genesis_storage: raw_genesis_storage.clone(),
202 initial_balances: endowed_accounts(),
203 permissioned_action_allowed_by: PermissionedActionAllowedBy::Anyone,
204 domain_runtime_config: DomainRuntimeConfig::default_evm(),
205 },
206 ))
207 .map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
208 )
209 .build())
210}
211
212fn subspace_genesis_config(
214 sudo_account: AccountId,
215 balances: Vec<(AccountId, Balance)>,
216 genesis_params: GenesisParams,
217 genesis_domain_params: GenesisDomainParams,
218) -> subspace_runtime::RuntimeGenesisConfig {
219 let GenesisParams {
220 enable_rewards_at,
221 allow_authoring_by,
222 pot_slot_iterations,
223 enable_domains,
224 enable_dynamic_cost_of_storage,
225 enable_balance_transfers,
226 confirmation_depth_k,
227 rewards_config,
228 domain_block_pruning_depth,
229 staking_withdrawal_period,
230 } = genesis_params;
231
232 subspace_runtime::RuntimeGenesisConfig {
233 system: subspace_runtime::SystemConfig::default(),
234 balances: subspace_runtime::BalancesConfig { balances },
235 transaction_payment: Default::default(),
236 sudo: subspace_runtime::SudoConfig {
237 key: Some(sudo_account.clone()),
239 },
240 subspace: SubspaceConfig {
241 enable_rewards_at,
242 allow_authoring_by,
243 pot_slot_iterations,
244 phantom: PhantomData,
245 },
246 rewards: rewards_config,
247 council: CouncilConfig::default(),
248 democracy: DemocracyConfig::default(),
249 runtime_configs: RuntimeConfigsConfig {
250 enable_domains,
251 enable_dynamic_cost_of_storage,
252 enable_balance_transfers,
253 confirmation_depth_k,
254 council_democracy_config_params:
255 CouncilDemocracyConfigParams::<BlockNumber>::fast_params(),
256 domain_block_pruning_depth,
257 staking_withdrawal_period,
258 },
259 domains: DomainsConfig {
260 permissioned_action_allowed_by: Some(
261 genesis_domain_params.permissioned_action_allowed_by,
262 ),
263 genesis_domains: vec![sp_domains::GenesisDomain {
264 runtime_name: "evm".to_owned(),
265 runtime_type: RuntimeType::Evm,
266 runtime_version: evm_domain_runtime::VERSION,
267 raw_genesis_storage: genesis_domain_params.raw_genesis_storage,
268
269 owner_account_id: sudo_account.clone(),
271 domain_name: genesis_domain_params.domain_name,
272 bundle_slot_probability: (1, 1),
273 operator_allow_list: genesis_domain_params.operator_allow_list,
274 signing_key: genesis_domain_params.operator_signing_key,
275 nomination_tax: Percent::from_percent(5),
276 minimum_nominator_stake: 100 * AI3,
277 initial_balances: genesis_domain_params.initial_balances,
278 domain_runtime_config: genesis_domain_params.domain_runtime_config,
279 }],
280 },
281 }
282}