@@ -12058,12 +12058,6 @@ fn test_feature_activation_loaded_programs_recompilation_phase() {
1205812058 .remove(&feature_set::reject_callx_r10::id());
1205912059 let (root_bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
1206012060
12061- // Test a basic transfer
12062- let amount = genesis_config.rent.minimum_balance(0);
12063- let pubkey = solana_sdk::pubkey::new_rand();
12064- root_bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
12065- assert_eq!(root_bank.get_balance(&pubkey), amount);
12066-
1206712061 // Program Setup
1206812062 let program_keypair = Keypair::new();
1206912063 let program_data =
@@ -12077,26 +12071,19 @@ fn test_feature_activation_loaded_programs_recompilation_phase() {
1207712071 });
1207812072 root_bank.store_account(&program_keypair.pubkey(), &program_account);
1207912073
12080- // Compose instruction using the desired program
12081- let instruction1 = Instruction::new_with_bytes(program_keypair.pubkey(), &[], Vec::new());
12082- let message1 = Message::new(&[instruction1], Some(&mint_keypair.pubkey()));
12083- let binding1 = mint_keypair.insecure_clone();
12084- let signers1 = vec![&binding1];
12085- let transaction1 = Transaction::new(&signers1, message1, root_bank.last_blockhash());
12074+ // Compose message using the desired program.
12075+ let instruction = Instruction::new_with_bytes(program_keypair.pubkey(), &[], Vec::new());
12076+ let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
12077+ let binding = mint_keypair.insecure_clone();
12078+ let signers = vec![&binding];
1208612079
12087- // Advance the bank so the next transaction can be submitted .
12080+ // Advance the bank so that the program becomes effective .
1208812081 goto_end_of_slot(root_bank.clone());
1208912082 let bank = new_from_parent_with_fork_next_slot(root_bank, bank_forks.as_ref());
1209012083
12091- // Compose second instruction using the same program with a different block hash
12092- let instruction2 = Instruction::new_with_bytes(program_keypair.pubkey(), &[], Vec::new());
12093- let message2 = Message::new(&[instruction2], Some(&mint_keypair.pubkey()));
12094- let binding2 = mint_keypair.insecure_clone();
12095- let signers2 = vec![&binding2];
12096- let transaction2 = Transaction::new(&signers2, message2, bank.last_blockhash());
12097-
12098- // Execute before feature is enabled to get program into the cache.
12099- let result_without_feature_enabled = bank.process_transaction(&transaction1);
12084+ // Load the program with the old environment.
12085+ let transaction = Transaction::new(&signers, message.clone(), bank.last_blockhash());
12086+ let result_without_feature_enabled = bank.process_transaction(&transaction);
1210012087 assert_eq!(
1210112088 result_without_feature_enabled,
1210212089 Err(TransactionError::InstructionError(
@@ -12105,20 +12092,65 @@ fn test_feature_activation_loaded_programs_recompilation_phase() {
1210512092 ))
1210612093 );
1210712094
12108- // Activate feature
12095+ // Schedule feature activation to trigger a change of environment at the epoch boundary.
1210912096 let feature_account_balance =
1211012097 std::cmp::max(genesis_config.rent.minimum_balance(Feature::size_of()), 1);
1211112098 bank.store_account(
1211212099 &feature_set::reject_callx_r10::id(),
1211312100 &feature::create_account(&Feature { activated_at: None }, feature_account_balance),
1211412101 );
1211512102
12103+ // Advance the bank to middle of epoch to start the recompilation phase.
12104+ goto_end_of_slot(bank.clone());
12105+ let bank = new_bank_from_parent_with_bank_forks(&bank_forks, bank, &Pubkey::default(), 16);
12106+ let current_env = bank
12107+ .loaded_programs_cache
12108+ .read()
12109+ .unwrap()
12110+ .get_environments_for_epoch(0)
12111+ .program_runtime_v1
12112+ .clone();
12113+ let upcoming_env = bank
12114+ .loaded_programs_cache
12115+ .read()
12116+ .unwrap()
12117+ .get_environments_for_epoch(1)
12118+ .program_runtime_v1
12119+ .clone();
12120+
12121+ // Advance the bank to recompile the program.
12122+ {
12123+ let program_cache = bank.loaded_programs_cache.read().unwrap();
12124+ let slot_versions = program_cache.get_slot_versions_for_tests(&program_keypair.pubkey());
12125+ assert_eq!(slot_versions.len(), 1);
12126+ assert!(Arc::ptr_eq(
12127+ slot_versions[0].program.get_environment().unwrap(),
12128+ ¤t_env
12129+ ));
12130+ }
12131+ goto_end_of_slot(bank.clone());
12132+ let bank = new_from_parent_with_fork_next_slot(bank, bank_forks.as_ref());
12133+ {
12134+ let program_cache = bank.loaded_programs_cache.write().unwrap();
12135+ let slot_versions = program_cache.get_slot_versions_for_tests(&program_keypair.pubkey());
12136+ assert_eq!(slot_versions.len(), 2);
12137+ assert!(Arc::ptr_eq(
12138+ slot_versions[0].program.get_environment().unwrap(),
12139+ &upcoming_env
12140+ ));
12141+ assert!(Arc::ptr_eq(
12142+ slot_versions[1].program.get_environment().unwrap(),
12143+ ¤t_env
12144+ ));
12145+ }
12146+
12147+ // Advance the bank to cross the epoch boundary and activate the feature.
1211612148 goto_end_of_slot(bank.clone());
12117- // Advance to next epoch, which starts the recompilation phase
12118- let bank = new_from_parent_next_epoch(bank, bank_forks.as_ref(), 1);
12149+ let bank = new_bank_from_parent_with_bank_forks(&bank_forks, bank, &Pubkey::default(), 33);
1211912150
12120- // Execute after feature is enabled to check it was filtered out and reverified.
12121- let result_with_feature_enabled = bank.process_transaction(&transaction2);
12151+ // Load the program with the new environment.
12152+ let transaction = Transaction::new(&signers, message, bank.last_blockhash());
12153+ let result_with_feature_enabled = bank.process_transaction(&transaction);
1212212154 assert_eq!(
1212312155 result_with_feature_enabled,
1212412156 Err(TransactionError::InstructionError(
@@ -12178,6 +12210,21 @@ fn test_feature_activation_loaded_programs_epoch_transition() {
1217812210 let bank = new_bank_from_parent_with_bank_forks(&bank_forks, bank, &Pubkey::default(), 33);
1217912211
1218012212 // Load the program with the new environment.
12213+ let transaction = Transaction::new(&signers, message.clone(), bank.last_blockhash());
12214+ assert!(bank.process_transaction(&transaction).is_ok());
12215+
12216+ {
12217+ // Prune for rerooting and thus finishing the recompilation phase.
12218+ let mut program_cache = bank.loaded_programs_cache.write().unwrap();
12219+ program_cache.prune(bank.slot(), bank.epoch());
12220+
12221+ // Unload all (which is only the entry with the new environment)
12222+ program_cache.sort_and_unload(percentage::Percentage::from(0));
12223+ }
12224+
12225+ // Reload the unloaded program with the new environment.
12226+ goto_end_of_slot(bank.clone());
12227+ let bank = new_from_parent_with_fork_next_slot(bank, bank_forks.as_ref());
1218112228 let transaction = Transaction::new(&signers, message, bank.last_blockhash());
1218212229 assert!(bank.process_transaction(&transaction).is_ok());
1218312230}
0 commit comments