subspace_test_client/
evm_domain_chain_spec.rs

1//! Chain specification for the evm domain.
2
3use crate::chain_spec::get_from_seed;
4use domain_runtime_primitives::AccountId20Converter;
5use evm_domain_test_runtime::{
6    AccountId as AccountId20, Precompiles, RuntimeGenesisConfig, Signature,
7};
8use parity_scale_codec::Encode;
9use sc_chain_spec::{ChainType, GenericChainSpec, NoExtension};
10use sp_core::{ecdsa, Pair, Public};
11use sp_domains::storage::RawGenesis;
12use sp_domains::{
13    DomainId, EvmDomainRuntimeConfig, EvmType, GenesisDomain, OperatorAllowList, OperatorPublicKey,
14    RuntimeType,
15};
16use sp_runtime::traits::{Convert, IdentifyAccount, Verify};
17use sp_runtime::{BuildStorage, Percent};
18use subspace_runtime_primitives::{AccountId, Balance, SSC};
19
20type AccountPublic = <Signature as Verify>::Signer;
21
22/// Helper function to generate an account ID from seed.
23pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId20
24where
25    AccountPublic: From<<TPublic::Pair as Pair>::Public>,
26{
27    AccountPublic::from(
28        TPublic::Pair::from_string(&format!("//{seed}"), None)
29            .expect("static values are valid; qed")
30            .public(),
31    )
32    .into_account()
33}
34
35pub(crate) fn endowed_accounts() -> Vec<AccountId20> {
36    vec![
37        get_account_id_from_seed::<ecdsa::Public>("Alice"),
38        get_account_id_from_seed::<ecdsa::Public>("Bob"),
39        get_account_id_from_seed::<ecdsa::Public>("Charlie"),
40        get_account_id_from_seed::<ecdsa::Public>("Dave"),
41        get_account_id_from_seed::<ecdsa::Public>("Eve"),
42        get_account_id_from_seed::<ecdsa::Public>("Ferdie"),
43        get_account_id_from_seed::<ecdsa::Public>("Alice//stash"),
44        get_account_id_from_seed::<ecdsa::Public>("Bob//stash"),
45        get_account_id_from_seed::<ecdsa::Public>("Charlie//stash"),
46        get_account_id_from_seed::<ecdsa::Public>("Dave//stash"),
47        get_account_id_from_seed::<ecdsa::Public>("Eve//stash"),
48        get_account_id_from_seed::<ecdsa::Public>("Ferdie//stash"),
49    ]
50}
51
52/// Get the genesis config of the evm domain
53pub fn testnet_evm_genesis() -> RuntimeGenesisConfig {
54    // This is the simplest bytecode to revert without returning any data.
55    // We will pre-deploy it under all of our precompiles to ensure they can be called from
56    // within contracts.
57    // (PUSH1 0x00 PUSH1 0x00 REVERT)
58    let revert_bytecode = vec![0x60, 0x00, 0x60, 0x00, 0xFD];
59
60    RuntimeGenesisConfig {
61        system: evm_domain_test_runtime::SystemConfig::default(),
62        balances: evm_domain_test_runtime::BalancesConfig::default(),
63        evm_chain_id: evm_domain_test_runtime::EVMChainIdConfig {
64            chain_id: 100,
65            ..Default::default()
66        },
67        evm: evm_domain_test_runtime::EVMConfig {
68            // We need _some_ code inserted at the precompile address so that
69            // the evm will actually call the address.
70            accounts: Precompiles::used_addresses()
71                .into_iter()
72                .map(|addr| {
73                    (
74                        addr,
75                        fp_evm::GenesisAccount {
76                            nonce: Default::default(),
77                            balance: Default::default(),
78                            storage: Default::default(),
79                            code: revert_bytecode.clone(),
80                        },
81                    )
82                })
83                .collect(),
84            ..Default::default()
85        },
86        self_domain_id: evm_domain_test_runtime::SelfDomainIdConfig {
87            // Set the domain id of the genesis domain to an arbitrary value
88            // it should be overwritten with the correct value
89            domain_id: Some(DomainId::new(123)),
90            ..Default::default()
91        },
92        ..Default::default()
93    }
94}
95
96pub fn get_genesis_domain(
97    sudo_account: subspace_runtime_primitives::AccountId,
98    evm_type: EvmType,
99) -> Result<GenesisDomain<AccountId, Balance>, String> {
100    let raw_genesis_storage = {
101        let domain_chain_spec = GenericChainSpec::<NoExtension, ()>::builder(
102            evm_domain_test_runtime::WASM_BINARY
103                .ok_or_else(|| "Development wasm not available".to_string())?,
104            None,
105        )
106        .with_chain_type(ChainType::Development)
107        .with_genesis_config(
108            serde_json::to_value(testnet_evm_genesis())
109                .map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
110        )
111        .build();
112        let storage = domain_chain_spec
113            .build_storage()
114            .expect("Failed to build genesis storage from genesis runtime config");
115        let raw_genesis = RawGenesis::from_storage(storage);
116        raw_genesis.encode()
117    };
118
119    Ok(GenesisDomain {
120        runtime_name: "evm".to_owned(),
121        runtime_type: RuntimeType::Evm,
122        runtime_version: evm_domain_test_runtime::VERSION,
123        raw_genesis_storage,
124
125        // Domain config, mainly for placeholder the concrete value TBD
126        owner_account_id: sudo_account,
127        domain_name: "evm-domain".to_owned(),
128        bundle_slot_probability: (1, 1),
129        operator_allow_list: OperatorAllowList::Anyone,
130
131        signing_key: get_from_seed::<OperatorPublicKey>("Alice"),
132        minimum_nominator_stake: 100 * SSC,
133        nomination_tax: Percent::from_percent(5),
134        initial_balances: endowed_accounts()
135            .iter()
136            .cloned()
137            .map(|k| (AccountId20Converter::convert(k), 2_000_000 * SSC))
138            .collect(),
139
140        domain_runtime_config: EvmDomainRuntimeConfig { evm_type }.into(),
141    })
142}