1use domain_runtime_primitives::{AccountId20Converter, DEFAULT_EVM_CHAIN_ID, 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 DomainRuntimeInfo, EvmDomainRuntimeConfig, EvmType, OperatorAllowList, OperatorPublicKey,
12 PermissionedActionAllowedBy, 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 .map(|addr| {
68 (
69 addr.into(),
70 fp_evm::GenesisAccount {
71 nonce: Default::default(),
72 balance: Default::default(),
73 storage: Default::default(),
74 code: revert_bytecode.clone(),
75 },
76 )
77 })
78 .collect(),
79 ..Default::default()
80 },
81 ..Default::default()
82 })
83 .map_err(|error| format!("Failed to serialize genesis config: {error}"))?
84 })
85 .build())
86}
87
88pub(crate) fn consensus_dev_sudo_account() -> AccountId32 {
89 get_account_id_from_seed("Alice")
90}
91
92pub fn create_domain_spec(chain_id: &str) -> Result<Box<dyn sc_cli::ChainSpec>, String> {
93 let chain_spec = match chain_id {
94 "dev" => domain_dev_config()?,
95 path => GenericChainSpec::from_json_file(std::path::PathBuf::from(path))?,
96 };
97 Ok(Box::new(chain_spec))
98}
99
100pub fn load_domain_chain_spec(spec_id: &str) -> Result<Box<dyn sc_cli::ChainSpec>, String> {
101 let chain_spec = match spec_id {
102 "dev" => domain_dev_config()?,
103 path => GenericChainSpec::from_json_file(std::path::PathBuf::from(path))?,
104 };
105 Ok(Box::new(chain_spec))
106}
107
108fn get_public_key_from_seed<TPublic: Public>(
110 seed: &'static str,
111) -> <TPublic::Pair as Pair>::Public {
112 TPublic::Pair::from_string(&format!("//{seed}"), None)
113 .expect("Static values are valid; qed")
114 .public()
115}
116
117fn get_account_id_from_seed(seed: &'static str) -> AccountId32 {
119 MultiSigner::from(get_public_key_from_seed::<sr25519::Public>(seed)).into_account()
120}
121
122struct GenesisParams {
124 enable_rewards_at: EnableRewardsAt<BlockNumber>,
125 allow_authoring_by: AllowAuthoringBy,
126 pot_slot_iterations: NonZeroU32,
127 enable_domains: bool,
128 enable_dynamic_cost_of_storage: bool,
129 enable_balance_transfers: bool,
130 confirmation_depth_k: u32,
131 rewards_config: RewardsConfig,
132 domain_block_pruning_depth: u32,
133 staking_withdrawal_period: u32,
134}
135
136struct GenesisDomainParams {
137 domain_name: String,
138 operator_allow_list: OperatorAllowList<AccountId>,
139 operator_signing_key: OperatorPublicKey,
140 raw_genesis_storage: Vec<u8>,
141 initial_balances: Vec<(MultiAccountId, Balance)>,
142 permissioned_action_allowed_by: PermissionedActionAllowedBy<AccountId>,
143 domain_runtime_info: DomainRuntimeInfo,
144}
145
146pub fn dev_config() -> Result<GenericChainSpec, String> {
147 let wasm_binary = subspace_runtime::WASM_BINARY
148 .ok_or_else(|| "Development wasm not available".to_string())?;
149
150 let raw_genesis_storage = {
151 let domain_genesis_config = domain_dev_config()?;
152 let storage = domain_genesis_config
153 .build_storage()
154 .expect("Failed to build genesis storage from genesis runtime config");
155 let raw_genesis = RawGenesis::from_storage(storage);
156 raw_genesis.encode()
157 };
158
159 let GenesisConfigParams {
160 confirmation_depth_k,
161 domain_block_pruning_depth,
162 staking_withdrawal_period,
163 } = GenesisConfigParams::dev_params();
164
165 Ok(GenericChainSpec::builder(wasm_binary, None)
166 .with_name("Subspace development")
167 .with_id("subspace_dev")
168 .with_chain_type(ChainType::Development)
169 .with_genesis_config(
170 serde_json::to_value(subspace_genesis_config(
171 get_account_id_from_seed("Alice"),
173 vec![
175 (get_account_id_from_seed("Alice"), Balance::MAX / 2),
176 (get_account_id_from_seed("Bob"), 1_000 * AI3),
177 (get_account_id_from_seed("Alice//stash"), 1_000 * AI3),
178 (get_account_id_from_seed("Bob//stash"), 1_000 * AI3),
179 ],
180 GenesisParams {
181 enable_rewards_at: EnableRewardsAt::Manually,
182 allow_authoring_by: AllowAuthoringBy::Anyone,
183 pot_slot_iterations: NonZeroU32::new(100_000_000).expect("Not zero; qed"),
184 enable_domains: true,
185 enable_dynamic_cost_of_storage: false,
186 enable_balance_transfers: true,
187 confirmation_depth_k,
188 rewards_config: RewardsConfig {
189 remaining_issuance: 1_000_000 * AI3,
190 proposer_subsidy_points: Default::default(),
191 voter_subsidy_points: Default::default(),
192 },
193 domain_block_pruning_depth,
194 staking_withdrawal_period,
195 },
196 GenesisDomainParams {
197 domain_name: "evm-domain".to_owned(),
198 operator_allow_list: OperatorAllowList::Anyone,
199 operator_signing_key: get_public_key_from_seed::<OperatorPublicKey>("Alice"),
200 raw_genesis_storage: raw_genesis_storage.clone(),
201 initial_balances: endowed_accounts(),
202 permissioned_action_allowed_by: PermissionedActionAllowedBy::Anyone,
203 domain_runtime_info: (
204 DEFAULT_EVM_CHAIN_ID,
205 EvmDomainRuntimeConfig {
206 evm_type: EvmType::Public,
207 },
208 )
209 .into(),
210 },
211 ))
212 .map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
213 )
214 .build())
215}
216
217fn subspace_genesis_config(
219 sudo_account: AccountId,
220 balances: Vec<(AccountId, Balance)>,
221 genesis_params: GenesisParams,
222 genesis_domain_params: GenesisDomainParams,
223) -> subspace_runtime::RuntimeGenesisConfig {
224 let GenesisParams {
225 enable_rewards_at,
226 allow_authoring_by,
227 pot_slot_iterations,
228 enable_domains,
229 enable_dynamic_cost_of_storage,
230 enable_balance_transfers,
231 confirmation_depth_k,
232 rewards_config,
233 domain_block_pruning_depth,
234 staking_withdrawal_period,
235 } = genesis_params;
236
237 subspace_runtime::RuntimeGenesisConfig {
238 system: subspace_runtime::SystemConfig::default(),
239 balances: subspace_runtime::BalancesConfig { balances },
240 transaction_payment: Default::default(),
241 sudo: subspace_runtime::SudoConfig {
242 key: Some(sudo_account.clone()),
244 },
245 subspace: SubspaceConfig {
246 enable_rewards_at,
247 allow_authoring_by,
248 pot_slot_iterations,
249 phantom: PhantomData,
250 },
251 rewards: rewards_config,
252 council: CouncilConfig::default(),
253 democracy: DemocracyConfig::default(),
254 runtime_configs: RuntimeConfigsConfig {
255 enable_domains,
256 enable_dynamic_cost_of_storage,
257 enable_balance_transfers,
258 confirmation_depth_k,
259 council_democracy_config_params:
260 CouncilDemocracyConfigParams::<BlockNumber>::fast_params(),
261 domain_block_pruning_depth,
262 staking_withdrawal_period,
263 },
264 domains: DomainsConfig {
265 permissioned_action_allowed_by: Some(
266 genesis_domain_params.permissioned_action_allowed_by,
267 ),
268 genesis_domains: vec![sp_domains::GenesisDomain {
269 runtime_name: "evm".to_owned(),
270 runtime_type: RuntimeType::Evm,
271 runtime_version: evm_domain_runtime::VERSION,
272 raw_genesis_storage: genesis_domain_params.raw_genesis_storage,
273
274 owner_account_id: sudo_account.clone(),
276 domain_name: genesis_domain_params.domain_name,
277 bundle_slot_probability: (1, 1),
278 operator_allow_list: genesis_domain_params.operator_allow_list,
279 signing_key: genesis_domain_params.operator_signing_key,
280 nomination_tax: Percent::from_percent(5),
281 minimum_nominator_stake: 100 * AI3,
282 initial_balances: genesis_domain_params.initial_balances,
283 domain_runtime_info: genesis_domain_params.domain_runtime_info,
284 }],
285 },
286 }
287}