Skip to content

Commit

Permalink
Add set_account to solana-program-test (solana-labs#21415)
Browse files Browse the repository at this point in the history
For writing tests, it is often desirable to create a certain situation
that would be tedious, or even impossible to create by sending
individual transactions.

For example, a common attack vector on Solana is to create a copy of
some existing account that stores configuration data, but manipulate the
data stored there, and then to call a program and pass in the
manipulated account, instead of the real account.

If one wants to test this, one option is to write a program that you can
call to write arbitrary data into a new account account (and possibly
change its owner), then include that program in the test context, and
send a transaction to call it. This is extremely tedious, and developers
are not going to bother doing it. I myself would rather fork
solana-program-test to add this `set_account` method, than to write that
program. Having a “god mode” method to just write an account, lowers the
barrier to writing comprehensive tests.

A second reason for introducing this method, is defense in depth. There
may be states of the bank that are not reachable *yet* by only sending
transactions, but that you might want to test against either way. For
example, right now, the balance of a stake account cannot decrease
without going through the stake program. But what if Solana were to
introduce slashing in the future, and you want to ensure your program is
robust against decreases in stake account balance? Right now there is no
way to test this, but by introducing this “god mode” to write accounts,
the situation becomes testable.

(cherry picked from commit e7fa412)
  • Loading branch information
ruuda authored and mvines committed Nov 29, 2021
1 parent 90f791a commit 6293b9d
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions program-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,18 @@ impl ProgramTestContext {
bank.store_account(vote_account_address, &vote_account);
}

/// Create or overwrite an account, subverting normal runtime checks.
///
/// This method exists to make it easier to set up artificial situations
/// that would be difficult to replicate by sending individual transactions.
/// Beware that it can be used to create states that would not be reachable
/// by sending transactions!
pub fn set_account(&mut self, address: &Pubkey, account: &AccountSharedData) {
let bank_forks = self.bank_forks.read().unwrap();
let bank = bank_forks.working_bank();
bank.store_account(address, account);
}

/// Force the working bank ahead to a new slot
pub fn warp_to_slot(&mut self, warp_slot: Slot) -> Result<(), ProgramTestError> {
let mut bank_forks = self.bank_forks.write().unwrap();
Expand Down

0 comments on commit 6293b9d

Please sign in to comment.