hash account state on store (#5573)

This commit is contained in:
sakridge
2019-09-20 13:21:12 -07:00
committed by GitHub
parent 5dd3a07a23
commit 19ae556857
14 changed files with 484 additions and 54 deletions

View File

@@ -285,7 +285,11 @@ impl Bank {
assert_ne!(slot, parent.slot());
let rc = BankRc {
accounts: Arc::new(Accounts::new_from_parent(&parent.rc.accounts)),
accounts: Arc::new(Accounts::new_from_parent(
&parent.rc.accounts,
slot,
parent.slot(),
)),
parent: RwLock::new(Some(parent.clone())),
slot,
};
@@ -1338,6 +1342,14 @@ impl Bank {
}
}
/// Recalculate the hash_internal_state from the account stores. Would be used to verify a
/// snaphsot.
pub fn verify_hash_internal_state(&self) -> bool {
self.rc
.accounts
.verify_hash_internal_state(self.slot(), &self.ancestors)
}
/// Return the number of ticks per slot
pub fn ticks_per_slot(&self) -> u64 {
self.ticks_per_slot
@@ -1807,6 +1819,7 @@ mod tests {
#[test]
fn test_transfer_to_newb() {
solana_logger::setup();
let (genesis_block, mint_keypair) = create_genesis_block(10_000);
let bank = Bank::new(&genesis_block);
let pubkey = Pubkey::new_rand();
@@ -2316,6 +2329,55 @@ mod tests {
// Checkpointing should not change its state
let bank2 = new_from_parent(&Arc::new(bank1));
assert_eq!(bank0.hash_internal_state(), bank2.hash_internal_state());
let pubkey2 = Pubkey::new_rand();
info!("transfer 2 {}", pubkey2);
bank2.transfer(10, &mint_keypair, &pubkey2).unwrap();
assert!(bank2.verify_hash_internal_state());
}
#[test]
fn test_bank_hash_internal_state_verify() {
solana_logger::setup();
let (genesis_block, mint_keypair) = create_genesis_block(2_000);
let bank0 = Bank::new(&genesis_block);
let pubkey = Pubkey::new_rand();
info!("transfer 0 {} mint: {}", pubkey, mint_keypair.pubkey());
bank0.transfer(1_000, &mint_keypair, &pubkey).unwrap();
let bank0_state = bank0.hash_internal_state();
// Checkpointing should not change its state
let bank2 = new_from_parent(&Arc::new(bank0));
assert_eq!(bank0_state, bank2.hash_internal_state());
let pubkey2 = Pubkey::new_rand();
info!("transfer 2 {}", pubkey2);
bank2.transfer(10, &mint_keypair, &pubkey2).unwrap();
assert!(bank2.verify_hash_internal_state());
}
// Test that two bank forks with the same accounts should not hash to the same value.
#[test]
fn test_bank_hash_internal_state_same_account_different_fork() {
solana_logger::setup();
let (genesis_block, mint_keypair) = create_genesis_block(2_000);
let bank0 = Arc::new(Bank::new(&genesis_block));
let initial_state = bank0.hash_internal_state();
let bank1 = Bank::new_from_parent(&bank0.clone(), &Pubkey::default(), 1);
assert_eq!(bank1.hash_internal_state(), initial_state);
info!("transfer bank1");
let pubkey = Pubkey::new_rand();
bank1.transfer(1_000, &mint_keypair, &pubkey).unwrap();
assert_ne!(bank1.hash_internal_state(), initial_state);
info!("transfer bank2");
// bank2 should not hash the same as bank1
let bank2 = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
bank2.transfer(1_000, &mint_keypair, &pubkey).unwrap();
assert_ne!(bank2.hash_internal_state(), initial_state);
assert_ne!(bank1.hash_internal_state(), bank2.hash_internal_state());
}
#[test]
@@ -2325,6 +2387,44 @@ mod tests {
assert_ne!(bank0.hash_internal_state(), bank1.hash_internal_state());
}
// See that the order of two transfers does not affect the result
// of hash_internal_state
#[test]
fn test_hash_internal_state_order() {
let (genesis_block, mint_keypair) = create_genesis_block(100);
let bank0 = Bank::new(&genesis_block);
let bank1 = Bank::new(&genesis_block);
assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
let key0 = Pubkey::new_rand();
let key1 = Pubkey::new_rand();
bank0.transfer(10, &mint_keypair, &key0).unwrap();
bank0.transfer(20, &mint_keypair, &key1).unwrap();
bank1.transfer(20, &mint_keypair, &key1).unwrap();
bank1.transfer(10, &mint_keypair, &key0).unwrap();
assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
}
#[test]
fn test_hash_internal_state_error() {
solana_logger::setup();
let (genesis_block, mint_keypair) = create_genesis_block(100);
let bank = Bank::new(&genesis_block);
let key0 = Pubkey::new_rand();
bank.transfer(10, &mint_keypair, &key0).unwrap();
let orig = bank.hash_internal_state();
// Transfer will error but still take a fee
assert!(bank.transfer(1000, &mint_keypair, &key0).is_err());
assert_ne!(orig, bank.hash_internal_state());
let orig = bank.hash_internal_state();
let empty_keypair = Keypair::new();
assert!(bank.transfer(1000, &empty_keypair, &key0).is_err());
assert_eq!(orig, bank.hash_internal_state());
}
#[test]
fn test_bank_hash_internal_state_squash() {
let collector_id = Pubkey::default();