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:
@@ -24,10 +24,10 @@ use solana_runtime::{
|
||||
commitment::VOTE_THRESHOLD_SIZE,
|
||||
transaction_batch::TransactionBatch,
|
||||
transaction_utils::OrderedIterator,
|
||||
vote_account::ArcVoteAccount,
|
||||
vote_sender_types::ReplayVoteSender,
|
||||
};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
clock::{Slot, MAX_PROCESSING_AGE},
|
||||
genesis_config::GenesisConfig,
|
||||
hash::Hash,
|
||||
@@ -36,7 +36,6 @@ use solana_sdk::{
|
||||
timing::duration_as_ms,
|
||||
transaction::{Result, Transaction, TransactionError},
|
||||
};
|
||||
use solana_vote_program::vote_state::VoteState;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::{HashMap, HashSet},
|
||||
@@ -868,8 +867,11 @@ fn load_frozen_forks(
|
||||
// for newer cluster confirmed roots
|
||||
let new_root_bank = {
|
||||
if *root == max_root {
|
||||
supermajority_root_from_vote_accounts(bank.slot(), bank.total_epoch_stake(), bank.vote_accounts()
|
||||
.into_iter()).and_then(|supermajority_root| {
|
||||
supermajority_root_from_vote_accounts(
|
||||
bank.slot(),
|
||||
bank.total_epoch_stake(),
|
||||
bank.vote_accounts(),
|
||||
).and_then(|supermajority_root| {
|
||||
if supermajority_root > *root {
|
||||
// If there's a cluster confirmed root greater than our last
|
||||
// replayed root, then beccause the cluster confirmed root should
|
||||
@@ -960,30 +962,28 @@ fn supermajority_root(roots: &[(Slot, u64)], total_epoch_stake: u64) -> Option<S
|
||||
fn supermajority_root_from_vote_accounts<I>(
|
||||
bank_slot: Slot,
|
||||
total_epoch_stake: u64,
|
||||
vote_accounts_iter: I,
|
||||
vote_accounts: I,
|
||||
) -> Option<Slot>
|
||||
where
|
||||
I: Iterator<Item = (Pubkey, (u64, Account))>,
|
||||
I: IntoIterator<Item = (Pubkey, (u64, ArcVoteAccount))>,
|
||||
{
|
||||
let mut roots_stakes: Vec<(Slot, u64)> = vote_accounts_iter
|
||||
let mut roots_stakes: Vec<(Slot, u64)> = vote_accounts
|
||||
.into_iter()
|
||||
.filter_map(|(key, (stake, account))| {
|
||||
if stake == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let vote_state = VoteState::from(&account);
|
||||
if vote_state.is_none() {
|
||||
warn!(
|
||||
"Unable to get vote_state from account {} in bank: {}",
|
||||
key, bank_slot
|
||||
);
|
||||
return None;
|
||||
match account.vote_state().as_ref() {
|
||||
Err(_) => {
|
||||
warn!(
|
||||
"Unable to get vote_state from account {} in bank: {}",
|
||||
key, bank_slot
|
||||
);
|
||||
None
|
||||
}
|
||||
Ok(vote_state) => vote_state.root_slot.map(|root_slot| (root_slot, stake)),
|
||||
}
|
||||
|
||||
vote_state
|
||||
.unwrap()
|
||||
.root_slot
|
||||
.map(|root_slot| (root_slot, stake))
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1112,6 +1112,7 @@ pub mod tests {
|
||||
self, create_genesis_config_with_vote_accounts, ValidatorVoteKeypairs,
|
||||
};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
epoch_schedule::EpochSchedule,
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
@@ -1122,7 +1123,7 @@ pub mod tests {
|
||||
};
|
||||
use solana_vote_program::{
|
||||
self,
|
||||
vote_state::{VoteStateVersions, MAX_LOCKOUT_HISTORY},
|
||||
vote_state::{VoteState, VoteStateVersions, MAX_LOCKOUT_HISTORY},
|
||||
vote_transaction,
|
||||
};
|
||||
use std::{collections::BTreeSet, sync::RwLock};
|
||||
@@ -3146,7 +3147,7 @@ pub mod tests {
|
||||
#[test]
|
||||
fn test_supermajority_root_from_vote_accounts() {
|
||||
let convert_to_vote_accounts =
|
||||
|roots_stakes: Vec<(Slot, u64)>| -> Vec<(Pubkey, (u64, Account))> {
|
||||
|roots_stakes: Vec<(Slot, u64)>| -> Vec<(Pubkey, (u64, ArcVoteAccount))> {
|
||||
roots_stakes
|
||||
.into_iter()
|
||||
.map(|(root, stake)| {
|
||||
@@ -3156,7 +3157,10 @@ pub mod tests {
|
||||
Account::new(1, VoteState::size_of(), &solana_vote_program::id());
|
||||
let versioned = VoteStateVersions::Current(Box::new(vote_state));
|
||||
VoteState::serialize(&versioned, &mut vote_account.data).unwrap();
|
||||
(solana_sdk::pubkey::new_rand(), (stake, vote_account))
|
||||
(
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
(stake, ArcVoteAccount::from(vote_account)),
|
||||
)
|
||||
})
|
||||
.collect_vec()
|
||||
};
|
||||
|
Reference in New Issue
Block a user