From d2a2eba69e2978028d5c02202c53980e566f34f8 Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Mon, 25 May 2020 00:34:54 -0700 Subject: [PATCH] v1.2: Include account.owner into account hash (#9918) (#10222) automerge --- runtime/src/accounts_db.rs | 58 ++++++++++++++++++++++++++++++-------- runtime/src/bank.rs | 8 +++--- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 63f3ec3078..75e9585016 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -1162,7 +1162,7 @@ impl AccountsDB { 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( slot, account.account_meta.lamports, @@ -1171,10 +1171,16 @@ impl AccountsDB { account.account_meta.rent_epoch, account.data, &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( slot, account.lamports, @@ -1183,6 +1189,7 @@ impl AccountsDB { account.rent_epoch, &account.data, pubkey, + include_owner, ) } @@ -1201,6 +1208,11 @@ impl AccountsDB { 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( slot: Slot, lamports: u64, @@ -1209,6 +1221,7 @@ impl AccountsDB { rent_epoch: Epoch, data: &[u8], pubkey: &Pubkey, + include_owner: bool, ) -> Hash { if lamports == 0 { return Hash::default(); @@ -1234,7 +1247,10 @@ impl AccountsDB { hasher.hash(&[0u8; 1]); } - hasher.hash(&owner.as_ref()); + if include_owner { + hasher.hash(&owner.as_ref()); + } + hasher.hash(&pubkey.as_ref()); hasher.result() @@ -1459,7 +1475,11 @@ impl AccountsDB { let account = store.accounts.get_account(account_info.offset)?.0; 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 { mismatch_found.fetch_add(1, Ordering::Relaxed); return None; @@ -1691,7 +1711,7 @@ impl AccountsDB { .iter() .map(|(pubkey, account)| { stats.update(account); - Self::hash_account(slot, account, pubkey) + Self::hash_account(slot, account, pubkey, Self::include_owner_in_hash(slot)) }) .collect(); @@ -3312,19 +3332,33 @@ pub mod tests { hash: &hash, }; let account = stored_account.clone_account(); - let expected_account_hash = - Hash::from_str("5iRNZVcAnq9JLYjSF2ibFhGEeq48r9Eq9HXxwm3BxywN").unwrap(); + let expected_account_hash_without_owner = + Hash::from_str("GGTsxvxwnMsNfN6yYbBVQaRgvbVLfxeWnGXNyB8iXDyE").unwrap(); assert_eq!( - AccountsDB::hash_stored_account(slot, &stored_account), - expected_account_hash, + AccountsDB::hash_stored_account(slot, &stored_account, false), + expected_account_hash_without_owner, "StoredAccount's data layout might be changed; update hashing if needed." ); assert_eq!( - AccountsDB::hash_account(slot, &account, &stored_account.meta.pubkey), - expected_account_hash, + AccountsDB::hash_account(slot, &account, &stored_account.meta.pubkey, false), + expected_account_hash_without_owner, "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] @@ -3463,7 +3497,7 @@ pub mod tests { for (key, account) in &accounts_keys { assert_eq!( db.load_account_hash(&ancestors, key), - AccountsDB::hash_account(some_slot, &account, &key) + AccountsDB::hash_account(some_slot, &account, &key, false) ); } } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 0ba7695f6b..015afabfd8 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -6882,25 +6882,25 @@ mod tests { if bank.slot == 0 { assert_eq!( bank.hash().to_string(), - "7MKHH6P7J5aQNN29Cr6aZQbEpQcXe8KTgchd4Suk9NCG" + "hRgSMcWvZVveC8TqHHBfeU3h6vkPy6qzR5bHXfDTCyd" ); } if bank.slot == 32 { assert_eq!( bank.hash().to_string(), - "3AxuV6GGcoqRi6pksN6btNEmeJCTesLbjgA88QZt9a8Q" + "C2isNuN27FB9wVFpR1txa6SsXi94td6WSy7Va5deGpX5" ); } if bank.slot == 64 { assert_eq!( bank.hash().to_string(), - "B32ZLAzeCW5FueeauiGYnujh8Efmxvpeac74W9JU68oB" + "2FJC56qpMyDFNtCvbr1MhyR2bawrhLtViaLVoBEMbj1n" ); } if bank.slot == 128 { assert_eq!( bank.hash().to_string(), - "A2tCz2EqryRZ7tHpw9H2918RZLCbqnSGzRWUqbnnESGz" + "GUae7X3qX6aRu5UJ6MTRmPEUNi94GP6thagRi9uFRHpG" ); break; }