use codec::Encode; use pallet_staking::Forcing; use sp_staking::StakerStatus; use crate::{opaque::SessionKeys, BABE_GENESIS_EPOCH_CONFIG}; use primitives::{AccountId, AccountPublic}; use casper_runtime_constants::currency::CSPR; use ghost_slow_clap::sr25519::AuthorityId as SlowClapId; use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; use babe_primitives::AuthorityId as BabeId; use grandpa_primitives::AuthorityId as GrandpaId; #[cfg(not(feature = "std"))] use sp_std::alloc::format; use sp_std::vec::Vec; use sp_std::prelude::*; use sp_core::{sr25519, Pair, Public}; use sp_runtime::{Perbill, traits::IdentifyAccount}; #[derive(Encode, Clone)] struct PreparedNetworkData { chain_name: Vec, default_endpoint: Vec, finality_delay: Option, release_delay: Option, network_type: u8, gatekeeper: Vec, topic_name: Vec, incoming_fee: u32, outgoing_fee: u32, } fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) .expect("static values are valid; qed") .public() } fn get_account_id_from_seed(seed: &str) -> AccountId where AccountPublic: From<::Public>, { AccountPublic::from(get_from_seed::(seed)).into_account() } fn get_authority_keys_from_seed( seed: &str, ) -> ( AccountId, AccountId, BabeId, GrandpaId, AuthorityDiscoveryId, SlowClapId, ) { ( get_account_id_from_seed::(&format!("{}//stash", seed)), get_account_id_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), ) } fn casper_testnet_accounts() -> Vec { Vec::from([ get_account_id_from_seed::("Alice"), get_account_id_from_seed::("Bob"), get_account_id_from_seed::("Charlie"), get_account_id_from_seed::("Dave"), get_account_id_from_seed::("Eve"), get_account_id_from_seed::("Feride"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Feride//stash"), ]) } fn casper_testnet_evm_accounts() -> Vec<(AccountId, u128, u8)> { vec![ // 01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198 (get_account_id_from_seed::("1A69d2D5568D1878023EeB121a73d33B9116A760"), 1337 * CSPR, 1), // b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139 (get_account_id_from_seed::("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12"), 1337 * CSPR, 2), // d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc (get_account_id_from_seed::("e83f67361Ac74D42A48E2DAfb6706eb047D8218D"), 69 * CSPR, 3), // c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4 (get_account_id_from_seed::("827ee4ad9b259b6fa1390ed60921508c78befd63"), 69 * CSPR, 4), ] } fn casper_testnet_evm_networks() -> Vec<(u32, Vec)> { vec![ (1, PreparedNetworkData { chain_name: "ethereum-mainnet".into(), default_endpoint: "https://nd-422-757-666.p2pify.com/0a9d79d93fb2f4a4b1e04695da2b77a7/".into(), finality_delay: Some(40), release_delay: Some(80), network_type: Default::default(), gatekeeper: "0x4d224452801aced8b2f0aebe155379bb5d594381".into(), topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".into(), incoming_fee: 0, outgoing_fee: 0, }.encode()), (56, PreparedNetworkData { chain_name: "bnb-mainnet".into(), default_endpoint: "https://bsc-mainnet.core.chainstack.com/35848e183f3e3303c8cfeacbea831cab/".into(), finality_delay: Some(20), release_delay: Some(40), network_type: Default::default(), gatekeeper: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82".into(), topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".into(), incoming_fee: 0, outgoing_fee: 0, }.encode()) ] } fn casper_session_keys( babe: BabeId, grandpa: GrandpaId, authority_discovery: AuthorityDiscoveryId, slow_clap: SlowClapId, ) -> SessionKeys { SessionKeys { babe, grandpa, authority_discovery, slow_clap } } fn testnet_config_genesis( initial_authorities: Vec<( AccountId, AccountId, BabeId, GrandpaId, AuthorityDiscoveryId, SlowClapId, )>, endowed_accounts: Option>, ghost_accounts: Option>, evm_networks: Option)>>, ) -> serde_json::Value { let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(casper_testnet_accounts); let ghost_accounts: Vec<(AccountId, u128, u8)> = ghost_accounts.unwrap_or_else(casper_testnet_evm_accounts); let evm_networks: Vec<(u32, Vec)> = evm_networks.unwrap_or_else(casper_testnet_evm_networks); const ENDOWMENT: u128 = 1_000 * CSPR; const STASH: u128 = 500 * CSPR; serde_json::json!({ "balances": { "balances": endowed_accounts .iter() .map(|k| (k.clone(), ENDOWMENT)) .chain(ghost_accounts .iter() .map(|k| (k.0.clone(), k.1.clone()))) .collect::>(), }, "session": { "keys": initial_authorities .iter() .map(|x| { ( x.0.clone(), x.0.clone(), casper_session_keys( x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone(), ), ) }) .collect::>(), }, "staking": { "validatorCount": initial_authorities.len() as u32, "minimumValidatorCount": 1, "invulnerables": initial_authorities .iter() .map(|x| x.0.clone()) .collect::>(), "forceEra": Forcing::NotForcing, "slashRewardFraction": Perbill::from_percent(10), "stakers": initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), STASH, StakerStatus::::Validator)) .collect::>(), }, "babe": { "epochConfig": Some(BABE_GENESIS_EPOCH_CONFIG), }, "ghostNetworks": { "networks": evm_networks, }, "ghostClaims": { "total": ghost_accounts .iter() .fold(0, |acc, k| acc + k.1), "membersAndRanks": ghost_accounts .iter() .map(|k| (k.0.clone(), k.2.clone())) .collect::>(), }, }) } // staging fn casper_staging_config_genesis() -> serde_json::Value { use hex_literal::hex; use sp_core::crypto::UncheckedInto; // Following keys are used in genesis config for testing (casper) chains. // DO NOT use them in production chains such as ghost. let endowed_accounts = vec![ // sfErNwRgZ6ypB7wY8M2smXMZjxqUkc2TgUcNvC1JNQJFXS8bw hex!["328d3b7c3046ef7700937d99fb2e98ce2591682c2b5dcf3f562e4da157650237"].into(), // sfEwRjyvEQcpRQ1qbCZum27nEkTggKEt7DtqxwyYQULt9UuUN hex!["3666e4e19f87bb8680495f31864ce1f1c69d4178002cc01911aef2cc7313f203"].into(), // sfHcJxw5cgkvukZZyxcNUMCdbm9e7773orByLrGgAREka81TK hex!["ac871e8bab00dd56ba3a1c0bd289357203dcaf10010b0b04ad7472870cd22a3c"].into(), ]; let initial_authorities: Vec<( AccountId, AccountId, BabeId, GrandpaId, AuthorityDiscoveryId, SlowClapId, )> = vec![ ( // sfFXZmnDVnkQ781J2gbqUpi7K5KgMWMdM4eeii74xxGgKYnNN hex!["507045c82be367f95408466cd054ca39bfa52697a3ef22809af14cf9de304f02"].into(), // sfFXZmnDVnkQ781J2gbqUpi7K5KgMWMdM4eeii74xxGgKYnNN hex!["507045c82be367f95408466cd054ca39bfa52697a3ef22809af14cf9de304f02"].into(), // sfJeojACBa7WiH6tBwikBKAMU2oKmseEBD1GYUYATvfWuLcPa hex!["daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f"].unchecked_into(), // sfFdtzNxJdeEkgHxvk144rJKxf7wcYvgX5tqfgZRutW9YvAKE hex!["55446f9a7aa99ced06b317c80ce90d56b84e56526775683af2525969e8da0b64"].unchecked_into(), // sfE8gsMYAjAJHk5gyYZN7AW6pfmJ7V9H7xxWto24nmhzCUXaQ hex!["12c14850562021eb99f58f90ab624fb6cfaf3ac9228a92f8b60115fe6a6af15a"].unchecked_into(), // sfE3GKSrKZzrZpdapJ2VGRpPor45T4D4i8QBZNumSNGqGv7PX hex!["0e9e698c7b2bf5ce3861cb4bc4ddf9e200237c282025b093ada850d764d12a35"].unchecked_into(), ), ( // sfHLqWNC4hMKHhwvPWmWcxZsDPhCTQKgh1Ap7pm3qML5GBTBa hex!["a0ba0196e6ee7e6b5b0553035c5cb5c04e9725001b5732839d0529cbc00c9600"].into(), // sfHLqWNC4hMKHhwvPWmWcxZsDPhCTQKgh1Ap7pm3qML5GBTBa hex!["a0ba0196e6ee7e6b5b0553035c5cb5c04e9725001b5732839d0529cbc00c9600"].into(), // sfGA6tPPF8dAc8QpMCMjxitG3j8sXPhkdpm5bwz4UsXAApUiw hex!["6c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e49"].unchecked_into(), // sfGxQZXFUQH1AXv82rpjiJHFs7YsdEuVGdyvKiS2Tajpvw6Se hex!["8f9ea20bf4a807a8e710f7559dece86e94672b5b361de157bdaa5c1f37849f8d"].unchecked_into(), // sfGz2enFUR22cQ5ey61MdtPqbCeEWZA1wsCFFSLGaK7vKnv8C hex!["90db5ed339a559ed157995a48d781f44c7df972dfba4bc855e4b59fa46438e17"].unchecked_into(), // sfEtwe5BoroNjkdLsvnjnMemUKiw8MS1X4YW8bepbbGvhS4LZ hex!["3481cdcbcf37a4669c29a78cf9ceb39383a10ef0a18b36b92d149fdd0c24ae00"].unchecked_into(), ), ( // sfGq75CrCrkcfqNzyyidu3D4jW3AoJSzL5tKKuv1UbS16ezzy hex!["8a0d0b66e827bf20e79f9a499317e73925ce4f422371067edfab690e43857f13"].into(), // sfGq75CrCrkcfqNzyyidu3D4jW3AoJSzL5tKKuv1UbS16ezzy hex!["8a0d0b66e827bf20e79f9a499317e73925ce4f422371067edfab690e43857f13"].into(), // sfJo2ogBpssRAU9ZPTvuXFZEdmJw9pKsPydLjXe8DypRScjzT hex!["e0f0a776ecc9fa5e1f22e2fa001fe3fba5aea52b9444bc894b45589d42132475"].unchecked_into(), // sfHq3EVT1sqY7o5ki3zA6LEdRDfdFc29YaZN3w2Thhz6JD5ZF hex!["b63c5a0cf342b9b04931bc8ed74d7d0165ab99ab5f8a4514797d4b299a4501fe"].unchecked_into(), // sfEj3wrDy9EDLCAodyEdQEYxJpNnM8Etaj3RJ5bCBRzdaDced hex!["2cf69452e9f2a8457119139408884941ed50f590c0fc0f2b044c4d82c69e4245"].unchecked_into(), // sfE32RmBp1xX4KRTphVGLUJBxLGPN3Dzg9BwCJktxMf3iEwck hex!["0e6fa6934f9e99fa84874f2ed9318825a0d5443a0ced984acfbd24ece72ba55e"].unchecked_into(), ), ]; let ghost_accounts: Vec<(AccountId, u128, u8)> = casper_testnet_evm_accounts(); let evm_networks = casper_testnet_evm_networks(); const ENDOWMENT: u128 = 5_000 * CSPR; const STASH: u128 = 500 * CSPR; serde_json::json!({ "balances": { "balances": endowed_accounts .iter() .map(|k: &AccountId| (k.clone(), ENDOWMENT)) .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) .collect::>(), }, "session": { "keys": initial_authorities .iter() .map(|x| { ( x.0.clone(), x.0.clone(), casper_session_keys( x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone(), ), ) }) .collect::>(), }, "staking": { "validatorCount": 50, "minimumValidatorCount": 4, "stakers": initial_authorities .iter() .map(|x| { ( x.0.clone(), x.0.clone(), STASH, StakerStatus::::Validator, ) }) .collect::>(), "invulnerables": initial_authorities.iter().map(|x| x.0.clone()).collect::>(), "forceEra": Forcing::ForceNone, "slashRewardFraction": Perbill::from_percent(10) }, "babe": { "epochConfig": Some(BABE_GENESIS_EPOCH_CONFIG), }, "ghostNetworks": { "networks": evm_networks, }, "ghostClaims": { "total": ghost_accounts .iter() .fold(0, |acc, k| acc + k.1), "membersAndRanks": ghost_accounts .iter() .map(|k| (k.0.clone(), k.2.clone())) .collect::>(), }, }) } // development fn casper_development_config_genesis() -> serde_json::Value { testnet_config_genesis( vec![get_authority_keys_from_seed("Alice")], None, None, None, ) } // local fn casper_local_config_genesis() -> serde_json::Value { testnet_config_genesis( vec![ get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob"), ], None, None, None, ) } /// Provides the JSON representation of predefined genesis config for given `id`. pub fn get_preset(id: &sp_genesis_builder::PresetId) -> Option> { let patch = match id.try_into() { Ok("development") => casper_development_config_genesis(), Ok("staging") => casper_staging_config_genesis(), Ok("local_testnet") => casper_local_config_genesis(), _ => return None, }; Some(serde_json::to_string(&patch) .expect("serialization to json is expected to work; qed") .into_bytes()) } /// Returns a list of identifiers for available builtin `RuntimeGenesisConfig` presets. pub fn preset_names() -> Vec { Vec::from([ sp_genesis_builder::PresetId::from("local_testnet"), sp_genesis_builder::PresetId::from("development"), sp_genesis_builder::PresetId::from("staging"), ]) }