Encapsulate Bank accounts
That way we don't need to TODOs saying "don't forget to iterate over checkpoints too". It should be assumed that when the bank references its previous checkpoint all its methods would acknowledge it.
This commit is contained in:
parent
7981865fd2
commit
1809277e05
29
src/bank.rs
29
src/bank.rs
|
@ -32,7 +32,7 @@ use solana_sdk::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::timing::duration_as_us;
|
use solana_sdk::timing::duration_as_us;
|
||||||
use solana_sdk::token_program;
|
use solana_sdk::token_program;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use solana_sdk::vote_program;
|
use solana_sdk::vote_program::{self, VoteState};
|
||||||
use std;
|
use std;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -93,7 +93,7 @@ type BankStatusCache = StatusCache<BankError>;
|
||||||
|
|
||||||
/// Manager for the state of all accounts and programs after processing its entries.
|
/// Manager for the state of all accounts and programs after processing its entries.
|
||||||
pub struct Bank {
|
pub struct Bank {
|
||||||
pub accounts: Accounts,
|
accounts: Accounts,
|
||||||
|
|
||||||
/// A cache of signature statuses
|
/// A cache of signature statuses
|
||||||
status_cache: RwLock<BankStatusCache>,
|
status_cache: RwLock<BankStatusCache>,
|
||||||
|
@ -183,7 +183,7 @@ impl Bank {
|
||||||
executable: false,
|
executable: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut vote_state = vote_program::VoteState::new(
|
let mut vote_state = VoteState::new(
|
||||||
genesis_block.bootstrap_leader_id,
|
genesis_block.bootstrap_leader_id,
|
||||||
genesis_block.bootstrap_leader_id,
|
genesis_block.bootstrap_leader_id,
|
||||||
);
|
);
|
||||||
|
@ -807,6 +807,29 @@ impl Bank {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn vote_states<F>(&self, cond: F) -> Vec<VoteState>
|
||||||
|
where
|
||||||
|
F: Fn(&VoteState) -> bool,
|
||||||
|
{
|
||||||
|
self.accounts
|
||||||
|
.accounts_db
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.accounts
|
||||||
|
.values()
|
||||||
|
.filter_map(|account| {
|
||||||
|
if vote_program::check_id(&account.owner) {
|
||||||
|
if let Ok(vote_state) = VoteState::deserialize(&account.userdata) {
|
||||||
|
if cond(&vote_state) {
|
||||||
|
return Some(vote_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn get_current_leader(&self) -> Option<Pubkey> {
|
fn get_current_leader(&self) -> Option<Pubkey> {
|
||||||
let tick_height = self.tick_height();
|
let tick_height = self.tick_height();
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::service::Service;
|
||||||
use solana_metrics::{influxdb, submit};
|
use solana_metrics::{influxdb, submit};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::timing;
|
use solana_sdk::timing;
|
||||||
use solana_sdk::vote_program::{self, VoteState};
|
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -37,24 +36,7 @@ impl ComputeLeaderConfirmationService {
|
||||||
|
|
||||||
// Hold an accounts_db read lock as briefly as possible, just long enough to collect all
|
// Hold an accounts_db read lock as briefly as possible, just long enough to collect all
|
||||||
// the vote states
|
// the vote states
|
||||||
let vote_states: Vec<VoteState> = bank
|
let vote_states = bank.vote_states(|vote_state| leader_id != vote_state.node_id);
|
||||||
.accounts
|
|
||||||
.accounts_db
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.accounts
|
|
||||||
.values()
|
|
||||||
.filter_map(|account| {
|
|
||||||
if vote_program::check_id(&account.owner) {
|
|
||||||
if let Ok(vote_state) = VoteState::deserialize(&account.userdata) {
|
|
||||||
if leader_id != vote_state.node_id {
|
|
||||||
return Some(vote_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut ticks_and_stakes: Vec<(u64, u64)> = vote_states
|
let mut ticks_and_stakes: Vec<(u64, u64)> = vote_states
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -11,7 +11,7 @@ use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_transaction::SystemTransaction;
|
use solana_sdk::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::vote_program::{self, VoteState};
|
use solana_sdk::vote_program::VoteState;
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
use solana_sdk::vote_transaction::VoteTransaction;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -195,6 +195,15 @@ impl LeaderScheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true of the latest vote is between the lower and upper bounds (inclusive)
|
||||||
|
fn is_active_staker(vote_state: &VoteState, lower_bound: u64, upper_bound: u64) -> bool {
|
||||||
|
vote_state
|
||||||
|
.votes
|
||||||
|
.back()
|
||||||
|
.filter(|vote| vote.tick_height >= lower_bound && vote.tick_height <= upper_bound)
|
||||||
|
.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: We use a HashSet for now because a single validator could potentially register
|
// TODO: We use a HashSet for now because a single validator could potentially register
|
||||||
// multiple vote account. Once that is no longer possible (see the TODO in vote_program.rs,
|
// multiple vote account. Once that is no longer possible (see the TODO in vote_program.rs,
|
||||||
// process_transaction(), case VoteInstruction::RegisterAccount), we can use a vector.
|
// process_transaction(), case VoteInstruction::RegisterAccount), we can use a vector.
|
||||||
|
@ -207,31 +216,10 @@ impl LeaderScheduler {
|
||||||
upper_bound
|
upper_bound
|
||||||
);
|
);
|
||||||
|
|
||||||
{
|
bank.vote_states(|vote_state| Self::is_active_staker(vote_state, lower_bound, upper_bound))
|
||||||
let accounts = bank.accounts.accounts_db.read().unwrap();
|
.iter()
|
||||||
// TODO: iterate through checkpoints, too
|
.map(|vote_state| vote_state.staker_id)
|
||||||
accounts
|
.collect()
|
||||||
.accounts
|
|
||||||
.values()
|
|
||||||
.filter_map(|account| {
|
|
||||||
if vote_program::check_id(&account.owner) {
|
|
||||||
if let Ok(vote_state) = VoteState::deserialize(&account.userdata) {
|
|
||||||
trace!("get_active_set: account vote_state: {:?}", vote_state);
|
|
||||||
return vote_state
|
|
||||||
.votes
|
|
||||||
.back()
|
|
||||||
.filter(|vote| {
|
|
||||||
vote.tick_height >= lower_bound
|
|
||||||
&& vote.tick_height <= upper_bound
|
|
||||||
})
|
|
||||||
.map(|_| vote_state.staker_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates the leader schedule to include ticks from tick_height to the first tick of the next epoch
|
// Updates the leader schedule to include ticks from tick_height to the first tick of the next epoch
|
||||||
|
|
Loading…
Reference in New Issue