Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions core/src/cluster_info_vote_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use solana_runtime::{
bank_forks::BankForks,
commitment::VOTE_THRESHOLD_SIZE,
epoch_stakes::{EpochAuthorizedVoters, EpochStakes},
stakes::Stakes,
vote_sender_types::{ReplayVoteReceiver, ReplayedVote},
};
use solana_sdk::{
Expand Down Expand Up @@ -601,7 +600,7 @@ impl ClusterInfoVoteListener {
// The last vote slot, which is the greatest slot in the stack
// of votes in a vote transaction, qualifies for optimistic confirmation.
if slot == last_vote_slot {
let vote_accounts = Stakes::vote_accounts(epoch_stakes.stakes());
let vote_accounts = epoch_stakes.stakes().vote_accounts();
let stake = vote_accounts
.get(vote_pubkey)
.map(|(stake, _)| *stake)
Expand Down
6 changes: 3 additions & 3 deletions core/src/commitment_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ impl AggregateCommitmentService {

let mut commitment = HashMap::new();
let mut rooted_stake: Vec<(Slot, u64)> = Vec::new();
for (_, (lamports, account)) in bank.vote_accounts().into_iter() {
if lamports == 0 {
for (lamports, account) in bank.vote_accounts().values() {
if *lamports == 0 {
continue;
}
if let Ok(vote_state) = account.vote_state().as_ref() {
Expand All @@ -193,7 +193,7 @@ impl AggregateCommitmentService {
&mut rooted_stake,
vote_state,
ancestors,
lamports,
*lamports,
);
}
}
Expand Down
130 changes: 66 additions & 64 deletions core/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,14 @@ impl Tower {
Self::new(node_pubkey, vote_account, root, &heaviest_bank)
}

pub(crate) fn collect_vote_lockouts<F>(
pub(crate) fn collect_vote_lockouts(
vote_account_pubkey: &Pubkey,
bank_slot: Slot,
vote_accounts: F,
vote_accounts: &HashMap<Pubkey, (/*stake:*/ u64, VoteAccount)>,
ancestors: &HashMap<Slot, HashSet<Slot>>,
get_frozen_hash: impl Fn(Slot) -> Option<Hash>,
latest_validator_votes_for_frozen_banks: &mut LatestValidatorVotesForFrozenBanks,
) -> ComputedBankState
where
F: IntoIterator<Item = (Pubkey, (u64, VoteAccount))>,
{
) -> ComputedBankState {
let mut vote_slots = HashSet::new();
let mut voted_stakes = HashMap::new();
let mut total_stake = 0;
Expand All @@ -217,7 +214,8 @@ impl Tower {
// keyed by end of the range
let mut lockout_intervals = LockoutIntervals::new();
let mut my_latest_landed_vote = None;
for (key, (voted_stake, account)) in vote_accounts {
for (&key, (voted_stake, account)) in vote_accounts.iter() {
let voted_stake = *voted_stake;
if voted_stake == 0 {
continue;
}
Expand Down Expand Up @@ -1270,56 +1268,60 @@ pub fn reconcile_blockstore_roots_with_tower(

#[cfg(test)]
pub mod test {
use super::*;
use crate::{
fork_choice::ForkChoice, heaviest_subtree_fork_choice::SlotHashKey,
replay_stage::HeaviestForkFailures, tower_storage::FileTowerStorage,
vote_simulator::VoteSimulator,
};
use solana_ledger::{blockstore::make_slot_entries, get_tmp_ledger_path};
use solana_runtime::bank::Bank;
use solana_sdk::{
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
clock::Slot,
hash::Hash,
pubkey::Pubkey,
signature::Signer,
slot_history::SlotHistory,
};
use solana_vote_program::vote_state::{Vote, VoteStateVersions, MAX_LOCKOUT_HISTORY};
use std::{
collections::HashMap,
fs::{remove_file, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
path::PathBuf,
sync::Arc,
use {
super::*,
crate::{
fork_choice::ForkChoice, heaviest_subtree_fork_choice::SlotHashKey,
replay_stage::HeaviestForkFailures, tower_storage::FileTowerStorage,
vote_simulator::VoteSimulator,
},
itertools::Itertools,
solana_ledger::{blockstore::make_slot_entries, get_tmp_ledger_path},
solana_runtime::bank::Bank,
solana_sdk::{
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
clock::Slot,
hash::Hash,
pubkey::Pubkey,
signature::Signer,
slot_history::SlotHistory,
},
solana_vote_program::vote_state::{Vote, VoteStateVersions, MAX_LOCKOUT_HISTORY},
std::{
collections::HashMap,
fs::{remove_file, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
path::PathBuf,
sync::Arc,
},
tempfile::TempDir,
trees::tr,
};
use tempfile::TempDir;
use trees::tr;

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 {
data: vec![0; VoteState::size_of()],
lamports: *lamports,
..Account::default()
});
let mut vote_state = VoteState::default();
for slot in *votes {
vote_state.process_slot_vote_unchecked(*slot);
}
VoteState::serialize(
&VoteStateVersions::new_current(vote_state),
&mut account.data_as_mut_slice(),
)
.expect("serialize state");
stakes.push((
solana_sdk::pubkey::new_rand(),
(*lamports, VoteAccount::from(account)),
));
}
stakes

fn gen_stakes(stake_votes: &[(u64, &[u64])]) -> HashMap<Pubkey, (u64, VoteAccount)> {
stake_votes
.iter()
.map(|(lamports, votes)| {
let mut account = AccountSharedData::from(Account {
data: vec![0; VoteState::size_of()],
lamports: *lamports,
..Account::default()
});
let mut vote_state = VoteState::default();
for slot in *votes {
vote_state.process_slot_vote_unchecked(*slot);
}
VoteState::serialize(
&VoteStateVersions::new_current(vote_state),
&mut account.data_as_mut_slice(),
)
.expect("serialize state");
(
solana_sdk::pubkey::new_rand(),
(*lamports, VoteAccount::from(account)),
)
})
.collect()
}

#[test]
Expand Down Expand Up @@ -1964,10 +1966,10 @@ pub mod test {
#[test]
fn test_collect_vote_lockouts_sums() {
//two accounts voting for slot 0 with 1 token staked
let mut accounts = gen_stakes(&[(1, &[0]), (1, &[0])]);
accounts.sort_by_key(|(pk, _)| *pk);
let accounts = gen_stakes(&[(1, &[0]), (1, &[0])]);
let account_latest_votes: Vec<(Pubkey, SlotHashKey)> = accounts
.iter()
.sorted_by_key(|(pk, _)| *pk)
.map(|(pubkey, _)| (*pubkey, (0, Hash::default())))
.collect();

Expand All @@ -1984,7 +1986,7 @@ pub mod test {
} = Tower::collect_vote_lockouts(
&Pubkey::default(),
1,
accounts.into_iter(),
&accounts,
&ancestors,
|_| Some(Hash::default()),
&mut latest_validator_votes_for_frozen_banks,
Expand All @@ -2004,10 +2006,10 @@ pub mod test {
fn test_collect_vote_lockouts_root() {
let votes: Vec<u64> = (0..MAX_LOCKOUT_HISTORY as u64).collect();
//two accounts voting for slots 0..MAX_LOCKOUT_HISTORY with 1 token staked
let mut accounts = gen_stakes(&[(1, &votes), (1, &votes)]);
accounts.sort_by_key(|(pk, _)| *pk);
let accounts = gen_stakes(&[(1, &votes), (1, &votes)]);
let account_latest_votes: Vec<(Pubkey, SlotHashKey)> = accounts
.iter()
.sorted_by_key(|(pk, _)| *pk)
.map(|(pubkey, _)| {
(
*pubkey,
Expand Down Expand Up @@ -2044,7 +2046,7 @@ pub mod test {
} = Tower::collect_vote_lockouts(
&Pubkey::default(),
MAX_LOCKOUT_HISTORY as u64,
accounts.into_iter(),
&accounts,
&ancestors,
|_| Some(Hash::default()),
&mut latest_validator_votes_for_frozen_banks,
Expand Down Expand Up @@ -2340,7 +2342,7 @@ pub mod test {
} = Tower::collect_vote_lockouts(
&Pubkey::default(),
vote_to_evaluate,
accounts.clone().into_iter(),
&accounts,
&ancestors,
|_| None,
&mut LatestValidatorVotesForFrozenBanks::default(),
Expand All @@ -2358,7 +2360,7 @@ pub mod test {
} = Tower::collect_vote_lockouts(
&Pubkey::default(),
vote_to_evaluate,
accounts.into_iter(),
&accounts,
&ancestors,
|_| None,
&mut LatestValidatorVotesForFrozenBanks::default(),
Expand Down
2 changes: 1 addition & 1 deletion core/src/replay_stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2169,7 +2169,7 @@ impl ReplayStage {
let computed_bank_state = Tower::collect_vote_lockouts(
my_vote_pubkey,
bank_slot,
bank.vote_accounts().into_iter(),
&bank.vote_accounts(),
ancestors,
|slot| progress.get_hash(slot),
latest_validator_votes_for_frozen_banks,
Expand Down
3 changes: 2 additions & 1 deletion core/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,7 +1544,8 @@ fn get_stake_percent_in_gossip(bank: &Bank, cluster_info: &ClusterInfo, log: boo
let my_shred_version = cluster_info.my_shred_version();
let my_id = cluster_info.id();

for (_, (activated_stake, vote_account)) in bank.vote_accounts() {
for (activated_stake, vote_account) in bank.vote_accounts().values() {
let activated_stake = *activated_stake;
total_activated_stake += activated_stake;

if activated_stake == 0 {
Expand Down
8 changes: 4 additions & 4 deletions ledger-tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,18 +353,18 @@ fn graph_forks(bank_forks: &BankForks, include_all_votes: bool) -> String {
.iter()
.map(|(_, (stake, _))| stake)
.sum();
for (_, (stake, vote_account)) in bank.vote_accounts() {
for (stake, vote_account) in bank.vote_accounts().values() {
let vote_state = vote_account.vote_state();
let vote_state = vote_state.as_ref().unwrap_or(&default_vote_state);
if let Some(last_vote) = vote_state.votes.iter().last() {
let entry = last_votes.entry(vote_state.node_pubkey).or_insert((
last_vote.slot,
vote_state.clone(),
stake,
*stake,
total_stake,
));
if entry.0 < last_vote.slot {
*entry = (last_vote.slot, vote_state.clone(), stake, total_stake);
*entry = (last_vote.slot, vote_state.clone(), *stake, total_stake);
}
}
}
Expand Down Expand Up @@ -394,7 +394,7 @@ fn graph_forks(bank_forks: &BankForks, include_all_votes: bool) -> String {

let mut first = true;
loop {
for (_, (_, vote_account)) in bank.vote_accounts() {
for (_, vote_account) in bank.vote_accounts().values() {
let vote_state = vote_account.vote_state();
let vote_state = vote_state.as_ref().unwrap_or(&default_vote_state);
if let Some(last_vote) = vote_state.votes.iter().last() {
Expand Down
32 changes: 13 additions & 19 deletions ledger/src/blockstore_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ fn load_frozen_forks(
supermajority_root_from_vote_accounts(
bank.slot(),
bank.total_epoch_stake(),
bank.vote_accounts(),
&bank.vote_accounts(),
).and_then(|supermajority_root| {
if supermajority_root > *root {
// If there's a cluster confirmed root greater than our last
Expand Down Expand Up @@ -1221,18 +1221,15 @@ fn supermajority_root(roots: &[(Slot, u64)], total_epoch_stake: u64) -> Option<S
None
}

fn supermajority_root_from_vote_accounts<I>(
fn supermajority_root_from_vote_accounts(
bank_slot: Slot,
total_epoch_stake: u64,
vote_accounts: I,
) -> Option<Slot>
where
I: IntoIterator<Item = (Pubkey, (u64, VoteAccount))>,
{
vote_accounts: &HashMap<Pubkey, (/*stake:*/ u64, VoteAccount)>,
) -> Option<Slot> {
let mut roots_stakes: Vec<(Slot, u64)> = vote_accounts
.into_iter()
.iter()
.filter_map(|(key, (stake, account))| {
if stake == 0 {
if *stake == 0 {
return None;
}

Expand All @@ -1244,7 +1241,7 @@ where
);
None
}
Ok(vote_state) => vote_state.root_slot.map(|root_slot| (root_slot, stake)),
Ok(vote_state) => Some((vote_state.root_slot?, *stake)),
}
})
.collect();
Expand Down Expand Up @@ -3581,7 +3578,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, VoteAccount))> {
|roots_stakes: Vec<(Slot, u64)>| -> HashMap<Pubkey, (u64, VoteAccount)> {
roots_stakes
.into_iter()
.map(|(root, stake)| {
Expand All @@ -3599,38 +3596,35 @@ pub mod tests {
(stake, VoteAccount::from(vote_account)),
)
})
.collect_vec()
.collect()
};

let total_stake = 10;
let slot = 100;

// Supermajority root should be None
assert!(
supermajority_root_from_vote_accounts(slot, total_stake, std::iter::empty()).is_none()
supermajority_root_from_vote_accounts(slot, total_stake, &HashMap::default()).is_none()
);

// Supermajority root should be None
let roots_stakes = vec![(8, 1), (3, 1), (4, 1), (8, 1)];
let accounts = convert_to_vote_accounts(roots_stakes);
assert!(
supermajority_root_from_vote_accounts(slot, total_stake, accounts.into_iter())
.is_none()
);
assert!(supermajority_root_from_vote_accounts(slot, total_stake, &accounts).is_none());

// Supermajority root should be 4, has 7/10 of the stake
let roots_stakes = vec![(8, 1), (3, 1), (4, 1), (8, 5)];
let accounts = convert_to_vote_accounts(roots_stakes);
assert_eq!(
supermajority_root_from_vote_accounts(slot, total_stake, accounts.into_iter()).unwrap(),
supermajority_root_from_vote_accounts(slot, total_stake, &accounts).unwrap(),
4
);

// Supermajority root should be 8, it has 7/10 of the stake
let roots_stakes = vec![(8, 1), (3, 1), (4, 1), (8, 6)];
let accounts = convert_to_vote_accounts(roots_stakes);
assert_eq!(
supermajority_root_from_vote_accounts(slot, total_stake, accounts.into_iter()).unwrap(),
supermajority_root_from_vote_accounts(slot, total_stake, &accounts).unwrap(),
8
);
}
Expand Down
Loading