From c717fb91cf3c1c60b65b410c284852dc10663fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Tue, 3 Sep 2024 15:05:31 +0200 Subject: [PATCH 1/2] Fixes two bugs in loader-v4. --- programs/loader-v4/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/loader-v4/src/lib.rs b/programs/loader-v4/src/lib.rs index f8e2d2f6eec80f..c35b67a45ff9ce 100644 --- a/programs/loader-v4/src/lib.rs +++ b/programs/loader-v4/src/lib.rs @@ -167,6 +167,7 @@ pub fn process_instruction_truncate( } else { let rent = invoke_context.get_sysvar_cache().get_rent()?; rent.minimum_balance(LoaderV4State::program_data_offset().saturating_add(new_size as usize)) + .max(1) }; match program.get_lamports().cmp(&required_lamports) { std::cmp::Ordering::Less => { @@ -279,7 +280,7 @@ pub fn process_instruction_deploy( }; let executor = ProgramCacheEntry::new( &loader_v4::id(), - environments.program_runtime_v2.clone(), + environments.program_runtime_v1.clone(), deployment_slot, effective_slot, programdata, From b9d5608f6dc5beef54193ccf765667987c54e925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Tue, 27 Aug 2024 16:54:44 +0200 Subject: [PATCH 2/2] Adds instructions_to_load_program_of_loader_v4() and load_program_of_loader_v4(). Removes load_and_finalize_program() and load_program(). --- runtime/src/loader_utils.rs | 147 ++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 58 deletions(-) diff --git a/runtime/src/loader_utils.rs b/runtime/src/loader_utils.rs index 436a7242d93fd7..61404464bce264 100644 --- a/runtime/src/loader_utils.rs +++ b/runtime/src/loader_utils.rs @@ -8,7 +8,7 @@ use { client::{Client, SyncClient}, clock::Clock, instruction::{AccountMeta, Instruction}, - loader_instruction, + loader_v4, message::Message, pubkey::Pubkey, signature::{Keypair, Signer}, @@ -65,63 +65,6 @@ pub fn create_program(bank: &Bank, loader_id: &Pubkey, name: &str) -> Pubkey { program_id } -pub fn load_and_finalize_program( - bank_client: &T, - loader_id: &Pubkey, - program_keypair: Option, - payer_keypair: &Keypair, - name: &str, -) -> (Keypair, Instruction) { - let program = load_program_from_file(name); - let program_keypair = program_keypair.unwrap_or_else(|| { - let program_keypair = Keypair::new(); - let instruction = system_instruction::create_account( - &payer_keypair.pubkey(), - &program_keypair.pubkey(), - 1.max( - bank_client - .get_minimum_balance_for_rent_exemption(program.len()) - .unwrap(), - ), - program.len() as u64, - loader_id, - ); - let message = Message::new(&[instruction], Some(&payer_keypair.pubkey())); - bank_client - .send_and_confirm_message(&[payer_keypair, &program_keypair], message) - .unwrap(); - program_keypair - }); - let chunk_size = CHUNK_SIZE; - let mut offset = 0; - for chunk in program.chunks(chunk_size) { - let instruction = - loader_instruction::write(&program_keypair.pubkey(), loader_id, offset, chunk.to_vec()); - let message = Message::new(&[instruction], Some(&payer_keypair.pubkey())); - bank_client - .send_and_confirm_message(&[payer_keypair, &program_keypair], message) - .unwrap(); - offset += chunk_size as u32; - } - let instruction = loader_instruction::finalize(&program_keypair.pubkey(), loader_id); - (program_keypair, instruction) -} - -pub fn load_program( - bank_client: &T, - loader_id: &Pubkey, - payer_keypair: &Keypair, - name: &str, -) -> Pubkey { - let (program_keypair, instruction) = - load_and_finalize_program(bank_client, loader_id, None, payer_keypair, name); - let message = Message::new(&[instruction], Some(&payer_keypair.pubkey())); - bank_client - .send_and_confirm_message(&[payer_keypair, &program_keypair], message) - .unwrap(); - program_keypair.pubkey() -} - pub fn load_upgradeable_buffer( bank_client: &T, from_keypair: &Keypair, @@ -313,6 +256,94 @@ pub fn set_upgrade_authority( .unwrap(); } +pub fn instructions_to_load_program_of_loader_v4( + bank_client: &T, + payer_keypair: &Keypair, + authority_keypair: &Keypair, + name: &str, + program_keypair: Option, + target_program_id: Option<&Pubkey>, +) -> (Keypair, Vec) { + let mut instructions = Vec::new(); + let loader_id = &loader_v4::id(); + let program = load_program_from_file(name); + let program_keypair = program_keypair.unwrap_or_else(|| { + let program_keypair = Keypair::new(); + instructions.push(system_instruction::create_account( + &payer_keypair.pubkey(), + &program_keypair.pubkey(), + bank_client + .get_minimum_balance_for_rent_exemption(program.len()) + .unwrap(), + 0, + loader_id, + )); + program_keypair + }); + instructions.push(loader_v4::truncate_uninitialized( + &program_keypair.pubkey(), + &authority_keypair.pubkey(), + program.len() as u32, + &payer_keypair.pubkey(), + )); + let chunk_size = CHUNK_SIZE; + let mut offset = 0; + for chunk in program.chunks(chunk_size) { + instructions.push(loader_v4::write( + &program_keypair.pubkey(), + &authority_keypair.pubkey(), + offset, + chunk.to_vec(), + )); + offset += chunk_size as u32; + } + instructions.push(if let Some(target_program_id) = target_program_id { + loader_v4::deploy_from_source( + target_program_id, + &authority_keypair.pubkey(), + &program_keypair.pubkey(), + ) + } else { + loader_v4::deploy(&program_keypair.pubkey(), &authority_keypair.pubkey()) + }); + (program_keypair, instructions) +} + +pub fn load_program_of_loader_v4( + bank_client: &mut BankClient, + bank_forks: &RwLock, + payer_keypair: &Keypair, + authority_keypair: &Keypair, + name: &str, +) -> (Arc, Pubkey) { + let (program_keypair, instructions) = instructions_to_load_program_of_loader_v4( + bank_client, + payer_keypair, + authority_keypair, + name, + None, + None, + ); + let signers: &[&[&Keypair]] = &[ + &[payer_keypair, &program_keypair], + &[payer_keypair, &program_keypair, authority_keypair], + &[payer_keypair, authority_keypair], + ]; + let signers = std::iter::once(signers[0]) + .chain(std::iter::once(signers[1])) + .chain(std::iter::repeat(signers[2])); + for (instruction, signers) in instructions.into_iter().zip(signers) { + let message = Message::new(&[instruction], Some(&payer_keypair.pubkey())); + bank_client + .send_and_confirm_message(signers, message) + .unwrap(); + } + let bank = bank_client + .advance_slot(1, bank_forks, &Pubkey::default()) + .expect("Failed to advance the slot"); + (bank, program_keypair.pubkey()) +} + // Return an Instruction that invokes `program_id` with `data` and required // a signature from `from_pubkey`. pub fn create_invoke_instruction(