diff --git a/src/accounts.rs b/src/accounts.rs index ab439f7029..d1916ceac8 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -1,6 +1,5 @@ use crate::bank::BankError; use crate::bank::Result; -use crate::checkpoint::Checkpoint; use crate::counter::Counter; use crate::status_deque::{StatusDeque, StatusDequeError}; use bincode::serialize; @@ -11,7 +10,6 @@ use solana_sdk::hash::{hash, Hash}; use solana_sdk::pubkey::Pubkey; use solana_sdk::transaction::Transaction; use std::collections::BTreeMap; -use std::collections::VecDeque; use std::sync::atomic::AtomicUsize; use std::sync::{Mutex, RwLock}; @@ -35,9 +33,6 @@ pub struct AccountsDB { /// Mapping of known public keys/IDs to accounts pub accounts: HashMap, - /// list of prior states - checkpoints: VecDeque<(HashMap, u64)>, - /// The number of transactions the bank has processed without error since the /// start of the ledger. transaction_count: u64, @@ -55,7 +50,6 @@ impl Default for AccountsDB { fn default() -> Self { Self { accounts: HashMap::new(), - checkpoints: VecDeque::new(), transaction_count: 0, } } @@ -91,24 +85,12 @@ impl AccountsDB { if let Some(account) = self.accounts.get(pubkey) { return Some(account); } - - for (accounts, _) in &self.checkpoints { - if let Some(account) = accounts.get(pubkey) { - return Some(account); - } - } None } pub fn store(&mut self, pubkey: &Pubkey, account: &Account) { if account.tokens == 0 { - if self.checkpoints.is_empty() { - // purge if balance is 0 and no checkpoints - self.accounts.remove(pubkey); - } else { - // store default account if balance is 0 and there's a checkpoint - self.accounts.insert(pubkey.clone(), Account::default()); - } + self.accounts.remove(pubkey); } else { self.accounts.insert(pubkey.clone(), account.clone()); } @@ -266,15 +248,6 @@ impl AccountsDB { pub fn transaction_count(&self) -> u64 { self.transaction_count } - - pub fn checkpoint_and_copy(&mut self) -> AccountsDB { - self.checkpoint(); - let (accounts, tx_count) = self.checkpoints.front().unwrap(); - let mut copy = AccountsDB::default(); - copy.accounts = accounts.clone(); - copy.transaction_count = *tx_count; - copy - } } impl Accounts { @@ -392,66 +365,6 @@ impl Accounts { pub fn transaction_count(&self) -> u64 { self.accounts_db.read().unwrap().transaction_count() } - - pub fn checkpoint(&self) { - self.accounts_db.write().unwrap().checkpoint() - } - - pub fn rollback(&self) { - self.accounts_db.write().unwrap().rollback() - } - - pub fn purge(&self, depth: usize) { - self.accounts_db.write().unwrap().purge(depth) - } - - pub fn depth(&self) -> usize { - self.accounts_db.read().unwrap().depth() - } - - pub fn checkpoint_and_copy(&self) -> Accounts { - let db = self.accounts_db.write().unwrap().checkpoint_and_copy(); - let mut copy = Accounts::default(); - copy.accounts_db = RwLock::new(db); - copy - } -} - -impl Checkpoint for AccountsDB { - fn checkpoint(&mut self) { - let accounts = self.accounts.clone(); - - self.checkpoints - .push_front((accounts, self.transaction_count())); - } - - fn rollback(&mut self) { - let (accounts, transaction_count) = self.checkpoints.pop_front().unwrap(); - self.accounts = accounts; - self.transaction_count = transaction_count; - } - - fn purge(&mut self, depth: usize) { - fn merge(into: &mut HashMap, purge: &mut HashMap) { - purge.retain(|pubkey, _| !into.contains_key(pubkey)); - into.extend(purge.drain()); - into.retain(|_, account| account.tokens != 0); - } - - while self.depth() > depth { - let (mut purge, _) = self.checkpoints.pop_back().unwrap(); - - if let Some((into, _)) = self.checkpoints.back_mut() { - merge(into, &mut purge); - continue; - } - merge(&mut self.accounts, &mut purge); - } - } - - fn depth(&self) -> usize { - self.checkpoints.len() - } } #[cfg(test)] diff --git a/src/bank.rs b/src/bank.rs index 76bd0ee924..871b727d13 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -4,7 +4,6 @@ //! already been signed and verified. use crate::accounts::{Accounts, ErrorCounters, InstructionAccounts, InstructionLoaders}; -use crate::checkpoint::Checkpoint; use crate::counter::Counter; use crate::entry::Entry; use crate::entry::EntrySlice; @@ -138,48 +137,6 @@ impl Bank { *sub = subscriptions } - /// Checkpoint this bank and return a copy of it - pub fn checkpoint_and_copy(&self) -> Bank { - let last_ids_cp = self.last_ids.write().unwrap().checkpoint_and_copy(); - let accounts = self.accounts.checkpoint_and_copy(); - - let mut copy = Bank::default(); - copy.accounts = accounts; - copy.last_ids = RwLock::new(last_ids_cp); - copy.leader_scheduler = - Arc::new(RwLock::new(self.leader_scheduler.read().unwrap().clone())); - copy.confirmation_time = AtomicUsize::new(self.confirmation_time.load(Ordering::Relaxed)); - copy - } - - pub fn checkpoint(&self) { - self.accounts.checkpoint(); - self.last_ids.write().unwrap().checkpoint(); - } - pub fn purge(&self, depth: usize) { - self.accounts.purge(depth); - self.last_ids.write().unwrap().purge(depth); - } - - pub fn rollback(&self) { - let rolled_back_pubkeys: Vec = self.accounts.keys(); - self.accounts.rollback(); - - rolled_back_pubkeys.iter().for_each(|pubkey| { - if let Some(account) = self.accounts.load_slow(&pubkey) { - self.subscriptions - .read() - .unwrap() - .check_account(&pubkey, &account) - } - }); - - self.last_ids.write().unwrap().rollback(); - } - pub fn checkpoint_depth(&self) -> usize { - self.accounts.depth() - } - fn process_genesis_block(&self, genesis_block: &GenesisBlock) { assert!(genesis_block.mint_id != Pubkey::default()); assert!(genesis_block.tokens >= genesis_block.bootstrap_leader_tokens); @@ -869,8 +826,6 @@ mod tests { use super::*; use crate::entry::{next_entries, next_entry, Entry}; use crate::gen_keys::GenKeys; - use crate::status_deque; - use crate::status_deque::StatusDequeError; use bincode::serialize; use hashbrown::HashSet; use solana_sdk::hash::hash; @@ -1577,199 +1532,6 @@ mod tests { assert!(ids.into_iter().all(move |id| unique.insert(id))); } - #[test] - fn test_bank_purge() { - let (genesis_block, alice) = GenesisBlock::new(10_000); - let bank = Bank::new(&genesis_block); - let bob = Keypair::new(); - let charlie = Keypair::new(); - - // bob should have 500 - bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - - bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - - bank.checkpoint(); - bank.checkpoint(); - assert_eq!(bank.checkpoint_depth(), 2); - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - assert_eq!(bank.get_balance(&alice.pubkey()), 9_000); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 2); - - // transfer money back, so bob has zero - bank.transfer(500, &bob, alice.pubkey(), genesis_block.last_id()) - .unwrap(); - // this has to be stored as zero in the top accounts hashmap ;) - assert!(bank.accounts.load_slow(&bob.pubkey()).is_some()); - assert_eq!(bank.get_balance(&bob.pubkey()), 0); - // double-checks - assert_eq!(bank.get_balance(&alice.pubkey()), 9_500); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 3); - bank.purge(1); - - assert_eq!(bank.get_balance(&bob.pubkey()), 0); - // double-checks - assert_eq!(bank.get_balance(&alice.pubkey()), 9_500); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 3); - assert_eq!(bank.checkpoint_depth(), 1); - - bank.purge(0); - - // bob should still have 0, alice should have 10_000 - assert_eq!(bank.get_balance(&bob.pubkey()), 0); - assert!(bank.accounts.load_slow(&bob.pubkey()).is_none()); - // double-checks - assert_eq!(bank.get_balance(&alice.pubkey()), 9_500); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 3); - assert_eq!(bank.checkpoint_depth(), 0); - } - - #[test] - fn test_bank_checkpoint_zero_balance() { - let (genesis_block, alice) = GenesisBlock::new(1_000); - let bank = Bank::new(&genesis_block); - let bob = Keypair::new(); - let charlie = Keypair::new(); - - // bob should have 500 - bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - assert_eq!(bank.checkpoint_depth(), 0); - - let account = bank.get_account(&alice.pubkey()).unwrap(); - let default_account = Account::default(); - assert_eq!(account.userdata, default_account.userdata); - assert_eq!(account.owner, default_account.owner); - assert_eq!(account.executable, default_account.executable); - assert_eq!(account.loader, default_account.loader); - - bank.checkpoint(); - assert_eq!(bank.checkpoint_depth(), 1); - - // charlie should have 500, alice should have 0 - bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.get_balance(&alice.pubkey()), 0); - - let account = bank.get_account(&alice.pubkey()).unwrap(); - assert_eq!(account.tokens, default_account.tokens); - assert_eq!(account.userdata, default_account.userdata); - assert_eq!(account.owner, default_account.owner); - assert_eq!(account.executable, default_account.executable); - assert_eq!(account.loader, default_account.loader); - } - - fn reserve_signature_with_last_id_test( - bank: &Bank, - sig: &Signature, - last_id: &Hash, - ) -> status_deque::Result<()> { - let mut last_ids = bank.last_ids.write().unwrap(); - last_ids.reserve_signature_with_last_id(last_id, sig) - } - - #[test] - fn test_bank_checkpoint_rollback() { - let (genesis_block, alice) = GenesisBlock::new(10_000); - let bank = Bank::new(&genesis_block); - let bob = Keypair::new(); - let charlie = Keypair::new(); - - // bob should have 500 - bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.checkpoint_depth(), 0); - - bank.checkpoint(); - bank.checkpoint(); - assert_eq!(bank.checkpoint_depth(), 2); - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 2); - - // transfer money back, so bob has zero - bank.transfer(500, &bob, alice.pubkey(), genesis_block.last_id()) - .unwrap(); - // this has to be stored as zero in the top accounts hashmap ;) - assert_eq!(bank.get_balance(&bob.pubkey()), 0); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 3); - bank.rollback(); - - // bob should have 500 again - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.transaction_count(), 2); - assert_eq!(bank.checkpoint_depth(), 1); - - let signature = Signature::default(); - for i in 0..MAX_ENTRY_IDS + 1 { - let last_id = hash(&serialize(&i).unwrap()); // Unique hash - bank.register_tick(&last_id); - } - assert_eq!(bank.tick_height(), MAX_ENTRY_IDS as u64 + 2); - assert_eq!( - reserve_signature_with_last_id_test(&bank, &signature, &genesis_block.last_id()), - Err(StatusDequeError::LastIdNotFound) - ); - bank.rollback(); - assert_eq!(bank.tick_height(), 1); - assert_eq!( - reserve_signature_with_last_id_test(&bank, &signature, &genesis_block.last_id()), - Ok(()) - ); - bank.checkpoint(); - assert_eq!( - reserve_signature_with_last_id_test(&bank, &signature, &genesis_block.last_id()), - Err(StatusDequeError::DuplicateSignature) - ); - } - - #[test] - fn test_bank_checkpoint_and_copy() { - let (genesis_block, alice) = GenesisBlock::new(10_000); - let bank = Bank::new(&genesis_block); - let bob = Keypair::new(); - let charlie = Keypair::new(); - - // bob should have 500 - bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&bob.pubkey()), 500); - bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id()) - .unwrap(); - assert_eq!(bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(bank.checkpoint_depth(), 0); - - let cp_bank = bank.checkpoint_and_copy(); - assert_eq!(cp_bank.get_balance(&bob.pubkey()), 500); - assert_eq!(cp_bank.get_balance(&charlie.pubkey()), 500); - assert_eq!(cp_bank.checkpoint_depth(), 0); - assert_eq!(bank.checkpoint_depth(), 1); - } - - #[test] - #[should_panic] - fn test_bank_rollback_panic() { - let (genesis_block, _) = GenesisBlock::new(10_000); - let bank = Bank::new(&genesis_block); - bank.rollback(); - } - #[test] fn test_bank_record_transactions() { let (genesis_block, mint_keypair) = GenesisBlock::new(10_000); diff --git a/src/broadcast_service.rs b/src/broadcast_service.rs index 8c4b12f300..ee4af66bac 100644 --- a/src/broadcast_service.rs +++ b/src/broadcast_service.rs @@ -213,7 +213,7 @@ impl BroadcastService { if let Err(e) = broadcast.run(&broadcast_table, receiver, sock, leader_scheduler) { match e { Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => { - return BroadcastServiceReturnType::ChannelDisconnected + return BroadcastServiceReturnType::ChannelDisconnected; } Error::RecvTimeoutError(RecvTimeoutError::Timeout) => (), Error::ClusterInfoError(ClusterInfoError::NoPeers) => (), // TODO: Why are the unit-tests throwing hundreds of these? diff --git a/src/checkpoint.rs b/src/checkpoint.rs deleted file mode 100644 index 9a5355f746..0000000000 --- a/src/checkpoint.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub trait Checkpoint { - /// add a checkpoint to this data at current state - fn checkpoint(&mut self); - - /// rollback to previous state, panics if no prior checkpoint - fn rollback(&mut self); - - /// cull checkpoints to depth, that is depth of zero means - /// no checkpoints, only current state - fn purge(&mut self, depth: usize); - - /// returns the number of checkpoints - fn depth(&self) -> usize; -} diff --git a/src/fullnode.rs b/src/fullnode.rs index fb99ce879e..8b8d409837 100644 --- a/src/fullnode.rs +++ b/src/fullnode.rs @@ -278,7 +278,7 @@ impl Fullnode { }; let tpu = Tpu::new( - &Arc::new(bank.checkpoint_and_copy()), + &bank, Default::default(), node.sockets .tpu @@ -360,7 +360,7 @@ impl Fullnode { let (to_validator_sender, to_validator_receiver) = channel(); self.role_notifiers.1 = to_validator_receiver; self.node_services.tpu.switch_to_leader( - &Arc::new(self.bank.checkpoint_and_copy()), + &self.bank, Default::default(), self.tpu_sockets .iter() diff --git a/src/lib.rs b/src/lib.rs index b268ff9b11..14693f074b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,6 @@ pub mod broadcast_service; pub mod chacha; #[cfg(all(feature = "chacha", feature = "cuda"))] pub mod chacha_cuda; -pub mod checkpoint; pub mod client; pub mod crds; pub mod crds_gossip; diff --git a/src/status_deque.rs b/src/status_deque.rs index 195155eaa6..8a44efcf9a 100644 --- a/src/status_deque.rs +++ b/src/status_deque.rs @@ -1,10 +1,8 @@ -use crate::checkpoint::Checkpoint; use crate::poh_service::NUM_TICKS_PER_SECOND; use hashbrown::HashMap; use solana_sdk::hash::Hash; use solana_sdk::signature::Signature; use solana_sdk::timing::timestamp; -use std::collections::VecDeque; use std::result; /// The number of most recent `last_id` values that the bank will track the signatures @@ -67,8 +65,6 @@ pub struct StatusDeque { /// reject transactions with signatures it's seen before and to reject /// transactions that are too old (nth is too small) entries: StatusEntryMap, - - checkpoints: VecDeque<(u64, Option, StatusEntryMap)>, } impl Default for StatusDeque { @@ -77,32 +73,10 @@ impl Default for StatusDeque { tick_height: 0, last_id: None, entries: HashMap::new(), - checkpoints: VecDeque::new(), } } } -impl Checkpoint for StatusDeque { - fn checkpoint(&mut self) { - self.checkpoints - .push_front((self.tick_height, self.last_id, self.entries.clone())); - } - fn rollback(&mut self) { - let (tick_height, last_id, entries) = self.checkpoints.pop_front().unwrap(); - self.tick_height = tick_height; - self.last_id = last_id; - self.entries = entries; - } - fn purge(&mut self, depth: usize) { - while self.depth() > depth { - self.checkpoints.pop_back().unwrap(); - } - } - fn depth(&self) -> usize { - self.checkpoints.len() - } -} - impl StatusDeque { pub fn update_signature_status_with_last_id( &mut self, @@ -116,15 +90,6 @@ impl StatusDeque { .insert(*signature, Status::Complete(result.clone())); } } - pub fn checkpoint_and_copy(&mut self) -> StatusDeque { - self.checkpoint(); - let (tick_height, last_id, entries) = self.checkpoints.front().unwrap().clone(); - let mut copy = StatusDeque::default(); - copy.tick_height = tick_height; - copy.last_id = last_id; - copy.entries = entries; - copy - } pub fn reserve_signature_with_last_id( &mut self, last_id: &Hash, @@ -264,23 +229,6 @@ mod tests { ); } - #[test] - fn test_duplicate_transaction_signature_checkpoint() { - let sig = Default::default(); - let last_id = Default::default(); - let mut status_deque: StatusDeque<()> = StatusDeque::default(); - status_deque.register_tick(&last_id); - assert_eq!( - status_deque.reserve_signature_with_last_id(&last_id, &sig), - Ok(()) - ); - status_deque.checkpoint(); - assert_eq!( - status_deque.reserve_signature_with_last_id(&last_id, &sig), - Err(StatusDequeError::DuplicateSignature) - ); - } - #[test] fn test_clear_signatures() { let signature = Signature::default(); @@ -297,23 +245,6 @@ mod tests { ); } - #[test] - fn test_clear_signatures_checkpoint() { - let signature = Signature::default(); - let last_id = Default::default(); - let mut status_deque: StatusDeque<()> = StatusDeque::default(); - status_deque.register_tick(&last_id); - status_deque - .reserve_signature_with_last_id(&last_id, &signature) - .unwrap(); - status_deque.checkpoint(); - status_deque.clear_signatures(); - assert_eq!( - status_deque.reserve_signature_with_last_id(&last_id, &signature), - Ok(()) - ); - } - #[test] fn test_get_signature_status() { let signature = Signature::default();