diff --git a/stake-o-matic/src/main.rs b/stake-o-matic/src/main.rs index 55cb597c6d..cf001e4cf0 100644 --- a/stake-o-matic/src/main.rs +++ b/stake-o-matic/src/main.rs @@ -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, + /// Only validators with an identity pubkey in this validator_list will be staked + validator_list: HashSet, 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)) - .unwrap_or_else(|err| { - error!("Unable to open whitelist: {}", err); - process::exit(1); - }); + let validator_list_file = + File::open(value_t_or_exit!(matches, "validator_list_file", PathBuf)) + .unwrap_or_else(|err| { + error!("Unable to open validator_list: {}", err); + process::exit(1); + }); - let whitelist = serde_yaml::from_reader::<_, Vec>(whitelist_file) + let validator_list = serde_yaml::from_reader::<_, Vec>(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::>(); + let validator_list = validator_list.into_iter().collect::>(); 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> { 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> { .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 diff --git a/stake-o-matic/src/whitelist.rs b/stake-o-matic/src/validator_list.rs similarity index 100% rename from stake-o-matic/src/whitelist.rs rename to stake-o-matic/src/validator_list.rs