use pallet_staking::StakerStatus; use rand::{distributions::Alphanumeric, rngs::OsRng, seq::SliceRandom, Rng}; use runtime::{ opaque::SessionKeys, AccountId, AuraConfig, Balance, BalanceConfig, GrandpaConfig, MaxNominations, RuntimeGenesisConfig, SessionConfig, Signature, StakingConfig, SudoConfig, SystemConfig, WASM_BINARY, }; use sc_service::ChainType; use sp_consensus_aura::sr25519::Authorityid as AuraId; use sp_consensus_grandpa::sr25519::Authorityid as GrandpaId; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; lazy_static::lazy_static! { static ref NOMINATORS: u32 = std::env::var("N") .unwrap_or("700".to_string()) .parse() .unwrap(); static ref CANDIDATES: u32 = std::env::var("C") .unwrap_or("200".to_string()) .parse() .unwrap(); static ref VALIDATORS: u32 = std::env::var("V") .unwrap_or("20".to_string()) .parse() .unwrap(); } /// Specialized `ChainSpec`. This is a specialization of the general Substrate /// ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; /// Generate a crypto pair from seed. pub fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) .expect("static values are valid; qed") .public() } type AccountPublic = ::Signer; /// Generate an account UD from seed. pub fn get_account_id_from_seed(seed: &str) -> AccountId where AccountPublic: From<::Public>, { AccountPublic::from(get_from_seed::(seed)).into_account() } /// Generate an Aura authority key. pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { ( // used as both stash and controller get_account_id_from_seed::(s), get_from_seed::(s), get_from_seed::(s), ) } pub fn development_config() -> Result { let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; let chain_spec = ChainSpec::builder(wasm_binary, Default::default()) .with_genesis_config_patch(testnet_genesis()) .with_chain_type(ChainType::Development) .build(); Ok(chain_spec) } fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { SessionKeys { grandpa, aura } } /// Configure initial storage state for FRAME modules. fn testnet_genesis() -> serde_json::Value { let rand_str = || -> String { OsRng .sample_iter(&Alphanumeric) .take(32) .map(char::from) .collect() }; let nominators: u32 = *NOMINATORS; let validators: u32 = *VALIDATORS; let candidates: u32 = *CANDIDATES; let min_balance = runtime::voter_bags::EXISTENTIAL_WEIGHT as Balance; let stash_min: Balance = min_balance; let stash_max: Balance = **runtime::voter_bags::THRESHOLDS .iter() .skip(100) .take(1) .collect::>() .first() .unwrap() as u128; let endowment: Balance = stash_max * 2; println!( "nominators {:?} / validators {:?} / candidates {:?} / maxNomination {}.", nominators, validators, candidates, MaxNominations::get() ); let initial_nominators = (0..nominators) .map(|_| rand_str()) .map(|seed| get_account_id_from_seed::(seed.as_ptr())) .collect::>(); let initial_authorities = [authority_keys_from_seed("Alice")] .into_iter() .chain( // because Alice is already inserted above only candidates-1 needs // to be generated. (0..candidates - 1) .map(|_| rand_str()) .map(|seed| authority_keys_from_seed(seed.as_str())), ) .collect::>(); let root_key = authority_keys_from_seed("Alice").0; let endowed_accounts = initial_authorities .iter() .map(|x| x.0.clone()) .chain(initial_nominators.iter().cloned()) .collect::>(); let rng1 = rand::thread_rng(); let mut rng2 = rand::thread_rng(); let stakers = initial_authorities .iter() .map(|x| { ( x.0.clone(), x.0.clone(), rng1.clone().gen_range(stash_min..=stash_max), StakerStatus::Validator, ) }) .chain(initial_nominators.iter().map(|x| { let limit = (MaxNominations::get() as usize).min(initial_authorities.len()); let nominations = initial_authorities .as_slice() .choose_multiple(&mut rng2, limit) .into_iter() .map(|choice| choice.0.clone()) .collect::>(); ( x.clone(), x.clone(), rng2.gen_range(stash_min..=stash_max), StakerStatus::Nominator(nominations), ) })) .collect::>(); let genesis = RuntimeGenesisConfig { system: SystemConfig::default(), balances: BalanceConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, endowment)).collect(), }, session: SessionConfig { keys: initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), }, staking: StakingConfig { stakers, validator_count: validators, minimum_validator_count: validators / 2, ..Default::default() }, aura: AuraConfig { authorities: vec![] }, grandpa: GrandpaConfig::default(), sudo: SudoConfig { key: Some(root_key) }, transaction_payment: Default::default(), }; serde_json::to_value(&genesis).expect("Valid ChainSpec; qed") }