diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 88fb0a0d30..9f6bfaaa3a 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -9,7 +9,7 @@ use { solana_measure::measure::Measure, solana_runtime::{ bank::Bank, bank_forks::BankForks, commitment::VOTE_THRESHOLD_SIZE, - vote_account::ArcVoteAccount, + vote_account::VoteAccount, }, solana_sdk::{ clock::{Slot, UnixTimestamp}, @@ -232,7 +232,7 @@ impl Tower { latest_validator_votes_for_frozen_banks: &mut LatestValidatorVotesForFrozenBanks, ) -> ComputedBankState where - F: IntoIterator, + F: IntoIterator, { let mut vote_slots = HashSet::new(); let mut voted_stakes = HashMap::new(); @@ -578,7 +578,7 @@ impl Tower { descendants: &HashMap>, progress: &ProgressMap, total_stake: u64, - epoch_vote_accounts: &HashMap, + epoch_vote_accounts: &HashMap, latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks, heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice, ) -> SwitchForkDecision { @@ -828,7 +828,7 @@ impl Tower { descendants: &HashMap>, progress: &ProgressMap, total_stake: u64, - epoch_vote_accounts: &HashMap, + epoch_vote_accounts: &HashMap, latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks, heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice, ) -> SwitchForkDecision { @@ -1722,7 +1722,7 @@ pub mod test { (bank_forks, progress, heaviest_subtree_fork_choice) } - fn gen_stakes(stake_votes: &[(u64, &[u64])]) -> Vec<(Pubkey, (u64, ArcVoteAccount))> { + fn gen_stakes(stake_votes: &[(u64, &[u64])]) -> Vec<(Pubkey, (u64, VoteAccount))> { let mut stakes = vec![]; for (lamports, votes) in stake_votes { let mut account = AccountSharedData::from(Account { @@ -1741,7 +1741,7 @@ pub mod test { .expect("serialize state"); stakes.push(( solana_sdk::pubkey::new_rand(), - (*lamports, ArcVoteAccount::from(account)), + (*lamports, VoteAccount::from(account)), )); } stakes diff --git a/core/src/progress_map.rs b/core/src/progress_map.rs index 8bc2e6b4fb..005b451630 100644 --- a/core/src/progress_map.rs +++ b/core/src/progress_map.rs @@ -6,7 +6,7 @@ use { replay_stage::SUPERMINORITY_THRESHOLD, }, solana_ledger::blockstore_processor::{ConfirmationProgress, ConfirmationTiming}, - solana_runtime::{bank::Bank, bank_forks::BankForks, vote_account::ArcVoteAccount}, + solana_runtime::{bank::Bank, bank_forks::BankForks, vote_account::VoteAccount}, solana_sdk::{clock::Slot, hash::Hash, pubkey::Pubkey}, std::{ collections::{BTreeMap, HashMap, HashSet}, @@ -343,7 +343,7 @@ impl PropagatedStats { &mut self, node_pubkey: &Pubkey, vote_account_pubkeys: &[Pubkey], - epoch_vote_accounts: &HashMap, + epoch_vote_accounts: &HashMap, ) { self.propagated_node_ids.insert(*node_pubkey); for vote_account_pubkey in vote_account_pubkeys.iter() { @@ -539,7 +539,7 @@ mod test { let epoch_vote_accounts: HashMap<_, _> = vote_account_pubkeys .iter() .skip(num_vote_accounts - staked_vote_accounts) - .map(|pubkey| (*pubkey, (1, ArcVoteAccount::default()))) + .map(|pubkey| (*pubkey, (1, VoteAccount::default()))) .collect(); let mut stats = PropagatedStats::default(); @@ -581,7 +581,7 @@ mod test { let epoch_vote_accounts: HashMap<_, _> = vote_account_pubkeys .iter() .skip(num_vote_accounts - staked_vote_accounts) - .map(|pubkey| (*pubkey, (1, ArcVoteAccount::default()))) + .map(|pubkey| (*pubkey, (1, VoteAccount::default()))) .collect(); stats.add_node_pubkey_internal(&node_pubkey, &vote_account_pubkeys, &epoch_vote_accounts); assert!(stats.propagated_node_ids.contains(&node_pubkey)); diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 10c0a07b6e..5f4f8ddae7 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -32,7 +32,7 @@ use { commitment::VOTE_THRESHOLD_SIZE, snapshot_utils::BankFromArchiveTimings, transaction_batch::TransactionBatch, - vote_account::ArcVoteAccount, + vote_account::VoteAccount, vote_sender_types::ReplayVoteSender, }, solana_sdk::{ @@ -1206,7 +1206,7 @@ fn supermajority_root_from_vote_accounts( vote_accounts: I, ) -> Option where - I: IntoIterator, + I: IntoIterator, { let mut roots_stakes: Vec<(Slot, u64)> = vote_accounts .into_iter() @@ -3591,7 +3591,7 @@ pub mod tests { #[allow(clippy::field_reassign_with_default)] fn test_supermajority_root_from_vote_accounts() { let convert_to_vote_accounts = - |roots_stakes: Vec<(Slot, u64)>| -> Vec<(Pubkey, (u64, ArcVoteAccount))> { + |roots_stakes: Vec<(Slot, u64)>| -> Vec<(Pubkey, (u64, VoteAccount))> { roots_stakes .into_iter() .map(|(root, stake)| { @@ -3606,7 +3606,7 @@ pub mod tests { VoteState::serialize(&versioned, vote_account.data_as_mut_slice()).unwrap(); ( solana_sdk::pubkey::new_rand(), - (stake, ArcVoteAccount::from(vote_account)), + (stake, VoteAccount::from(vote_account)), ) }) .collect_vec() diff --git a/ledger/src/staking_utils.rs b/ledger/src/staking_utils.rs index 9785fbfa56..02953124af 100644 --- a/ledger/src/staking_utils.rs +++ b/ledger/src/staking_utils.rs @@ -69,7 +69,7 @@ pub(crate) mod tests { bootstrap_validator_stake_lamports, create_genesis_config, GenesisConfigInfo, }, rand::Rng, - solana_runtime::vote_account::{ArcVoteAccount, VoteAccounts}, + solana_runtime::vote_account::{VoteAccount, VoteAccounts}, solana_sdk::{ account::{from_account, AccountSharedData}, clock::Clock, @@ -312,7 +312,7 @@ pub(crate) mod tests { ) .unwrap(); let vote_pubkey = Pubkey::new_unique(); - (vote_pubkey, (stake, ArcVoteAccount::from(account))) + (vote_pubkey, (stake, VoteAccount::from(account))) }); let result = vote_accounts.collect::().staked_nodes(); assert_eq!(result.len(), 2); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index fa45578a74..f5b6210fe5 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -61,7 +61,7 @@ use { status_cache::{SlotDelta, StatusCache}, system_instruction_processor::{get_system_account_kind, SystemAccountKind}, transaction_batch::TransactionBatch, - vote_account::ArcVoteAccount, + vote_account::VoteAccount, }, byteorder::{ByteOrder, LittleEndian}, dashmap::DashMap, @@ -3809,7 +3809,7 @@ impl Bank { #[allow(clippy::needless_collect)] fn distribute_rent_to_validators(&self, vote_accounts: I, rent_to_be_distributed: u64) where - I: IntoIterator, + I: IntoIterator, { let mut total_staked = 0; @@ -5196,7 +5196,7 @@ impl Bank { /// attributed to each account /// Note: This clones the entire vote-accounts hashmap. For a single /// account lookup use get_vote_account instead. - pub fn vote_accounts(&self) -> Vec<(Pubkey, (u64 /*stake*/, ArcVoteAccount))> { + pub fn vote_accounts(&self) -> Vec<(Pubkey, (/*stake:*/ u64, VoteAccount))> { self.stakes_cache .stakes() .vote_accounts() @@ -5206,10 +5206,7 @@ impl Bank { } /// Vote account for the given vote account pubkey along with the stake. - pub fn get_vote_account( - &self, - vote_account: &Pubkey, - ) -> Option<(u64 /*stake*/, ArcVoteAccount)> { + pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<(/*stake:*/ u64, VoteAccount)> { self.stakes_cache .stakes() .vote_accounts() @@ -5235,7 +5232,7 @@ impl Bank { pub fn epoch_vote_accounts( &self, epoch: Epoch, - ) -> Option<&HashMap> { + ) -> Option<&HashMap> { self.epoch_stakes .get(&epoch) .map(|epoch_stakes| Stakes::vote_accounts(epoch_stakes.stakes())) diff --git a/runtime/src/epoch_stakes.rs b/runtime/src/epoch_stakes.rs index 1f6e6e4663..79337293dc 100644 --- a/runtime/src/epoch_stakes.rs +++ b/runtime/src/epoch_stakes.rs @@ -1,5 +1,5 @@ use { - crate::{stakes::Stakes, vote_account::ArcVoteAccount}, + crate::{stakes::Stakes, vote_account::VoteAccount}, serde::{Deserialize, Serialize}, solana_sdk::{clock::Epoch, pubkey::Pubkey}, std::{collections::HashMap, sync::Arc}, @@ -59,7 +59,7 @@ impl EpochStakes { } fn parse_epoch_vote_accounts( - epoch_vote_accounts: &HashMap, + epoch_vote_accounts: &HashMap, leader_schedule_epoch: Epoch, ) -> (u64, NodeIdToVoteAccounts, EpochAuthorizedVoters) { let mut node_id_to_vote_accounts: NodeIdToVoteAccounts = HashMap::new(); @@ -190,7 +190,7 @@ pub(crate) mod tests { vote_accounts.iter().map(|v| { ( v.vote_account, - (stake_per_account, ArcVoteAccount::from(v.account.clone())), + (stake_per_account, VoteAccount::from(v.account.clone())), ) }) }) diff --git a/runtime/src/serde_snapshot/tests.rs b/runtime/src/serde_snapshot/tests.rs index 23a44758d9..885f3fbdd3 100644 --- a/runtime/src/serde_snapshot/tests.rs +++ b/runtime/src/serde_snapshot/tests.rs @@ -296,7 +296,7 @@ mod test_bank_serialize { // This some what long test harness is required to freeze the ABI of // Bank's serialization due to versioned nature - #[frozen_abi(digest = "9NFbb7BMUbSjUr8xwRGhW5kT5jCTQj2U2vZtMxvovsTn")] + #[frozen_abi(digest = "9jiGyuG8pK3nBNbCEtLZBghXRNg3PHhkf1jS1GgTTdGz")] #[derive(Serialize, AbiExample)] pub struct BankAbiTestWrapperFuture { #[serde(serialize_with = "wrapper_future")] diff --git a/runtime/src/stake_weighted_timestamp.rs b/runtime/src/stake_weighted_timestamp.rs index fbb268f317..1756e85a29 100644 --- a/runtime/src/stake_weighted_timestamp.rs +++ b/runtime/src/stake_weighted_timestamp.rs @@ -23,7 +23,7 @@ pub(crate) struct MaxAllowableDrift { pub(crate) fn calculate_stake_weighted_timestamp( unique_timestamps: I, - stakes: &HashMap, + stakes: &HashMap, slot: Slot, slot_duration: Duration, epoch_start_timestamp: Option<(Slot, UnixTimestamp)>, diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index 98ed7738d5..146d3aeaac 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -1,7 +1,7 @@ //! Stakes serve as a cache of stake and vote accounts to derive //! node stakes use { - crate::vote_account::{ArcVoteAccount, VoteAccounts, VoteAccountsHashMap}, + crate::vote_account::{VoteAccount, VoteAccounts, VoteAccountsHashMap}, dashmap::DashMap, num_derive::ToPrimitive, num_traits::ToPrimitive, @@ -268,7 +268,7 @@ impl Stakes { ); self.vote_accounts - .insert(*pubkey, (stake, ArcVoteAccount::from(account.clone()))); + .insert(*pubkey, (stake, VoteAccount::from(account.clone()))); } } else if stake::program::check_id(account.owner()) { // old_stake is stake lamports and voter_pubkey from the pre-store() version diff --git a/runtime/src/vote_account.rs b/runtime/src/vote_account.rs index 72909c9da3..2de715c893 100644 --- a/runtime/src/vote_account.rs +++ b/runtime/src/vote_account.rs @@ -13,7 +13,6 @@ use { cmp::Ordering, collections::{hash_map::Entry, HashMap}, iter::FromIterator, - ops::Deref, sync::{Arc, Once, RwLock, RwLockReadGuard}, }, }; @@ -24,20 +23,22 @@ const INVALID_VOTE_STATE: Result = Err(InstructionError::InvalidAccountData); #[derive(Clone, Debug, Default, PartialEq, AbiExample)] -pub struct ArcVoteAccount(Arc); +pub struct VoteAccount(Arc); #[derive(Debug, AbiExample)] -pub struct VoteAccount { +struct VoteAccountInner { account: Account, vote_state: RwLock>, vote_state_once: Once, } -pub type VoteAccountsHashMap = HashMap; +pub type VoteAccountsHashMap = HashMap; #[derive(Debug, AbiExample)] pub struct VoteAccounts { vote_accounts: VoteAccountsHashMap, + // Inner Arc is meant to implement copy-on-write semantics as opposed to + // sharing mutations (hence RwLock> instead of Arc>). staked_nodes: RwLock< HashMap< Pubkey, // VoteAccount.vote_state.node_pubkey. @@ -48,19 +49,17 @@ pub struct VoteAccounts { } impl VoteAccount { - pub fn account(&self) -> &Account { - &self.account - } - pub fn lamports(&self) -> u64 { - self.account.lamports + self.0.account.lamports } pub fn vote_state(&self) -> RwLockReadGuard> { - self.vote_state_once.call_once(|| { - *self.vote_state.write().unwrap() = VoteState::deserialize(&self.account.data); + let inner = &self.0; + inner.vote_state_once.call_once(|| { + let vote_state = VoteState::deserialize(&inner.account.data); + *inner.vote_state.write().unwrap() = vote_state; }); - self.vote_state.read().unwrap() + inner.vote_state.read().unwrap() } /// VoteState.node_pubkey of this vote-account. @@ -88,11 +87,11 @@ impl VoteAccounts { self.staked_nodes.read().unwrap().clone() } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.vote_accounts.iter() } - pub fn insert(&mut self, pubkey: Pubkey, (stake, vote_account): (u64, ArcVoteAccount)) { + pub fn insert(&mut self, pubkey: Pubkey, (stake, vote_account): (u64, VoteAccount)) { self.add_node_stake(stake, &vote_account); if let Some((stake, vote_account)) = self.vote_accounts.insert(pubkey, (stake, vote_account)) @@ -101,7 +100,7 @@ impl VoteAccounts { } } - pub fn remove(&mut self, pubkey: &Pubkey) -> Option<(u64, ArcVoteAccount)> { + pub fn remove(&mut self, pubkey: &Pubkey) -> Option<(u64, VoteAccount)> { let value = self.vote_accounts.remove(pubkey); if let Some((stake, ref vote_account)) = value { self.sub_node_stake(stake, vote_account); @@ -127,7 +126,7 @@ impl VoteAccounts { } } - fn add_node_stake(&mut self, stake: u64, vote_account: &ArcVoteAccount) { + fn add_node_stake(&mut self, stake: u64, vote_account: &VoteAccount) { if stake != 0 && self.staked_nodes_once.is_completed() { if let Some(node_pubkey) = vote_account.node_pubkey() { self.staked_nodes @@ -140,7 +139,7 @@ impl VoteAccounts { } } - fn sub_node_stake(&mut self, stake: u64, vote_account: &ArcVoteAccount) { + fn sub_node_stake(&mut self, stake: u64, vote_account: &VoteAccount) { if stake != 0 && self.staked_nodes_once.is_completed() { if let Some(node_pubkey) = vote_account.node_pubkey() { match self.staked_nodes.write().unwrap().entry(node_pubkey) { @@ -158,24 +157,16 @@ impl VoteAccounts { } } -impl Deref for ArcVoteAccount { - type Target = VoteAccount; - - fn deref(&self) -> &Self::Target { - self.0.deref() - } -} - -impl Serialize for ArcVoteAccount { +impl Serialize for VoteAccount { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - self.account.serialize(serializer) + self.0.account.serialize(serializer) } } -impl<'de> Deserialize<'de> for ArcVoteAccount { +impl<'de> Deserialize<'de> for VoteAccount { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -185,34 +176,25 @@ impl<'de> Deserialize<'de> for ArcVoteAccount { } } -impl From for ArcVoteAccount { - fn from(account: AccountSharedData) -> Self { - Self(Arc::new(VoteAccount::from(account))) - } -} -impl From for ArcVoteAccount { - fn from(account: Account) -> Self { - Self(Arc::new(VoteAccount::from(account))) - } -} - -impl AsRef for ArcVoteAccount { - fn as_ref(&self) -> &VoteAccount { - &self.0 - } -} - impl From for VoteAccount { fn from(account: AccountSharedData) -> Self { - Self { - account: Account::from(account), - vote_state: RwLock::new(INVALID_VOTE_STATE), - vote_state_once: Once::new(), - } + Self(Arc::new(VoteAccountInner::from(account))) } } impl From for VoteAccount { + fn from(account: Account) -> Self { + Self(Arc::new(VoteAccountInner::from(account))) + } +} + +impl From for VoteAccountInner { + fn from(account: AccountSharedData) -> Self { + Self::from(Account::from(account)) + } +} + +impl From for VoteAccountInner { fn from(account: Account) -> Self { Self { account, @@ -222,7 +204,7 @@ impl From for VoteAccount { } } -impl Default for VoteAccount { +impl Default for VoteAccountInner { fn default() -> Self { Self { account: Account::default(), @@ -232,7 +214,7 @@ impl Default for VoteAccount { } } -impl PartialEq for VoteAccount { +impl PartialEq for VoteAccountInner { fn eq(&self, other: &Self) -> bool { self.account == other.account } @@ -291,10 +273,10 @@ impl AsRef for VoteAccounts { } } -impl FromIterator<(Pubkey, (u64 /*stake*/, ArcVoteAccount))> for VoteAccounts { +impl FromIterator<(Pubkey, (/*stake:*/ u64, VoteAccount))> for VoteAccounts { fn from_iter(iter: I) -> Self where - I: IntoIterator, + I: IntoIterator, { Self::from(HashMap::from_iter(iter)) } @@ -360,19 +342,19 @@ mod tests { fn new_rand_vote_accounts( rng: &mut R, num_nodes: usize, - ) -> impl Iterator + '_ { + ) -> impl Iterator + '_ { let nodes: Vec<_> = repeat_with(Pubkey::new_unique).take(num_nodes).collect(); repeat_with(move || { let node = nodes[rng.gen_range(0, nodes.len())]; let (account, _) = new_rand_vote_account(rng, Some(node)); let stake = rng.gen_range(0, 997); - (Pubkey::new_unique(), (stake, ArcVoteAccount::from(account))) + (Pubkey::new_unique(), (stake, VoteAccount::from(account))) }) } fn staked_nodes<'a, I>(vote_accounts: I) -> HashMap where - I: IntoIterator, + I: IntoIterator, { let mut staked_nodes = HashMap::new(); for (_, (stake, vote_account)) in vote_accounts @@ -394,7 +376,7 @@ mod tests { let mut rng = rand::thread_rng(); let (account, vote_state) = new_rand_vote_account(&mut rng, None); let lamports = account.lamports; - let vote_account = ArcVoteAccount::from(account); + let vote_account = VoteAccount::from(account); assert_eq!(lamports, vote_account.lamports()); assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap()); // 2nd call to .vote_state() should return the cached value. @@ -405,9 +387,9 @@ mod tests { fn test_vote_account_serialize() { let mut rng = rand::thread_rng(); let (account, vote_state) = new_rand_vote_account(&mut rng, None); - let vote_account = ArcVoteAccount::from(account.clone()); + let vote_account = VoteAccount::from(account.clone()); assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap()); - // Assert than ArcVoteAccount has the same wire format as Account. + // Assert than VoteAccount has the same wire format as Account. assert_eq!( bincode::serialize(&account).unwrap(), bincode::serialize(&vote_account).unwrap() @@ -419,9 +401,9 @@ mod tests { let mut rng = rand::thread_rng(); let (account, vote_state) = new_rand_vote_account(&mut rng, None); let data = bincode::serialize(&account).unwrap(); - let vote_account = ArcVoteAccount::from(account); + let vote_account = VoteAccount::from(account); assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap()); - let other_vote_account: ArcVoteAccount = bincode::deserialize(&data).unwrap(); + let other_vote_account: VoteAccount = bincode::deserialize(&data).unwrap(); assert_eq!(vote_account, other_vote_account); assert_eq!( vote_state, @@ -433,11 +415,11 @@ mod tests { fn test_vote_account_round_trip() { let mut rng = rand::thread_rng(); let (account, vote_state) = new_rand_vote_account(&mut rng, None); - let vote_account = ArcVoteAccount::from(account); + let vote_account = VoteAccount::from(account); assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap()); let data = bincode::serialize(&vote_account).unwrap(); - let other_vote_account: ArcVoteAccount = bincode::deserialize(&data).unwrap(); - // Assert that serialize->deserialized returns the same ArcVoteAccount. + let other_vote_account: VoteAccount = bincode::deserialize(&data).unwrap(); + // Assert that serialize->deserialized returns the same VoteAccount. assert_eq!(vote_account, other_vote_account); assert_eq!( vote_state, @@ -448,7 +430,7 @@ mod tests { #[test] fn test_vote_accounts_serialize() { let mut rng = rand::thread_rng(); - let vote_accounts_hash_map: HashMap = + let vote_accounts_hash_map: HashMap = new_rand_vote_accounts(&mut rng, 64).take(1024).collect(); let vote_accounts = VoteAccounts::from(vote_accounts_hash_map.clone()); assert!(vote_accounts.staked_nodes().len() > 32); @@ -467,7 +449,7 @@ mod tests { #[test] fn test_vote_accounts_deserialize() { let mut rng = rand::thread_rng(); - let vote_accounts_hash_map: HashMap = + let vote_accounts_hash_map: HashMap = new_rand_vote_accounts(&mut rng, 64).take(1024).collect(); let data = bincode::serialize(&vote_accounts_hash_map).unwrap(); let vote_accounts: VoteAccounts = bincode::deserialize(&data).unwrap();