Change range of leader scheduler to match current broadcasts (#1920)
This commit is contained in:
parent
1fbbf13ec9
commit
4ae58cc854
|
@ -1300,7 +1300,7 @@ impl Bank {
|
|||
self.leader_scheduler
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_scheduled_leader(self.tick_height())
|
||||
.get_scheduled_leader(self.tick_height() + 1)
|
||||
}
|
||||
|
||||
pub fn tick_height(&self) -> u64 {
|
||||
|
|
|
@ -280,6 +280,9 @@ pub fn process_blob(
|
|||
let slot = blob.read().unwrap().slot()?;
|
||||
let leader = leader_scheduler.get_leader_for_slot(slot);
|
||||
|
||||
// TODO: Once the original leader signature is added to the blob, make sure that
|
||||
// the blob was originally generated by the expected leader for this slot
|
||||
|
||||
if leader.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
@ -306,8 +306,9 @@ impl Fullnode {
|
|||
} else {
|
||||
let max_tick_height = {
|
||||
let ls_lock = bank.leader_scheduler.read().unwrap();
|
||||
ls_lock.max_height_for_leader(bank.tick_height())
|
||||
ls_lock.max_height_for_leader(bank.tick_height() + 1)
|
||||
};
|
||||
|
||||
// Start in leader mode.
|
||||
let (tpu, entry_receiver, tpu_exit) = Tpu::new(
|
||||
&bank,
|
||||
|
@ -468,7 +469,7 @@ impl Fullnode {
|
|||
|
||||
let max_tick_height = {
|
||||
let ls_lock = self.bank.leader_scheduler.read().unwrap();
|
||||
ls_lock.max_height_for_leader(tick_height)
|
||||
ls_lock.max_height_for_leader(tick_height + 1)
|
||||
};
|
||||
|
||||
let (tpu, blob_receiver, tpu_exit) = Tpu::new(
|
||||
|
|
|
@ -155,7 +155,8 @@ impl LeaderScheduler {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_leader_rotation_height(&self, height: u64) -> bool {
|
||||
// Returns true if the given height is the first tick of a slot
|
||||
pub fn is_first_slot_tick(&self, height: u64) -> bool {
|
||||
if self.use_only_bootstrap_leader {
|
||||
return false;
|
||||
}
|
||||
|
@ -164,16 +165,19 @@ impl LeaderScheduler {
|
|||
return false;
|
||||
}
|
||||
|
||||
(height - self.bootstrap_height) % self.leader_rotation_interval == 0
|
||||
(height - self.bootstrap_height) % self.leader_rotation_interval == 1
|
||||
}
|
||||
|
||||
pub fn count_until_next_leader_rotation(&self, height: u64) -> Option<u64> {
|
||||
// Returns the number of ticks until the last tick the current slot
|
||||
pub fn num_ticks_left_in_slot(&self, height: u64) -> Option<u64> {
|
||||
if self.use_only_bootstrap_leader {
|
||||
return None;
|
||||
}
|
||||
|
||||
if height < self.bootstrap_height {
|
||||
if height <= self.bootstrap_height {
|
||||
Some(self.bootstrap_height - height)
|
||||
} else if (height - self.bootstrap_height) % self.leader_rotation_interval == 0 {
|
||||
Some(0)
|
||||
} else {
|
||||
Some(
|
||||
self.leader_rotation_interval
|
||||
|
@ -190,7 +194,7 @@ impl LeaderScheduler {
|
|||
}
|
||||
|
||||
let result = {
|
||||
if height < self.bootstrap_height || self.leader_schedule.len() > 1 {
|
||||
if height <= self.bootstrap_height || self.leader_schedule.len() > 1 {
|
||||
// Two cases to consider:
|
||||
//
|
||||
// 1) If height is less than the bootstrap height, then the current leader's
|
||||
|
@ -202,8 +206,8 @@ impl LeaderScheduler {
|
|||
// to take over)
|
||||
//
|
||||
// Both above cases are calculated by the function:
|
||||
// count_until_next_leader_rotation() + height
|
||||
self.count_until_next_leader_rotation(height).expect(
|
||||
// num_ticks_left_in_slot() + height
|
||||
self.num_ticks_left_in_slot(height).expect(
|
||||
"Should return some value when not using default implementation
|
||||
of LeaderScheduler",
|
||||
) + height
|
||||
|
@ -255,7 +259,7 @@ impl LeaderScheduler {
|
|||
|
||||
// This covers cases where the schedule isn't yet generated.
|
||||
if self.last_seed_height == None {
|
||||
if height < self.bootstrap_height {
|
||||
if height <= self.bootstrap_height {
|
||||
return Some((self.bootstrap_leader, 0));
|
||||
} else {
|
||||
// If there's been no schedule generated yet before we reach the end of the
|
||||
|
@ -265,16 +269,23 @@ impl LeaderScheduler {
|
|||
}
|
||||
|
||||
// If we have a schedule, then just check that we are within the bounds of that
|
||||
// schedule [last_seed_height, last_seed_height + seed_rotation_interval).
|
||||
// schedule (last_seed_height, last_seed_height + seed_rotation_interval].
|
||||
// Leaders outside of this bound are undefined.
|
||||
let last_seed_height = self.last_seed_height.unwrap();
|
||||
if height >= last_seed_height + self.seed_rotation_interval || height < last_seed_height {
|
||||
|
||||
if height > last_seed_height + self.seed_rotation_interval || height <= last_seed_height {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Find index into the leader_schedule that this PoH height maps to
|
||||
let leader_slot = (height - self.bootstrap_height) / self.leader_rotation_interval + 1;
|
||||
let index = (height - last_seed_height) / self.leader_rotation_interval;
|
||||
// Find index into the leader_schedule that this PoH height maps to. Note by the time
|
||||
// we reach here, last_seed_height is not None, which implies:
|
||||
//
|
||||
// last_seed_height >= self.bootstrap_height
|
||||
//
|
||||
// Also we know from the recent range check that height > last_seed_height, so
|
||||
// height - self.bootstrap_height >= 1, so the below logic is safe.
|
||||
let leader_slot = (height - self.bootstrap_height - 1) / self.leader_rotation_interval + 1;
|
||||
let index = (height - last_seed_height - 1) / self.leader_rotation_interval;
|
||||
let validator_index = index as usize % self.leader_schedule.len();
|
||||
Some((self.leader_schedule[validator_index], leader_slot))
|
||||
}
|
||||
|
@ -290,7 +301,7 @@ impl LeaderScheduler {
|
|||
if slot_height == 0 {
|
||||
0
|
||||
} else {
|
||||
(slot_height - 1) * self.leader_rotation_interval + self.bootstrap_height
|
||||
(slot_height - 1) * self.leader_rotation_interval + self.bootstrap_height + 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,7 +338,7 @@ impl LeaderScheduler {
|
|||
}
|
||||
|
||||
// Called every seed_rotation_interval entries, generates the leader schedule
|
||||
// for the range of entries: [height, height + seed_rotation_interval)
|
||||
// for the range of entries: (height, height + seed_rotation_interval]
|
||||
fn generate_schedule(&mut self, height: u64, bank: &Bank) {
|
||||
assert!(height >= self.bootstrap_height);
|
||||
assert!((height - self.bootstrap_height) % self.seed_rotation_interval == 0);
|
||||
|
@ -598,6 +609,10 @@ mod tests {
|
|||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.get_scheduled_leader(bootstrap_height),
|
||||
Some((bootstrap_leader_id, 0))
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.get_scheduled_leader(bootstrap_height + 1),
|
||||
None
|
||||
);
|
||||
|
||||
|
@ -606,15 +621,15 @@ mod tests {
|
|||
leader_scheduler.generate_schedule(bootstrap_height, &bank);
|
||||
|
||||
// The leader outside of the newly generated schedule window:
|
||||
// [bootstrap_height, bootstrap_height + seed_rotation_interval)
|
||||
// (bootstrap_height, bootstrap_height + seed_rotation_interval]
|
||||
// should be undefined
|
||||
assert_eq!(
|
||||
leader_scheduler.get_scheduled_leader(bootstrap_height - 1),
|
||||
leader_scheduler.get_scheduled_leader(bootstrap_height),
|
||||
None,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
leader_scheduler.get_scheduled_leader(bootstrap_height + seed_rotation_interval),
|
||||
leader_scheduler.get_scheduled_leader(bootstrap_height + seed_rotation_interval + 1),
|
||||
None,
|
||||
);
|
||||
|
||||
|
@ -627,7 +642,7 @@ mod tests {
|
|||
let num_rounds = seed_rotation_interval / leader_rotation_interval;
|
||||
let mut start_leader_index = None;
|
||||
for i in 0..num_rounds {
|
||||
let begin_height = bootstrap_height + i * leader_rotation_interval;
|
||||
let begin_height = bootstrap_height + i * leader_rotation_interval + 1;
|
||||
let (current_leader, slot) = leader_scheduler
|
||||
.get_scheduled_leader(begin_height)
|
||||
.expect("Expected a leader from scheduler");
|
||||
|
@ -649,7 +664,7 @@ mod tests {
|
|||
validators[(start_leader_index.unwrap() + i as usize) % num_validators];
|
||||
assert_eq!(current_leader, expected_leader);
|
||||
assert_eq!(slot, i + 1);
|
||||
// Check that the same leader is in power for the next leader_rotation_interval entries
|
||||
// Check that the same leader is in power for the next leader_rotation_interval - 1 entries
|
||||
assert_eq!(
|
||||
leader_scheduler.get_scheduled_leader(begin_height + leader_rotation_interval - 1),
|
||||
Some((current_leader, slot))
|
||||
|
@ -1281,8 +1296,8 @@ mod tests {
|
|||
.id;
|
||||
let initial_vote_height = 1;
|
||||
|
||||
// No schedule generated yet, so for all heights < bootstrap height, the
|
||||
// max height will be bootstrap leader
|
||||
// No schedule generated yet, so for all heights <= bootstrap height, the
|
||||
// max height will be bootstrap height
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(0),
|
||||
Some(bootstrap_height)
|
||||
|
@ -1293,6 +1308,10 @@ mod tests {
|
|||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height),
|
||||
Some(bootstrap_height)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + 1),
|
||||
None
|
||||
);
|
||||
|
||||
|
@ -1306,19 +1325,23 @@ mod tests {
|
|||
leader_scheduler.generate_schedule(bootstrap_height, &bank);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height),
|
||||
Some(bootstrap_height + seed_rotation_interval)
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height - 1),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + 1),
|
||||
Some(bootstrap_height + seed_rotation_interval)
|
||||
);
|
||||
leader_scheduler.generate_schedule(bootstrap_height + seed_rotation_interval, &bank);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval),
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval + 1),
|
||||
Some(bootstrap_height + 2 * seed_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval - 1),
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval),
|
||||
None
|
||||
);
|
||||
|
||||
|
@ -1361,33 +1384,55 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height),
|
||||
Some(bootstrap_height + leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height - 1),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + 1),
|
||||
Some(bootstrap_height + leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + leader_rotation_interval - 1),
|
||||
Some(bootstrap_height + leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + leader_rotation_interval),
|
||||
Some(bootstrap_height + leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + leader_rotation_interval + 1),
|
||||
Some(bootstrap_height + 2 * leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval - 1),
|
||||
Some(bootstrap_height + seed_rotation_interval),
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval),
|
||||
Some(bootstrap_height + seed_rotation_interval),
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval + 1),
|
||||
None,
|
||||
);
|
||||
|
||||
// Generate another schedule
|
||||
leader_scheduler.generate_schedule(bootstrap_height + seed_rotation_interval, &bank);
|
||||
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval),
|
||||
Some(bootstrap_height + seed_rotation_interval + leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval - 1),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + seed_rotation_interval + 1),
|
||||
Some(bootstrap_height + seed_rotation_interval + leader_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler.max_height_for_leader(bootstrap_height + 2 * seed_rotation_interval),
|
||||
Some(bootstrap_height + 2 * seed_rotation_interval)
|
||||
);
|
||||
assert_eq!(
|
||||
leader_scheduler
|
||||
.max_height_for_leader(bootstrap_height + 2 * seed_rotation_interval + 1),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue