changed vote_states to vote_accounts, more useable (#3047)

This commit is contained in:
Rob Walker 2019-03-01 17:22:49 -08:00 committed by GitHub
parent 29d12d9ff1
commit 54417acfba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 40 additions and 23 deletions

View File

@ -113,7 +113,7 @@ pub struct Bank {
/// staked nodes on epoch boundaries, saved off when a bank.slot() is at /// staked nodes on epoch boundaries, saved off when a bank.slot() is at
/// a leader schedule boundary /// a leader schedule boundary
epoch_vote_states: HashMap<u64, HashMap<Pubkey, VoteState>>, epoch_vote_accounts: HashMap<u64, HashMap<Pubkey, Account>>,
} }
impl Bank { impl Bank {
@ -129,9 +129,9 @@ impl Bank {
// genesis needs stakes for all epochs up to the epoch implied by // genesis needs stakes for all epochs up to the epoch implied by
// slot = 0 and genesis configuration // slot = 0 and genesis configuration
let vote_states = bank.vote_states(|_, _| true); let vote_accounts = bank.vote_accounts(|k, v| Some((*k, v.clone())));
for i in 0..=bank.epoch_from_stakers_slot_offset() { for i in 0..=bank.epoch_from_stakers_slot_offset() {
bank.epoch_vote_states.insert(i, vote_states.clone()); bank.epoch_vote_accounts.insert(i, vote_accounts.clone());
} }
bank bank
@ -154,17 +154,17 @@ impl Bank {
bank.accounts = Some(parent.accounts()); bank.accounts = Some(parent.accounts());
bank.accounts().new_from_parent(bank.slot, parent.slot); bank.accounts().new_from_parent(bank.slot, parent.slot);
bank.epoch_vote_states = { bank.epoch_vote_accounts = {
let mut epoch_vote_states = parent.epoch_vote_states.clone(); let mut epoch_vote_accounts = parent.epoch_vote_accounts.clone();
let epoch = bank.epoch_from_stakers_slot_offset(); let epoch = bank.epoch_from_stakers_slot_offset();
// update epoch_vote_states cache // update epoch_vote_states cache
// if my parent didn't populate for this epoch, we've // if my parent didn't populate for this epoch, we've
// crossed a boundary // crossed a boundary
if epoch_vote_states.get(&epoch).is_none() { if epoch_vote_accounts.get(&epoch).is_none() {
epoch_vote_states.insert(epoch, bank.vote_states(|_, _| true)); epoch_vote_accounts.insert(epoch, bank.vote_accounts(|k, v| Some((*k, v.clone()))));
} }
epoch_vote_states epoch_vote_accounts
}; };
bank bank
@ -754,14 +754,27 @@ impl Bank {
(self.slot + self.stakers_slot_offset) / self.slots_per_epoch (self.slot + self.stakers_slot_offset) / self.slots_per_epoch
} }
pub fn epoch_vote_states<F, T>(&self, epoch: u64, check: F) -> Option<HashMap<Pubkey, T>> /// current vote accounts for this bank
pub fn vote_accounts<F, T>(&self, filter: F) -> HashMap<Pubkey, T>
where where
F: Fn(&Pubkey, &VoteState) -> Option<(Pubkey, T)>, F: Fn(&Pubkey, &Account) -> Option<(Pubkey, T)>,
{ {
self.epoch_vote_states.get(&epoch).map(|vote_states| { self.accounts()
vote_states .get_vote_accounts(self.slot)
.iter()
.filter_map(|(pubkey, account)| filter(pubkey, account))
.collect()
}
/// vote accounts for the specific epoch
pub fn epoch_vote_accounts<F, T>(&self, epoch: u64, filter: F) -> Option<HashMap<Pubkey, T>>
where
F: Fn(&Pubkey, &Account) -> Option<(Pubkey, T)>,
{
self.epoch_vote_accounts.get(&epoch).map(|accounts| {
accounts
.iter() .iter()
.filter_map(|(p, vote_state)| check(p, vote_state)) .filter_map(|(pubkey, account)| filter(pubkey, account))
.collect() .collect()
}) })
} }
@ -1457,7 +1470,7 @@ mod tests {
} }
#[test] #[test]
fn test_bank_epoch_vote_states() { fn test_bank_epoch_vote_accounts() {
let leader_id = Keypair::new().pubkey(); let leader_id = Keypair::new().pubkey();
let leader_tokens = 2; let leader_tokens = 2;
let (mut genesis_block, _) = GenesisBlock::new_with_leader(5, leader_id, leader_tokens); let (mut genesis_block, _) = GenesisBlock::new_with_leader(5, leader_id, leader_tokens);
@ -1473,17 +1486,21 @@ mod tests {
let parent = Arc::new(Bank::new(&genesis_block)); let parent = Arc::new(Bank::new(&genesis_block));
let vote_states0 = parent.epoch_vote_states(0, |pubkey, vote_state| { let vote_accounts0 = parent.epoch_vote_accounts(0, |pubkey, account| {
if vote_state.delegate_id == leader_id { if let Ok(vote_state) = VoteState::deserialize(&account.userdata) {
Some((*pubkey, true)) if vote_state.delegate_id == leader_id {
Some((*pubkey, true))
} else {
None
}
} else { } else {
None None
} }
}); });
assert!(vote_states0.is_some()); assert!(vote_accounts0.is_some());
assert!(vote_states0.iter().len() != 0); assert!(vote_accounts0.iter().len() != 0);
fn all(key: &Pubkey, _vote_state: &VoteState) -> Option<(Pubkey, Option<()>)> { fn all(key: &Pubkey, _account: &Account) -> Option<(Pubkey, Option<()>)> {
Some((*key, None)) Some((*key, None))
} }
@ -1492,7 +1509,7 @@ mod tests {
if i > STAKERS_SLOT_OFFSET / SLOTS_PER_EPOCH { if i > STAKERS_SLOT_OFFSET / SLOTS_PER_EPOCH {
break; break;
} }
assert!(parent.epoch_vote_states(i, all).is_some()); assert!(parent.epoch_vote_accounts(i, all).is_some());
i += 1; i += 1;
} }
@ -1503,7 +1520,7 @@ mod tests {
SLOTS_PER_EPOCH - (STAKERS_SLOT_OFFSET % SLOTS_PER_EPOCH), SLOTS_PER_EPOCH - (STAKERS_SLOT_OFFSET % SLOTS_PER_EPOCH),
); );
assert!(child.epoch_vote_states(i, all).is_some()); assert!(child.epoch_vote_accounts(i, all).is_some());
// child crosses epoch boundary but isn't the first slot in the epoch // child crosses epoch boundary but isn't the first slot in the epoch
let child = Bank::new_from_parent( let child = Bank::new_from_parent(
@ -1511,7 +1528,7 @@ mod tests {
leader_id, leader_id,
SLOTS_PER_EPOCH - (STAKERS_SLOT_OFFSET % SLOTS_PER_EPOCH) + 1, SLOTS_PER_EPOCH - (STAKERS_SLOT_OFFSET % SLOTS_PER_EPOCH) + 1,
); );
assert!(child.epoch_vote_states(i, all).is_some()); assert!(child.epoch_vote_accounts(i, all).is_some());
} }
} }