subspace_test_client/
chain_spec.rs

1//! Chain specification for the test runtime.
2
3use sc_chain_spec::{ChainType, GenericChainSpec};
4use sp_core::{sr25519, Pair, Public};
5use sp_domains::{EvmType, PermissionedActionAllowedBy};
6use sp_runtime::traits::{IdentifyAccount, Verify};
7use std::marker::PhantomData;
8use std::num::NonZeroU32;
9use subspace_runtime_primitives::{AccountId, Balance, Signature, SSC};
10use subspace_test_runtime::{
11    AllowAuthoringBy, BalancesConfig, DomainsConfig, EnableRewardsAt, RewardsConfig,
12    RuntimeGenesisConfig, SubspaceConfig, SudoConfig, SystemConfig, WASM_BINARY,
13};
14
15/// Generate a crypto pair from seed.
16pub 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
22type AccountPublic = <Signature as Verify>::Signer;
23
24/// Generate an account ID from seed.
25pub fn get_account_id_from_seed(seed: &str) -> AccountId {
26    AccountPublic::from(get_from_seed::<sr25519::Public>(seed)).into_account()
27}
28
29/// Local testnet config (multivalidator Alice + Bob).
30///
31/// If `private_evm` is `true`, contract creation will have an allow list, which is set to `Anyone` by default.
32/// Otherwise, any account can create contracts, and the allow list can't be changed.
33///
34/// If the EVM owner account isn't specified, `sudo_account` will be used.
35pub fn subspace_local_testnet_config(
36    private_evm: bool,
37    evm_owner_account: Option<AccountId>,
38) -> Result<GenericChainSpec, String> {
39    let evm_type = if private_evm {
40        EvmType::Private {
41            initial_contract_creation_allow_list: PermissionedActionAllowedBy::Anyone,
42        }
43    } else {
44        EvmType::Public
45    };
46
47    let sudo_account = get_account_id_from_seed("Alice");
48    let evm_owner_account = evm_owner_account.unwrap_or_else(|| sudo_account.clone());
49
50    // Pre-funded accounts
51    // Alice and the EVM owner get more funds that are used during domain instantiation
52    let mut balances = vec![
53        (get_account_id_from_seed("Alice"), 1_000_000_000 * SSC),
54        (get_account_id_from_seed("Bob"), 1_000 * SSC),
55        (get_account_id_from_seed("Charlie"), 1_000 * SSC),
56        (get_account_id_from_seed("Dave"), 1_000 * SSC),
57        (get_account_id_from_seed("Eve"), 1_000 * SSC),
58        (get_account_id_from_seed("Ferdie"), 1_000 * SSC),
59        (get_account_id_from_seed("Alice//stash"), 1_000 * SSC),
60        (get_account_id_from_seed("Bob//stash"), 1_000 * SSC),
61        (get_account_id_from_seed("Charlie//stash"), 1_000 * SSC),
62        (get_account_id_from_seed("Dave//stash"), 1_000 * SSC),
63        (get_account_id_from_seed("Eve//stash"), 1_000 * SSC),
64        (get_account_id_from_seed("Ferdie//stash"), 1_000 * SSC),
65    ];
66
67    if let Some((_existing_account, balance)) = balances
68        .iter_mut()
69        .find(|(account_id, _balance)| account_id == &evm_owner_account)
70    {
71        *balance = 1_000_000_000 * SSC;
72    } else {
73        balances.push((evm_owner_account.clone(), 1_000_000_000 * SSC));
74    }
75
76    Ok(GenericChainSpec::builder(
77        WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
78        None,
79    )
80    .with_name("Local Testnet")
81    .with_id("local_testnet")
82    .with_chain_type(ChainType::Local)
83    .with_genesis_config(
84        serde_json::to_value(create_genesis_config(
85            // Sudo account
86            sudo_account,
87            balances,
88            evm_type,
89            evm_owner_account,
90        )?)
91        .map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
92    )
93    .with_protocol_id("subspace-test")
94    .build())
95}
96
97/// Configure initial storage state for FRAME modules.
98fn create_genesis_config(
99    sudo_account: AccountId,
100    balances: Vec<(AccountId, Balance)>,
101    evm_type: EvmType,
102    evm_owner_account: AccountId,
103) -> Result<RuntimeGenesisConfig, String> {
104    Ok(RuntimeGenesisConfig {
105        system: SystemConfig::default(),
106        balances: BalancesConfig { balances },
107        transaction_payment: Default::default(),
108        sudo: SudoConfig {
109            // Assign network admin rights.
110            key: Some(sudo_account.clone()),
111        },
112        subspace: SubspaceConfig {
113            enable_rewards_at: EnableRewardsAt::Manually,
114            allow_authoring_by: AllowAuthoringBy::Anyone,
115            pot_slot_iterations: NonZeroU32::new(50_000_000).expect("Not zero; qed"),
116            phantom: PhantomData,
117        },
118        rewards: RewardsConfig {
119            remaining_issuance: 1_000_000 * SSC,
120            proposer_subsidy_points: Default::default(),
121            voter_subsidy_points: Default::default(),
122        },
123        domains: DomainsConfig {
124            permissioned_action_allowed_by: Some(sp_domains::PermissionedActionAllowedBy::Anyone),
125            genesis_domains: vec![
126                crate::evm_domain_chain_spec::get_genesis_domain(evm_owner_account, evm_type)
127                    .expect("hard-coded values are valid; qed"),
128                crate::auto_id_domain_chain_spec::get_genesis_domain(sudo_account)
129                    .expect("hard-coded values are valid; qed"),
130            ],
131        },
132        runtime_configs: Default::default(),
133    })
134}