ghost-node/utils/staking-miner/playground/node/src/chain_spec.rs

188 lines
6.0 KiB
Rust
Raw Normal View History

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<RuntimeGenesisConfig>;
/// Generate a crypto pair from seed.
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}
type AccountPublic = <Signature as Verify>::Signer;
/// Generate an account UD from seed.
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(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::<sr25519::Public>(s),
get_from_seed::<AuraId>(s),
get_from_seed::<GrandpaId>(s),
)
}
pub fn development_config() -> Result<ChainSpec, String> {
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::<Vec<_>>()
.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::<sr25519::Public>(seed.as_ptr()))
.collect::<Vec<_>>();
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::<Vec<_>>();
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::<Vec<_>>();
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::<Vec<_>>();
(
x.clone(),
x.clone(),
rng2.gen_range(stash_min..=stash_max),
StakerStatus::Nominator(nominations),
)
}))
.collect::<Vec<_>>();
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::<Vec<_>>(),
},
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")
}