Absorb LeaderScheduler's rank_active_set()

Delete overly-complicated tests
This commit is contained in:
Greg Fitzgerald 2019-02-20 12:24:29 -07:00
parent 1c2169aec7
commit e9daf57d7f
2 changed files with 35 additions and 107 deletions

View File

@ -60,6 +60,10 @@ impl ActiveStakers {
Self::new_with_bounds(bank, DEFAULT_ACTIVE_WINDOW_TICK_LENGTH, bank.tick_height())
}
pub fn ranked_stakes(&self) -> Vec<(Pubkey, u64)> {
self.stakes.clone()
}
/// Return the pubkeys of each staker.
pub fn pubkeys(&self) -> Vec<Pubkey> {
self.stakes.iter().map(|(pubkey, _stake)| *pubkey).collect()
@ -77,6 +81,7 @@ impl ActiveStakers {
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use solana_runtime::bank::Bank;
@ -294,4 +299,31 @@ pub mod tests {
assert_eq!(result.len(), 0);
}
}
#[test]
fn test_rank_stakes_basic() {
let pubkey0 = Keypair::new().pubkey();
let pubkey1 = Keypair::new().pubkey();
let mut stakes = vec![(pubkey0, 2), (pubkey1, 1)];
rank_stakes(&mut stakes);
assert_eq!(stakes, vec![(pubkey1, 1), (pubkey0, 2)]);
}
#[test]
fn test_rank_stakes_with_dup() {
let pubkey0 = Keypair::new().pubkey();
let pubkey1 = Keypair::new().pubkey();
let mut stakes = vec![(pubkey0, 1), (pubkey1, 2), (pubkey0, 1)];
rank_stakes(&mut stakes);
assert_eq!(stakes, vec![(pubkey0, 1), (pubkey1, 2)]);
}
#[test]
fn test_rank_stakes_with_equal_stakes() {
let pubkey0 = Pubkey::default();
let pubkey1 = Keypair::new().pubkey();
let mut stakes = vec![(pubkey0, 1), (pubkey1, 1)];
rank_stakes(&mut stakes);
assert_eq!(stakes, vec![(pubkey0, 1), (pubkey1, 1)]);
}
}

View File

@ -1,7 +1,7 @@
//! The `leader_scheduler` module implements a structure and functions for tracking and
//! managing the schedule for leader rotation
use crate::active_stakers::{self, ActiveStakers, DEFAULT_ACTIVE_WINDOW_TICK_LENGTH};
use crate::active_stakers::{ActiveStakers, DEFAULT_ACTIVE_WINDOW_TICK_LENGTH};
use crate::entry::{create_ticks, next_entry_mut, Entry};
use crate::voting_keypair::VotingKeypair;
use bincode::serialize;
@ -228,10 +228,9 @@ impl LeaderScheduler {
}
self.seed = Self::calculate_seed(tick_height);
let active_set =
let ranked_active_set =
ActiveStakers::new_with_bounds(&bank, self.active_window_tick_length, tick_height)
.pubkeys();
let ranked_active_set = Self::rank_active_set(bank, active_set);
.ranked_stakes();
if ranked_active_set.is_empty() {
info!(
@ -288,22 +287,6 @@ impl LeaderScheduler {
);
}
fn rank_active_set(bank: &Bank, active: Vec<Pubkey>) -> Vec<(Pubkey, u64)> {
let mut active_accounts: Vec<_> = active
.into_iter()
.filter_map(|pubkey| {
let stake = bank.get_balance(&pubkey);
if stake > 0 {
Some((pubkey, stake as u64))
} else {
None
}
})
.collect();
active_stakers::rank_stakes(&mut active_accounts);
active_accounts
}
fn calculate_seed(tick_height: u64) -> u64 {
let hash = hash(&serialize(&tick_height).unwrap());
let bytes = hash.as_ref();
@ -578,93 +561,6 @@ pub mod tests {
}
}
#[test]
fn test_rank_active_set() {
let num_validators: usize = 101;
// Give genesis_block sum(1..num_validators) tokens
let (genesis_block, mint_keypair) =
GenesisBlock::new((((num_validators + 1) / 2) * (num_validators + 1)) as u64);
let bank = Bank::new(&genesis_block);
let mut validators = vec![];
let last_id = genesis_block.last_id();
for i in 0..num_validators {
let new_validator = Keypair::new();
let new_pubkey = new_validator.pubkey();
validators.push(new_validator);
bank.transfer(
(num_validators - i) as u64,
&mint_keypair,
new_pubkey,
last_id,
)
.unwrap();
}
let validator_pubkeys: Vec<_> = validators.iter().map(Keypair::pubkey).collect();
let result = LeaderScheduler::rank_active_set(&bank, validator_pubkeys);
assert_eq!(result.len(), validators.len());
// Expect the result to be the reverse of the list we passed into the rank_active_set()
for (i, (pubkey, stake)) in result.into_iter().enumerate() {
assert_eq!(stake, i as u64 + 1);
assert_eq!(pubkey, validators[num_validators - i - 1].pubkey());
}
// Transfer all the tokens to a new set of validators, old validators should now
// have balance of zero and get filtered out of the rankings
let mut new_validators = vec![];
for i in 0..num_validators {
let new_validator = Keypair::new();
let new_pubkey = new_validator.pubkey();
new_validators.push(new_validator);
bank.transfer(
(num_validators - i) as u64,
&validators[i],
new_pubkey,
last_id,
)
.unwrap();
}
let all_validators: Vec<Pubkey> = validators
.iter()
.chain(new_validators.iter())
.map(Keypair::pubkey)
.collect();
let result = LeaderScheduler::rank_active_set(&bank, all_validators);
assert_eq!(result.len(), new_validators.len());
for (i, (pubkey, balance)) in result.into_iter().enumerate() {
assert_eq!(balance, i as u64 + 1);
assert_eq!(pubkey, new_validators[num_validators - i - 1].pubkey());
}
// Break ties between validators with the same balances using public key
let (genesis_block, mint_keypair) = GenesisBlock::new((num_validators + 1) as u64);
let bank = Bank::new(&genesis_block);
let mut tied_validators_pk = vec![];
let last_id = genesis_block.last_id();
for _i in 0..num_validators {
let new_validator = Keypair::new();
let new_pubkey = new_validator.pubkey();
tied_validators_pk.push(new_pubkey);
assert!(bank.get_balance(&mint_keypair.pubkey()) > 1);
bank.transfer(1, &mint_keypair, new_pubkey, last_id)
.unwrap();
}
let mut sorted = tied_validators_pk.clone();
sorted.sort_by(|pk1, pk2| pk1.cmp(pk2));
let result = LeaderScheduler::rank_active_set(&bank, tied_validators_pk);
assert_eq!(result.len(), sorted.len());
for (i, (pk, s)) in result.into_iter().enumerate() {
assert_eq!(s, 1);
assert_eq!(pk, sorted[i]);
}
}
#[test]
fn test_choose_account() {
let tokens = vec![10, 30, 50, 5, 1];