From 68c8f8fa8546a9f61312f166c88bb7990b195538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Wed, 29 Jan 2025 15:02:58 +0000 Subject: [PATCH] Adds test_loader_v3_to_v4_migration. --- runtime/src/bank/tests.rs | 174 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index a45a7a5eefcd82..89c3839a4f09ac 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -13381,6 +13381,180 @@ fn test_deploy_last_epoch_slot() { assert_eq!(result_with_feature_enabled, Ok(())); } +#[test] +fn test_loader_v3_to_v4_migration() { + solana_logger::setup(); + + // Bank Setup + let (mut genesis_config, mint_keypair) = create_genesis_config(1_000_000 * LAMPORTS_PER_SOL); + activate_feature( + &mut genesis_config, + solana_feature_set::enable_loader_v4::id(), + ); + let mut bank = Bank::new_for_tests(&genesis_config); + bank.activate_feature(&feature_set::remove_accounts_executable_flag_checks::id()); + let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); + let fee_calculator = genesis_config.fee_rate_governor.create_fee_calculator(); + + // deploy a program + let mut file = File::open("../programs/bpf_loader/test_elfs/out/noop_aligned.so").unwrap(); + let mut elf = Vec::new(); + file.read_to_end(&mut elf).unwrap(); + + let program_keypair = Keypair::new(); + let (programdata_address, _) = Pubkey::find_program_address( + &[program_keypair.pubkey().as_ref()], + &bpf_loader_upgradeable::id(), + ); + let payer_keypair = Keypair::new(); + let upgrade_authority_keypair = Keypair::new(); + let migration_authority_keypair = &upgrade_authority_keypair; + + let min_program_balance = + bank.get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_program()); + let mut program_account = AccountSharedData::new( + min_program_balance, + UpgradeableLoaderState::size_of_program(), + &bpf_loader_upgradeable::id(), + ); + program_account + .set_state(&UpgradeableLoaderState::Program { + programdata_address, + }) + .unwrap(); + + let closed_programdata_account = AccountSharedData::new(0, 0, &bpf_loader_upgradeable::id()); + + let mut uninitialized_programdata_account = AccountSharedData::new( + 0, + UpgradeableLoaderState::size_of_programdata_metadata(), + &bpf_loader_upgradeable::id(), + ); + uninitialized_programdata_account + .set_state(&UpgradeableLoaderState::Uninitialized) + .unwrap(); + + let mut finalized_programdata_account = AccountSharedData::new( + 0, + UpgradeableLoaderState::size_of_programdata(elf.len()), + &bpf_loader_upgradeable::id(), + ); + finalized_programdata_account + .set_state(&UpgradeableLoaderState::ProgramData { + slot: 0, + upgrade_authority_address: None, + }) + .unwrap(); + finalized_programdata_account + .data_as_mut_slice() + .get_mut(UpgradeableLoaderState::size_of_programdata_metadata()..) + .unwrap() + .copy_from_slice(&elf); + let message = Message::new( + &[bpf_loader_upgradeable::migrate_program( + &programdata_address, + &program_keypair.pubkey(), + &program_keypair.pubkey(), + )], + Some(&payer_keypair.pubkey()), + ); + let signers = &[&payer_keypair, &program_keypair]; + let finalized_migration_transaction = + Transaction::new(signers, message.clone(), bank.last_blockhash()); + + let mut upgradeable_programdata_account = AccountSharedData::new( + 0, + UpgradeableLoaderState::size_of_programdata(elf.len()), + &bpf_loader_upgradeable::id(), + ); + upgradeable_programdata_account + .set_state(&UpgradeableLoaderState::ProgramData { + slot: 0, + upgrade_authority_address: Some(upgrade_authority_keypair.pubkey()), + }) + .unwrap(); + upgradeable_programdata_account + .data_as_mut_slice() + .get_mut(UpgradeableLoaderState::size_of_programdata_metadata()..) + .unwrap() + .copy_from_slice(&elf); + let message = Message::new( + &[bpf_loader_upgradeable::migrate_program( + &programdata_address, + &program_keypair.pubkey(), + &migration_authority_keypair.pubkey(), + )], + Some(&payer_keypair.pubkey()), + ); + let signers = &[&payer_keypair, migration_authority_keypair]; + let upgradeable_migration_transaction = + Transaction::new(signers, message.clone(), bank.last_blockhash()); + + let mut next_slot = 1; + for (mut programdata_account, transaction, expected_execution_result) in [ + ( + closed_programdata_account, + finalized_migration_transaction.clone(), + Err(TransactionError::InstructionError( + 0, + InstructionError::InvalidInstructionData, + )), + ), + ( + uninitialized_programdata_account, + finalized_migration_transaction.clone(), + Err(TransactionError::InstructionError( + 0, + InstructionError::InvalidInstructionData, + )), + ), + ( + finalized_programdata_account, + finalized_migration_transaction, + Ok(()), + ), + ( + upgradeable_programdata_account, + upgradeable_migration_transaction, + Ok(()), + ), + ] { + let bank = new_bank_from_parent_with_bank_forks( + &bank_forks, + bank.clone(), + &Pubkey::default(), + next_slot, + ); + next_slot += 1; + + let min_programdata_balance = + bank.get_minimum_balance_for_rent_exemption(programdata_account.data().len()); + programdata_account.set_lamports(min_programdata_balance); + let payer_balance = min_program_balance + .saturating_add(min_programdata_balance) + .saturating_add(LAMPORTS_PER_SOL) + .saturating_add(fee_calculator.lamports_per_signature); + let payer_account = AccountSharedData::new(payer_balance, 0, &system_program::id()); + bank.store_account(&program_keypair.pubkey(), &program_account); + bank.store_account(&programdata_address, &programdata_account); + bank.store_account(&payer_keypair.pubkey(), &payer_account); + let result = bank.process_transaction(&transaction); + assert!(result.is_ok(), "result: {:?}", result); + + goto_end_of_slot(bank.clone()); + let bank = + new_bank_from_parent_with_bank_forks(&bank_forks, bank, &Pubkey::default(), next_slot); + next_slot += 1; + + let instruction = Instruction::new_with_bytes(program_keypair.pubkey(), &[], Vec::new()); + let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); + let binding = mint_keypair.insecure_clone(); + let transaction = Transaction::new(&[&binding], message, bank.last_blockhash()); + let execution_result = bank.process_transaction(&transaction); + assert_eq!(execution_result, expected_execution_result); + } +} + #[test] fn test_blockhash_last_valid_block_height() { let genesis_config = GenesisConfig::default();