2019-02-16 19:58:07 -08:00
|
|
|
//! The `bank_forks` module implments BankForks a DAG of checkpointed Banks
|
|
|
|
|
2019-02-18 22:26:22 -08:00
|
|
|
use solana_runtime::bank::Bank;
|
2019-02-16 19:58:07 -08:00
|
|
|
use std::collections::HashMap;
|
2019-02-28 10:57:58 -08:00
|
|
|
use std::ops::Index;
|
2019-02-16 19:58:07 -08:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
pub struct BankForks {
|
|
|
|
banks: HashMap<u64, Arc<Bank>>,
|
2019-02-28 10:57:58 -08:00
|
|
|
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]
|
|
|
|
}
|
2019-02-16 19:58:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BankForks {
|
2019-02-28 10:57:58 -08:00
|
|
|
pub fn new(bank_id: u64, bank: Bank) -> Self {
|
2019-02-16 19:58:07 -08:00
|
|
|
let mut banks = HashMap::new();
|
2019-02-28 10:57:58 -08:00
|
|
|
let working_bank = Arc::new(bank);
|
|
|
|
banks.insert(bank_id, working_bank.clone());
|
2019-02-16 19:58:07 -08:00
|
|
|
Self {
|
|
|
|
banks,
|
2019-02-28 10:57:58 -08:00
|
|
|
working_bank,
|
2019-02-16 19:58:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-28 12:09:19 -08:00
|
|
|
pub fn new_from_banks(initial_banks: &[Arc<Bank>]) -> 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 {
|
|
|
|
banks,
|
|
|
|
working_bank,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-28 10:57:58 -08:00
|
|
|
// 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) {
|
2019-02-26 09:18:24 -08:00
|
|
|
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() {
|
2019-02-28 10:57:58 -08:00
|
|
|
self.working_bank = bank.clone()
|
|
|
|
}
|
|
|
|
|
2019-02-26 09:18:24 -08:00
|
|
|
// 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());
|
2019-02-26 09:18:24 -08:00
|
|
|
bank = parent;
|
|
|
|
}
|
2019-02-16 19:58:07 -08:00
|
|
|
}
|
|
|
|
|
2019-02-28 10:57:58 -08:00
|
|
|
// TODO: really want to kill this...
|
|
|
|
pub fn working_bank(&self) -> Arc<Bank> {
|
|
|
|
self.working_bank.clone()
|
2019-02-16 19:58:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2019-02-20 16:14:58 -08:00
|
|
|
use solana_sdk::genesis_block::GenesisBlock;
|
2019-02-20 21:31:24 -08:00
|
|
|
use solana_sdk::hash::Hash;
|
2019-02-16 19:58:07 -08:00
|
|
|
|
|
|
|
#[test]
|
2019-02-28 10:57:58 -08:00
|
|
|
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);
|
2019-02-28 10:57:58 -08:00
|
|
|
let child_bank = Bank::new_from_parent(&bank_forks[0u64]);
|
2019-02-16 19:58:07 -08:00
|
|
|
child_bank.register_tick(&Hash::default());
|
2019-02-26 09:18:24 -08:00
|
|
|
bank_forks.insert(1, child_bank);
|
2019-02-28 10:57:58 -08:00
|
|
|
assert_eq!(bank_forks[1u64].tick_height(), 1);
|
2019-02-26 09:18:24 -08:00
|
|
|
assert_eq!(bank_forks.working_bank().tick_height(), 1);
|
2019-02-16 19:58:07 -08:00
|
|
|
}
|
|
|
|
}
|