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,16 +1,16 @@
//! Stakes serve as a cache of stake and vote accounts to derive
//! node stakes
use crate::vote_account::ArcVoteAccount;
use solana_sdk::{
account::Account, clock::Epoch, pubkey::Pubkey, sysvar::stake_history::StakeHistory,
};
use solana_stake_program::stake_state::{new_stake_history_entry, Delegation, StakeState};
use solana_vote_program::vote_state::VoteState;
use std::collections::HashMap;
#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)]
pub struct Stakes {
/// vote accounts
vote_accounts: HashMap<Pubkey, (u64, Account)>,
vote_accounts: HashMap<Pubkey, (u64, ArcVoteAccount)>,
/// stake_delegations
stake_delegations: HashMap<Pubkey, Delegation>,
@@ -106,7 +106,7 @@ impl Stakes {
+ self
.vote_accounts
.iter()
.map(|(_pubkey, (_staked, vote_account))| vote_account.lamports)
.map(|(_pubkey, (_staked, vote_account))| vote_account.lamports())
.sum::<u64>()
}
@@ -121,7 +121,7 @@ impl Stakes {
pubkey: &Pubkey,
account: &Account,
fix_stake_deactivate: bool,
) -> Option<Account> {
) -> Option<ArcVoteAccount> {
if solana_vote_program::check_id(&account.owner) {
let old = self.vote_accounts.remove(pubkey);
if account.lamports != 0 {
@@ -137,7 +137,8 @@ impl Stakes {
|v| v.0,
);
self.vote_accounts.insert(*pubkey, (stake, account.clone()));
self.vote_accounts
.insert(*pubkey, (stake, ArcVoteAccount::from(account.clone())));
}
old.map(|(_, account)| account)
} else if solana_stake_program::check_id(&account.owner) {
@@ -191,7 +192,7 @@ impl Stakes {
}
}
pub fn vote_accounts(&self) -> &HashMap<Pubkey, (u64, Account)> {
pub fn vote_accounts(&self) -> &HashMap<Pubkey, (u64, ArcVoteAccount)> {
&self.vote_accounts
}
@@ -200,11 +201,12 @@ impl Stakes {
}
pub fn highest_staked_node(&self) -> Option<Pubkey> {
self.vote_accounts
let (_pubkey, (_stake, vote_account)) = self
.vote_accounts
.iter()
.max_by(|(_ak, av), (_bk, bv)| av.0.cmp(&bv.0))
.and_then(|(_k, (_stake, account))| VoteState::from(account))
.map(|vote_state| vote_state.node_pubkey)
.max_by(|(_ak, av), (_bk, bv)| av.0.cmp(&bv.0))?;
let node_pubkey = vote_account.vote_state().as_ref().ok()?.node_pubkey;
Some(node_pubkey)
}
}
@@ -523,7 +525,7 @@ pub mod tests {
pub fn vote_balance_and_warmed_staked(&self) -> u64 {
self.vote_accounts
.iter()
.map(|(_pubkey, (staked, account))| staked + account.lamports)
.map(|(_pubkey, (staked, account))| staked + account.lamports())
.sum()
}
}