Reduce grace ticks, and ignore grace ticks for missing leaders (#7764)
* Reduce grace ticks, and ignore grace ticks for missing leaders * address review comments * blockstore related renames
This commit is contained in:
parent
81ae44f858
commit
156292e408
|
@ -29,7 +29,7 @@ use std::time::Instant;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
const GRACE_TICKS_FACTOR: u64 = 2;
|
const GRACE_TICKS_FACTOR: u64 = 2;
|
||||||
const MAX_GRACE_SLOTS: u64 = 3;
|
const MAX_GRACE_SLOTS: u64 = 2;
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum PohRecorderError {
|
pub enum PohRecorderError {
|
||||||
|
@ -136,6 +136,33 @@ impl PohRecorder {
|
||||||
self.ticks_per_slot
|
self.ticks_per_slot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn received_any_previous_leader_data(&self, slot: Slot) -> bool {
|
||||||
|
(slot.saturating_sub(NUM_CONSECUTIVE_LEADER_SLOTS)..slot).any(|i| {
|
||||||
|
// Check if we have received any data in previous leader's slots
|
||||||
|
if let Ok(slot_meta) = self.blockstore.meta(i as Slot) {
|
||||||
|
if let Some(slot_meta) = slot_meta {
|
||||||
|
slot_meta.received > 0
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reached_leader_tick(&self, leader_first_tick_height: u64) -> bool {
|
||||||
|
let target_tick_height = leader_first_tick_height.saturating_sub(1);
|
||||||
|
let ideal_target_tick_height = target_tick_height.saturating_sub(self.grace_ticks);
|
||||||
|
let current_slot = self.tick_height / self.ticks_per_slot;
|
||||||
|
// we've approached target_tick_height OR poh was reset to run immediately
|
||||||
|
// Or, previous leader didn't transmit in any of its leader slots, so ignore grace ticks
|
||||||
|
self.tick_height >= target_tick_height
|
||||||
|
|| self.start_tick_height + self.grace_ticks == leader_first_tick_height
|
||||||
|
|| (self.tick_height >= ideal_target_tick_height
|
||||||
|
&& !self.received_any_previous_leader_data(current_slot))
|
||||||
|
}
|
||||||
|
|
||||||
/// returns if leader slot has been reached, how many grace ticks were afforded,
|
/// returns if leader slot has been reached, how many grace ticks were afforded,
|
||||||
/// imputed leader_slot and self.start_slot
|
/// imputed leader_slot and self.start_slot
|
||||||
/// reached_leader_slot() == true means "ready for a bank"
|
/// reached_leader_slot() == true means "ready for a bank"
|
||||||
|
@ -153,10 +180,7 @@ impl PohRecorder {
|
||||||
let next_leader_slot = (next_tick_height - 1) / self.ticks_per_slot;
|
let next_leader_slot = (next_tick_height - 1) / self.ticks_per_slot;
|
||||||
if let Some(leader_first_tick_height) = self.leader_first_tick_height {
|
if let Some(leader_first_tick_height) = self.leader_first_tick_height {
|
||||||
let target_tick_height = leader_first_tick_height.saturating_sub(1);
|
let target_tick_height = leader_first_tick_height.saturating_sub(1);
|
||||||
// we've approached target_tick_height OR poh was reset to run immediately
|
if self.reached_leader_tick(leader_first_tick_height) {
|
||||||
if self.tick_height >= target_tick_height
|
|
||||||
|| self.start_tick_height + self.grace_ticks == leader_first_tick_height
|
|
||||||
{
|
|
||||||
assert!(next_tick_height >= self.start_tick_height);
|
assert!(next_tick_height >= self.start_tick_height);
|
||||||
let ideal_target_tick_height = target_tick_height.saturating_sub(self.grace_ticks);
|
let ideal_target_tick_height = target_tick_height.saturating_sub(self.grace_ticks);
|
||||||
|
|
||||||
|
@ -475,7 +499,8 @@ impl PohRecorder {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::genesis_utils::{create_genesis_config, GenesisConfigInfo};
|
use crate::genesis_utils::{create_genesis_config, GenesisConfigInfo};
|
||||||
use solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path};
|
use bincode::serialize;
|
||||||
|
use solana_ledger::{blockstore::Blockstore, blockstore_meta::SlotMeta, get_tmp_ledger_path};
|
||||||
use solana_perf::test_tx::test_tx;
|
use solana_perf::test_tx::test_tx;
|
||||||
use solana_sdk::clock::DEFAULT_TICKS_PER_SLOT;
|
use solana_sdk::clock::DEFAULT_TICKS_PER_SLOT;
|
||||||
use solana_sdk::hash::hash;
|
use solana_sdk::hash::hash;
|
||||||
|
@ -1094,6 +1119,60 @@ mod tests {
|
||||||
Blockstore::destroy(&ledger_path).unwrap();
|
Blockstore::destroy(&ledger_path).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_reached_leader_tick() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let ledger_path = get_tmp_ledger_path!();
|
||||||
|
{
|
||||||
|
let blockstore = Blockstore::open(&ledger_path)
|
||||||
|
.expect("Expected to be able to open database ledger");
|
||||||
|
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2);
|
||||||
|
let bank = Arc::new(Bank::new(&genesis_config));
|
||||||
|
let prev_hash = bank.last_blockhash();
|
||||||
|
let (mut poh_recorder, _entry_receiver) = PohRecorder::new(
|
||||||
|
0,
|
||||||
|
prev_hash,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
bank.ticks_per_slot(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Arc::new(blockstore),
|
||||||
|
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
|
||||||
|
&Arc::new(PohConfig::default()),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(poh_recorder.reached_leader_tick(0), true);
|
||||||
|
|
||||||
|
let grace_ticks = bank.ticks_per_slot() * MAX_GRACE_SLOTS;
|
||||||
|
let new_tick_height = NUM_CONSECUTIVE_LEADER_SLOTS * bank.ticks_per_slot();
|
||||||
|
for _ in 0..new_tick_height {
|
||||||
|
poh_recorder.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
poh_recorder.grace_ticks = grace_ticks;
|
||||||
|
// True, as previous leader did not transmit in its slots
|
||||||
|
assert_eq!(
|
||||||
|
poh_recorder.reached_leader_tick(new_tick_height + grace_ticks),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut parent_meta = SlotMeta::default();
|
||||||
|
parent_meta.received = 1;
|
||||||
|
poh_recorder
|
||||||
|
.blockstore
|
||||||
|
.put_meta_bytes(0, &serialize(&parent_meta).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// False, as previous leader transmitted in one of its recent slots
|
||||||
|
// and grace ticks have not expired
|
||||||
|
assert_eq!(
|
||||||
|
poh_recorder.reached_leader_tick(new_tick_height + grace_ticks),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reached_leader_slot() {
|
fn test_reached_leader_slot() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
@ -1140,6 +1219,13 @@ mod tests {
|
||||||
init_ticks + bank.ticks_per_slot()
|
init_ticks + bank.ticks_per_slot()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut parent_meta = SlotMeta::default();
|
||||||
|
parent_meta.received = 1;
|
||||||
|
poh_recorder
|
||||||
|
.blockstore
|
||||||
|
.put_meta_bytes(0, &serialize(&parent_meta).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Test that we don't reach the leader slot because of grace ticks
|
// Test that we don't reach the leader slot because of grace ticks
|
||||||
assert_eq!(poh_recorder.reached_leader_slot().0, false);
|
assert_eq!(poh_recorder.reached_leader_slot().0, false);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub mod block_error;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod blockstore;
|
pub mod blockstore;
|
||||||
pub mod blockstore_db;
|
pub mod blockstore_db;
|
||||||
mod blockstore_meta;
|
pub mod blockstore_meta;
|
||||||
pub mod blockstore_processor;
|
pub mod blockstore_processor;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
pub mod erasure;
|
pub mod erasure;
|
||||||
|
|
Loading…
Reference in New Issue