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:
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
Reference in New Issue
Block a user