Skip to content

Commit

Permalink
Adjustments of loader-v4 (part 3) (#2821)
Browse files Browse the repository at this point in the history
* Fixes two bugs in loader-v4.

* Adds instructions_to_load_program_of_loader_v4() and load_program_of_loader_v4().
Removes load_and_finalize_program() and load_program().
  • Loading branch information
Lichtso authored Sep 5, 2024
1 parent 98c8853 commit 7f2013d
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 59 deletions.
3 changes: 2 additions & 1 deletion programs/loader-v4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down Expand Up @@ -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,
Expand Down
147 changes: 89 additions & 58 deletions runtime/src/loader_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use {
client::{Client, SyncClient},
clock::Clock,
instruction::{AccountMeta, Instruction},
loader_instruction,
loader_v4,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
Expand Down Expand Up @@ -65,63 +65,6 @@ pub fn create_program(bank: &Bank, loader_id: &Pubkey, name: &str) -> Pubkey {
program_id
}

pub fn load_and_finalize_program<T: Client>(
bank_client: &T,
loader_id: &Pubkey,
program_keypair: Option<Keypair>,
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<T: Client>(
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<T: Client>(
bank_client: &T,
from_keypair: &Keypair,
Expand Down Expand Up @@ -313,6 +256,94 @@ pub fn set_upgrade_authority<T: Client>(
.unwrap();
}

pub fn instructions_to_load_program_of_loader_v4<T: Client>(
bank_client: &T,
payer_keypair: &Keypair,
authority_keypair: &Keypair,
name: &str,
program_keypair: Option<Keypair>,
target_program_id: Option<&Pubkey>,
) -> (Keypair, Vec<Instruction>) {
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<BankForks>,
payer_keypair: &Keypair,
authority_keypair: &Keypair,
name: &str,
) -> (Arc<Bank>, 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<T: Serialize>(
Expand Down

0 comments on commit 7f2013d

Please sign in to comment.