* 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:
@ -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,9 +2119,12 @@ 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)
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
println!("{}", err);
|
println!("{}", err);
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
@ -2134,7 +2162,11 @@ 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 =
|
||||||
|
value_t_or_exit!(subcommand_matches, "max_delinquent_stake", u8);
|
||||||
|
|
||||||
|
wait_for_restart_window(&ledger_path, identity, min_idle_time, max_delinquent_stake)
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
println!("{}", err);
|
println!("{}", err);
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user