From aad0d90fddc4b63bb415ba4d3625e1fb69a6e093 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 25 Feb 2019 07:23:21 -0700 Subject: [PATCH] Use epoch_height to generate schedule instead of last_id I had suggested the last_id, but that puts an unnecessary dependency on LastIdsQueue. Using epoch height is pretty interesting in that given the same set of stakers, you simply increment the seed once per epoch. Also, tighten up the LeaderSchedule code. --- runtime/src/leader_schedule.rs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/runtime/src/leader_schedule.rs b/runtime/src/leader_schedule.rs index 8c95fe9105..f4acad54cd 100644 --- a/runtime/src/leader_schedule.rs +++ b/runtime/src/leader_schedule.rs @@ -12,27 +12,20 @@ pub struct LeaderSchedule { } impl LeaderSchedule { - pub fn new(ids_and_stakes: &[(Pubkey, u64)], seed: &[u8; 32], len: u64) -> Self { - let (pubkeys, stakes): (Vec, Vec) = ids_and_stakes - .iter() - .map(|&(ref id, ref stake)| (id, stake)) - .unzip(); - - // Should have no zero weighted stakes - let mut rng = ChaChaRng::from_seed(*seed); + // Note: passing in zero stakers will cause a panic. + pub fn new(ids_and_stakes: &[(Pubkey, u64)], seed: [u8; 32], len: u64) -> Self { + let (ids, stakes): (Vec<_>, Vec<_>) = ids_and_stakes.iter().cloned().unzip(); + let rng = &mut ChaChaRng::from_seed(seed); let weighted_index = WeightedIndex::new(stakes).unwrap(); - let slot_leaders = (0..len) - .map(|_| pubkeys[weighted_index.sample(&mut rng)]) - .collect(); - + let slot_leaders = (0..len).map(|_| ids[weighted_index.sample(rng)]).collect(); Self { slot_leaders } } pub fn new_with_bank(bank: &Bank) -> Self { + let id_and_stakes: Vec<_> = bank.staked_nodes().into_iter().collect(); let mut seed = [0u8; 32]; - seed.copy_from_slice(bank.last_id().as_ref()); - let stakes: Vec<_> = bank.staked_nodes().into_iter().collect(); - Self::new(&stakes, &seed, bank.slots_per_epoch()) + seed[0..8].copy_from_slice(&bank.epoch_height().to_le_bytes()); + Self::new(&id_and_stakes, seed, bank.slots_per_epoch()) } } @@ -73,8 +66,8 @@ mod tests { let mut seed_bytes = [0u8; 32]; seed_bytes.copy_from_slice(seed.as_ref()); let len = num_keys * 10; - let leader_schedule = LeaderSchedule::new(&stakes, &seed_bytes, len); - let leader_schedule2 = LeaderSchedule::new(&stakes, &seed_bytes, len); + let leader_schedule = LeaderSchedule::new(&stakes, seed_bytes, len); + let leader_schedule2 = LeaderSchedule::new(&stakes, seed_bytes, len); assert_eq!(leader_schedule.slot_leaders.len() as u64, len); // Check that the same schedule is reproducibly generated assert_eq!(leader_schedule, leader_schedule2);