Ignore delinquent stake on exit (backport #20367) (#20612)

* Ignore delinquent stake on exit (#20367)

* add --ignore-delinquency flag to validator exit and wait-for-restart-window sub commands

* Fix a merge issue

* Add missing variable declaration

* Remove empty line to help CI checks pass

* run rustfmt

* Change argument wording for clarity and verbosity

* Change --ignore-delinquent-stake to --max-delinquent-stake

* cargo fmtgit add validator/src/main.rsgit add validator/src/main.rs

* Adjust per mvines

* Formatting

* Improve input validation

* Please automate cargo fmt somehow

(cherry picked from commit fc5dd7f3bc)

# Conflicts:
#	validator/src/main.rs

* Fixes cherry-pick conflict

Co-authored-by: Michael <68944931+michaelh-laine@users.noreply.github.com>
Co-authored-by: Steven Czabaniuk <steven@solana.com>
This commit is contained in:
mergify[bot]
2021-10-12 20:30:47 +00:00
committed by GitHub
parent 0d1dbb6160
commit 29eae21057

View File

@ -11,7 +11,7 @@ use {
input_parsers::{keypair_of, keypairs_of, pubkey_of, value_of}, input_parsers::{keypair_of, keypairs_of, pubkey_of, value_of},
input_validators::{ input_validators::{
is_keypair, is_keypair_or_ask_keyword, is_parsable, is_pubkey, is_pubkey_or_keypair, is_keypair, is_keypair_or_ask_keyword, is_parsable, is_pubkey, is_pubkey_or_keypair,
is_slot, is_slot, is_valid_percentage,
}, },
keypair::SKIP_SEED_PHRASE_VALIDATION_ARG, keypair::SKIP_SEED_PHRASE_VALIDATION_ARG,
}, },
@ -114,9 +114,9 @@ fn wait_for_restart_window(
ledger_path: &Path, ledger_path: &Path,
identity: Option<Pubkey>, identity: Option<Pubkey>,
min_idle_time_in_minutes: usize, min_idle_time_in_minutes: usize,
max_delinquency_percentage: u8,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let sleep_interval = Duration::from_secs(5); let sleep_interval = Duration::from_secs(5);
let min_delinquency_percentage = 0.05;
let min_idle_slots = (min_idle_time_in_minutes as f64 * 60. / DEFAULT_S_PER_SLOT) as Slot; let min_idle_slots = (min_idle_time_in_minutes as f64 * 60. / DEFAULT_S_PER_SLOT) as Slot;
@ -142,6 +142,11 @@ fn wait_for_restart_window(
), ),
); );
println!(
"Maximum permitted delinquency: {}%",
max_delinquency_percentage
);
let mut current_epoch = None; let mut current_epoch = None;
let mut leader_schedule = VecDeque::new(); let mut leader_schedule = VecDeque::new();
let mut restart_snapshot = None; let mut restart_snapshot = None;
@ -287,7 +292,9 @@ fn wait_for_restart_window(
if restart_snapshot == snapshot_slot && !monitoring_another_validator { if restart_snapshot == snapshot_slot && !monitoring_another_validator {
"Waiting for a new snapshot".to_string() "Waiting for a new snapshot".to_string()
} else if delinquent_stake_percentage >= min_delinquency_percentage { } else if delinquent_stake_percentage
>= (max_delinquency_percentage as f64 / 100.)
{
style("Delinquency too high").red().to_string() style("Delinquency too high").red().to_string()
} else { } else {
break; // Restart! break; // Restart!
@ -1958,6 +1965,15 @@ pub fn main() {
.default_value("10") .default_value("10")
.help("Minimum time that the validator should not be leader before restarting") .help("Minimum time that the validator should not be leader before restarting")
) )
.arg(
Arg::with_name("max_delinquent_stake")
.long("max-delinquent-stake")
.takes_value(true)
.validator(is_valid_percentage)
.default_value("5")
.value_name("PERCENT")
.help("The maximum delinquent stake % permitted for an exit")
)
) )
.subcommand( .subcommand(
SubCommand::with_name("authorized-voter") SubCommand::with_name("authorized-voter")
@ -2028,6 +2044,15 @@ pub fn main() {
.validator(is_pubkey_or_keypair) .validator(is_pubkey_or_keypair)
.help("Validator identity to monitor [default: your validator]") .help("Validator identity to monitor [default: your validator]")
) )
.arg(
Arg::with_name("max_delinquent_stake")
.long("max-delinquent-stake")
.takes_value(true)
.validator(is_valid_percentage)
.default_value("5")
.value_name("PERCENT")
.help("The maximum delinquent stake % permitted for a restart")
)
.after_help("Note: If this command exits with a non-zero status \ .after_help("Note: If this command exits with a non-zero status \
then this not a good time for a restart") then this not a good time for a restart")
) )
@ -2094,12 +2119,15 @@ pub fn main() {
let min_idle_time = value_t_or_exit!(subcommand_matches, "min_idle_time", usize); let min_idle_time = value_t_or_exit!(subcommand_matches, "min_idle_time", usize);
let force = subcommand_matches.is_present("force"); let force = subcommand_matches.is_present("force");
let monitor = subcommand_matches.is_present("monitor"); let monitor = subcommand_matches.is_present("monitor");
let max_delinquent_stake =
value_t_or_exit!(subcommand_matches, "max_delinquent_stake", u8);
if !force { if !force {
wait_for_restart_window(&ledger_path, None, min_idle_time).unwrap_or_else(|err| { wait_for_restart_window(&ledger_path, None, min_idle_time, max_delinquent_stake)
println!("{}", err); .unwrap_or_else(|err| {
exit(1); println!("{}", err);
}); exit(1);
});
} }
let admin_client = admin_rpc_service::connect(&ledger_path); let admin_client = admin_rpc_service::connect(&ledger_path);
@ -2134,10 +2162,14 @@ pub fn main() {
("wait-for-restart-window", Some(subcommand_matches)) => { ("wait-for-restart-window", Some(subcommand_matches)) => {
let min_idle_time = value_t_or_exit!(subcommand_matches, "min_idle_time", usize); let min_idle_time = value_t_or_exit!(subcommand_matches, "min_idle_time", usize);
let identity = pubkey_of(subcommand_matches, "identity"); let identity = pubkey_of(subcommand_matches, "identity");
wait_for_restart_window(&ledger_path, identity, min_idle_time).unwrap_or_else(|err| { let max_delinquent_stake =
println!("{}", err); value_t_or_exit!(subcommand_matches, "max_delinquent_stake", u8);
exit(1);
}); wait_for_restart_window(&ledger_path, identity, min_idle_time, max_delinquent_stake)
.unwrap_or_else(|err| {
println!("{}", err);
exit(1);
});
return; return;
} }
_ => unreachable!(), _ => unreachable!(),