Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validator: Split PoH speed measurement from check #4185

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions core/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ use {
tokio::runtime::Runtime as TokioRuntime,
};

// The current hash rate on Solana MNB, Testnet, and Devnet
// If the hash rate on these clusters changes, we might consider updating this
// constant. However, the PoH speed check compares hashes / second so this
// constant does not have to be updated
const POH_SPEED_CHECK_NUM_HASHES: u64 = 10_000_000;

const MAX_COMPLETED_DATA_SETS_IN_CHANNEL: usize = 100_000;
const WAIT_FOR_SUPERMAJORITY_THRESHOLD_PERCENT: u64 = 80;
// Right now since we reuse the wait for supermajority code, the
Expand Down Expand Up @@ -555,6 +561,12 @@ impl Validator {

let start_time = Instant::now();

let my_poh_hashes_per_second = if config.no_poh_speed_test {
None
} else {
Some(measure_poh_speed(POH_SPEED_CHECK_NUM_HASHES))
};

// Initialize the global rayon pool first to ensure the value in config
// is honored. Otherwise, some code accessing the global pool could
// cause it to get initialized with Rayon's default (not ours)
Expand Down Expand Up @@ -768,8 +780,11 @@ impl Validator {
)
.map_err(ValidatorError::Other)?;

if !config.no_poh_speed_test {
check_poh_speed(&bank_forks.read().unwrap().root_bank(), None)?;
if let Some(my_hashes_per_second) = my_poh_hashes_per_second {
check_poh_speed(
&bank_forks.read().unwrap().root_bank(),
my_hashes_per_second,
)?;
}

let (root_slot, hard_forks) = {
Expand Down Expand Up @@ -1775,19 +1790,25 @@ fn active_vote_account_exists_in_bank(bank: &Bank, vote_account: &Pubkey) -> boo
false
}

fn check_poh_speed(bank: &Bank, maybe_hash_samples: Option<u64>) -> Result<(), ValidatorError> {
// Compute the PoH speed (hashes / second) by measuring the time required to
// compute `num_hashes` hashes
fn measure_poh_speed(num_hashes: u64) -> u64 {
let hash_time = compute_hash_time(num_hashes);
(num_hashes as f64 / hash_time.as_secs_f64()) as u64
}

// Compare a computed PoH speed against the target value derived from a Bank
// and error if the computed PoH speed is less than the target speed
//
// Measurement and comparison are split so that the measurement can occur early
// in validator startup before other services start competing for CPU time
fn check_poh_speed(bank: &Bank, my_hashes_per_second: u64) -> Result<(), ValidatorError> {
let Some(hashes_per_tick) = bank.hashes_per_tick() else {
warn!("Unable to read hashes per tick from Bank, skipping PoH speed check");
return Ok(());
};

let ticks_per_slot = bank.ticks_per_slot();
let hashes_per_slot = hashes_per_tick * ticks_per_slot;
let hash_samples = maybe_hash_samples.unwrap_or(hashes_per_slot);

let hash_time = compute_hash_time(hash_samples);
let my_hashes_per_second = (hash_samples as f64 / hash_time.as_secs_f64()) as u64;

let target_slot_duration = Duration::from_nanos(bank.ns_per_slot as u64);
let target_hashes_per_second =
(hashes_per_slot as f64 / target_slot_duration.as_secs_f64()) as u64;
Expand Down Expand Up @@ -3254,7 +3275,7 @@ mod tests {
..GenesisConfig::default()
};
let bank = Bank::new_for_tests(&genesis_config);
assert!(check_poh_speed(&bank, Some(10_000)).is_err());
assert!(check_poh_speed(&bank, measure_poh_speed(10_000)).is_err());
}

#[test]
Expand All @@ -3270,6 +3291,6 @@ mod tests {
..GenesisConfig::default()
};
let bank = Bank::new_for_tests(&genesis_config);
check_poh_speed(&bank, Some(10_000)).unwrap();
check_poh_speed(&bank, measure_poh_speed(10_000)).unwrap();
}
}
Loading