Test stake program execution restricted in reward period (#32404)

test stake program execution restricted in reward period

Co-authored-by: HaoranYi <haoran.yi@solana.com>
This commit is contained in:
HaoranYi 2023-07-07 10:24:49 -05:00 committed by GitHub
parent b3d9c87612
commit 37a36384f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 65 additions and 0 deletions

View File

@ -101,6 +101,7 @@ use {
vote_state::{
self, BlockTimestamp, Vote, VoteInit, VoteState, VoteStateVersions, MAX_LOCKOUT_HISTORY,
},
vote_transaction,
},
std::{
collections::{HashMap, HashSet},
@ -12773,6 +12774,70 @@ fn test_epoch_rewards_sysvar() {
assert!(account.is_none());
}
/// Test that program execution that involves stake accounts should fail during reward period.
/// Any programs, which result in stake account changes, will throw `ProgramExecutionTemporarilyRestricted` error when
/// in reward period.
#[test]
fn test_program_execution_restricted_for_stake_account_in_reward_period() {
use solana_sdk::transaction::TransactionError::ProgramExecutionTemporarilyRestricted;
let validator_vote_keypairs = ValidatorVoteKeypairs::new_rand();
let validator_keypairs = vec![&validator_vote_keypairs];
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config_with_vote_accounts(
1_000_000_000,
&validator_keypairs,
vec![1_000_000_000; 1],
);
let node_key = &validator_keypairs[0].node_keypair;
let stake_key = &validator_keypairs[0].stake_keypair;
let bank0 = Bank::new_for_tests(&genesis_config);
let num_slots_in_epoch = bank0.get_slots_in_epoch(bank0.epoch());
assert_eq!(num_slots_in_epoch, 32);
let mut previous_bank = Arc::new(bank0);
for slot in 1..=num_slots_in_epoch + 2 {
let bank = Bank::new_from_parent(&previous_bank, &Pubkey::default(), slot);
// Fill bank_forks with banks with votes landing in the next slot
// So that rewards will be paid out at the epoch boundary, i.e. slot = 32
let vote = vote_transaction::new_vote_transaction(
vec![slot - 1],
previous_bank.hash(),
previous_bank.last_blockhash(),
&validator_vote_keypairs.node_keypair,
&validator_vote_keypairs.vote_keypair,
&validator_vote_keypairs.vote_keypair,
None,
);
bank.process_transaction(&vote).unwrap();
// Insert a transfer transaction from node account to stake account
let tx =
system_transaction::transfer(node_key, &stake_key.pubkey(), 1, bank.last_blockhash());
let r = bank.process_transaction(&tx);
if slot == num_slots_in_epoch {
// When the bank is at the beginning of the new epoch, i.e. slot 32,
// ProgramExecutionTemporarilyRestricted should be thrown for the transfer transaction.
assert_eq!(
r,
Err(ProgramExecutionTemporarilyRestricted { account_index: 1 })
);
} else {
// When the bank is outside of reward interval, the transfer transaction should not be affected and will succeed.
assert!(r.is_ok());
}
// Push a dummy blockhash, so that the latest_blockhash() for the transfer transaction in each
// iteration are different. Otherwise, all those transactions will be the same, and will not be
// executed by the bank except the first one.
bank.register_recent_blockhash(&Hash::new_unique());
previous_bank = Arc::new(bank);
}
}
/// Test rewards compuation and partitioned rewards distribution at the epoch boundary
#[test]
fn test_store_stake_accounts_in_partition() {