Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjustments of loader-v4 (part 3) #2821

Merged
merged 2 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we split this in its own PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been in #2750 already but I missed it. Only noticed as I was working on the tests in #2796.

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>(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this function unused?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they were for the loaders-v1 and v2, which we deprecated.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So these are pure deletion of the code. The new functions are not related to these.
(trying to avoid comparing two independent functions).

Copy link
Author

@Lichtso Lichtso Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, implementation / code wise they are unrelated. Conceptually they are related because these are their replacements but for the newest loader. However, loader-v4 is closest to loader-v3 so comparing the new functions against load_upgradeable_program_and_advance_slot() makes more sense.

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