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, DEFAULT_EVM_CHAIN_ID};
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::{Pair, Public, ecdsa};
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::{AI3, AccountId, Balance};
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                .map(|addr| {
72                    (
73                        addr.into(),
74                        fp_evm::GenesisAccount {
75                            nonce: Default::default(),
76                            balance: Default::default(),
77                            storage: Default::default(),
78                            code: revert_bytecode.clone(),
79                        },
80                    )
81                })
82                .collect(),
83            ..Default::default()
84        },
85        self_domain_id: evm_domain_test_runtime::SelfDomainIdConfig {
86            // Set the domain id of the genesis domain to an arbitrary value
87            // it should be overwritten with the correct value
88            domain_id: Some(DomainId::new(123)),
89            ..Default::default()
90        },
91        ..Default::default()
92    }
93}
94
95pub fn get_genesis_domain(
96    sudo_account: subspace_runtime_primitives::AccountId,
97    evm_type: EvmType,
98) -> Result<GenesisDomain<AccountId, Balance>, String> {
99    let raw_genesis_storage = {
100        let domain_chain_spec = GenericChainSpec::<NoExtension, ()>::builder(
101            evm_domain_test_runtime::WASM_BINARY
102                .ok_or_else(|| "Development wasm not available".to_string())?,
103            None,
104        )
105        .with_chain_type(ChainType::Development)
106        .with_genesis_config(
107            serde_json::to_value(testnet_evm_genesis())
108                .map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
109        )
110        .build();
111        let storage = domain_chain_spec
112            .build_storage()
113            .expect("Failed to build genesis storage from genesis runtime config");
114        let raw_genesis = RawGenesis::from_storage(storage);
115        raw_genesis.encode()
116    };
117
118    Ok(GenesisDomain {
119        runtime_name: "evm".to_owned(),
120        runtime_type: RuntimeType::Evm,
121        runtime_version: evm_domain_test_runtime::VERSION,
122        raw_genesis_storage,
123
124        // Domain config, mainly for placeholder the concrete value TBD
125        owner_account_id: sudo_account,
126        domain_name: "evm-domain".to_owned(),
127        bundle_slot_probability: (1, 1),
128        operator_allow_list: OperatorAllowList::Anyone,
129
130        signing_key: get_from_seed::<OperatorPublicKey>("Alice"),
131        minimum_nominator_stake: 100 * AI3,
132        nomination_tax: Percent::from_percent(5),
133        initial_balances: endowed_accounts()
134            .iter()
135            .cloned()
136            .map(|k| (AccountId20Converter::convert(k), 2_000_000 * AI3))
137            .collect(),
138
139        domain_runtime_info: (DEFAULT_EVM_CHAIN_ID, EvmDomainRuntimeConfig { evm_type }).into(),
140    })
141}