Get rid of the HashSet special case

ActiveSet ranks on construction. get_active_set() is on its way out.
This is a stepping stone.
This commit is contained in:
Greg Fitzgerald 2019-02-20 10:49:25 -07:00
parent 6e24a4aa50
commit b13fb6097f
1 changed files with 23 additions and 30 deletions

View File

@ -6,7 +6,6 @@ use crate::entry::{create_ticks, next_entry_mut, Entry};
use crate::voting_keypair::VotingKeypair; use crate::voting_keypair::VotingKeypair;
use bincode::serialize; use bincode::serialize;
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use hashbrown::HashSet;
use solana_runtime::bank::Bank; use solana_runtime::bank::Bank;
use solana_sdk::hash::{hash, Hash}; use solana_sdk::hash::{hash, Hash};
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
@ -202,10 +201,7 @@ impl LeaderScheduler {
} }
} }
// TODO: We use a HashSet for now because a single validator could potentially register fn get_active_set(&mut self, tick_height: u64, bank: &Bank) -> Vec<Pubkey> {
// multiple vote account. Once that is no longer possible (see the TODO in vote_program.rs,
// process_transaction(), case VoteInstruction::RegisterAccount), we can use a vector.
fn get_active_set(&mut self, tick_height: u64, bank: &Bank) -> HashSet<Pubkey> {
let upper_bound = tick_height; let upper_bound = tick_height;
let lower_bound = tick_height.saturating_sub(self.active_window_tick_length); let lower_bound = tick_height.saturating_sub(self.active_window_tick_length);
trace!( trace!(
@ -214,8 +210,7 @@ impl LeaderScheduler {
upper_bound upper_bound
); );
let active_stakers = ActiveStakers::new_with_upper_bound(&bank, lower_bound, upper_bound); ActiveStakers::new_with_upper_bound(&bank, lower_bound, upper_bound).pubkeys()
active_stakers.pubkeys().into_iter().collect()
} }
// Updates the leader schedule to include ticks from tick_height to the first tick of the next epoch // Updates the leader schedule to include ticks from tick_height to the first tick of the next epoch
@ -431,17 +426,8 @@ pub mod tests {
use crate::active_stakers::tests::{new_vote_account_with_vote, push_vote}; use crate::active_stakers::tests::{new_vote_account_with_vote, push_vote};
use hashbrown::HashSet; use hashbrown::HashSet;
use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_TOKENS}; use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_TOKENS};
use std::hash::Hash as StdHash;
use std::iter::FromIterator;
use std::sync::RwLock; use std::sync::RwLock;
fn to_hashset_owned<T>(slice: &[T]) -> HashSet<T>
where
T: Eq + StdHash + Clone,
{
HashSet::from_iter(slice.iter().cloned())
}
fn run_scheduler_test(num_validators: usize, ticks_per_slot: u64, ticks_per_epoch: u64) { fn run_scheduler_test(num_validators: usize, ticks_per_slot: u64, ticks_per_epoch: u64) {
info!( info!(
"run_scheduler_test({}, {}, {})", "run_scheduler_test({}, {}, {})",
@ -613,16 +599,16 @@ pub mod tests {
let bank = Bank::new(&genesis_block); let bank = Bank::new(&genesis_block);
let mut leader_scheduler = LeaderScheduler::new_with_bank(&leader_scheduler_config, &bank); let mut leader_scheduler = LeaderScheduler::new_with_bank(&leader_scheduler_config, &bank);
let bootstrap_ids = to_hashset_owned(&vec![genesis_block.bootstrap_leader_id]); let bootstrap_ids = vec![genesis_block.bootstrap_leader_id];
// Insert a bunch of votes at height "start_height" // Insert a bunch of votes at height "start_height"
let start_height = 3; let start_height = 3;
let num_old_ids = 20; let num_old_ids = 20;
let mut old_ids = HashSet::new(); let mut old_ids = vec![];
for _ in 0..num_old_ids { for _ in 0..num_old_ids {
let new_keypair = Keypair::new(); let new_keypair = Keypair::new();
let pk = new_keypair.pubkey(); let pk = new_keypair.pubkey();
old_ids.insert(pk.clone()); old_ids.push(pk);
// Give the account some stake // Give the account some stake
bank.transfer(5, &mint_keypair, pk, genesis_block.last_id()) bank.transfer(5, &mint_keypair, pk, genesis_block.last_id())
@ -631,14 +617,15 @@ pub mod tests {
// Create a vote account and push a vote // Create a vote account and push a vote
new_vote_account_with_vote(&new_keypair, &Keypair::new(), &bank, 1, start_height); new_vote_account_with_vote(&new_keypair, &Keypair::new(), &bank, 1, start_height);
} }
old_ids.sort();
// Insert a bunch of votes at height "start_height + active_window_tick_length" // Insert a bunch of votes at height "start_height + active_window_tick_length"
let num_new_ids = 10; let num_new_ids = 10;
let mut new_ids = HashSet::new(); let mut new_ids = vec![];
for _ in 0..num_new_ids { for _ in 0..num_new_ids {
let new_keypair = Keypair::new(); let new_keypair = Keypair::new();
let pk = new_keypair.pubkey(); let pk = new_keypair.pubkey();
new_ids.insert(pk); new_ids.push(pk);
// Give the account some stake // Give the account some stake
bank.transfer(5, &mint_keypair, pk, genesis_block.last_id()) bank.transfer(5, &mint_keypair, pk, genesis_block.last_id())
.unwrap(); .unwrap();
@ -647,6 +634,7 @@ pub mod tests {
let tick_height = start_height + active_window_tick_length + 1; let tick_height = start_height + active_window_tick_length + 1;
new_vote_account_with_vote(&new_keypair, &Keypair::new(), &bank, 1, tick_height); new_vote_account_with_vote(&new_keypair, &Keypair::new(), &bank, 1, tick_height);
} }
new_ids.sort();
// Query for the active set at various heights // Query for the active set at various heights
let result = leader_scheduler.get_active_set(0, &bank); let result = leader_scheduler.get_active_set(0, &bank);
@ -655,24 +643,29 @@ pub mod tests {
let result = leader_scheduler.get_active_set(start_height - 1, &bank); let result = leader_scheduler.get_active_set(start_height - 1, &bank);
assert_eq!(result, bootstrap_ids); assert_eq!(result, bootstrap_ids);
let result = let mut result =
leader_scheduler.get_active_set(active_window_tick_length + start_height - 1, &bank); leader_scheduler.get_active_set(active_window_tick_length + start_height - 1, &bank);
result.sort();
assert_eq!(result, old_ids); assert_eq!(result, old_ids);
let result = let mut result =
leader_scheduler.get_active_set(active_window_tick_length + start_height, &bank); leader_scheduler.get_active_set(active_window_tick_length + start_height, &bank);
result.sort();
assert_eq!(result, old_ids); assert_eq!(result, old_ids);
let result = let mut result =
leader_scheduler.get_active_set(active_window_tick_length + start_height + 1, &bank); leader_scheduler.get_active_set(active_window_tick_length + start_height + 1, &bank);
result.sort();
assert_eq!(result, new_ids); assert_eq!(result, new_ids);
let result = let mut result =
leader_scheduler.get_active_set(2 * active_window_tick_length + start_height, &bank); leader_scheduler.get_active_set(2 * active_window_tick_length + start_height, &bank);
result.sort();
assert_eq!(result, new_ids); assert_eq!(result, new_ids);
let result = leader_scheduler let mut result = leader_scheduler
.get_active_set(2 * active_window_tick_length + start_height + 1, &bank); .get_active_set(2 * active_window_tick_length + start_height + 1, &bank);
result.sort();
assert_eq!(result, new_ids); assert_eq!(result, new_ids);
let result = leader_scheduler let result = leader_scheduler
@ -946,10 +939,10 @@ pub mod tests {
{ {
let mut leader_scheduler = leader_scheduler.write().unwrap(); let mut leader_scheduler = leader_scheduler.write().unwrap();
let result = leader_scheduler.get_active_set(0, &bank); let result = leader_scheduler.get_active_set(0, &bank);
assert_eq!(result, to_hashset_owned(&vec![leader_id])); assert_eq!(result, vec![leader_id]);
let result = leader_scheduler.get_active_set(active_window_tick_length, &bank); let result = leader_scheduler.get_active_set(active_window_tick_length, &bank);
assert_eq!(result, to_hashset_owned(&vec![leader_id])); assert_eq!(result, vec![leader_id]);
let result = leader_scheduler.get_active_set(active_window_tick_length + 1, &bank); let result = leader_scheduler.get_active_set(active_window_tick_length + 1, &bank);
assert!(result.is_empty()); assert!(result.is_empty());
@ -965,7 +958,7 @@ pub mod tests {
{ {
let mut leader_scheduler = leader_scheduler.write().unwrap(); let mut leader_scheduler = leader_scheduler.write().unwrap();
let result = leader_scheduler.get_active_set(active_window_tick_length + 1, &bank); let result = leader_scheduler.get_active_set(active_window_tick_length + 1, &bank);
assert_eq!(result, to_hashset_owned(&vec![leader_id])); assert_eq!(result, vec![leader_id]);
let result = leader_scheduler.get_active_set(active_window_tick_length + 2, &bank); let result = leader_scheduler.get_active_set(active_window_tick_length + 2, &bank);
assert!(result.is_empty()); assert!(result.is_empty());
@ -977,7 +970,7 @@ pub mod tests {
{ {
let mut leader_scheduler = leader_scheduler.write().unwrap(); let mut leader_scheduler = leader_scheduler.write().unwrap();
let result = leader_scheduler.get_active_set(active_window_tick_length + 2, &bank); let result = leader_scheduler.get_active_set(active_window_tick_length + 2, &bank);
assert_eq!(result, to_hashset_owned(&vec![leader_id])); assert_eq!(result, vec![leader_id]);
let result = leader_scheduler.get_active_set(active_window_tick_length + 3, &bank); let result = leader_scheduler.get_active_set(active_window_tick_length + 3, &bank);
assert!(result.is_empty()); assert!(result.is_empty());