caches vote-state de-serialized from vote accounts (#13795)

Gossip and other places repeatedly de-serialize vote-state stored in
vote accounts. Ideally the first de-serialization should cache the
result.

This commit adds new VoteAccount type which lazily de-serializes
VoteState from Account data and caches the result internally.

Serialize and Deserialize traits are manually implemented to match
existing code. So, despite changes to frozen_abi, this commit should be
backward compatible.
This commit is contained in:
behzad nouri
2020-11-30 17:18:33 +00:00
committed by GitHub
parent 6203d1c94c
commit e1793e5a13
18 changed files with 433 additions and 198 deletions

View File

@@ -1,7 +1,6 @@
use crate::stakes::Stakes;
use crate::{stakes::Stakes, vote_account::ArcVoteAccount};
use serde::{Deserialize, Serialize};
use solana_sdk::{account::Account, clock::Epoch, pubkey::Pubkey};
use solana_vote_program::vote_state::VoteState;
use solana_sdk::{clock::Epoch, pubkey::Pubkey};
use std::{collections::HashMap, sync::Arc};
pub type NodeIdToVoteAccounts = HashMap<Pubkey, NodeVoteAccounts>;
@@ -58,7 +57,7 @@ impl EpochStakes {
}
fn parse_epoch_vote_accounts(
epoch_vote_accounts: &HashMap<Pubkey, (u64, Account)>,
epoch_vote_accounts: &HashMap<Pubkey, (u64, ArcVoteAccount)>,
leader_schedule_epoch: Epoch,
) -> (u64, NodeIdToVoteAccounts, EpochAuthorizedVoters) {
let mut node_id_to_vote_accounts: NodeIdToVoteAccounts = HashMap::new();
@@ -69,19 +68,21 @@ impl EpochStakes {
let epoch_authorized_voters = epoch_vote_accounts
.iter()
.filter_map(|(key, (stake, account))| {
let vote_state = VoteState::from(&account);
if vote_state.is_none() {
datapoint_warn!(
"parse_epoch_vote_accounts",
(
"warn",
format!("Unable to get vote_state from account {}", key),
String
),
);
return None;
}
let vote_state = vote_state.unwrap();
let vote_state = account.vote_state();
let vote_state = match vote_state.as_ref() {
Err(_) => {
datapoint_warn!(
"parse_epoch_vote_accounts",
(
"warn",
format!("Unable to get vote_state from account {}", key),
String
),
);
return None;
}
Ok(vote_state) => vote_state,
};
if *stake > 0 {
// Read out the authorized voters
let authorized_voter = vote_state
@@ -113,6 +114,7 @@ impl EpochStakes {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use solana_sdk::account::Account;
use solana_vote_program::vote_state::create_account_with_authorized;
use std::iter;
@@ -181,9 +183,12 @@ pub(crate) mod tests {
let epoch_vote_accounts: HashMap<_, _> = vote_accounts_map
.iter()
.flat_map(|(_, vote_accounts)| {
vote_accounts
.iter()
.map(|v| (v.vote_account, (stake_per_account, v.account.clone())))
vote_accounts.iter().map(|v| {
(
v.vote_account,
(stake_per_account, ArcVoteAccount::from(v.account.clone())),
)
})
})
.collect();