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::{sr25519, Pair, Public};
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 AccountId, Balance, BlockNumber, CouncilDemocracyConfigParams, SSC,
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 * SSC))
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}
134
135struct GenesisDomainParams {
136 domain_name: String,
137 operator_allow_list: OperatorAllowList<AccountId>,
138 operator_signing_key: OperatorPublicKey,
139 raw_genesis_storage: Vec<u8>,
140 initial_balances: Vec<(MultiAccountId, Balance)>,
141 permissioned_action_allowed_by: PermissionedActionAllowedBy<AccountId>,
142 domain_runtime_config: DomainRuntimeConfig,
143}
144
145pub fn dev_config() -> Result<GenericChainSpec, String> {
146 let wasm_binary = subspace_runtime::WASM_BINARY
147 .ok_or_else(|| "Development wasm not available".to_string())?;
148
149 let raw_genesis_storage = {
150 let domain_genesis_config = domain_dev_config()?;
151 let storage = domain_genesis_config
152 .build_storage()
153 .expect("Failed to build genesis storage from genesis runtime config");
154 let raw_genesis = RawGenesis::from_storage(storage);
155 raw_genesis.encode()
156 };
157
158 Ok(GenericChainSpec::builder(wasm_binary, None)
159 .with_name("Subspace development")
160 .with_id("subspace_dev")
161 .with_chain_type(ChainType::Development)
162 .with_genesis_config(
163 serde_json::to_value(subspace_genesis_config(
164 get_account_id_from_seed("Alice"),
166 vec![
168 (get_account_id_from_seed("Alice"), Balance::MAX / 2),
169 (get_account_id_from_seed("Bob"), 1_000 * SSC),
170 (get_account_id_from_seed("Alice//stash"), 1_000 * SSC),
171 (get_account_id_from_seed("Bob//stash"), 1_000 * SSC),
172 ],
173 GenesisParams {
174 enable_rewards_at: EnableRewardsAt::Manually,
175 allow_authoring_by: AllowAuthoringBy::Anyone,
176 pot_slot_iterations: NonZeroU32::new(100_000_000).expect("Not zero; qed"),
177 enable_domains: true,
178 enable_dynamic_cost_of_storage: false,
179 enable_balance_transfers: true,
180 confirmation_depth_k: 5,
181 rewards_config: RewardsConfig {
182 remaining_issuance: 1_000_000 * SSC,
183 proposer_subsidy_points: Default::default(),
184 voter_subsidy_points: Default::default(),
185 },
186 },
187 GenesisDomainParams {
188 domain_name: "evm-domain".to_owned(),
189 operator_allow_list: OperatorAllowList::Anyone,
190 operator_signing_key: get_public_key_from_seed::<OperatorPublicKey>("Alice"),
191 raw_genesis_storage: raw_genesis_storage.clone(),
192 initial_balances: endowed_accounts(),
193 permissioned_action_allowed_by: PermissionedActionAllowedBy::Anyone,
194 domain_runtime_config: DomainRuntimeConfig::default_evm(),
195 },
196 ))
197 .map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
198 )
199 .build())
200}
201
202fn subspace_genesis_config(
204 sudo_account: AccountId,
205 balances: Vec<(AccountId, Balance)>,
206 genesis_params: GenesisParams,
207 genesis_domain_params: GenesisDomainParams,
208) -> subspace_runtime::RuntimeGenesisConfig {
209 let GenesisParams {
210 enable_rewards_at,
211 allow_authoring_by,
212 pot_slot_iterations,
213 enable_domains,
214 enable_dynamic_cost_of_storage,
215 enable_balance_transfers,
216 confirmation_depth_k,
217 rewards_config,
218 } = genesis_params;
219
220 subspace_runtime::RuntimeGenesisConfig {
221 system: subspace_runtime::SystemConfig::default(),
222 balances: subspace_runtime::BalancesConfig { balances },
223 transaction_payment: Default::default(),
224 sudo: subspace_runtime::SudoConfig {
225 key: Some(sudo_account.clone()),
227 },
228 subspace: SubspaceConfig {
229 enable_rewards_at,
230 allow_authoring_by,
231 pot_slot_iterations,
232 phantom: PhantomData,
233 },
234 rewards: rewards_config,
235 council: CouncilConfig::default(),
236 democracy: DemocracyConfig::default(),
237 runtime_configs: RuntimeConfigsConfig {
238 enable_domains,
239 enable_dynamic_cost_of_storage,
240 enable_balance_transfers,
241 confirmation_depth_k,
242 council_democracy_config_params:
243 CouncilDemocracyConfigParams::<BlockNumber>::fast_params(),
244 },
245 domains: DomainsConfig {
246 permissioned_action_allowed_by: Some(
247 genesis_domain_params.permissioned_action_allowed_by,
248 ),
249 genesis_domains: vec![sp_domains::GenesisDomain {
250 runtime_name: "evm".to_owned(),
251 runtime_type: RuntimeType::Evm,
252 runtime_version: evm_domain_runtime::VERSION,
253 raw_genesis_storage: genesis_domain_params.raw_genesis_storage,
254
255 owner_account_id: sudo_account.clone(),
257 domain_name: genesis_domain_params.domain_name,
258 bundle_slot_probability: (1, 1),
259 operator_allow_list: genesis_domain_params.operator_allow_list,
260 signing_key: genesis_domain_params.operator_signing_key,
261 nomination_tax: Percent::from_percent(5),
262 minimum_nominator_stake: 100 * SSC,
263 initial_balances: genesis_domain_params.initial_balances,
264 domain_runtime_config: genesis_domain_params.domain_runtime_config,
265 }],
266 },
267 }
268}