Remove hash field from account (#9915)

This commit is contained in:
Justin Starry 2020-05-12 23:39:46 +08:00 committed by GitHub
parent a75086287c
commit 5cc252d471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 54 deletions

View File

@ -93,7 +93,6 @@ impl RpcAccount {
})?, })?,
executable: self.executable, executable: self.executable,
rent_epoch: self.rent_epoch, rent_epoch: self.rent_epoch,
..Account::default()
}) })
} }
} }

View File

@ -13,7 +13,6 @@ use solana_sdk::{
bpf_loader, bpf_loader,
entrypoint::SUCCESS, entrypoint::SUCCESS,
entrypoint_native::InvokeContext, entrypoint_native::InvokeContext,
hash::Hash,
instruction::{AccountMeta, Instruction, InstructionError}, instruction::{AccountMeta, Instruction, InstructionError},
message::Message, message::Message,
program_error::ProgramError, program_error::ProgramError,
@ -399,7 +398,6 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
executable: account_info.executable, executable: account_info.executable,
owner: *owner, owner: *owner,
rent_epoch: account_info.rent_epoch, rent_epoch: account_info.rent_epoch,
hash: Hash::default(),
}))); })));
refs.push((lamports_ref, data)); refs.push((lamports_ref, data));
continue 'root; continue 'root;
@ -599,7 +597,6 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
executable: account_info.executable, executable: account_info.executable,
owner: *owner, owner: *owner,
rent_epoch: account_info.rent_epoch, rent_epoch: account_info.rent_epoch,
hash: Hash::default(),
}))); })));
refs.push((lamports_ref, data)); refs.push((lamports_ref, data));
continue 'root; continue 'root;

View File

@ -396,8 +396,8 @@ impl<'a, 'b> Serialize for AccountsDBSerialize<'a, 'b> {
#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct BankHashStats { pub struct BankHashStats {
pub num_updated_accounts: u64,
pub num_removed_accounts: u64, pub num_removed_accounts: u64,
pub num_added_accounts: u64,
pub num_lamports_stored: u64, pub num_lamports_stored: u64,
pub total_data_len: u64, pub total_data_len: u64,
pub num_executable_accounts: u64, pub num_executable_accounts: u64,
@ -405,10 +405,10 @@ pub struct BankHashStats {
impl BankHashStats { impl BankHashStats {
pub fn update(&mut self, account: &Account) { pub fn update(&mut self, account: &Account) {
if Hash::default() == account.hash { if account.lamports == 0 {
self.num_added_accounts += 1;
} else {
self.num_removed_accounts += 1; self.num_removed_accounts += 1;
} else {
self.num_updated_accounts += 1;
} }
self.total_data_len = self.total_data_len.wrapping_add(account.data.len() as u64); self.total_data_len = self.total_data_len.wrapping_add(account.data.len() as u64);
if account.executable { if account.executable {
@ -418,8 +418,8 @@ impl BankHashStats {
} }
pub fn merge(&mut self, other: &BankHashStats) { pub fn merge(&mut self, other: &BankHashStats) {
self.num_updated_accounts += other.num_updated_accounts;
self.num_removed_accounts += other.num_removed_accounts; self.num_removed_accounts += other.num_removed_accounts;
self.num_added_accounts += other.num_added_accounts;
self.total_data_len = self.total_data_len.wrapping_add(other.total_data_len); self.total_data_len = self.total_data_len.wrapping_add(other.total_data_len);
self.num_lamports_stored = self self.num_lamports_stored = self
.num_lamports_stored .num_lamports_stored
@ -956,6 +956,7 @@ impl AccountsDB {
stored_accounts.push(( stored_accounts.push((
account.meta.pubkey, account.meta.pubkey,
account.clone_account(), account.clone_account(),
*account.hash,
next - start, next - start,
(store.id, account.offset), (store.id, account.offset),
account.meta.write_version, account.meta.write_version,
@ -980,7 +981,14 @@ impl AccountsDB {
stored_accounts stored_accounts
.iter() .iter()
.filter( .filter(
|(pubkey, _account, _storage_size, (store_id, offset), _write_version)| { |(
pubkey,
_account,
_account_hash,
_storage_size,
(store_id, offset),
_write_version,
)| {
if let Some((list, _)) = accounts_index.get(pubkey, &no_ancestors) { if let Some((list, _)) = accounts_index.get(pubkey, &no_ancestors) {
list.iter() list.iter()
.any(|(_slot, i)| i.store_id == *store_id && i.offset == *offset) .any(|(_slot, i)| i.store_id == *store_id && i.offset == *offset)
@ -994,7 +1002,11 @@ impl AccountsDB {
let alive_total: u64 = alive_accounts let alive_total: u64 = alive_accounts
.iter() .iter()
.map(|(_pubkey, _account, account_size, _location, _write_verion)| *account_size as u64) .map(
|(_pubkey, _account, _account_hash, account_size, _location, _write_verion)| {
*account_size as u64
},
)
.sum(); .sum();
let aligned_total: u64 = (alive_total + (PAGE_SIZE - 1)) & !(PAGE_SIZE - 1); let aligned_total: u64 = (alive_total + (PAGE_SIZE - 1)) & !(PAGE_SIZE - 1);
@ -1012,9 +1024,9 @@ impl AccountsDB {
let mut hashes = Vec::with_capacity(alive_accounts.len()); let mut hashes = Vec::with_capacity(alive_accounts.len());
let mut write_versions = Vec::with_capacity(alive_accounts.len()); let mut write_versions = Vec::with_capacity(alive_accounts.len());
for (pubkey, account, _size, _location, write_version) in alive_accounts { for (pubkey, account, account_hash, _size, _location, write_version) in alive_accounts {
accounts.push((pubkey, account)); accounts.push((pubkey, account));
hashes.push(account.hash); hashes.push(*account_hash);
write_versions.push(*write_version); write_versions.push(*write_version);
} }
@ -1183,6 +1195,19 @@ impl AccountsDB {
} }
} }
#[cfg(test)]
fn load_account_hash(&self, ancestors: &Ancestors, pubkey: &Pubkey) -> Hash {
let accounts_index = self.accounts_index.read().unwrap();
let (lock, index) = accounts_index.get(pubkey, ancestors).unwrap();
let slot = lock[index].0;
let storage = self.storage.read().unwrap();
let slot_storage = storage.0.get(&slot).unwrap();
let info = &lock[index].1;
let entry = slot_storage.get(&info.store_id).unwrap();
let account = entry.accounts.get_account(info.offset);
*account.as_ref().unwrap().0.hash
}
pub fn load_slow(&self, ancestors: &Ancestors, pubkey: &Pubkey) -> Option<(Account, Slot)> { pub fn load_slow(&self, ancestors: &Ancestors, pubkey: &Pubkey) -> Option<(Account, Slot)> {
let accounts_index = self.accounts_index.read().unwrap(); let accounts_index = self.accounts_index.read().unwrap();
let storage = self.storage.read().unwrap(); let storage = self.storage.read().unwrap();
@ -3500,16 +3525,16 @@ pub mod tests {
db.store(some_slot, &[(&key, &account)]); db.store(some_slot, &[(&key, &account)]);
let mut account = db.load_slow(&ancestors, &key).unwrap().0; let mut account = db.load_slow(&ancestors, &key).unwrap().0;
account.lamports += 1; account.lamports -= 1;
account.executable = true; account.executable = true;
db.store(some_slot, &[(&key, &account)]); db.store(some_slot, &[(&key, &account)]);
db.add_root(some_slot); db.add_root(some_slot);
let bank_hashes = db.bank_hashes.read().unwrap(); let bank_hashes = db.bank_hashes.read().unwrap();
let bank_hash = bank_hashes.get(&some_slot).unwrap(); let bank_hash = bank_hashes.get(&some_slot).unwrap();
assert_eq!(bank_hash.stats.num_updated_accounts, 1);
assert_eq!(bank_hash.stats.num_removed_accounts, 1); assert_eq!(bank_hash.stats.num_removed_accounts, 1);
assert_eq!(bank_hash.stats.num_added_accounts, 1); assert_eq!(bank_hash.stats.num_lamports_stored, 1);
assert_eq!(bank_hash.stats.num_lamports_stored, 3);
assert_eq!(bank_hash.stats.total_data_len, 2 * some_data_len as u64); assert_eq!(bank_hash.stats.total_data_len, 2 * some_data_len as u64);
assert_eq!(bank_hash.stats.num_executable_accounts, 1); assert_eq!(bank_hash.stats.num_executable_accounts, 1);
} }
@ -3622,9 +3647,8 @@ pub mod tests {
db.store(some_slot, &account_refs); db.store(some_slot, &account_refs);
for (key, account) in &accounts_keys { for (key, account) in &accounts_keys {
let loaded_account = db.load_slow(&ancestors, key).unwrap().0;
assert_eq!( assert_eq!(
loaded_account.hash, db.load_account_hash(&ancestors, key),
AccountsDB::hash_account(some_slot, &account, &key) AccountsDB::hash_account(some_slot, &account, &key)
); );
} }

View File

@ -75,7 +75,6 @@ impl<'a> StoredAccount<'a> {
executable: self.account_meta.executable, executable: self.account_meta.executable,
rent_epoch: self.account_meta.rent_epoch, rent_epoch: self.account_meta.rent_epoch,
data: self.data.to_vec(), data: self.data.to_vec(),
hash: *self.hash,
} }
} }

View File

@ -550,16 +550,7 @@ impl Bank {
F: Fn(&Option<Account>) -> Account, F: Fn(&Option<Account>) -> Account,
{ {
let old_account = self.get_sysvar_account(pubkey); let old_account = self.get_sysvar_account(pubkey);
let mut new_account = updater(&old_account); let new_account = updater(&old_account);
// Normally, just use the hash from parent slot. However, use the
// existing stored hash if any for the sake of bank hash's idempotent.
if let Some((modified_account, _)) = self.get_account_modified_since_parent(pubkey) {
new_account.hash = modified_account.hash;
} else if let Some(old_account) = old_account {
new_account.hash = old_account.hash;
}
self.store_account(pubkey, &new_account); self.store_account(pubkey, &new_account);
} }
@ -4518,7 +4509,6 @@ mod tests {
.create_account(1) .create_account(1)
}); });
let current_account = bank2.get_account(&dummy_clock_id).unwrap(); let current_account = bank2.get_account(&dummy_clock_id).unwrap();
//let added_bank_hash = BankHash::from_hash(&current_account.hash);
assert_eq!( assert_eq!(
expected_next_slot, expected_next_slot,
Clock::from_account(&current_account).unwrap().slot Clock::from_account(&current_account).unwrap().slot

View File

@ -1,4 +1,4 @@
use crate::{clock::Epoch, hash::Hash, instruction::InstructionError, pubkey::Pubkey}; use crate::{clock::Epoch, instruction::InstructionError, pubkey::Pubkey};
use std::{ use std::{
cell::{Ref, RefCell, RefMut}, cell::{Ref, RefCell, RefMut},
cmp, fmt, cmp, fmt,
@ -8,7 +8,7 @@ use std::{
/// An Account with data that is stored on chain /// An Account with data that is stored on chain
#[repr(C)] #[repr(C)]
#[derive(Serialize, Deserialize, Clone, Default)] #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Account { pub struct Account {
/// lamports in the account /// lamports in the account
@ -22,26 +22,8 @@ pub struct Account {
pub executable: bool, pub executable: bool,
/// the epoch at which this account will next owe rent /// the epoch at which this account will next owe rent
pub rent_epoch: Epoch, pub rent_epoch: Epoch,
/// Hash of this account's state, skip serializing as to not expose to external api
/// Used for keeping the accounts state hash updated.
#[serde(skip)]
pub hash: Hash,
} }
/// skip comparison of account.hash, since it is only meaningful when the account is loaded in a
/// given fork and some tests do not have that.
impl PartialEq for Account {
fn eq(&self, other: &Self) -> bool {
self.lamports == other.lamports
&& self.data == other.data
&& self.owner == other.owner
&& self.executable == other.executable
&& self.rent_epoch == other.rent_epoch
}
}
impl Eq for Account {}
impl fmt::Debug for Account { impl fmt::Debug for Account {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let data_len = cmp::min(64, self.data.len()); let data_len = cmp::min(64, self.data.len());
@ -52,14 +34,13 @@ impl fmt::Debug for Account {
}; };
write!( write!(
f, f,
"Account {{ lamports: {} data.len: {} owner: {} executable: {} rent_epoch: {}{} hash: {} }}", "Account {{ lamports: {} data.len: {} owner: {} executable: {} rent_epoch: {}{} }}",
self.lamports, self.lamports,
self.data.len(), self.data.len(),
self.owner, self.owner,
self.executable, self.executable,
self.rent_epoch, self.rent_epoch,
data_str, data_str,
self.hash,
) )
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{account::Account, hash::Hash}; use crate::account::Account;
crate::declare_id!("NativeLoader1111111111111111111111111111111"); crate::declare_id!("NativeLoader1111111111111111111111111111111");
@ -10,6 +10,5 @@ pub fn create_loadable_account(name: &str) -> Account {
data: name.as_bytes().to_vec(), data: name.as_bytes().to_vec(),
executable: true, executable: true,
rent_epoch: 0, rent_epoch: 0,
hash: Hash::default(),
} }
} }