som: Add --quality-block-producer-percentage (#10462)

automerge
This commit is contained in:
Michael Vines
2020-06-08 22:15:59 -07:00
committed by GitHub
parent 9d07a23c46
commit 4cfb7588d9
2 changed files with 43 additions and 28 deletions

View File

@ -2,7 +2,7 @@ use clap::{crate_description, crate_name, crate_version, value_t, value_t_or_exi
use log::*;
use solana_clap_utils::{
input_parsers::{keypair_of, pubkey_of},
input_validators::{is_keypair, is_pubkey_or_keypair, is_url},
input_validators::{is_keypair, is_pubkey_or_keypair, is_url, is_valid_percentage},
};
use solana_client::{
client_error, rpc_client::RpcClient, rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
@ -34,7 +34,7 @@ use std::{
time::{Duration, Instant},
};
mod whitelist;
mod validator_list;
struct Config {
json_rpc_url: String,
@ -42,18 +42,19 @@ struct Config {
source_stake_address: Pubkey,
authorized_staker: Keypair,
/// Only validators with an identity pubkey in this whitelist will be staked
whitelist: HashSet<Pubkey>,
/// Only validators with an identity pubkey in this validator_list will be staked
validator_list: HashSet<Pubkey>,
dry_run: bool,
/// Amount of lamports to stake any validator in the whitelist that is not delinquent
/// Amount of lamports to stake any validator in the validator_list that is not delinquent
baseline_stake_amount: u64,
/// Amount of additional lamports to stake quality block producers in the whitelist
/// Amount of additional lamports to stake quality block producers in the validator_list
bonus_stake_amount: u64,
/// Quality validators produce a block in more than this percentage of their leader slots
/// Quality validators produce a block at least this percentage of their leader slots over the
/// previous epoch
quality_block_producer_percentage: usize,
/// A delinquent validator gets this number of slots of grace (from the current slot) before it
@ -98,8 +99,8 @@ fn get_config() -> Config {
.help("Name of the cluster to operate on")
)
.arg(
Arg::with_name("whitelist_file")
.long("whitelist")
Arg::with_name("validator_list_file")
.long("validator-list")
.value_name("FILE")
.required(true)
.takes_value(true)
@ -128,7 +129,17 @@ fn get_config() -> Config {
.validator(is_keypair)
.required(true)
.takes_value(true)
) .get_matches();
)
.arg(
Arg::with_name("quality_block_producer_percentage")
.long("quality-block-producer-percentage")
.value_name("PERCENTAGE")
.takes_value(true)
.default_value("75")
.validator(is_valid_percentage)
.help("Quality validators produce a block in at least this percentage of their leader slots over the previous epoch")
)
.get_matches();
let config = if let Some(config_file) = matches.value_of("config_file") {
solana_cli_config::Config::load(config_file).unwrap_or_default()
@ -140,56 +151,59 @@ fn get_config() -> Config {
let authorized_staker = keypair_of(&matches, "authorized_staker").unwrap();
let dry_run = !matches.is_present("confirm");
let cluster = value_t!(matches, "cluster", String).unwrap_or_else(|_| "unknown".into());
let quality_block_producer_percentage =
value_t_or_exit!(matches, "quality_block_producer_percentage", usize);
let (json_rpc_url, whitelist) = match cluster.as_str() {
let (json_rpc_url, validator_list) = match cluster.as_str() {
"mainnet-beta" => (
"http://api.mainnet-beta.solana.com".into(),
whitelist::mainnet_beta_validators(),
validator_list::mainnet_beta_validators(),
),
"testnet" => (
"http://testnet.solana.com".into(),
whitelist::testnet_validators(),
validator_list::testnet_validators(),
),
"unknown" => {
let whitelist_file = File::open(value_t_or_exit!(matches, "whitelist_file", PathBuf))
let validator_list_file =
File::open(value_t_or_exit!(matches, "validator_list_file", PathBuf))
.unwrap_or_else(|err| {
error!("Unable to open whitelist: {}", err);
error!("Unable to open validator_list: {}", err);
process::exit(1);
});
let whitelist = serde_yaml::from_reader::<_, Vec<String>>(whitelist_file)
let validator_list = serde_yaml::from_reader::<_, Vec<String>>(validator_list_file)
.unwrap_or_else(|err| {
error!("Unable to read whitelist: {}", err);
error!("Unable to read validator_list: {}", err);
process::exit(1);
})
.into_iter()
.map(|p| {
Pubkey::from_str(&p).unwrap_or_else(|err| {
error!("Invalid whitelist pubkey '{}': {}", p, err);
error!("Invalid validator_list pubkey '{}': {}", p, err);
process::exit(1);
})
})
.collect();
(
value_t!(matches, "json_rpc_url", String).unwrap_or_else(|_| config.json_rpc_url),
whitelist,
validator_list,
)
}
_ => unreachable!(),
};
let whitelist = whitelist.into_iter().collect::<HashSet<_>>();
let validator_list = validator_list.into_iter().collect::<HashSet<_>>();
let config = Config {
json_rpc_url,
cluster,
source_stake_address,
authorized_staker,
whitelist,
validator_list,
dry_run,
baseline_stake_amount: sol_to_lamports(5000.),
bonus_stake_amount: sol_to_lamports(50_000.),
delinquent_grace_slot_distance: 21600, // ~24 hours worth of slots at 2.5 slots per second
quality_block_producer_percentage: 75,
quality_block_producer_percentage,
};
info!("RPC URL: {}", config.json_rpc_url);
@ -279,7 +293,8 @@ fn classify_block_producers(
);
if validator_slots > 0 {
let validator_identity = Pubkey::from_str(&validator_identity)?;
if validator_blocks * 100 / validator_slots > config.quality_block_producer_percentage {
if validator_blocks * 100 / validator_slots >= config.quality_block_producer_percentage
{
quality_block_producers.insert(validator_identity);
} else {
poor_block_producers.insert(validator_identity);
@ -563,7 +578,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
let (quality_block_producers, _poor_block_producers) =
classify_block_producers(&rpc_client, &config, last_epoch)?;
// Fetch vote account status for all the whitelisted validators
// Fetch vote account status for all the validator_listed validators
let vote_account_status = rpc_client.get_vote_accounts()?;
let vote_account_info = vote_account_status
.current
@ -571,7 +586,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.chain(vote_account_status.delinquent.into_iter())
.filter_map(|vai| {
let node_pubkey = Pubkey::from_str(&vai.node_pubkey).ok()?;
if config.whitelist.contains(&node_pubkey) {
if config.validator_list.contains(&node_pubkey) {
Some(vai)
} else {
None