Leader scheduler groundwork for Blocktree (#2599)

* Groundwork for entry tree, align constants with definitions in the book

* Fix edge case in test, node can keep generating ticks between handle_role_transition and exit() call
This commit is contained in:
carllin
2019-01-31 13:44:24 -08:00
committed by GitHub
parent 32162ef0f1
commit 84567d36cf
3 changed files with 26 additions and 14 deletions

View File

@ -18,11 +18,14 @@ use solana_sdk::vote_transaction::VoteTransaction;
use std::io::Cursor; use std::io::Cursor;
use std::sync::Arc; use std::sync::Arc;
pub const TICKS_PER_BLOCK: u64 = 4; // At 10 ticks/s, 8 ticks per slot implies that leader rotation and voting will happen
pub const DEFAULT_BOOTSTRAP_HEIGHT: u64 = TICKS_PER_BLOCK * 256; // every 800 ms. A fast voting cadence ensures faster finality and convergence
pub const DEFAULT_LEADER_ROTATION_INTERVAL: u64 = TICKS_PER_BLOCK * 32; pub const DEFAULT_TICKS_PER_SLOT: u64 = 8;
pub const DEFAULT_SEED_ROTATION_INTERVAL: u64 = TICKS_PER_BLOCK * 256; // Bootstrap height lasts for ~100 seconds
pub const DEFAULT_ACTIVE_WINDOW_LENGTH: u64 = TICKS_PER_BLOCK * 256; pub const DEFAULT_BOOTSTRAP_HEIGHT: u64 = 1024;
pub const DEFAULT_SLOTS_PER_EPOCH: u64 = 64;
pub const DEFAULT_SEED_ROTATION_INTERVAL: u64 = DEFAULT_SLOTS_PER_EPOCH * DEFAULT_TICKS_PER_SLOT;
pub const DEFAULT_ACTIVE_WINDOW_LENGTH: u64 = DEFAULT_SEED_ROTATION_INTERVAL;
pub struct LeaderSchedulerConfig { pub struct LeaderSchedulerConfig {
// The interval at which to rotate the leader, should be much less than // The interval at which to rotate the leader, should be much less than
@ -62,7 +65,7 @@ impl Default for LeaderSchedulerConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
bootstrap_height: DEFAULT_BOOTSTRAP_HEIGHT, bootstrap_height: DEFAULT_BOOTSTRAP_HEIGHT,
leader_rotation_interval: DEFAULT_LEADER_ROTATION_INTERVAL, leader_rotation_interval: DEFAULT_TICKS_PER_SLOT,
seed_rotation_interval: DEFAULT_SEED_ROTATION_INTERVAL, seed_rotation_interval: DEFAULT_SEED_ROTATION_INTERVAL,
active_window_length: DEFAULT_ACTIVE_WINDOW_LENGTH, active_window_length: DEFAULT_ACTIVE_WINDOW_LENGTH,
} }
@ -184,6 +187,15 @@ impl LeaderScheduler {
} }
} }
// Returns the last tick height for a given slot index
pub fn max_tick_height_for_slot(&self, slot_index: u64) -> u64 {
if self.use_only_bootstrap_leader {
std::u64::MAX
} else {
slot_index * self.leader_rotation_interval + self.bootstrap_height
}
}
// Let Leader X be the leader at the input tick height. This function returns the // Let Leader X be the leader at the input tick height. This function returns the
// the PoH height at which Leader X's slot ends. // the PoH height at which Leader X's slot ends.
pub fn max_height_for_leader(&self, height: u64) -> Option<u64> { pub fn max_height_for_leader(&self, height: u64) -> Option<u64> {
@ -517,7 +529,7 @@ pub mod tests {
use crate::genesis_block::GenesisBlock; use crate::genesis_block::GenesisBlock;
use crate::leader_scheduler::{ use crate::leader_scheduler::{
LeaderScheduler, LeaderSchedulerConfig, DEFAULT_BOOTSTRAP_HEIGHT, LeaderScheduler, LeaderSchedulerConfig, DEFAULT_BOOTSTRAP_HEIGHT,
DEFAULT_LEADER_ROTATION_INTERVAL, DEFAULT_SEED_ROTATION_INTERVAL, DEFAULT_SEED_ROTATION_INTERVAL, DEFAULT_TICKS_PER_SLOT,
}; };
use crate::vote_signer_proxy::VoteSignerProxy; use crate::vote_signer_proxy::VoteSignerProxy;
use hashbrown::HashSet; use hashbrown::HashSet;
@ -964,8 +976,8 @@ pub mod tests {
// only one validator should be selected // only one validator should be selected
num_validators = 10; num_validators = 10;
bootstrap_height = 1; bootstrap_height = 1;
leader_rotation_interval = 1; leader_rotation_interval = 1 as usize;
seed_rotation_interval = 1; seed_rotation_interval = 1 as usize;
run_scheduler_test( run_scheduler_test(
num_validators, num_validators,
bootstrap_height, bootstrap_height,
@ -1156,7 +1168,7 @@ pub mod tests {
assert_eq!( assert_eq!(
leader_scheduler.leader_rotation_interval, leader_scheduler.leader_rotation_interval,
DEFAULT_LEADER_ROTATION_INTERVAL DEFAULT_TICKS_PER_SLOT
); );
assert_eq!( assert_eq!(
leader_scheduler.seed_rotation_interval, leader_scheduler.seed_rotation_interval,

View File

@ -10,7 +10,7 @@ use crate::entry_stream::EntryStreamHandler;
#[cfg(test)] #[cfg(test)]
use crate::entry_stream::MockEntryStream as EntryStream; use crate::entry_stream::MockEntryStream as EntryStream;
use crate::fullnode::TvuRotationSender; use crate::fullnode::TvuRotationSender;
use crate::leader_scheduler::TICKS_PER_BLOCK; use crate::leader_scheduler::DEFAULT_TICKS_PER_SLOT;
use crate::packet::BlobError; use crate::packet::BlobError;
use crate::result::{Error, Result}; use crate::result::{Error, Result};
use crate::service::Service; use crate::service::Service;
@ -112,7 +112,8 @@ impl ReplayStage {
let mut did_rotate = false; let mut did_rotate = false;
// Next vote tick is ceiling of (current tick/ticks per block) // Next vote tick is ceiling of (current tick/ticks per block)
let mut num_ticks_to_next_vote = TICKS_PER_BLOCK - (bank.tick_height() % TICKS_PER_BLOCK); let mut num_ticks_to_next_vote =
DEFAULT_TICKS_PER_SLOT - (bank.tick_height() % DEFAULT_TICKS_PER_SLOT);
let mut start_entry_index = 0; let mut start_entry_index = 0;
for (i, entry) in entries.iter().enumerate() { for (i, entry) in entries.iter().enumerate() {
inc_new_counter_info!("replicate-stage_bank-tick", bank.tick_height() as usize); inc_new_counter_info!("replicate-stage_bank-tick", bank.tick_height() as usize);
@ -168,7 +169,7 @@ impl ReplayStage {
break; break;
} }
start_entry_index = i + 1; start_entry_index = i + 1;
num_ticks_to_next_vote = TICKS_PER_BLOCK; num_ticks_to_next_vote = DEFAULT_TICKS_PER_SLOT;
} }
} }

View File

@ -1238,7 +1238,6 @@ fn test_leader_validator_basic() {
let leader_entries = read_ledger(&leader_ledger_path); let leader_entries = read_ledger(&leader_ledger_path);
assert_eq!(leader_entries.len(), validator_entries.len());
assert!(leader_entries.len() as u64 >= bootstrap_height); assert!(leader_entries.len() as u64 >= bootstrap_height);
for (v, l) in validator_entries.iter().zip(leader_entries) { for (v, l) in validator_entries.iter().zip(leader_entries) {