subspace_test_client/
chain_spec.rs

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