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

Update PoH speed check to derive rate from Bank #2447

Merged
merged 4 commits into from
Aug 6, 2024
Merged
Changes from 1 commit
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
50 changes: 34 additions & 16 deletions core/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,11 @@ impl Validator {
Some(poh_timing_point_sender.clone()),
)
.map_err(ValidatorError::Other)?;

if !config.no_poh_speed_test {
check_poh_speed(&bank_forks.read().unwrap().root_bank(), None)?;
}

let hard_forks = bank_forks.read().unwrap().root_bank().hard_forks();
if !hard_forks.is_empty() {
info!("Hard forks: {:?}", hard_forks);
Expand All @@ -745,7 +750,6 @@ impl Validator {
&genesis_config.hash(),
Some(&hard_forks),
));

Self::print_node_info(&node);

if let Some(expected_shred_version) = config.expected_shred_version {
Expand Down Expand Up @@ -1677,18 +1681,16 @@ fn active_vote_account_exists_in_bank(bank: &Bank, vote_account: &Pubkey) -> boo
false
}

fn check_poh_speed(
genesis_config: &GenesisConfig,
maybe_hash_samples: Option<u64>,
) -> Result<(), ValidatorError> {
if let Some(hashes_per_tick) = genesis_config.hashes_per_tick() {
let ticks_per_slot = genesis_config.ticks_per_slot();
fn check_poh_speed(bank: &Bank, maybe_hash_samples: Option<u64>) -> Result<(), ValidatorError> {
if let Some(hashes_per_tick) = bank.hashes_per_tick() {
steviez marked this conversation as resolved.
Show resolved Hide resolved
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(genesis_config.ns_per_slot() as u64);

let target_slot_duration = Duration::from_nanos(bank.ns_per_slot as u64);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure ns_per_slot should be public in Bank, but seemingly a refactor for after this:

pub ns_per_slot: u128,

let target_hashes_per_second =
(hashes_per_slot as f64 / target_slot_duration.as_secs_f64()) as u64;

Expand All @@ -1703,7 +1705,10 @@ fn check_poh_speed(
target: target_hashes_per_second,
});
}
} else {
warn!("Unable to read hashes per tick from Bank, skipping PoH speed check");
}

Ok(())
}

Expand Down Expand Up @@ -1835,10 +1840,6 @@ fn load_genesis(
}
}

if !config.no_poh_speed_test {
check_poh_speed(&genesis_config, None)?;
}

Ok(genesis_config)
}

Expand Down Expand Up @@ -2937,11 +2938,25 @@ mod tests {
));
}

fn target_tick_duration() -> Duration {
// DEFAULT_MS_PER_SLOT = 400
// DEFAULT_TICKS_PER_SLOT = 64
// MS_PER_TICK = 6
//
// But, DEFAULT_MS_PER_SLOT / DEFAULT_TICKS_PER_SLOT = 6.25
//
// So, convert to microseconds first to avoid the integer rounding error
let target_tick_duration_us = solana_sdk::clock::DEFAULT_MS_PER_SLOT * 1000
/ solana_sdk::clock::DEFAULT_TICKS_PER_SLOT;
assert_eq!(target_tick_duration_us, 6250);
Duration::from_micros(target_tick_duration_us)
}

#[test]
fn test_poh_speed() {
solana_logger::setup();
let poh_config = PohConfig {
target_tick_duration: Duration::from_millis(solana_sdk::clock::MS_PER_TICK),
target_tick_duration: target_tick_duration(),
Comment on lines -2944 to +2960
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, this change isn't critical for the PR. But, the constant MS_PER_TICK is 6ms; 6 ms/tick * 64 ticks/slot = 384 ms/slot. It annoyed me that this didn't come out to the 400ms, and I noticed when observing the info log from speed check. Can revert it back if desired

// make PoH rate really fast to cause the panic condition
hashes_per_tick: Some(100 * solana_sdk::clock::DEFAULT_HASHES_PER_TICK),
..PohConfig::default()
Expand All @@ -2950,20 +2965,23 @@ mod tests {
poh_config,
..GenesisConfig::default()
};
assert!(check_poh_speed(&genesis_config, Some(10_000)).is_err());
let bank = Bank::new_for_tests(&genesis_config);
assert!(check_poh_speed(&bank, Some(10_000)).is_err());
}

#[test]
fn test_poh_speed_no_hashes_per_tick() {
solana_logger::setup();
let poh_config = PohConfig {
target_tick_duration: Duration::from_millis(solana_sdk::clock::MS_PER_TICK),
target_tick_duration: target_tick_duration(),
hashes_per_tick: None,
..PohConfig::default()
};
let genesis_config = GenesisConfig {
poh_config,
..GenesisConfig::default()
};
check_poh_speed(&genesis_config, Some(10_000)).unwrap();
let bank = Bank::new_for_tests(&genesis_config);
check_poh_speed(&bank, Some(10_000)).unwrap();
}
}