v1.2: Include account.owner into account hash (#9918) (#10222)

automerge
This commit is contained in:
Michael Vines
2020-05-25 00:34:54 -07:00
committed by GitHub
parent 156387aba4
commit d2a2eba69e
2 changed files with 50 additions and 16 deletions

View File

@ -1162,7 +1162,7 @@ impl AccountsDB {
assert!(self.storage.read().unwrap().0.get(&remove_slot).is_none()); assert!(self.storage.read().unwrap().0.get(&remove_slot).is_none());
} }
pub fn hash_stored_account(slot: Slot, account: &StoredAccount) -> Hash { pub fn hash_stored_account(slot: Slot, account: &StoredAccount, include_owner: bool) -> Hash {
Self::hash_account_data( Self::hash_account_data(
slot, slot,
account.account_meta.lamports, account.account_meta.lamports,
@ -1171,10 +1171,16 @@ impl AccountsDB {
account.account_meta.rent_epoch, account.account_meta.rent_epoch,
account.data, account.data,
&account.meta.pubkey, &account.meta.pubkey,
include_owner,
) )
} }
pub fn hash_account(slot: Slot, account: &Account, pubkey: &Pubkey) -> Hash { pub fn hash_account(
slot: Slot,
account: &Account,
pubkey: &Pubkey,
include_owner: bool,
) -> Hash {
Self::hash_account_data( Self::hash_account_data(
slot, slot,
account.lamports, account.lamports,
@ -1183,6 +1189,7 @@ impl AccountsDB {
account.rent_epoch, account.rent_epoch,
&account.data, &account.data,
pubkey, pubkey,
include_owner,
) )
} }
@ -1201,6 +1208,11 @@ impl AccountsDB {
hasher.result() hasher.result()
} }
pub fn include_owner_in_hash(slot: Slot) -> bool {
// Account hashing updated to include owner activates at this slot on the testnet
slot >= 14_000_000
}
pub fn hash_account_data( pub fn hash_account_data(
slot: Slot, slot: Slot,
lamports: u64, lamports: u64,
@ -1209,6 +1221,7 @@ impl AccountsDB {
rent_epoch: Epoch, rent_epoch: Epoch,
data: &[u8], data: &[u8],
pubkey: &Pubkey, pubkey: &Pubkey,
include_owner: bool,
) -> Hash { ) -> Hash {
if lamports == 0 { if lamports == 0 {
return Hash::default(); return Hash::default();
@ -1234,7 +1247,10 @@ impl AccountsDB {
hasher.hash(&[0u8; 1]); hasher.hash(&[0u8; 1]);
} }
if include_owner {
hasher.hash(&owner.as_ref()); hasher.hash(&owner.as_ref());
}
hasher.hash(&pubkey.as_ref()); hasher.hash(&pubkey.as_ref());
hasher.result() hasher.result()
@ -1459,7 +1475,11 @@ impl AccountsDB {
let account = store.accounts.get_account(account_info.offset)?.0; let account = store.accounts.get_account(account_info.offset)?.0;
if check_hash { if check_hash {
let hash = Self::hash_stored_account(*slot, &account); let hash = Self::hash_stored_account(
*slot,
&account,
Self::include_owner_in_hash(*slot),
);
if hash != *account.hash { if hash != *account.hash {
mismatch_found.fetch_add(1, Ordering::Relaxed); mismatch_found.fetch_add(1, Ordering::Relaxed);
return None; return None;
@ -1691,7 +1711,7 @@ impl AccountsDB {
.iter() .iter()
.map(|(pubkey, account)| { .map(|(pubkey, account)| {
stats.update(account); stats.update(account);
Self::hash_account(slot, account, pubkey) Self::hash_account(slot, account, pubkey, Self::include_owner_in_hash(slot))
}) })
.collect(); .collect();
@ -3312,19 +3332,33 @@ pub mod tests {
hash: &hash, hash: &hash,
}; };
let account = stored_account.clone_account(); let account = stored_account.clone_account();
let expected_account_hash = let expected_account_hash_without_owner =
Hash::from_str("5iRNZVcAnq9JLYjSF2ibFhGEeq48r9Eq9HXxwm3BxywN").unwrap(); Hash::from_str("GGTsxvxwnMsNfN6yYbBVQaRgvbVLfxeWnGXNyB8iXDyE").unwrap();
assert_eq!( assert_eq!(
AccountsDB::hash_stored_account(slot, &stored_account), AccountsDB::hash_stored_account(slot, &stored_account, false),
expected_account_hash, expected_account_hash_without_owner,
"StoredAccount's data layout might be changed; update hashing if needed." "StoredAccount's data layout might be changed; update hashing if needed."
); );
assert_eq!( assert_eq!(
AccountsDB::hash_account(slot, &account, &stored_account.meta.pubkey), AccountsDB::hash_account(slot, &account, &stored_account.meta.pubkey, false),
expected_account_hash, expected_account_hash_without_owner,
"Account-based hashing must be consistent with StoredAccount-based one." "Account-based hashing must be consistent with StoredAccount-based one."
); );
let expected_account_hash_with_owner =
Hash::from_str("5iRNZVcAnq9JLYjSF2ibFhGEeq48r9Eq9HXxwm3BxywN").unwrap();
assert_eq!(
AccountsDB::hash_stored_account(slot, &stored_account, true),
expected_account_hash_with_owner,
"StoredAccount's data layout might be changed; update hashing if needed (with owner)."
);
assert_eq!(
AccountsDB::hash_account(slot, &account, &stored_account.meta.pubkey, true),
expected_account_hash_with_owner,
"Account-based hashing must be consistent with StoredAccount-based one (with owner)."
);
} }
#[test] #[test]
@ -3463,7 +3497,7 @@ pub mod tests {
for (key, account) in &accounts_keys { for (key, account) in &accounts_keys {
assert_eq!( assert_eq!(
db.load_account_hash(&ancestors, key), db.load_account_hash(&ancestors, key),
AccountsDB::hash_account(some_slot, &account, &key) AccountsDB::hash_account(some_slot, &account, &key, false)
); );
} }
} }

View File

@ -6882,25 +6882,25 @@ mod tests {
if bank.slot == 0 { if bank.slot == 0 {
assert_eq!( assert_eq!(
bank.hash().to_string(), bank.hash().to_string(),
"7MKHH6P7J5aQNN29Cr6aZQbEpQcXe8KTgchd4Suk9NCG" "hRgSMcWvZVveC8TqHHBfeU3h6vkPy6qzR5bHXfDTCyd"
); );
} }
if bank.slot == 32 { if bank.slot == 32 {
assert_eq!( assert_eq!(
bank.hash().to_string(), bank.hash().to_string(),
"3AxuV6GGcoqRi6pksN6btNEmeJCTesLbjgA88QZt9a8Q" "C2isNuN27FB9wVFpR1txa6SsXi94td6WSy7Va5deGpX5"
); );
} }
if bank.slot == 64 { if bank.slot == 64 {
assert_eq!( assert_eq!(
bank.hash().to_string(), bank.hash().to_string(),
"B32ZLAzeCW5FueeauiGYnujh8Efmxvpeac74W9JU68oB" "2FJC56qpMyDFNtCvbr1MhyR2bawrhLtViaLVoBEMbj1n"
); );
} }
if bank.slot == 128 { if bank.slot == 128 {
assert_eq!( assert_eq!(
bank.hash().to_string(), bank.hash().to_string(),
"A2tCz2EqryRZ7tHpw9H2918RZLCbqnSGzRWUqbnnESGz" "GUae7X3qX6aRu5UJ6MTRmPEUNi94GP6thagRi9uFRHpG"
); );
break; break;
} }