solana/core/src/bank_forks.rs

223 lines
7.2 KiB
Rust
Raw Normal View History

//! The `bank_forks` module implments BankForks a DAG of checkpointed Banks
use hashbrown::{HashMap, HashSet};
2019-05-10 08:33:58 -07:00
use solana_metrics::inc_new_counter_info;
use solana_runtime::bank::Bank;
2019-03-29 21:21:59 -07:00
use solana_sdk::timing;
use std::ops::Index;
use std::sync::Arc;
2019-03-29 21:21:59 -07:00
use std::time::Instant;
pub struct BankForks {
banks: HashMap<u64, Arc<Bank>>,
working_bank: Arc<Bank>,
2019-05-07 23:34:10 -07:00
root: u64,
}
impl Index<u64> for BankForks {
type Output = Arc<Bank>;
2019-03-04 16:40:28 -08:00
fn index(&self, bank_slot: u64) -> &Arc<Bank> {
&self.banks[&bank_slot]
}
}
impl BankForks {
2019-03-04 16:40:28 -08:00
pub fn new(bank_slot: u64, bank: Bank) -> Self {
let mut banks = HashMap::new();
let working_bank = Arc::new(bank);
2019-03-04 16:40:28 -08:00
banks.insert(bank_slot, working_bank.clone());
Self {
banks,
working_bank,
2019-05-07 23:34:10 -07:00
root: 0,
}
}
/// Create a map of bank slot id to the set of ancestors for the bank slot.
pub fn ancestors(&self) -> HashMap<u64, HashSet<u64>> {
let mut ancestors = HashMap::new();
for bank in self.banks.values() {
2019-04-28 10:27:09 -07:00
let mut set: HashSet<u64> = bank.ancestors.keys().cloned().collect();
set.remove(&bank.slot());
ancestors.insert(bank.slot(), set);
}
ancestors
}
/// Create a map of bank slot id to the set of all of its descendants
2019-03-18 15:20:04 -07:00
pub fn descendants(&self) -> HashMap<u64, HashSet<u64>> {
let mut descendants = HashMap::new();
for bank in self.banks.values() {
2019-03-18 15:20:04 -07:00
let _ = descendants.entry(bank.slot()).or_insert(HashSet::new());
2019-04-28 10:27:09 -07:00
let mut set: HashSet<u64> = bank.ancestors.keys().cloned().collect();
set.remove(&bank.slot());
for parent in set {
2019-03-18 15:20:04 -07:00
descendants
2019-04-28 10:27:09 -07:00
.entry(parent)
.or_insert(HashSet::new())
.insert(bank.slot());
}
}
2019-03-18 15:20:04 -07:00
descendants
}
2019-02-26 21:57:45 -08:00
pub fn frozen_banks(&self) -> HashMap<u64, Arc<Bank>> {
self.banks
.iter()
.filter(|(_, b)| b.is_frozen())
.map(|(k, b)| (*k, b.clone()))
.collect()
2019-02-26 21:57:45 -08:00
}
2019-02-26 21:57:45 -08:00
pub fn active_banks(&self) -> Vec<u64> {
self.banks
.iter()
.filter(|(_, v)| !v.is_frozen())
.map(|(k, _v)| *k)
.collect()
2019-02-26 21:57:45 -08:00
}
2019-03-19 17:30:36 -07:00
2019-03-04 16:40:28 -08:00
pub fn get(&self, bank_slot: u64) -> Option<&Arc<Bank>> {
self.banks.get(&bank_slot)
2019-02-26 21:57:45 -08:00
}
2019-05-07 23:34:10 -07:00
pub fn new_from_banks(initial_banks: &[Arc<Bank>], root: u64) -> Self {
let mut banks = HashMap::new();
let working_bank = initial_banks[0].clone();
for bank in initial_banks {
banks.insert(bank.slot(), bank.clone());
}
Self {
2019-05-07 23:34:10 -07:00
root,
banks,
working_bank,
}
}
2019-03-18 20:23:34 -07:00
pub fn insert(&mut self, bank: Bank) {
let bank = Arc::new(bank);
2019-03-18 20:23:34 -07:00
let prev = self.banks.insert(bank.slot(), bank.clone());
assert!(prev.is_none());
self.working_bank = bank.clone();
}
// TODO: really want to kill this...
pub fn working_bank(&self) -> Arc<Bank> {
self.working_bank.clone()
}
pub fn set_root(&mut self, root: u64) {
2019-05-07 23:34:10 -07:00
self.root = root;
2019-03-29 21:21:59 -07:00
let set_root_start = Instant::now();
let root_bank = self
.banks
.get(&root)
.expect("root bank didn't exist in bank_forks");
let root_tx_count = root_bank
.parents()
.last()
.map(|bank| bank.transaction_count())
.unwrap_or(0);
root_bank.squash();
let new_tx_count = root_bank.transaction_count();
self.prune_non_root(root);
2019-05-07 23:34:10 -07:00
2019-03-29 21:21:59 -07:00
inc_new_counter_info!(
"bank-forks_set_root_ms",
timing::duration_as_ms(&set_root_start.elapsed()) as usize
);
inc_new_counter_info!(
"bank-forks_set_root_tx_count",
(new_tx_count - root_tx_count) as usize
);
}
2019-05-07 23:34:10 -07:00
pub fn root(&self) -> u64 {
self.root
}
fn prune_non_root(&mut self, root: u64) {
2019-04-28 10:27:09 -07:00
let descendants = self.descendants();
2019-03-18 20:23:34 -07:00
self.banks
.retain(|slot, _| descendants[&root].contains(slot))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::genesis_utils::{create_genesis_block, GenesisBlockInfo};
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
#[test]
fn test_bank_forks() {
let GenesisBlockInfo { genesis_block, .. } = create_genesis_block(10_000);
2019-02-20 16:14:58 -08:00
let bank = Bank::new(&genesis_block);
2019-02-18 14:35:02 -08:00
let mut bank_forks = BankForks::new(0, bank);
let child_bank = Bank::new_from_parent(&bank_forks[0u64], &Pubkey::default(), 1);
child_bank.register_tick(&Hash::default());
2019-03-18 20:23:34 -07:00
bank_forks.insert(child_bank);
assert_eq!(bank_forks[1u64].tick_height(), 1);
assert_eq!(bank_forks.working_bank().tick_height(), 1);
}
2019-02-26 21:57:45 -08:00
#[test]
2019-03-18 15:20:04 -07:00
fn test_bank_forks_descendants() {
let GenesisBlockInfo { genesis_block, .. } = create_genesis_block(10_000);
let bank = Bank::new(&genesis_block);
let mut bank_forks = BankForks::new(0, bank);
let bank0 = bank_forks[0].clone();
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
2019-03-18 20:23:34 -07:00
bank_forks.insert(bank);
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
2019-03-18 20:23:34 -07:00
bank_forks.insert(bank);
2019-03-18 15:20:04 -07:00
let descendants = bank_forks.descendants();
let children: Vec<u64> = descendants[&0].iter().cloned().collect();
assert_eq!(children, vec![1, 2]);
2019-03-18 15:20:04 -07:00
assert!(descendants[&1].is_empty());
assert!(descendants[&2].is_empty());
}
#[test]
fn test_bank_forks_ancestors() {
let GenesisBlockInfo { genesis_block, .. } = create_genesis_block(10_000);
let bank = Bank::new(&genesis_block);
let mut bank_forks = BankForks::new(0, bank);
let bank0 = bank_forks[0].clone();
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
2019-03-18 20:23:34 -07:00
bank_forks.insert(bank);
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
2019-03-18 20:23:34 -07:00
bank_forks.insert(bank);
let ancestors = bank_forks.ancestors();
assert!(ancestors[&0].is_empty());
let parents: Vec<u64> = ancestors[&1].iter().cloned().collect();
assert_eq!(parents, vec![0]);
let parents: Vec<u64> = ancestors[&2].iter().cloned().collect();
assert_eq!(parents, vec![0]);
}
2019-02-26 21:57:45 -08:00
#[test]
fn test_bank_forks_frozen_banks() {
let GenesisBlockInfo { genesis_block, .. } = create_genesis_block(10_000);
2019-02-26 21:57:45 -08:00
let bank = Bank::new(&genesis_block);
let mut bank_forks = BankForks::new(0, bank);
let child_bank = Bank::new_from_parent(&bank_forks[0u64], &Pubkey::default(), 1);
2019-03-18 20:23:34 -07:00
bank_forks.insert(child_bank);
2019-02-26 21:57:45 -08:00
assert!(bank_forks.frozen_banks().get(&0).is_some());
assert!(bank_forks.frozen_banks().get(&1).is_none());
}
#[test]
fn test_bank_forks_active_banks() {
let GenesisBlockInfo { genesis_block, .. } = create_genesis_block(10_000);
2019-02-26 21:57:45 -08:00
let bank = Bank::new(&genesis_block);
let mut bank_forks = BankForks::new(0, bank);
let child_bank = Bank::new_from_parent(&bank_forks[0u64], &Pubkey::default(), 1);
2019-03-18 20:23:34 -07:00
bank_forks.insert(child_bank);
2019-02-26 21:57:45 -08:00
assert_eq!(bank_forks.active_banks(), vec![1]);
}
}