Make Bank::hash_internal_state() work with checkpoints
This commit is contained in:
parent
760a82cb08
commit
90684483e2
26
src/bank.rs
26
src/bank.rs
|
@ -10,13 +10,13 @@ use crate::last_id_queue::{LastIdQueue, MAX_ENTRY_IDS};
|
|||
use crate::poh_service::NUM_TICKS_PER_SECOND;
|
||||
use crate::rpc_subscriptions::RpcSubscriptions;
|
||||
use crate::status_cache::StatusCache;
|
||||
use bincode::deserialize;
|
||||
use bincode::{deserialize, serialize};
|
||||
use log::Level;
|
||||
use solana_runtime::{self, RuntimeError};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::bpf_loader;
|
||||
use solana_sdk::budget_program;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::hash::{extend_and_hash, Hash};
|
||||
use solana_sdk::native_loader;
|
||||
use solana_sdk::native_program::ProgramError;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
@ -92,6 +92,8 @@ pub struct Bank {
|
|||
subscriptions: RwLock<Option<Arc<RpcSubscriptions>>>,
|
||||
|
||||
parent: Option<Arc<Bank>>,
|
||||
|
||||
parent_hash: Hash,
|
||||
}
|
||||
|
||||
impl Default for Bank {
|
||||
|
@ -102,14 +104,16 @@ impl Default for Bank {
|
|||
status_cache: RwLock::new(BankStatusCache::default()),
|
||||
subscriptions: RwLock::new(None),
|
||||
parent: None,
|
||||
parent_hash: Hash::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Bank {
|
||||
pub fn new(genesis_block: &GenesisBlock) -> Self {
|
||||
let bank = Self::default();
|
||||
let mut bank = Self::default();
|
||||
bank.process_genesis_block(genesis_block);
|
||||
bank.parent_hash = bank.hash_internal_state();
|
||||
bank.add_builtin_programs();
|
||||
bank
|
||||
}
|
||||
|
@ -117,6 +121,7 @@ impl Bank {
|
|||
pub fn new_from_parent(parent: &Arc<Bank>) -> Self {
|
||||
let mut bank = Self::default();
|
||||
bank.last_id_queue = RwLock::new(parent.last_id_queue.read().unwrap().clone());
|
||||
bank.parent_hash = parent.hash_internal_state();
|
||||
bank.parent = Some(parent.clone());
|
||||
bank
|
||||
}
|
||||
|
@ -131,7 +136,7 @@ impl Bank {
|
|||
*sub = Some(subscriptions)
|
||||
}
|
||||
|
||||
pub fn process_genesis_block(&self, genesis_block: &GenesisBlock) {
|
||||
fn process_genesis_block(&self, genesis_block: &GenesisBlock) {
|
||||
assert!(genesis_block.mint_id != Pubkey::default());
|
||||
assert!(genesis_block.bootstrap_leader_id != Pubkey::default());
|
||||
assert!(genesis_block.bootstrap_leader_vote_account_id != Pubkey::default());
|
||||
|
@ -181,7 +186,7 @@ impl Bank {
|
|||
.genesis_last_id(&genesis_block.last_id());
|
||||
}
|
||||
|
||||
pub fn add_builtin_programs(&self) {
|
||||
fn add_builtin_programs(&self) {
|
||||
let system_program_account = native_loader::create_program_account("solana_system_program");
|
||||
self.accounts
|
||||
.store_slow(true, &system_program::id(), &system_program_account);
|
||||
|
@ -593,7 +598,15 @@ impl Bank {
|
|||
/// Hash the `accounts` HashMap. This represents a validator's interpretation
|
||||
/// of the delta of the ledger since the last vote and up to now
|
||||
pub fn hash_internal_state(&self) -> Hash {
|
||||
self.accounts.hash_internal_state()
|
||||
// If there are no accounts, return the same hash as we did before
|
||||
// checkpointing.
|
||||
let accounts = &self.accounts.accounts_db.read().unwrap().accounts;
|
||||
if accounts.is_empty() {
|
||||
return self.parent_hash;
|
||||
}
|
||||
|
||||
let accounts_delta_hash = self.accounts.hash_internal_state();
|
||||
extend_and_hash(&self.parent_hash, &serialize(&accounts_delta_hash).unwrap())
|
||||
}
|
||||
|
||||
fn send_account_notifications(
|
||||
|
@ -653,7 +666,6 @@ impl Bank {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bincode::serialize;
|
||||
use hashbrown::HashSet;
|
||||
use solana_sdk::hash::hash;
|
||||
use solana_sdk::native_program::ProgramError;
|
||||
|
|
|
@ -315,13 +315,9 @@ mod tests {
|
|||
&keypairs,
|
||||
);
|
||||
|
||||
let bank0 = Bank::default();
|
||||
bank0.add_builtin_programs();
|
||||
bank0.process_genesis_block(&genesis_block);
|
||||
let bank0 = Bank::new(&genesis_block);
|
||||
par_process_entries(&bank0, &entries0).unwrap();
|
||||
let bank1 = Bank::default();
|
||||
bank1.add_builtin_programs();
|
||||
bank1.process_genesis_block(&genesis_block);
|
||||
let bank1 = Bank::new(&genesis_block);
|
||||
par_process_entries(&bank1, &entries1).unwrap();
|
||||
|
||||
let initial_state = bank0.hash_internal_state();
|
||||
|
@ -337,6 +333,17 @@ mod tests {
|
|||
.transfer(1_000, &mint_keypair, pubkey, bank1.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
|
||||
|
||||
// Checkpointing should not change its state
|
||||
let bank2 = Bank::new_from_parent(&Arc::new(bank1));
|
||||
assert_eq!(bank0.hash_internal_state(), bank2.hash_internal_state());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_internal_state_parents() {
|
||||
let bank0 = Bank::new(&GenesisBlock::new(10).0);
|
||||
let bank1 = Bank::new(&GenesisBlock::new(20).0);
|
||||
assert_ne!(bank0.hash_internal_state(), bank1.hash_internal_state());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue