Add nominators option to chain-spec-builder (#8502)

* Add nominators option to chain-spec-builder

* Update bin/utils/chain-spec-builder/src/main.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Kian Paimani
2021-04-05 14:30:30 +02:00
committed by GitHub
parent 4e334f59d6
commit 6d26adce01
3 changed files with 98 additions and 52 deletions
+32 -15
View File
@@ -23,9 +23,9 @@ use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use node_runtime::{ use node_runtime::{
AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig,
DemocracyConfig,GrandpaConfig, ImOnlineConfig, SessionConfig, SessionKeys, StakerStatus, DemocracyConfig, GrandpaConfig, ImOnlineConfig, SessionConfig, SessionKeys, StakerStatus,
StakingConfig, ElectionsConfig, IndicesConfig, SocietyConfig, SudoConfig, SystemConfig, StakingConfig, ElectionsConfig, IndicesConfig, SocietyConfig, SudoConfig, SystemConfig,
TechnicalCommitteeConfig, wasm_binary_unwrap, TechnicalCommitteeConfig, wasm_binary_unwrap, MAX_NOMINATIONS,
}; };
use node_runtime::Block; use node_runtime::Block;
use node_runtime::constants::currency::*; use node_runtime::constants::currency::*;
@@ -146,12 +146,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
let endowed_accounts: Vec<AccountId> = vec![root_key.clone()]; let endowed_accounts: Vec<AccountId> = vec![root_key.clone()];
testnet_genesis( testnet_genesis(initial_authorities, vec![], root_key, Some(endowed_accounts), false)
initial_authorities,
root_key,
Some(endowed_accounts),
false,
)
} }
/// Staging testnet config. /// Staging testnet config.
@@ -214,6 +209,7 @@ pub fn testnet_genesis(
ImOnlineId, ImOnlineId,
AuthorityDiscoveryId, AuthorityDiscoveryId,
)>, )>,
initial_nominators: Vec<AccountId>,
root_key: AccountId, root_key: AccountId,
endowed_accounts: Option<Vec<AccountId>>, endowed_accounts: Option<Vec<AccountId>>,
enable_println: bool, enable_println: bool,
@@ -234,11 +230,31 @@ pub fn testnet_genesis(
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"), get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
] ]
}); });
initial_authorities.iter().for_each(|x| // endow all authorities and nominators.
if !endowed_accounts.contains(&x.0) { initial_authorities.iter().map(|x| &x.0).chain(initial_nominators.iter()).for_each(|x| {
endowed_accounts.push(x.0.clone()) if !endowed_accounts.contains(&x) {
endowed_accounts.push(x.clone())
} }
); });
// stakers: all validators and nominators.
let mut rng = rand::thread_rng();
let stakers = initial_authorities
.iter()
.map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator))
.chain(initial_nominators.iter().map(|x| {
use rand::{seq::SliceRandom, Rng};
let limit = (MAX_NOMINATIONS as usize).min(initial_authorities.len());
let count = rng.gen::<usize>() % limit;
let nominations = initial_authorities
.as_slice()
.choose_multiple(&mut rng, count)
.into_iter()
.map(|choice| choice.0.clone())
.collect::<Vec<_>>();
(x.clone(), x.clone(), STASH, StakerStatus::Nominator(nominations))
}))
.collect::<Vec<_>>();
let num_endowed_accounts = endowed_accounts.len(); let num_endowed_accounts = endowed_accounts.len();
@@ -271,11 +287,9 @@ pub fn testnet_genesis(
pallet_staking: StakingConfig { pallet_staking: StakingConfig {
validator_count: initial_authorities.len() as u32 * 2, validator_count: initial_authorities.len() as u32 * 2,
minimum_validator_count: initial_authorities.len() as u32, minimum_validator_count: initial_authorities.len() as u32,
stakers: initial_authorities.iter().map(|x| {
(x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)
}).collect(),
invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
slash_reward_fraction: Perbill::from_percent(10), slash_reward_fraction: Perbill::from_percent(10),
stakers,
.. Default::default() .. Default::default()
}, },
pallet_democracy: DemocracyConfig::default(), pallet_democracy: DemocracyConfig::default(),
@@ -335,6 +349,7 @@ fn development_config_genesis() -> GenesisConfig {
vec![ vec![
authority_keys_from_seed("Alice"), authority_keys_from_seed("Alice"),
], ],
vec![],
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
None, None,
true, true,
@@ -362,6 +377,7 @@ fn local_testnet_genesis() -> GenesisConfig {
authority_keys_from_seed("Alice"), authority_keys_from_seed("Alice"),
authority_keys_from_seed("Bob"), authority_keys_from_seed("Bob"),
], ],
vec![],
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
None, None,
false, false,
@@ -395,6 +411,7 @@ pub(crate) mod tests {
vec![ vec![
authority_keys_from_seed("Alice"), authority_keys_from_seed("Alice"),
], ],
vec![],
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
None, None,
false, false,
+4 -2
View File
@@ -472,8 +472,7 @@ parameter_types! {
} }
impl pallet_staking::Config for Runtime { impl pallet_staking::Config for Runtime {
const MAX_NOMINATIONS: u32 = const MAX_NOMINATIONS: u32 = MAX_NOMINATIONS;
<NposCompactSolution16 as sp_npos_elections::CompactSolution>::LIMIT as u32;
type Currency = Balances; type Currency = Balances;
type UnixTime = Timestamp; type UnixTime = Timestamp;
type CurrencyToVote = U128CurrencyToVote; type CurrencyToVote = U128CurrencyToVote;
@@ -527,6 +526,9 @@ sp_npos_elections::generate_solution_type!(
>(16) >(16)
); );
pub const MAX_NOMINATIONS: u32 =
<NposCompactSolution16 as sp_npos_elections::CompactSolution>::LIMIT as u32;
impl pallet_election_provider_multi_phase::Config for Runtime { impl pallet_election_provider_multi_phase::Config for Runtime {
type Event = Event; type Event = Event;
type Currency = Balances; type Currency = Balances;
@@ -41,6 +41,10 @@ enum ChainSpecBuilder {
/// Authority key seed. /// Authority key seed.
#[structopt(long, short, required = true)] #[structopt(long, short, required = true)]
authority_seeds: Vec<String>, authority_seeds: Vec<String>,
/// Active nominators (SS58 format), each backing a random subset of the aforementioned
/// authorities.
#[structopt(long, short, default_value = "0")]
nominator_accounts: Vec<String>,
/// Endowed account address (SS58 format). /// Endowed account address (SS58 format).
#[structopt(long, short)] #[structopt(long, short)]
endowed_accounts: Vec<String>, endowed_accounts: Vec<String>,
@@ -57,6 +61,11 @@ enum ChainSpecBuilder {
/// The number of authorities. /// The number of authorities.
#[structopt(long, short)] #[structopt(long, short)]
authorities: usize, authorities: usize,
/// The number of nominators backing the aforementioned authorities.
///
/// Will nominate a random subset of `authorities`.
#[structopt(long, short, default_value = "0")]
nominators: usize,
/// The number of endowed accounts. /// The number of endowed accounts.
#[structopt(long, short, default_value = "0")] #[structopt(long, short, default_value = "0")]
endowed: usize, endowed: usize,
@@ -87,6 +96,7 @@ impl ChainSpecBuilder {
fn genesis_constructor( fn genesis_constructor(
authority_seeds: &[String], authority_seeds: &[String],
nominator_accounts: &[AccountId],
endowed_accounts: &[AccountId], endowed_accounts: &[AccountId],
sudo_account: &AccountId, sudo_account: &AccountId,
) -> chain_spec::GenesisConfig { ) -> chain_spec::GenesisConfig {
@@ -100,6 +110,7 @@ fn genesis_constructor(
chain_spec::testnet_genesis( chain_spec::testnet_genesis(
authorities, authorities,
nominator_accounts.to_vec(),
sudo_account.clone(), sudo_account.clone(),
Some(endowed_accounts.to_vec()), Some(endowed_accounts.to_vec()),
enable_println, enable_println,
@@ -108,26 +119,28 @@ fn genesis_constructor(
fn generate_chain_spec( fn generate_chain_spec(
authority_seeds: Vec<String>, authority_seeds: Vec<String>,
nominator_accounts: Vec<String>,
endowed_accounts: Vec<String>, endowed_accounts: Vec<String>,
sudo_account: String, sudo_account: String,
) -> Result<String, String> { ) -> Result<String, String> {
let parse_account = |address: &String| { let parse_account = |address: String| {
AccountId::from_string(address) AccountId::from_string(&address)
.map_err(|err| format!("Failed to parse account address: {:?}", err)) .map_err(|err| format!("Failed to parse account address: {:?}", err))
}; };
let endowed_accounts = endowed_accounts let nominator_accounts =
.iter() nominator_accounts.into_iter().map(parse_account).collect::<Result<Vec<_>, String>>()?;
.map(parse_account)
.collect::<Result<Vec<_>, String>>()?;
let sudo_account = parse_account(&sudo_account)?; let endowed_accounts =
endowed_accounts.into_iter().map(parse_account).collect::<Result<Vec<_>, String>>()?;
let sudo_account = parse_account(sudo_account)?;
let chain_spec = chain_spec::ChainSpec::from_genesis( let chain_spec = chain_spec::ChainSpec::from_genesis(
"Custom", "Custom",
"custom", "custom",
sc_chain_spec::ChainType::Live, sc_chain_spec::ChainType::Live,
move || genesis_constructor(&authority_seeds, &endowed_accounts, &sudo_account), move || genesis_constructor(&authority_seeds, &nominator_accounts, &endowed_accounts, &sudo_account),
vec![], vec![],
None, None,
None, None,
@@ -186,6 +199,7 @@ fn generate_authority_keys_and_store(
fn print_seeds( fn print_seeds(
authority_seeds: &[String], authority_seeds: &[String],
nominator_seeds: &[String],
endowed_seeds: &[String], endowed_seeds: &[String],
sudo_seed: &str, sudo_seed: &str,
) { ) {
@@ -201,6 +215,12 @@ fn print_seeds(
); );
} }
println!("{}", header.paint("Nominator seeds"));
for (n, seed) in nominator_seeds.iter().enumerate() {
println!("{} //{}", entry.paint(format!("nom-{}:", n)), seed);
}
println!(); println!();
if !endowed_seeds.is_empty() { if !endowed_seeds.is_empty() {
@@ -220,34 +240,27 @@ fn print_seeds(
} }
fn main() -> Result<(), String> { fn main() -> Result<(), String> {
#[cfg(build_type="debug")] #[cfg(build_type = "debug")]
println!( println!(
"The chain spec builder builds a chain specification that includes a Substrate runtime compiled as WASM. To \ "The chain spec builder builds a chain specification that includes a Substrate runtime \
ensure proper functioning of the included runtime compile (or run) the chain spec builder binary in \ compiled as WASM. To ensure proper functioning of the included runtime compile (or run) \
`--release` mode.\n", the chain spec builder binary in `--release` mode.\n",
); );
let builder = ChainSpecBuilder::from_args(); let builder = ChainSpecBuilder::from_args();
let chain_spec_path = builder.chain_spec_path().to_path_buf(); let chain_spec_path = builder.chain_spec_path().to_path_buf();
let (authority_seeds, endowed_accounts, sudo_account) = match builder { let (authority_seeds, nominator_accounts, endowed_accounts, sudo_account) = match builder {
ChainSpecBuilder::Generate { authorities, endowed, keystore_path, .. } => { ChainSpecBuilder::Generate { authorities, nominators, endowed, keystore_path, .. } => {
let authorities = authorities.max(1); let authorities = authorities.max(1);
let rand_str = || -> String { let rand_str = || -> String { OsRng.sample_iter(&Alphanumeric).take(32).collect() };
OsRng.sample_iter(&Alphanumeric)
.take(32)
.collect()
};
let authority_seeds = (0..authorities).map(|_| rand_str()).collect::<Vec<_>>(); let authority_seeds = (0..authorities).map(|_| rand_str()).collect::<Vec<_>>();
let nominator_seeds = (0..nominators).map(|_| rand_str()).collect::<Vec<_>>();
let endowed_seeds = (0..endowed).map(|_| rand_str()).collect::<Vec<_>>(); let endowed_seeds = (0..endowed).map(|_| rand_str()).collect::<Vec<_>>();
let sudo_seed = rand_str(); let sudo_seed = rand_str();
print_seeds( print_seeds(&authority_seeds, &nominator_seeds, &endowed_seeds, &sudo_seed);
&authority_seeds,
&endowed_seeds,
&sudo_seed,
);
if let Some(keystore_path) = keystore_path { if let Some(keystore_path) = keystore_path {
generate_authority_keys_and_store( generate_authority_keys_and_store(
@@ -256,23 +269,37 @@ fn main() -> Result<(), String> {
)?; )?;
} }
let endowed_accounts = endowed_seeds.iter().map(|seed| { let nominator_accounts = nominator_seeds
chain_spec::get_account_id_from_seed::<sr25519::Public>(seed) .into_iter()
.to_ss58check() .map(|seed| {
}).collect(); chain_spec::get_account_id_from_seed::<sr25519::Public>(&seed).to_ss58check()
})
.collect();
let sudo_account = chain_spec::get_account_id_from_seed::<sr25519::Public>(&sudo_seed) let endowed_accounts = endowed_seeds
.to_ss58check(); .into_iter()
.map(|seed| {
chain_spec::get_account_id_from_seed::<sr25519::Public>(&seed).to_ss58check()
})
.collect();
(authority_seeds, endowed_accounts, sudo_account) let sudo_account =
}, chain_spec::get_account_id_from_seed::<sr25519::Public>(&sudo_seed).to_ss58check();
ChainSpecBuilder::New { authority_seeds, endowed_accounts, sudo_account, .. } => {
(authority_seeds, endowed_accounts, sudo_account) (authority_seeds, nominator_accounts, endowed_accounts, sudo_account)
}, }
ChainSpecBuilder::New {
authority_seeds,
nominator_accounts,
endowed_accounts,
sudo_account,
..
} => (authority_seeds, nominator_accounts, endowed_accounts, sudo_account),
}; };
let json = generate_chain_spec( let json = generate_chain_spec(
authority_seeds, authority_seeds,
nominator_accounts,
endowed_accounts, endowed_accounts,
sudo_account, sudo_account,
)?; )?;