Skip to content

Commit

Permalink
Rehashing is not allowed to change accounts (#3180)
Browse files Browse the repository at this point in the history
  • Loading branch information
brooksprumo authored Oct 15, 2024
1 parent 20460f5 commit 20aa3be
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
25 changes: 24 additions & 1 deletion runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2869,11 +2869,34 @@ impl Bank {
stake_weighted_timestamp
}

/// Recalculates the bank hash
///
/// This is used by ledger-tool when creating a snapshot, which
/// recalcuates the bank hash.
///
/// Note that the account state is *not* allowed to change by rehashing.
/// If it does, this function will panic.
/// If modifying accounts in ledger-tool is needed, create a new bank.
pub fn rehash(&self) {
let get_delta_hash = || {
self.rc
.accounts
.accounts_db
.get_accounts_delta_hash(self.slot())
};

let mut hash = self.hash.write().unwrap();
let curr_accounts_delta_hash = get_delta_hash();
let new = self.hash_internal_state();
if let Some(curr_accounts_delta_hash) = curr_accounts_delta_hash {
let new_accounts_delta_hash = get_delta_hash().unwrap();
assert_eq!(
new_accounts_delta_hash, curr_accounts_delta_hash,
"rehashing is not allowed to change the account state",
);
}
if new != *hash {
warn!("Updating bank hash to {}", new);
warn!("Updating bank hash to {new}");
*hash = new;
}
}
Expand Down
45 changes: 45 additions & 0 deletions runtime/src/bank/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13252,3 +13252,48 @@ fn test_bank_epoch_stakes() {
);
}
}

#[test]
fn test_rehash_good() {
let ten_sol = 10 * LAMPORTS_PER_SOL;
let (genesis_config, _mint) = create_genesis_config(ten_sol);
let bank = Bank::new_for_tests(&genesis_config);

let lamports = 123_456_789;
let account = AccountSharedData::new(lamports, 0, &Pubkey::default());
let pubkey = Pubkey::new_unique();
bank.store_account_and_update_capitalization(&pubkey, &account);

// freeze the bank to trigger hash calculation
bank.freeze();

// ensure the bank hash is the same before and after rehashing
let prev_bank_hash = bank.hash();
bank.rehash();
let post_bank_hash = bank.hash();
assert_eq!(post_bank_hash, prev_bank_hash);
}

#[test]
#[should_panic(expected = "rehashing is not allowed to change the account state")]
fn test_rehash_bad() {
let ten_sol = 10 * LAMPORTS_PER_SOL;
let (genesis_config, _mint) = create_genesis_config(ten_sol);
let bank = Bank::new_for_tests(&genesis_config);

let mut account = AccountSharedData::new(ten_sol, 0, &Pubkey::default());
let pubkey = Pubkey::new_unique();
bank.store_account_and_update_capitalization(&pubkey, &account);

// freeze the bank to trigger hash calculation
bank.freeze();

// change an account, which will cause rehashing to panic
account.checked_add_lamports(ten_sol).unwrap();
bank.rc
.accounts
.store_accounts_cached((bank.slot(), [(&pubkey, &account)].as_slice()));

// let the show begin
bank.rehash();
}

0 comments on commit 20aa3be

Please sign in to comment.