Change range of leader scheduler to match current broadcasts (#1920)

This commit is contained in:
carllin 2018-12-03 00:10:43 -08:00 committed by GitHub
parent 1fbbf13ec9
commit 4ae58cc854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 36 deletions

View File

@ -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 {

View File

@ -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(());
}

View File

@ -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(

View File

@ -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
);
}