solana/src/bank_forks.rs

73 lines
2.0 KiB
Rust
Raw Normal View History

//! The `bank_forks` module implments BankForks a DAG of checkpointed Banks
use solana_runtime::bank::Bank;
use std::collections::HashMap;
use std::ops::Index;
use std::sync::Arc;
pub struct BankForks {
banks: HashMap<u64, Arc<Bank>>,
working_bank: Arc<Bank>,
}
impl Index<u64> for BankForks {
type Output = Arc<Bank>;
fn index(&self, bank_id: u64) -> &Arc<Bank> {
&self.banks[&bank_id]
}
}
impl BankForks {
pub fn new(bank_id: u64, bank: Bank) -> Self {
let mut banks = HashMap::new();
let working_bank = Arc::new(bank);
banks.insert(bank_id, working_bank.clone());
Self {
banks,
working_bank,
}
}
// TODO: use the bank's own ID instead of receiving a parameter?
2019-02-18 14:35:02 -08:00
pub fn insert(&mut self, bank_id: u64, bank: Bank) {
let mut bank = Arc::new(bank);
self.banks.insert(bank_id, bank.clone());
2019-02-28 18:02:45 -08:00
if bank_id > self.working_bank.slot() {
self.working_bank = bank.clone()
}
// TODO: this really only needs to look at the first
// parent if we're always calling insert()
// when we construct a child bank
while let Some(parent) = bank.parent() {
2019-02-28 18:02:45 -08:00
self.banks.remove(&parent.slot());
bank = parent;
}
}
// TODO: really want to kill this...
pub fn working_bank(&self) -> Arc<Bank> {
self.working_bank.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
2019-02-20 16:14:58 -08:00
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
#[test]
fn test_bank_forks() {
2019-02-20 16:14:58 -08:00
let (genesis_block, _) = GenesisBlock::new(10_000);
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]);
child_bank.register_tick(&Hash::default());
bank_forks.insert(1, child_bank);
assert_eq!(bank_forks[1u64].tick_height(), 1);
assert_eq!(bank_forks.working_bank().tick_height(), 1);
}
}