1#![cfg(feature = "agave-unstable-api")]
2#![deny(clippy::arithmetic_side_effects)]
3#![deny(clippy::indexing_slicing)]
4
5#[cfg(feature = "svm-internal")]
6use qualifier_attr::qualifiers;
7use {
8 solana_bincode::limited_deserialize,
9 solana_instruction::AccountMeta,
10 solana_instruction_error::InstructionError,
11 solana_loader_v3_interface::{
12 instruction::{MINIMUM_EXTEND_PROGRAM_BYTES, UpgradeableLoaderInstruction},
13 state::UpgradeableLoaderState,
14 },
15 solana_program_runtime::{
16 deploy_program,
17 invoke_context::InvokeContext,
18 program_cache_entry::{ProgramCacheEntry, ProgramCacheEntryOwner, ProgramCacheEntryType},
19 sysvar_cache::get_sysvar_with_account_check,
20 vm::execute,
21 },
22 solana_pubkey::Pubkey,
23 solana_sbpf::{declare_builtin_function, elf::get_sbpf_version, program::SBPFVersion},
24 solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, native_loader},
25 solana_svm_log_collector::{LogCollector, ic_logger_msg, ic_msg},
26 solana_svm_measure::measure::Measure,
27 solana_svm_type_overrides::sync::Arc,
28 solana_system_interface::{MAX_PERMITTED_DATA_LENGTH, instruction as system_instruction},
29 solana_transaction_context::{IndexOfAccount, instruction::InstructionContext},
30 std::{cell::RefCell, rc::Rc},
31};
32
33#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
34const DEFAULT_LOADER_COMPUTE_UNITS: u64 = 570;
35#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
36const DEPRECATED_LOADER_COMPUTE_UNITS: u64 = 1_140;
37#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
38const UPGRADEABLE_LOADER_COMPUTE_UNITS: u64 = 2_370;
39
40fn write_program_data(
41 program_data_offset: usize,
42 bytes: &[u8],
43 invoke_context: &mut InvokeContext,
44) -> Result<(), InstructionError> {
45 let transaction_context = &invoke_context.transaction_context;
46 let instruction_context = transaction_context.get_current_instruction_context()?;
47 let mut program = instruction_context.try_borrow_instruction_account(0)?;
48 let data = program.get_data_mut()?;
49 let write_offset = program_data_offset.saturating_add(bytes.len());
50 if data.len() < write_offset {
51 ic_msg!(
52 invoke_context,
53 "Write overflow: {} < {}",
54 data.len(),
55 write_offset,
56 );
57 return Err(InstructionError::AccountDataTooSmall);
58 }
59 data.get_mut(program_data_offset..write_offset)
60 .ok_or(InstructionError::AccountDataTooSmall)?
61 .copy_from_slice(bytes);
62 Ok(())
63}
64
65declare_builtin_function!(
66 Entrypoint,
67 fn rust(
68 invoke_context: &mut InvokeContext<'static, 'static>,
69 _arg0: u64,
70 _arg1: u64,
71 _arg2: u64,
72 _arg3: u64,
73 _arg4: u64,
74 ) -> Result<u64, Box<dyn std::error::Error>> {
75 process_instruction_inner(invoke_context)
76 }
77);
78
79mod migration_authority {
80 solana_pubkey::declare_id!("3Scf35jMNk2xXBD6areNjgMtXgp5ZspDhms8vdcbzC42");
81}
82
83#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
84pub(crate) fn process_instruction_inner<'a>(
85 invoke_context: &mut InvokeContext<'a, 'a>,
86) -> Result<u64, Box<dyn std::error::Error>> {
87 let log_collector = invoke_context.get_log_collector();
88 let transaction_context = &invoke_context.transaction_context;
89 let instruction_context = transaction_context.get_current_instruction_context()?;
90 let program_id = instruction_context.get_program_key()?;
91 let owner_id = instruction_context.get_program_owner()?;
92
93 if native_loader::check_id(&owner_id) {
95 let program_id = instruction_context.get_program_key()?;
96 return if bpf_loader_upgradeable::check_id(program_id) {
97 invoke_context
98 .compute_meter
99 .consume_checked(UPGRADEABLE_LOADER_COMPUTE_UNITS)?;
100 process_loader_upgradeable_instruction(invoke_context)
101 } else if bpf_loader::check_id(program_id) {
102 invoke_context
103 .compute_meter
104 .consume_checked(DEFAULT_LOADER_COMPUTE_UNITS)?;
105 ic_logger_msg!(
106 log_collector,
107 "BPF loader management instructions are no longer supported",
108 );
109 Err(InstructionError::UnsupportedProgramId)
110 } else if bpf_loader_deprecated::check_id(program_id) {
111 invoke_context
112 .compute_meter
113 .consume_checked(DEPRECATED_LOADER_COMPUTE_UNITS)?;
114 ic_logger_msg!(log_collector, "Deprecated loader is no longer supported");
115 Err(InstructionError::UnsupportedProgramId)
116 } else {
117 ic_logger_msg!(log_collector, "Invalid BPF loader id");
118 Err(InstructionError::UnsupportedProgramId)
119 }
120 .map(|_| 0)
121 .map_err(|error| Box::new(error) as Box<dyn std::error::Error>);
122 }
123
124 let mut get_or_create_executor_time = Measure::start("get_or_create_executor_time");
126 let executor = invoke_context
127 .program_cache_for_tx_batch
128 .find(program_id)
129 .ok_or_else(|| {
130 ic_logger_msg!(log_collector, "Program is not cached");
131 InstructionError::UnsupportedProgramId
132 })?;
133 get_or_create_executor_time.stop();
134 invoke_context.timings.get_or_create_executor_us += get_or_create_executor_time.as_us();
135
136 match &executor.program {
137 ProgramCacheEntryType::FailedVerification(_)
138 | ProgramCacheEntryType::Closed
139 | ProgramCacheEntryType::DelayVisibility => {
140 ic_logger_msg!(log_collector, "Program is not deployed");
141 Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
142 }
143 ProgramCacheEntryType::Loaded(executable) => execute(executable, invoke_context, &executor),
144 _ => Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>),
145 }
146 .map(|_| 0)
147}
148
149fn process_loader_upgradeable_instruction(
150 invoke_context: &mut InvokeContext,
151) -> Result<(), InstructionError> {
152 let log_collector = invoke_context.get_log_collector();
153 let transaction_context = &invoke_context.transaction_context;
154 let instruction_context = transaction_context.get_current_instruction_context()?;
155 let instruction_data = instruction_context.get_instruction_data();
156 let program_id = instruction_context.get_program_key()?;
157
158 match limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)? {
159 UpgradeableLoaderInstruction::InitializeBuffer => {
160 instruction_context.check_number_of_instruction_accounts(2)?;
161 let mut buffer = instruction_context.try_borrow_instruction_account(0)?;
162
163 if UpgradeableLoaderState::Uninitialized != buffer.get_state()? {
164 ic_logger_msg!(log_collector, "Buffer account already initialized");
165 return Err(InstructionError::AccountAlreadyInitialized);
166 }
167
168 let authority_key = Some(*instruction_context.get_key_of_instruction_account(1)?);
169
170 buffer.set_state(&UpgradeableLoaderState::Buffer {
171 authority_address: authority_key,
172 })?;
173 }
174 UpgradeableLoaderInstruction::Write { offset, bytes } => {
175 instruction_context.check_number_of_instruction_accounts(2)?;
176 let buffer = instruction_context.try_borrow_instruction_account(0)?;
177
178 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
179 if authority_address.is_none() {
180 ic_logger_msg!(log_collector, "Buffer is immutable");
181 return Err(InstructionError::Immutable); }
183 let authority_key = Some(*instruction_context.get_key_of_instruction_account(1)?);
184 if authority_address != authority_key {
185 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
186 return Err(InstructionError::IncorrectAuthority);
187 }
188 if !instruction_context.is_instruction_account_signer(1)? {
189 ic_logger_msg!(log_collector, "Buffer authority did not sign");
190 return Err(InstructionError::MissingRequiredSignature);
191 }
192 } else {
193 ic_logger_msg!(log_collector, "Invalid Buffer account");
194 return Err(InstructionError::InvalidAccountData);
195 }
196 drop(buffer);
197 write_program_data(
198 UpgradeableLoaderState::size_of_buffer_metadata().saturating_add(offset as usize),
199 &bytes,
200 invoke_context,
201 )?;
202 }
203 UpgradeableLoaderInstruction::DeployWithMaxDataLen { max_data_len } => {
204 instruction_context.check_number_of_instruction_accounts(4)?;
205 let payer_key = *instruction_context.get_key_of_instruction_account(0)?;
206 let programdata_key = *instruction_context.get_key_of_instruction_account(1)?;
207 let rent =
208 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 4)?;
209 let clock =
210 get_sysvar_with_account_check::clock(invoke_context, &instruction_context, 5)?;
211 instruction_context.check_number_of_instruction_accounts(8)?;
212 let authority_key = Some(*instruction_context.get_key_of_instruction_account(7)?);
213
214 let program = instruction_context.try_borrow_instruction_account(2)?;
217 if UpgradeableLoaderState::Uninitialized != program.get_state()? {
218 ic_logger_msg!(log_collector, "Program account already initialized");
219 return Err(InstructionError::AccountAlreadyInitialized);
220 }
221 if program.get_data().len() < UpgradeableLoaderState::size_of_program() {
222 ic_logger_msg!(log_collector, "Program account too small");
223 return Err(InstructionError::AccountDataTooSmall);
224 }
225 if program.get_lamports() < rent.minimum_balance(program.get_data().len()) {
226 ic_logger_msg!(log_collector, "Program account not rent-exempt");
227 return Err(InstructionError::ExecutableAccountNotRentExempt);
228 }
229 let new_program_id = *program.get_key();
230 drop(program);
231
232 let buffer = instruction_context.try_borrow_instruction_account(3)?;
235 if !buffer.is_writable() {
236 ic_logger_msg!(log_collector, "Buffer account not writeable");
237 return Err(InstructionError::InvalidArgument);
238 }
239 if buffer.get_owner() != program_id {
240 ic_logger_msg!(log_collector, "Buffer account not owned by loader");
241 return Err(InstructionError::IncorrectProgramId);
242 }
243 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
244 if authority_address != authority_key {
245 ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
246 return Err(InstructionError::IncorrectAuthority);
247 }
248 if !instruction_context.is_instruction_account_signer(7)? {
249 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
250 return Err(InstructionError::MissingRequiredSignature);
251 }
252 } else {
253 ic_logger_msg!(log_collector, "Invalid Buffer account");
254 return Err(InstructionError::InvalidArgument);
255 }
256 let buffer_key = *buffer.get_key();
257 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
258 let buffer_data_len = buffer.get_data().len().saturating_sub(buffer_data_offset);
259 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
260 let programdata_len = UpgradeableLoaderState::size_of_programdata(max_data_len);
261 if buffer.get_data().len() < UpgradeableLoaderState::size_of_buffer_metadata()
262 || buffer_data_len == 0
263 {
264 ic_logger_msg!(log_collector, "Buffer account too small");
265 return Err(InstructionError::InvalidAccountData);
266 }
267 drop(buffer);
268 if max_data_len < buffer_data_len {
269 ic_logger_msg!(
270 log_collector,
271 "Max data length is too small to hold Buffer data"
272 );
273 return Err(InstructionError::AccountDataTooSmall);
274 }
275 if programdata_len > MAX_PERMITTED_DATA_LENGTH as usize {
276 ic_logger_msg!(log_collector, "Max data length is too large");
277 return Err(InstructionError::InvalidArgument);
278 }
279
280 let (derived_address, bump_seed) =
282 Pubkey::find_program_address(&[new_program_id.as_ref()], program_id);
283 if derived_address != programdata_key {
284 ic_logger_msg!(log_collector, "ProgramData address is not derived");
285 return Err(InstructionError::InvalidArgument);
286 }
287
288 {
290 let mut buffer = instruction_context.try_borrow_instruction_account(3)?;
291 let mut payer = instruction_context.try_borrow_instruction_account(0)?;
292 payer.checked_add_lamports(buffer.get_lamports())?;
293 buffer.set_lamports(0)?;
294 }
295
296 let owner_id = *program_id;
297 let mut instruction = system_instruction::create_account(
298 &payer_key,
299 &programdata_key,
300 1.max(rent.minimum_balance(programdata_len)),
301 programdata_len as u64,
302 program_id,
303 );
304
305 instruction
307 .accounts
308 .push(AccountMeta::new(buffer_key, false));
309
310 invoke_context
311 .native_invoke_signed(instruction, &[&[new_program_id.as_ref(), &[bump_seed]]])?;
312
313 let transaction_context = &invoke_context.transaction_context;
315 let instruction_context = transaction_context.get_current_instruction_context()?;
316 let buffer = instruction_context.try_borrow_instruction_account(3)?;
317 deploy_program!(
318 invoke_context,
319 &new_program_id,
320 &owner_id,
321 buffer
322 .get_data()
323 .get(buffer_data_offset..)
324 .ok_or(InstructionError::AccountDataTooSmall)?,
325 clock.slot,
326 invoke_context
327 .get_feature_set()
328 .disable_sbpf_v0_v1_v2_deployment,
329 );
330 drop(buffer);
331
332 let transaction_context = &invoke_context.transaction_context;
333 let instruction_context = transaction_context.get_current_instruction_context()?;
334
335 {
337 let mut programdata = instruction_context.try_borrow_instruction_account(1)?;
338 programdata.set_state(&UpgradeableLoaderState::ProgramData {
339 slot: clock.slot,
340 upgrade_authority_address: authority_key,
341 })?;
342 let dst_slice = programdata
343 .get_data_mut()?
344 .get_mut(
345 programdata_data_offset
346 ..programdata_data_offset.saturating_add(buffer_data_len),
347 )
348 .ok_or(InstructionError::AccountDataTooSmall)?;
349 let mut buffer = instruction_context.try_borrow_instruction_account(3)?;
350 let src_slice = buffer
351 .get_data()
352 .get(buffer_data_offset..)
353 .ok_or(InstructionError::AccountDataTooSmall)?;
354 dst_slice.copy_from_slice(src_slice);
355 buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
356 }
357
358 let mut program = instruction_context.try_borrow_instruction_account(2)?;
360 program.set_state(&UpgradeableLoaderState::Program {
361 programdata_address: programdata_key,
362 })?;
363 program.set_executable(true)?;
364 drop(program);
365
366 ic_logger_msg!(log_collector, "Deployed program {:?}", new_program_id);
367 }
368 UpgradeableLoaderInstruction::Upgrade => {
369 instruction_context.check_number_of_instruction_accounts(3)?;
370 let programdata_key = *instruction_context.get_key_of_instruction_account(0)?;
371 let rent =
372 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 4)?;
373 let clock =
374 get_sysvar_with_account_check::clock(invoke_context, &instruction_context, 5)?;
375 instruction_context.check_number_of_instruction_accounts(7)?;
376 let authority_key = Some(*instruction_context.get_key_of_instruction_account(6)?);
377
378 let set_programdata_to_elf_len = invoke_context
379 .get_feature_set()
380 .loader_v3_set_program_data_to_elf_length;
381
382 let program = instruction_context.try_borrow_instruction_account(1)?;
385 if !program.is_writable() {
386 ic_logger_msg!(log_collector, "Program account not writeable");
387 return Err(InstructionError::InvalidArgument);
388 }
389 if program.get_owner() != program_id {
390 ic_logger_msg!(log_collector, "Program account not owned by loader");
391 return Err(InstructionError::IncorrectProgramId);
392 }
393 if let UpgradeableLoaderState::Program {
394 programdata_address,
395 } = program.get_state()?
396 {
397 if programdata_address != programdata_key {
398 ic_logger_msg!(log_collector, "Program and ProgramData account mismatch");
399 return Err(InstructionError::InvalidArgument);
400 }
401 } else {
402 ic_logger_msg!(log_collector, "Invalid Program account");
403 return Err(InstructionError::InvalidAccountData);
404 }
405 let new_program_id = *program.get_key();
406 drop(program);
407
408 let buffer = instruction_context.try_borrow_instruction_account(2)?;
411 if !buffer.is_writable() {
412 ic_logger_msg!(log_collector, "Buffer account not writeable");
413 return Err(InstructionError::InvalidArgument);
414 }
415 if buffer.get_owner() != program_id {
416 ic_logger_msg!(log_collector, "Buffer account not owned by loader");
417 return Err(InstructionError::IncorrectProgramId);
418 }
419 if let UpgradeableLoaderState::Buffer { authority_address } = buffer.get_state()? {
420 if authority_address != authority_key {
421 ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
422 return Err(InstructionError::IncorrectAuthority);
423 }
424 if !instruction_context.is_instruction_account_signer(6)? {
425 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
426 return Err(InstructionError::MissingRequiredSignature);
427 }
428 } else {
429 ic_logger_msg!(log_collector, "Invalid Buffer account");
430 return Err(InstructionError::InvalidArgument);
431 }
432 let buffer_lamports = buffer.get_lamports();
433 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
434 let buffer_data_len = buffer.get_data().len().saturating_sub(buffer_data_offset);
435 if buffer.get_data().len() < UpgradeableLoaderState::size_of_buffer_metadata()
436 || buffer_data_len == 0
437 {
438 ic_logger_msg!(log_collector, "Buffer account too small");
439 return Err(InstructionError::InvalidAccountData);
440 }
441 drop(buffer);
442
443 let programdata = instruction_context.try_borrow_instruction_account(0)?;
446 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
447 let (programdata_len, programdata_balance_required) = if set_programdata_to_elf_len {
448 let new_len = programdata_data_offset.saturating_add(buffer_data_len);
450 if new_len > MAX_PERMITTED_DATA_LENGTH as usize {
451 ic_logger_msg!(
452 log_collector,
453 "Resized ProgramData length of {} bytes exceeds max account data length",
454 new_len
455 );
456 return Err(InstructionError::InvalidAccountData);
457 }
458 (new_len, 1.max(rent.minimum_balance(new_len)))
459 } else {
460 let len = programdata.get_data().len();
463 if len < UpgradeableLoaderState::size_of_programdata(buffer_data_len) {
464 ic_logger_msg!(log_collector, "ProgramData account not large enough");
465 return Err(InstructionError::AccountDataTooSmall);
466 }
467 (len, 1.max(rent.minimum_balance(len)))
468 };
469 if programdata.get_lamports().saturating_add(buffer_lamports)
470 < programdata_balance_required
471 {
472 ic_logger_msg!(
473 log_collector,
474 "Buffer account balance too low to fund upgrade"
475 );
476 return Err(InstructionError::InsufficientFunds);
477 }
478 if let UpgradeableLoaderState::ProgramData {
479 slot,
480 upgrade_authority_address,
481 } = programdata.get_state()?
482 {
483 if clock.slot == slot {
484 ic_logger_msg!(log_collector, "Program was deployed in this block already");
485 return Err(InstructionError::InvalidArgument);
486 }
487 if upgrade_authority_address.is_none() {
488 ic_logger_msg!(log_collector, "Program not upgradeable");
489 return Err(InstructionError::Immutable);
490 }
491 if upgrade_authority_address != authority_key {
492 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
493 return Err(InstructionError::IncorrectAuthority);
494 }
495 if !instruction_context.is_instruction_account_signer(6)? {
496 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
497 return Err(InstructionError::MissingRequiredSignature);
498 }
499 } else {
500 ic_logger_msg!(log_collector, "Invalid ProgramData account");
501 return Err(InstructionError::InvalidAccountData);
502 };
503 drop(programdata);
504
505 let buffer = instruction_context.try_borrow_instruction_account(2)?;
507 deploy_program!(
508 invoke_context,
509 &new_program_id,
510 program_id,
511 buffer
512 .get_data()
513 .get(buffer_data_offset..)
514 .ok_or(InstructionError::AccountDataTooSmall)?,
515 clock.slot,
516 invoke_context
517 .get_feature_set()
518 .disable_sbpf_v0_v1_v2_deployment,
519 );
520 drop(buffer);
521
522 let transaction_context = &invoke_context.transaction_context;
523 let instruction_context = transaction_context.get_current_instruction_context()?;
524
525 let mut programdata = instruction_context.try_borrow_instruction_account(0)?;
527 {
528 programdata.set_data_length(programdata_len)?;
529 programdata.set_state(&UpgradeableLoaderState::ProgramData {
530 slot: clock.slot,
531 upgrade_authority_address: authority_key,
532 })?;
533 let dst_slice = programdata
534 .get_data_mut()?
535 .get_mut(
536 programdata_data_offset
537 ..programdata_data_offset.saturating_add(buffer_data_len),
538 )
539 .ok_or(InstructionError::AccountDataTooSmall)?;
540 let buffer = instruction_context.try_borrow_instruction_account(2)?;
541 let src_slice = buffer
542 .get_data()
543 .get(buffer_data_offset..)
544 .ok_or(InstructionError::AccountDataTooSmall)?;
545 dst_slice.copy_from_slice(src_slice);
546 }
547 programdata
548 .get_data_mut()?
549 .get_mut(programdata_data_offset.saturating_add(buffer_data_len)..)
550 .ok_or(InstructionError::AccountDataTooSmall)?
551 .fill(0);
552
553 let mut buffer = instruction_context.try_borrow_instruction_account(2)?;
555 let mut spill = instruction_context.try_borrow_instruction_account(3)?;
556 spill.checked_add_lamports(
557 programdata
558 .get_lamports()
559 .saturating_add(buffer_lamports)
560 .saturating_sub(programdata_balance_required),
561 )?;
562 buffer.set_lamports(0)?;
563 programdata.set_lamports(programdata_balance_required)?;
564 buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
565
566 ic_logger_msg!(log_collector, "Upgraded program {:?}", new_program_id);
567 }
568 UpgradeableLoaderInstruction::SetAuthority => {
569 instruction_context.check_number_of_instruction_accounts(2)?;
570 let mut account = instruction_context.try_borrow_instruction_account(0)?;
571 let present_authority_key = instruction_context.get_key_of_instruction_account(1)?;
572 let new_authority = instruction_context.get_key_of_instruction_account(2).ok();
573
574 match account.get_state()? {
575 UpgradeableLoaderState::Buffer { authority_address } => {
576 if new_authority.is_none() {
577 ic_logger_msg!(log_collector, "Buffer authority is not optional");
578 return Err(InstructionError::IncorrectAuthority);
579 }
580 if authority_address.is_none() {
581 ic_logger_msg!(log_collector, "Buffer is immutable");
582 return Err(InstructionError::Immutable);
583 }
584 if authority_address != Some(*present_authority_key) {
585 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
586 return Err(InstructionError::IncorrectAuthority);
587 }
588 if !instruction_context.is_instruction_account_signer(1)? {
589 ic_logger_msg!(log_collector, "Buffer authority did not sign");
590 return Err(InstructionError::MissingRequiredSignature);
591 }
592 account.set_state(&UpgradeableLoaderState::Buffer {
593 authority_address: new_authority.cloned(),
594 })?;
595 }
596 UpgradeableLoaderState::ProgramData {
597 slot,
598 upgrade_authority_address,
599 } => {
600 if upgrade_authority_address.is_none() {
601 ic_logger_msg!(log_collector, "Program not upgradeable");
602 return Err(InstructionError::Immutable);
603 }
604 if upgrade_authority_address != Some(*present_authority_key) {
605 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
606 return Err(InstructionError::IncorrectAuthority);
607 }
608 if !instruction_context.is_instruction_account_signer(1)? {
609 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
610 return Err(InstructionError::MissingRequiredSignature);
611 }
612 if invoke_context
613 .get_feature_set()
614 .disable_sbpf_v0_v1_v2_deployment
615 && new_authority.is_none()
616 && let Some(program) = account
617 .get_data()
618 .get(UpgradeableLoaderState::size_of_programdata_metadata()..)
619 && let Ok(sbpf_version) = get_sbpf_version(program)
620 && sbpf_version < SBPFVersion::V3
621 {
622 return Err(InstructionError::InvalidAccountData);
623 }
624 account.set_state(&UpgradeableLoaderState::ProgramData {
625 slot,
626 upgrade_authority_address: new_authority.cloned(),
627 })?;
628 }
629 _ => {
630 ic_logger_msg!(log_collector, "Account does not support authorities");
631 return Err(InstructionError::InvalidArgument);
632 }
633 }
634
635 ic_logger_msg!(log_collector, "New authority {:?}", new_authority);
636 }
637 UpgradeableLoaderInstruction::SetAuthorityChecked => {
638 if !invoke_context
639 .get_feature_set()
640 .enable_bpf_loader_set_authority_checked_ix
641 {
642 return Err(InstructionError::InvalidInstructionData);
643 }
644
645 instruction_context.check_number_of_instruction_accounts(3)?;
646 let mut account = instruction_context.try_borrow_instruction_account(0)?;
647 let present_authority_key = instruction_context.get_key_of_instruction_account(1)?;
648 let new_authority_key = instruction_context.get_key_of_instruction_account(2)?;
649
650 match account.get_state()? {
651 UpgradeableLoaderState::Buffer { authority_address } => {
652 if authority_address.is_none() {
653 ic_logger_msg!(log_collector, "Buffer is immutable");
654 return Err(InstructionError::Immutable);
655 }
656 if authority_address != Some(*present_authority_key) {
657 ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
658 return Err(InstructionError::IncorrectAuthority);
659 }
660 if !instruction_context.is_instruction_account_signer(1)? {
661 ic_logger_msg!(log_collector, "Buffer authority did not sign");
662 return Err(InstructionError::MissingRequiredSignature);
663 }
664 if !instruction_context.is_instruction_account_signer(2)? {
665 ic_logger_msg!(log_collector, "New authority did not sign");
666 return Err(InstructionError::MissingRequiredSignature);
667 }
668 account.set_state(&UpgradeableLoaderState::Buffer {
669 authority_address: Some(*new_authority_key),
670 })?;
671 }
672 UpgradeableLoaderState::ProgramData {
673 slot,
674 upgrade_authority_address,
675 } => {
676 if upgrade_authority_address.is_none() {
677 ic_logger_msg!(log_collector, "Program not upgradeable");
678 return Err(InstructionError::Immutable);
679 }
680 if upgrade_authority_address != Some(*present_authority_key) {
681 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
682 return Err(InstructionError::IncorrectAuthority);
683 }
684 if !instruction_context.is_instruction_account_signer(1)? {
685 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
686 return Err(InstructionError::MissingRequiredSignature);
687 }
688 if !instruction_context.is_instruction_account_signer(2)? {
689 ic_logger_msg!(log_collector, "New authority did not sign");
690 return Err(InstructionError::MissingRequiredSignature);
691 }
692 account.set_state(&UpgradeableLoaderState::ProgramData {
693 slot,
694 upgrade_authority_address: Some(*new_authority_key),
695 })?;
696 }
697 _ => {
698 ic_logger_msg!(log_collector, "Account does not support authorities");
699 return Err(InstructionError::InvalidArgument);
700 }
701 }
702
703 ic_logger_msg!(log_collector, "New authority {:?}", new_authority_key);
704 }
705 UpgradeableLoaderInstruction::Close => {
706 instruction_context.check_number_of_instruction_accounts(2)?;
707 if instruction_context.get_index_of_instruction_account_in_transaction(0)?
708 == instruction_context.get_index_of_instruction_account_in_transaction(1)?
709 {
710 ic_logger_msg!(
711 log_collector,
712 "Recipient is the same as the account being closed"
713 );
714 return Err(InstructionError::InvalidArgument);
715 }
716 let mut close_account = instruction_context.try_borrow_instruction_account(0)?;
717 let close_key = *close_account.get_key();
718 let close_account_state = close_account.get_state()?;
719 match close_account_state {
720 UpgradeableLoaderState::Uninitialized => {
721 let mut recipient_account =
722 instruction_context.try_borrow_instruction_account(1)?;
723 recipient_account.checked_add_lamports(close_account.get_lamports())?;
724 close_account.set_lamports(0)?;
725 close_account
726 .set_data_length(UpgradeableLoaderState::size_of_uninitialized())?;
727 ic_logger_msg!(log_collector, "Closed Uninitialized {}", close_key);
728 }
729 UpgradeableLoaderState::Buffer { authority_address } => {
730 instruction_context.check_number_of_instruction_accounts(3)?;
731 drop(close_account);
732 common_close_account(&authority_address, &instruction_context, &log_collector)?;
733 ic_logger_msg!(log_collector, "Closed Buffer {}", close_key);
734 }
735 UpgradeableLoaderState::ProgramData {
736 slot,
737 upgrade_authority_address: authority_address,
738 } => {
739 instruction_context.check_number_of_instruction_accounts(4)?;
740 drop(close_account);
741 let program_account = instruction_context.try_borrow_instruction_account(3)?;
742 let program_key = *program_account.get_key();
743
744 if !program_account.is_writable() {
745 ic_logger_msg!(log_collector, "Program account is not writable");
746 return Err(InstructionError::InvalidArgument);
747 }
748 if program_account.get_owner() != program_id {
749 ic_logger_msg!(log_collector, "Program account not owned by loader");
750 return Err(InstructionError::IncorrectProgramId);
751 }
752 let clock = invoke_context
753 .environment_config
754 .sysvar_cache()
755 .get_clock()?;
756 if clock.slot == slot {
757 ic_logger_msg!(log_collector, "Program was deployed in this block already");
758 return Err(InstructionError::InvalidArgument);
759 }
760
761 match program_account.get_state()? {
762 UpgradeableLoaderState::Program {
763 programdata_address,
764 } => {
765 if programdata_address != close_key {
766 ic_logger_msg!(
767 log_collector,
768 "ProgramData account does not match ProgramData account"
769 );
770 return Err(InstructionError::InvalidArgument);
771 }
772
773 drop(program_account);
774 common_close_account(
775 &authority_address,
776 &instruction_context,
777 &log_collector,
778 )?;
779 let clock = invoke_context
780 .environment_config
781 .sysvar_cache()
782 .get_clock()?;
783 invoke_context
784 .program_cache_for_tx_batch
785 .store_modified_entry(
786 program_key,
787 Arc::new(ProgramCacheEntry::new_closed_tombstone(
788 clock.slot,
789 ProgramCacheEntryOwner::LoaderV3,
790 )),
791 );
792 }
793 _ => {
794 ic_logger_msg!(log_collector, "Invalid Program account");
795 return Err(InstructionError::InvalidArgument);
796 }
797 }
798
799 ic_logger_msg!(log_collector, "Closed Program {}", program_key);
800 }
801 _ => {
802 ic_logger_msg!(log_collector, "Account does not support closing");
803 return Err(InstructionError::InvalidArgument);
804 }
805 }
806 }
807 UpgradeableLoaderInstruction::ExtendProgram { additional_bytes } => {
808 common_extend_program(invoke_context, additional_bytes, false)?;
809 }
810 }
811
812 Ok(())
813}
814
815fn common_extend_program(
816 invoke_context: &mut InvokeContext,
817 additional_bytes: u32,
818 check_authority: bool,
819) -> Result<(), InstructionError> {
820 let log_collector = invoke_context.get_log_collector();
821 let transaction_context = &invoke_context.transaction_context;
822 let instruction_context = transaction_context.get_current_instruction_context()?;
823 let program_id = instruction_context.get_program_key()?;
824
825 const PROGRAM_DATA_ACCOUNT_INDEX: IndexOfAccount = 0;
826 const PROGRAM_ACCOUNT_INDEX: IndexOfAccount = 1;
827 const AUTHORITY_ACCOUNT_INDEX: IndexOfAccount = 2;
828 let optional_payer_account_index = if check_authority { 4 } else { 3 };
830
831 if additional_bytes == 0 {
832 ic_logger_msg!(log_collector, "Additional bytes must be greater than 0");
833 return Err(InstructionError::InvalidInstructionData);
834 }
835
836 let programdata_account =
837 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
838 let programdata_key = *programdata_account.get_key();
839
840 if program_id != programdata_account.get_owner() {
841 ic_logger_msg!(log_collector, "ProgramData owner is invalid");
842 return Err(InstructionError::InvalidAccountOwner);
843 }
844 if !programdata_account.is_writable() {
845 ic_logger_msg!(log_collector, "ProgramData is not writable");
846 return Err(InstructionError::InvalidArgument);
847 }
848
849 let program_account =
850 instruction_context.try_borrow_instruction_account(PROGRAM_ACCOUNT_INDEX)?;
851 if !program_account.is_writable() {
852 ic_logger_msg!(log_collector, "Program account is not writable");
853 return Err(InstructionError::InvalidArgument);
854 }
855 if program_account.get_owner() != program_id {
856 ic_logger_msg!(log_collector, "Program account not owned by loader");
857 return Err(InstructionError::InvalidAccountOwner);
858 }
859 let program_key = *program_account.get_key();
860 match program_account.get_state()? {
861 UpgradeableLoaderState::Program {
862 programdata_address,
863 } => {
864 if programdata_address != programdata_key {
865 ic_logger_msg!(
866 log_collector,
867 "Program account does not match ProgramData account"
868 );
869 return Err(InstructionError::InvalidArgument);
870 }
871 }
872 _ => {
873 ic_logger_msg!(log_collector, "Invalid Program account");
874 return Err(InstructionError::InvalidAccountData);
875 }
876 }
877 drop(program_account);
878
879 let old_len = programdata_account.get_data().len();
880 let new_len = old_len.saturating_add(additional_bytes as usize);
881 if new_len > MAX_PERMITTED_DATA_LENGTH as usize {
882 ic_logger_msg!(
883 log_collector,
884 "Extended ProgramData length of {} bytes exceeds max account data length of {} bytes",
885 new_len,
886 MAX_PERMITTED_DATA_LENGTH
887 );
888 return Err(InstructionError::InvalidRealloc);
889 }
890
891 if invoke_context
892 .get_feature_set()
893 .loader_v3_minimum_extend_program_size
894 {
895 let headroom = (MAX_PERMITTED_DATA_LENGTH as usize).saturating_sub(old_len);
901 if additional_bytes < MINIMUM_EXTEND_PROGRAM_BYTES
902 && (additional_bytes as usize) != headroom
903 {
904 ic_logger_msg!(
905 log_collector,
906 "ExtendProgram requires a minimum of {} additional bytes or to extend to maximum \
907 size, but only {} were requested",
908 MINIMUM_EXTEND_PROGRAM_BYTES,
909 additional_bytes,
910 );
911 return Err(InstructionError::InvalidArgument);
912 }
913 }
914
915 let clock_slot = invoke_context
916 .environment_config
917 .sysvar_cache()
918 .get_clock()
919 .map(|clock| clock.slot)?;
920
921 let upgrade_authority_address = if let UpgradeableLoaderState::ProgramData {
922 slot,
923 upgrade_authority_address,
924 } = programdata_account.get_state()?
925 {
926 if clock_slot == slot {
927 ic_logger_msg!(log_collector, "Program was extended in this block already");
928 return Err(InstructionError::InvalidArgument);
929 }
930
931 if upgrade_authority_address.is_none() {
932 ic_logger_msg!(
933 log_collector,
934 "Cannot extend ProgramData accounts that are not upgradeable"
935 );
936 return Err(InstructionError::Immutable);
937 }
938
939 if check_authority {
940 let authority_key =
941 Some(*instruction_context.get_key_of_instruction_account(AUTHORITY_ACCOUNT_INDEX)?);
942 if upgrade_authority_address != authority_key {
943 ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
944 return Err(InstructionError::IncorrectAuthority);
945 }
946 if !instruction_context.is_instruction_account_signer(AUTHORITY_ACCOUNT_INDEX)? {
947 ic_logger_msg!(log_collector, "Upgrade authority did not sign");
948 return Err(InstructionError::MissingRequiredSignature);
949 }
950 }
951
952 upgrade_authority_address
953 } else {
954 ic_logger_msg!(log_collector, "ProgramData state is invalid");
955 return Err(InstructionError::InvalidAccountData);
956 };
957
958 let required_payment = {
959 let balance = programdata_account.get_lamports();
960 let rent = invoke_context
961 .environment_config
962 .sysvar_cache()
963 .get_rent()?;
964 let min_balance = rent.minimum_balance(new_len).max(1);
965 min_balance.saturating_sub(balance)
966 };
967
968 drop(programdata_account);
970
971 let program_id = *program_id;
973 if required_payment > 0 {
974 let payer_key =
975 *instruction_context.get_key_of_instruction_account(optional_payer_account_index)?;
976
977 invoke_context.native_invoke_signed(
978 system_instruction::transfer(&payer_key, &programdata_key, required_payment),
979 &[],
980 )?;
981 }
982
983 let transaction_context = &invoke_context.transaction_context;
984 let instruction_context = transaction_context.get_current_instruction_context()?;
985 let mut programdata_account =
986 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
987 programdata_account.set_data_length(new_len)?;
988
989 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
990
991 deploy_program!(
992 invoke_context,
993 &program_key,
994 &program_id,
995 programdata_account
996 .get_data()
997 .get(programdata_data_offset..)
998 .ok_or(InstructionError::AccountDataTooSmall)?,
999 clock_slot,
1000 false, );
1002 drop(programdata_account);
1003
1004 let mut programdata_account =
1005 instruction_context.try_borrow_instruction_account(PROGRAM_DATA_ACCOUNT_INDEX)?;
1006 programdata_account.set_state(&UpgradeableLoaderState::ProgramData {
1007 slot: clock_slot,
1008 upgrade_authority_address,
1009 })?;
1010
1011 ic_logger_msg!(
1012 log_collector,
1013 "Extended ProgramData account by {} bytes",
1014 additional_bytes
1015 );
1016
1017 Ok(())
1018}
1019
1020fn common_close_account(
1021 authority_address: &Option<Pubkey>,
1022 instruction_context: &InstructionContext,
1023 log_collector: &Option<Rc<RefCell<LogCollector>>>,
1024) -> Result<(), InstructionError> {
1025 if authority_address.is_none() {
1026 ic_logger_msg!(log_collector, "Account is immutable");
1027 return Err(InstructionError::Immutable);
1028 }
1029 if *authority_address != Some(*instruction_context.get_key_of_instruction_account(2)?) {
1030 ic_logger_msg!(log_collector, "Incorrect authority provided");
1031 return Err(InstructionError::IncorrectAuthority);
1032 }
1033 if !instruction_context.is_instruction_account_signer(2)? {
1034 ic_logger_msg!(log_collector, "Authority did not sign");
1035 return Err(InstructionError::MissingRequiredSignature);
1036 }
1037
1038 let mut close_account = instruction_context.try_borrow_instruction_account(0)?;
1039 let mut recipient_account = instruction_context.try_borrow_instruction_account(1)?;
1040
1041 recipient_account.checked_add_lamports(close_account.get_lamports())?;
1042 close_account.set_lamports(0)?;
1043 close_account.set_data_length(UpgradeableLoaderState::size_of_uninitialized())?;
1044 close_account.set_state(&UpgradeableLoaderState::Uninitialized)?;
1045 Ok(())
1046}
1047
1048#[cfg_attr(feature = "svm-internal", qualifiers(pub))]
1049mod test_utils {
1050 #[cfg(all(feature = "svm-internal", feature = "metrics"))]
1051 use solana_program_runtime::program_metrics::LoadProgramMetrics;
1052 #[cfg(feature = "svm-internal")]
1053 use {
1054 super::*, solana_account::ReadableAccount,
1055 solana_program_runtime::loaded_programs::ProgramRuntimeEnvironment,
1056 solana_syscalls::create_program_runtime_environment,
1057 };
1058
1059 #[cfg(feature = "svm-internal")]
1060 fn check_loader_id(id: &Pubkey) -> bool {
1061 bpf_loader::check_id(id)
1062 || bpf_loader_deprecated::check_id(id)
1063 || bpf_loader_upgradeable::check_id(id)
1064 }
1065
1066 #[cfg(feature = "svm-internal")]
1067 #[cfg_attr(feature = "svm-internal", qualifiers(pub))]
1068 fn load_all_invoked_programs(invoke_context: &mut InvokeContext) {
1069 let program_runtime_environment = create_program_runtime_environment(
1070 invoke_context.get_feature_set(),
1071 invoke_context.get_compute_budget(),
1072 false, false, )
1075 .unwrap();
1076 let num_accounts = invoke_context.transaction_context.get_number_of_accounts();
1077 for index in 0..num_accounts {
1078 let account = invoke_context
1079 .transaction_context
1080 .accounts()
1081 .try_borrow(index)
1082 .expect("Failed to get the account");
1083
1084 let owner = account.owner();
1085 if check_loader_id(owner) {
1086 let programdata_data_offset = 0;
1087 let pubkey = invoke_context
1088 .transaction_context
1089 .get_key_of_account_at_index(index)
1090 .expect("Failed to get account key");
1091
1092 let programdata = account
1093 .data()
1094 .get(programdata_data_offset.min(account.data().len())..)
1095 .unwrap();
1096 let loaded_program = ProgramCacheEntry::load(
1097 owner,
1098 ProgramRuntimeEnvironment::clone(&program_runtime_environment),
1099 0,
1100 programdata,
1101 #[cfg(feature = "metrics")]
1102 &mut LoadProgramMetrics::default(),
1103 )
1104 .map_err(|_| InstructionError::InvalidAccountData);
1105 if let Ok(loaded_program) = loaded_program {
1106 invoke_context
1107 .program_cache_for_tx_batch
1108 .store_modified_entry(*pubkey, Arc::new(loaded_program));
1109 }
1110 }
1111 }
1112 }
1113}
1114
1115#[cfg(test)]
1116mod tests {
1117 use {
1118 super::*,
1119 assert_matches::assert_matches,
1120 rand::Rng,
1121 solana_account::{
1122 AccountSharedData, ReadableAccount, WritableAccount,
1123 state_traits::StateMutWincode as StateMut,
1124 },
1125 solana_clock::Clock,
1126 solana_epoch_schedule::EpochSchedule,
1127 solana_instruction::AccountMeta,
1128 solana_instruction_error::InstructionError,
1129 solana_program_runtime::{
1130 invoke_context::mock_process_instruction_with_feature_set,
1131 loaded_programs::ProgramRuntimeEnvironment, program_metrics::ProgramStatistics,
1132 vm::calculate_heap_cost, with_mock_invoke_context,
1133 },
1134 solana_pubkey::Pubkey,
1135 solana_rent::Rent,
1136 solana_sbpf::program::{BuiltinFunctionDefinition, BuiltinProgram},
1137 solana_sdk_ids::{system_program, sysvar},
1138 solana_svm_feature_set::SVMFeatureSet,
1139 solana_svm_type_overrides::sync::atomic::{AtomicU64, Ordering},
1140 solana_sysvar_id::SysvarId,
1141 std::{fs::File, io::Read, ops::Range},
1142 test_case::test_case,
1143 };
1144
1145 #[derive(Clone, Copy)]
1146 struct LoaderV3Features {
1147 pub set_programdata_to_elf_length: bool,
1149 }
1150
1151 impl LoaderV3Features {
1152 fn all_enabled() -> Self {
1153 Self {
1154 set_programdata_to_elf_length: true,
1155 }
1156 }
1157 }
1158
1159 fn setup_features(feature_set: &mut SVMFeatureSet, loader_v3_features: LoaderV3Features) {
1160 let LoaderV3Features {
1161 set_programdata_to_elf_length,
1162 } = loader_v3_features;
1163 feature_set.loader_v3_set_program_data_to_elf_length = set_programdata_to_elf_length;
1164 }
1165
1166 fn create_sysvar_account<T>(value: &T) -> AccountSharedData
1167 where
1168 T: wincode::Serialize<Src = T> + SysvarId,
1169 {
1170 let serialized_len = wincode::serialized_size(value).unwrap() as usize;
1171 let canonical_data_len = match T::id() {
1172 sysvar::clock::ID => solana_clock::SIZE,
1173 sysvar::epoch_schedule::ID => solana_epoch_schedule::SIZE,
1174 sysvar::rent::ID => solana_rent::SIZE,
1175 id => panic!("unsupported sysvar: {id}"),
1176 };
1177 let required_data_len = canonical_data_len.max(serialized_len);
1178 let mut account = AccountSharedData::new(1, required_data_len, &sysvar::id());
1179 wincode::serialize_into(account.data_as_mut_slice(), value).unwrap();
1180 account
1181 }
1182
1183 #[cfg(feature = "shuttle-test")]
1189 const MOCK_PROCESS_RANDOM_ITERATIONS: usize = 10;
1190
1191 fn process_instruction_with_setup(
1214 program_id: &Pubkey,
1215 instruction_data: &[u8],
1216 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1217 instruction_accounts: Vec<AccountMeta>,
1218 loader_v3_features: LoaderV3Features,
1219 expected_result: Result<(), InstructionError>,
1220 setup: fn(&mut InvokeContext),
1221 ) -> Vec<AccountSharedData> {
1222 let mut feature_set = SVMFeatureSet::all_enabled();
1223 setup_features(&mut feature_set, loader_v3_features);
1224
1225 #[cfg(feature = "shuttle-test")]
1226 {
1227 let program_id = *program_id;
1228 let instruction_data = instruction_data.to_vec();
1229 let result = shuttle::sync::Arc::new(shuttle::sync::Mutex::new(None));
1230 let result_for_test = shuttle::sync::Arc::clone(&result);
1231 shuttle::check_random(
1232 move || {
1233 let accounts = mock_process_instruction_with_feature_set(
1234 &program_id,
1235 &instruction_data,
1236 transaction_accounts.clone(),
1237 instruction_accounts.clone(),
1238 expected_result.clone(),
1239 Entrypoint::register,
1240 setup,
1241 |_invoke_context| {},
1242 &feature_set,
1243 );
1244 *result_for_test.lock().unwrap() = Some(accounts);
1245 },
1246 MOCK_PROCESS_RANDOM_ITERATIONS,
1247 );
1248
1249 let Ok(mut result) = shuttle::sync::Arc::try_unwrap(result) else {
1252 panic!("shuttle test result still has outstanding references")
1253 };
1254 result
1255 .get_mut()
1256 .unwrap()
1257 .take()
1258 .expect("shuttle test did not produce a result")
1259 }
1260
1261 #[cfg(not(feature = "shuttle-test"))]
1262 mock_process_instruction_with_feature_set(
1263 program_id,
1264 instruction_data,
1265 transaction_accounts,
1266 instruction_accounts,
1267 expected_result,
1268 Entrypoint::register,
1269 setup,
1270 |_invoke_context| {},
1271 &feature_set,
1272 )
1273 }
1274
1275 fn process_instruction(
1276 program_id: &Pubkey,
1277 instruction_data: &[u8],
1278 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1279 instruction_accounts: Vec<AccountMeta>,
1280 expected_result: Result<(), InstructionError>,
1281 ) -> Vec<AccountSharedData> {
1282 process_instruction_with_setup(
1283 program_id,
1284 instruction_data,
1285 transaction_accounts,
1286 instruction_accounts,
1287 LoaderV3Features::all_enabled(),
1288 expected_result,
1289 |invoke_context| {
1290 test_utils::load_all_invoked_programs(invoke_context);
1291 },
1292 )
1293 }
1294
1295 fn load_program_account_from_elf(loader_id: &Pubkey, path: &str) -> AccountSharedData {
1296 let mut file = File::open(path).expect("file open failed");
1297 let mut elf = Vec::new();
1298 file.read_to_end(&mut elf).unwrap();
1299 let rent = Rent::default();
1300 let mut program_account =
1301 AccountSharedData::new(rent.minimum_balance(elf.len()), 0, loader_id);
1302 program_account.set_data_from_slice(&elf);
1303 program_account.set_executable(true);
1304 program_account
1305 }
1306
1307 #[test]
1308 fn test_bpf_loader_invoke_main() {
1309 let loader_id = bpf_loader::id();
1310 let program_id = Pubkey::new_unique();
1311 let program_account =
1312 load_program_account_from_elf(&loader_id, "test_elfs/out/sbpfv3_return_ok.so");
1313 let parameter_id = Pubkey::new_unique();
1314 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1315 let parameter_meta = AccountMeta {
1316 pubkey: parameter_id,
1317 is_signer: false,
1318 is_writable: false,
1319 };
1320
1321 process_instruction(
1323 &loader_id,
1324 &[],
1325 Vec::new(),
1326 Vec::new(),
1327 Err(InstructionError::UnsupportedProgramId),
1328 );
1329
1330 process_instruction(
1332 &program_id,
1333 &[],
1334 vec![(program_id, program_account.clone())],
1335 Vec::new(),
1336 Ok(()),
1337 );
1338
1339 process_instruction(
1341 &program_id,
1342 &[],
1343 vec![
1344 (program_id, program_account.clone()),
1345 (parameter_id, parameter_account.clone()),
1346 ],
1347 vec![parameter_meta.clone()],
1348 Ok(()),
1349 );
1350
1351 process_instruction(
1353 &program_id,
1354 &[],
1355 vec![
1356 (program_id, program_account.clone()),
1357 (parameter_id, parameter_account.clone()),
1358 ],
1359 vec![parameter_meta.clone(), parameter_meta],
1360 Ok(()),
1361 );
1362
1363 process_instruction_with_setup(
1365 &program_id,
1366 &[],
1367 vec![(program_id, program_account)],
1368 Vec::new(),
1369 LoaderV3Features::all_enabled(),
1370 Err(InstructionError::ProgramFailedToComplete),
1371 |invoke_context| {
1372 invoke_context.compute_meter.mock_set_remaining(0);
1373 test_utils::load_all_invoked_programs(invoke_context);
1374 },
1375 );
1376
1377 process_instruction_with_setup(
1379 &program_id,
1380 &[],
1381 vec![(program_id, parameter_account.clone())],
1382 Vec::new(),
1383 LoaderV3Features::all_enabled(),
1384 Err(InstructionError::UnsupportedProgramId),
1385 |invoke_context| {
1386 test_utils::load_all_invoked_programs(invoke_context);
1387 },
1388 );
1389 process_instruction(
1390 &program_id,
1391 &[],
1392 vec![(program_id, parameter_account)],
1393 Vec::new(),
1394 Err(InstructionError::UnsupportedProgramId),
1395 );
1396 }
1397
1398 #[test]
1399 fn test_bpf_loader_serialize_unaligned() {
1400 let loader_id = bpf_loader_deprecated::id();
1401 let program_id = Pubkey::new_unique();
1402 let program_account =
1403 load_program_account_from_elf(&loader_id, "test_elfs/out/noop_unaligned.so");
1404 let parameter_id = Pubkey::new_unique();
1405 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1406 let parameter_meta = AccountMeta {
1407 pubkey: parameter_id,
1408 is_signer: false,
1409 is_writable: false,
1410 };
1411
1412 process_instruction(
1414 &program_id,
1415 &[],
1416 vec![
1417 (program_id, program_account.clone()),
1418 (parameter_id, parameter_account.clone()),
1419 ],
1420 vec![parameter_meta.clone()],
1421 Ok(()),
1422 );
1423
1424 process_instruction(
1426 &program_id,
1427 &[],
1428 vec![
1429 (program_id, program_account),
1430 (parameter_id, parameter_account),
1431 ],
1432 vec![parameter_meta.clone(), parameter_meta],
1433 Ok(()),
1434 );
1435 }
1436
1437 #[test]
1438 fn test_bpf_loader_serialize_aligned() {
1439 let loader_id = bpf_loader::id();
1440 let program_id = Pubkey::new_unique();
1441 let program_account =
1442 load_program_account_from_elf(&loader_id, "test_elfs/out/noop_aligned.so");
1443 let parameter_id = Pubkey::new_unique();
1444 let parameter_account = AccountSharedData::new(1, 0, &loader_id);
1445 let parameter_meta = AccountMeta {
1446 pubkey: parameter_id,
1447 is_signer: false,
1448 is_writable: false,
1449 };
1450
1451 process_instruction(
1453 &program_id,
1454 &[],
1455 vec![
1456 (program_id, program_account.clone()),
1457 (parameter_id, parameter_account.clone()),
1458 ],
1459 vec![parameter_meta.clone()],
1460 Ok(()),
1461 );
1462
1463 process_instruction(
1465 &program_id,
1466 &[],
1467 vec![
1468 (program_id, program_account),
1469 (parameter_id, parameter_account),
1470 ],
1471 vec![parameter_meta.clone(), parameter_meta],
1472 Ok(()),
1473 );
1474 }
1475
1476 #[test]
1477 fn test_bpf_loader_upgradeable_initialize_buffer() {
1478 let loader_id = bpf_loader_upgradeable::id();
1479 let buffer_address = Pubkey::new_unique();
1480 let buffer_account =
1481 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1482 let authority_address = Pubkey::new_unique();
1483 let authority_account =
1484 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1485 let instruction_data =
1486 bincode::serialize(&UpgradeableLoaderInstruction::InitializeBuffer).unwrap();
1487 let instruction_accounts = vec![
1488 AccountMeta {
1489 pubkey: buffer_address,
1490 is_signer: false,
1491 is_writable: true,
1492 },
1493 AccountMeta {
1494 pubkey: authority_address,
1495 is_signer: false,
1496 is_writable: false,
1497 },
1498 ];
1499
1500 let accounts = process_instruction(
1502 &loader_id,
1503 &instruction_data,
1504 vec![
1505 (buffer_address, buffer_account),
1506 (authority_address, authority_account),
1507 ],
1508 instruction_accounts.clone(),
1509 Ok(()),
1510 );
1511 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1512 assert_eq!(
1513 state,
1514 UpgradeableLoaderState::Buffer {
1515 authority_address: Some(authority_address)
1516 }
1517 );
1518
1519 let accounts = process_instruction(
1521 &loader_id,
1522 &instruction_data,
1523 vec![
1524 (buffer_address, accounts.first().unwrap().clone()),
1525 (authority_address, accounts.get(1).unwrap().clone()),
1526 ],
1527 instruction_accounts,
1528 Err(InstructionError::AccountAlreadyInitialized),
1529 );
1530 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1531 assert_eq!(
1532 state,
1533 UpgradeableLoaderState::Buffer {
1534 authority_address: Some(authority_address)
1535 }
1536 );
1537 }
1538
1539 #[test]
1540 fn test_bpf_loader_upgradeable_write() {
1541 let loader_id = bpf_loader_upgradeable::id();
1542 let buffer_address = Pubkey::new_unique();
1543 let mut buffer_account =
1544 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1545 let instruction_accounts = vec![
1546 AccountMeta {
1547 pubkey: buffer_address,
1548 is_signer: false,
1549 is_writable: true,
1550 },
1551 AccountMeta {
1552 pubkey: buffer_address,
1553 is_signer: true,
1554 is_writable: false,
1555 },
1556 ];
1557
1558 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1560 offset: 0,
1561 bytes: vec![42; 9],
1562 })
1563 .unwrap();
1564 process_instruction(
1565 &loader_id,
1566 &instruction,
1567 vec![(buffer_address, buffer_account.clone())],
1568 instruction_accounts.clone(),
1569 Err(InstructionError::InvalidAccountData),
1570 );
1571
1572 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1574 offset: 0,
1575 bytes: vec![42; 9],
1576 })
1577 .unwrap();
1578 buffer_account
1579 .set_state(&UpgradeableLoaderState::Buffer {
1580 authority_address: Some(buffer_address),
1581 })
1582 .unwrap();
1583 let accounts = process_instruction(
1584 &loader_id,
1585 &instruction,
1586 vec![(buffer_address, buffer_account.clone())],
1587 instruction_accounts.clone(),
1588 Ok(()),
1589 );
1590 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1591 assert_eq!(
1592 state,
1593 UpgradeableLoaderState::Buffer {
1594 authority_address: Some(buffer_address)
1595 }
1596 );
1597 assert_eq!(
1598 &accounts
1599 .first()
1600 .unwrap()
1601 .data()
1602 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1603 .unwrap(),
1604 &[42; 9]
1605 );
1606
1607 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1609 offset: 3,
1610 bytes: vec![42; 6],
1611 })
1612 .unwrap();
1613 let mut buffer_account =
1614 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(9), &loader_id);
1615 buffer_account
1616 .set_state(&UpgradeableLoaderState::Buffer {
1617 authority_address: Some(buffer_address),
1618 })
1619 .unwrap();
1620 let accounts = process_instruction(
1621 &loader_id,
1622 &instruction,
1623 vec![(buffer_address, buffer_account.clone())],
1624 instruction_accounts.clone(),
1625 Ok(()),
1626 );
1627 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1628 assert_eq!(
1629 state,
1630 UpgradeableLoaderState::Buffer {
1631 authority_address: Some(buffer_address)
1632 }
1633 );
1634 assert_eq!(
1635 &accounts
1636 .first()
1637 .unwrap()
1638 .data()
1639 .get(UpgradeableLoaderState::size_of_buffer_metadata()..)
1640 .unwrap(),
1641 &[0, 0, 0, 42, 42, 42, 42, 42, 42]
1642 );
1643
1644 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1646 offset: 0,
1647 bytes: vec![42; 10],
1648 })
1649 .unwrap();
1650 buffer_account
1651 .set_state(&UpgradeableLoaderState::Buffer {
1652 authority_address: Some(buffer_address),
1653 })
1654 .unwrap();
1655 process_instruction(
1656 &loader_id,
1657 &instruction,
1658 vec![(buffer_address, buffer_account.clone())],
1659 instruction_accounts.clone(),
1660 Err(InstructionError::AccountDataTooSmall),
1661 );
1662
1663 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1665 offset: 1,
1666 bytes: vec![42; 9],
1667 })
1668 .unwrap();
1669 buffer_account
1670 .set_state(&UpgradeableLoaderState::Buffer {
1671 authority_address: Some(buffer_address),
1672 })
1673 .unwrap();
1674 process_instruction(
1675 &loader_id,
1676 &instruction,
1677 vec![(buffer_address, buffer_account.clone())],
1678 instruction_accounts.clone(),
1679 Err(InstructionError::AccountDataTooSmall),
1680 );
1681
1682 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1684 offset: 0,
1685 bytes: vec![42; 9],
1686 })
1687 .unwrap();
1688 buffer_account
1689 .set_state(&UpgradeableLoaderState::Buffer {
1690 authority_address: Some(buffer_address),
1691 })
1692 .unwrap();
1693 process_instruction(
1694 &loader_id,
1695 &instruction,
1696 vec![(buffer_address, buffer_account.clone())],
1697 vec![
1698 AccountMeta {
1699 pubkey: buffer_address,
1700 is_signer: false,
1701 is_writable: false,
1702 },
1703 AccountMeta {
1704 pubkey: buffer_address,
1705 is_signer: false,
1706 is_writable: false,
1707 },
1708 ],
1709 Err(InstructionError::MissingRequiredSignature),
1710 );
1711
1712 let authority_address = Pubkey::new_unique();
1714 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1715 offset: 1,
1716 bytes: vec![42; 9],
1717 })
1718 .unwrap();
1719 buffer_account
1720 .set_state(&UpgradeableLoaderState::Buffer {
1721 authority_address: Some(buffer_address),
1722 })
1723 .unwrap();
1724 process_instruction(
1725 &loader_id,
1726 &instruction,
1727 vec![
1728 (buffer_address, buffer_account.clone()),
1729 (authority_address, buffer_account.clone()),
1730 ],
1731 vec![
1732 AccountMeta {
1733 pubkey: buffer_address,
1734 is_signer: false,
1735 is_writable: false,
1736 },
1737 AccountMeta {
1738 pubkey: authority_address,
1739 is_signer: false,
1740 is_writable: false,
1741 },
1742 ],
1743 Err(InstructionError::IncorrectAuthority),
1744 );
1745
1746 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Write {
1748 offset: 1,
1749 bytes: vec![42; 9],
1750 })
1751 .unwrap();
1752 buffer_account
1753 .set_state(&UpgradeableLoaderState::Buffer {
1754 authority_address: None,
1755 })
1756 .unwrap();
1757 process_instruction(
1758 &loader_id,
1759 &instruction,
1760 vec![(buffer_address, buffer_account.clone())],
1761 instruction_accounts,
1762 Err(InstructionError::Immutable),
1763 );
1764 }
1765
1766 fn truncate_data(account: &mut AccountSharedData, len: usize) {
1767 let mut data = account.data().to_vec();
1768 data.truncate(len);
1769 account.set_data_from_slice(&data);
1770 }
1771
1772 #[test_case(true; "simd_0433_enabled")]
1773 #[test_case(false; "simd_0433_disabled")]
1774 fn test_bpf_loader_upgradeable_upgrade(set_programdata_to_elf_length: bool) {
1775 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
1776 let mut elf_orig = Vec::new();
1777 file.read_to_end(&mut elf_orig).unwrap();
1778 let mut file = File::open("test_elfs/out/sbpfv3_return_err.so").expect("file open failed");
1779 let mut elf_new = Vec::new();
1780 file.read_to_end(&mut elf_new).unwrap();
1781 assert_ne!(elf_orig.len(), elf_new.len());
1782 const SLOT: u64 = 42;
1783 let buffer_address = Pubkey::new_unique();
1784 let upgrade_authority_address = Pubkey::new_unique();
1785
1786 fn get_accounts(
1787 buffer_address: &Pubkey,
1788 buffer_authority: &Pubkey,
1789 upgrade_authority_address: &Pubkey,
1790 elf_orig: &[u8],
1791 elf_new: &[u8],
1792 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
1793 let loader_id = bpf_loader_upgradeable::id();
1794 let program_address = Pubkey::new_unique();
1795 let spill_address = Pubkey::new_unique();
1796 let rent = Rent::default();
1797 let min_program_balance =
1798 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_program()));
1799 let min_programdata_balance = 1.max(rent.minimum_balance(
1800 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1801 ));
1802 let (programdata_address, _) =
1803 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
1804 let mut buffer_account = AccountSharedData::new(
1805 1,
1806 UpgradeableLoaderState::size_of_buffer(elf_new.len()),
1807 &bpf_loader_upgradeable::id(),
1808 );
1809 buffer_account
1810 .set_state(&UpgradeableLoaderState::Buffer {
1811 authority_address: Some(*buffer_authority),
1812 })
1813 .unwrap();
1814 buffer_account
1815 .data_as_mut_slice()
1816 .get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
1817 .unwrap()
1818 .copy_from_slice(elf_new);
1819 let mut programdata_account = AccountSharedData::new(
1820 min_programdata_balance,
1821 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len())),
1822 &bpf_loader_upgradeable::id(),
1823 );
1824 programdata_account
1825 .set_state(&UpgradeableLoaderState::ProgramData {
1826 slot: SLOT,
1827 upgrade_authority_address: Some(*upgrade_authority_address),
1828 })
1829 .unwrap();
1830 let mut program_account = AccountSharedData::new(
1831 min_program_balance,
1832 UpgradeableLoaderState::size_of_program(),
1833 &bpf_loader_upgradeable::id(),
1834 );
1835 program_account.set_executable(true);
1836 program_account
1837 .set_state(&UpgradeableLoaderState::Program {
1838 programdata_address,
1839 })
1840 .unwrap();
1841 let spill_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
1842 let rent_account = create_sysvar_account(&rent);
1843 let clock_account = create_sysvar_account(&Clock {
1844 slot: SLOT.saturating_add(1),
1845 ..Clock::default()
1846 });
1847 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
1848 let transaction_accounts = vec![
1849 (programdata_address, programdata_account),
1850 (program_address, program_account),
1851 (*buffer_address, buffer_account),
1852 (spill_address, spill_account),
1853 (sysvar::rent::id(), rent_account),
1854 (sysvar::clock::id(), clock_account),
1855 (*upgrade_authority_address, upgrade_authority_account),
1856 ];
1857 let instruction_accounts = vec![
1858 AccountMeta {
1859 pubkey: programdata_address,
1860 is_signer: false,
1861 is_writable: true,
1862 },
1863 AccountMeta {
1864 pubkey: program_address,
1865 is_signer: false,
1866 is_writable: true,
1867 },
1868 AccountMeta {
1869 pubkey: *buffer_address,
1870 is_signer: false,
1871 is_writable: true,
1872 },
1873 AccountMeta {
1874 pubkey: spill_address,
1875 is_signer: false,
1876 is_writable: true,
1877 },
1878 AccountMeta {
1879 pubkey: sysvar::rent::id(),
1880 is_signer: false,
1881 is_writable: false,
1882 },
1883 AccountMeta {
1884 pubkey: sysvar::clock::id(),
1885 is_signer: false,
1886 is_writable: false,
1887 },
1888 AccountMeta {
1889 pubkey: *upgrade_authority_address,
1890 is_signer: true,
1891 is_writable: false,
1892 },
1893 ];
1894 (transaction_accounts, instruction_accounts)
1895 }
1896
1897 let process_instruction =
1898 |transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
1899 instruction_accounts: Vec<AccountMeta>,
1900 expected_result: Result<(), InstructionError>| {
1901 let instruction_data =
1902 bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
1903 process_instruction_with_setup(
1904 &bpf_loader_upgradeable::id(),
1905 &instruction_data,
1906 transaction_accounts,
1907 instruction_accounts,
1908 LoaderV3Features {
1909 set_programdata_to_elf_length,
1910 },
1911 expected_result,
1912 |_invoke_context| {},
1913 )
1914 };
1915
1916 let (transaction_accounts, instruction_accounts) = get_accounts(
1918 &buffer_address,
1919 &upgrade_authority_address,
1920 &upgrade_authority_address,
1921 &elf_orig,
1922 &elf_new,
1923 );
1924 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
1925 let starting_programdata_len =
1926 UpgradeableLoaderState::size_of_programdata(elf_orig.len().max(elf_new.len()));
1927 let starting_programdata_balance =
1928 Rent::default().minimum_balance(starting_programdata_len);
1929 let expected_programdata_len = if set_programdata_to_elf_length {
1930 UpgradeableLoaderState::size_of_programdata(elf_new.len())
1931 } else {
1932 starting_programdata_len
1933 };
1934 let expected_programdata_balance =
1935 Rent::default().minimum_balance(expected_programdata_len);
1936 assert_eq!(
1937 expected_programdata_len,
1938 accounts.first().unwrap().data().len()
1939 );
1940 assert_eq!(
1941 expected_programdata_balance,
1942 accounts.first().unwrap().lamports()
1943 );
1944 assert_eq!(0, accounts.get(2).unwrap().lamports());
1945 assert_eq!(
1947 starting_programdata_balance
1948 .saturating_sub(expected_programdata_balance)
1949 .saturating_add(1),
1950 accounts.get(3).unwrap().lamports()
1951 );
1952 assert_eq!(
1953 UpgradeableLoaderState::size_of_buffer(0),
1954 accounts.get(2).unwrap().data().len()
1955 );
1956 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
1957 assert_eq!(
1958 state,
1959 UpgradeableLoaderState::ProgramData {
1960 slot: SLOT.saturating_add(1),
1961 upgrade_authority_address: Some(upgrade_authority_address)
1962 }
1963 );
1964 for (i, byte) in accounts
1965 .first()
1966 .unwrap()
1967 .data()
1968 .get(
1969 UpgradeableLoaderState::size_of_programdata_metadata()
1970 ..UpgradeableLoaderState::size_of_programdata(elf_new.len()),
1971 )
1972 .unwrap()
1973 .iter()
1974 .enumerate()
1975 {
1976 assert_eq!(*elf_new.get(i).unwrap(), *byte);
1977 }
1978
1979 let (mut transaction_accounts, instruction_accounts) = get_accounts(
1981 &buffer_address,
1982 &upgrade_authority_address,
1983 &upgrade_authority_address,
1984 &elf_orig,
1985 &elf_new,
1986 );
1987 transaction_accounts
1988 .get_mut(0)
1989 .unwrap()
1990 .1
1991 .set_state(&UpgradeableLoaderState::ProgramData {
1992 slot: SLOT,
1993 upgrade_authority_address: None,
1994 })
1995 .unwrap();
1996 process_instruction(
1997 transaction_accounts,
1998 instruction_accounts,
1999 Err(InstructionError::Immutable),
2000 );
2001
2002 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2004 &buffer_address,
2005 &upgrade_authority_address,
2006 &upgrade_authority_address,
2007 &elf_orig,
2008 &elf_new,
2009 );
2010 let invalid_upgrade_authority_address = Pubkey::new_unique();
2011 transaction_accounts.get_mut(6).unwrap().0 = invalid_upgrade_authority_address;
2012 instruction_accounts.get_mut(6).unwrap().pubkey = invalid_upgrade_authority_address;
2013 process_instruction(
2014 transaction_accounts,
2015 instruction_accounts,
2016 Err(InstructionError::IncorrectAuthority),
2017 );
2018
2019 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2021 &buffer_address,
2022 &upgrade_authority_address,
2023 &upgrade_authority_address,
2024 &elf_orig,
2025 &elf_new,
2026 );
2027 instruction_accounts.get_mut(6).unwrap().is_signer = false;
2028 process_instruction(
2029 transaction_accounts,
2030 instruction_accounts,
2031 Err(InstructionError::MissingRequiredSignature),
2032 );
2033
2034 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2036 &buffer_address,
2037 &upgrade_authority_address,
2038 &upgrade_authority_address,
2039 &elf_orig,
2040 &elf_new,
2041 );
2042 *instruction_accounts.get_mut(3).unwrap() = instruction_accounts.get(2).unwrap().clone();
2043 process_instruction(
2044 transaction_accounts,
2045 instruction_accounts,
2046 Err(InstructionError::AccountBorrowFailed),
2047 );
2048
2049 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2051 &buffer_address,
2052 &upgrade_authority_address,
2053 &upgrade_authority_address,
2054 &elf_orig,
2055 &elf_new,
2056 );
2057 *instruction_accounts.get_mut(3).unwrap() = instruction_accounts.first().unwrap().clone();
2058 process_instruction(
2059 transaction_accounts,
2060 instruction_accounts,
2061 Err(InstructionError::AccountBorrowFailed),
2062 );
2063
2064 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2066 &buffer_address,
2067 &upgrade_authority_address,
2068 &upgrade_authority_address,
2069 &elf_orig,
2070 &elf_new,
2071 );
2072 *instruction_accounts.get_mut(1).unwrap() = instruction_accounts.get(2).unwrap().clone();
2073 let instruction_data = bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
2074
2075 process_instruction_with_setup(
2076 &bpf_loader_upgradeable::id(),
2077 &instruction_data,
2078 transaction_accounts.clone(),
2079 instruction_accounts.clone(),
2080 LoaderV3Features {
2081 set_programdata_to_elf_length,
2082 },
2083 Err(InstructionError::InvalidAccountData),
2084 |invoke_context| {
2085 test_utils::load_all_invoked_programs(invoke_context);
2086 },
2087 );
2088 process_instruction(
2089 transaction_accounts.clone(),
2090 instruction_accounts.clone(),
2091 Err(InstructionError::InvalidAccountData),
2092 );
2093
2094 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2096 &buffer_address,
2097 &upgrade_authority_address,
2098 &upgrade_authority_address,
2099 &elf_orig,
2100 &elf_new,
2101 );
2102 transaction_accounts
2103 .get_mut(1)
2104 .unwrap()
2105 .1
2106 .set_owner(Pubkey::new_unique());
2107 process_instruction(
2108 transaction_accounts,
2109 instruction_accounts,
2110 Err(InstructionError::IncorrectProgramId),
2111 );
2112
2113 let (transaction_accounts, mut instruction_accounts) = get_accounts(
2115 &buffer_address,
2116 &upgrade_authority_address,
2117 &upgrade_authority_address,
2118 &elf_orig,
2119 &elf_new,
2120 );
2121 instruction_accounts.get_mut(1).unwrap().is_writable = false;
2122 process_instruction(
2123 transaction_accounts,
2124 instruction_accounts,
2125 Err(InstructionError::InvalidArgument),
2126 );
2127
2128 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2130 &buffer_address,
2131 &upgrade_authority_address,
2132 &upgrade_authority_address,
2133 &elf_orig,
2134 &elf_new,
2135 );
2136 transaction_accounts
2137 .get_mut(1)
2138 .unwrap()
2139 .1
2140 .set_state(&UpgradeableLoaderState::Uninitialized)
2141 .unwrap();
2142 process_instruction(
2143 transaction_accounts,
2144 instruction_accounts,
2145 Err(InstructionError::InvalidAccountData),
2146 );
2147
2148 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2150 &buffer_address,
2151 &upgrade_authority_address,
2152 &upgrade_authority_address,
2153 &elf_orig,
2154 &elf_new,
2155 );
2156 let invalid_programdata_address = Pubkey::new_unique();
2157 transaction_accounts.get_mut(0).unwrap().0 = invalid_programdata_address;
2158 instruction_accounts.get_mut(0).unwrap().pubkey = invalid_programdata_address;
2159 process_instruction(
2160 transaction_accounts,
2161 instruction_accounts,
2162 Err(InstructionError::InvalidArgument),
2163 );
2164
2165 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2167 &buffer_address,
2168 &upgrade_authority_address,
2169 &upgrade_authority_address,
2170 &elf_orig,
2171 &elf_new,
2172 );
2173 transaction_accounts
2174 .get_mut(2)
2175 .unwrap()
2176 .1
2177 .set_state(&UpgradeableLoaderState::Uninitialized)
2178 .unwrap();
2179 process_instruction(
2180 transaction_accounts,
2181 instruction_accounts,
2182 Err(InstructionError::InvalidArgument),
2183 );
2184
2185 for buffer_balance in [0, 1_000_000, 15 * 1_000_000_000] {
2187 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
2188 &buffer_address,
2189 &upgrade_authority_address,
2190 &upgrade_authority_address,
2191 &elf_orig,
2192 &elf_new,
2193 );
2194 transaction_accounts
2195 .get_mut(2)
2196 .unwrap()
2197 .1
2198 .set_lamports(buffer_balance);
2199 instruction_accounts.get_mut(2).unwrap().is_writable = false;
2200 process_instruction(
2201 transaction_accounts,
2202 instruction_accounts,
2203 Err(InstructionError::InvalidArgument),
2204 );
2205 }
2206
2207 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2213 &buffer_address,
2214 &upgrade_authority_address,
2215 &upgrade_authority_address,
2216 &elf_orig,
2217 &elf_new,
2218 );
2219 {
2220 let required_rent = |elf_len| {
2222 Rent::default()
2223 .minimum_balance(UpgradeableLoaderState::size_of_programdata(elf_len))
2224 };
2225 let rent_orig = required_rent(elf_orig.len());
2226 let rent_new = required_rent(elf_new.len());
2227 let programdata = &mut transaction_accounts.first_mut().unwrap().1;
2228 programdata.set_lamports(rent_orig);
2229 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2230 buffer.set_owner(Pubkey::new_unique());
2231 buffer.set_lamports(rent_new);
2232 }
2233 process_instruction(
2234 transaction_accounts,
2235 instruction_accounts,
2236 Err(InstructionError::IncorrectProgramId),
2237 );
2238
2239 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2244 &buffer_address,
2245 &upgrade_authority_address,
2246 &upgrade_authority_address,
2247 &elf_orig,
2248 &elf_new,
2249 );
2250 {
2251 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2253 buffer.set_owner(Pubkey::new_unique());
2254 buffer.set_lamports(0);
2255 }
2256 process_instruction(
2257 transaction_accounts,
2258 instruction_accounts,
2259 Err(InstructionError::IncorrectProgramId),
2260 );
2261
2262 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2268 &buffer_address,
2269 &upgrade_authority_address,
2270 &upgrade_authority_address,
2271 &elf_orig,
2272 &elf_new,
2273 );
2274 {
2275 let buffer = &mut transaction_accounts.get_mut(2).unwrap().1;
2277 buffer.set_owner(Pubkey::new_unique());
2278 buffer.set_lamports(0);
2279 truncate_data(buffer, UpgradeableLoaderState::size_of_buffer(0));
2280 }
2281 process_instruction(
2282 transaction_accounts,
2283 instruction_accounts,
2284 Err(InstructionError::IncorrectProgramId),
2285 );
2286
2287 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2289 &buffer_address,
2290 &upgrade_authority_address,
2291 &upgrade_authority_address,
2292 &elf_orig,
2293 &elf_new,
2294 );
2295 transaction_accounts.get_mut(2).unwrap().1 = AccountSharedData::new(
2296 1,
2297 UpgradeableLoaderState::size_of_buffer(
2298 elf_orig.len().max(elf_new.len()).saturating_add(1),
2299 ),
2300 &bpf_loader_upgradeable::id(),
2301 );
2302 transaction_accounts
2303 .get_mut(2)
2304 .unwrap()
2305 .1
2306 .set_state(&UpgradeableLoaderState::Buffer {
2307 authority_address: Some(upgrade_authority_address),
2308 })
2309 .unwrap();
2310 process_instruction(
2311 transaction_accounts,
2312 instruction_accounts,
2313 if set_programdata_to_elf_length {
2314 Err(InstructionError::InsufficientFunds)
2315 } else {
2316 Err(InstructionError::AccountDataTooSmall)
2317 },
2318 );
2319
2320 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2322 &buffer_address,
2323 &upgrade_authority_address,
2324 &upgrade_authority_address,
2325 &elf_orig,
2326 &elf_new,
2327 );
2328 transaction_accounts
2329 .get_mut(2)
2330 .unwrap()
2331 .1
2332 .set_state(&UpgradeableLoaderState::Buffer {
2333 authority_address: Some(upgrade_authority_address),
2334 })
2335 .unwrap();
2336 truncate_data(&mut transaction_accounts.get_mut(2).unwrap().1, 5);
2337 process_instruction(
2338 transaction_accounts,
2339 instruction_accounts,
2340 Err(InstructionError::InvalidAccountData),
2341 );
2342
2343 let (transaction_accounts, instruction_accounts) = get_accounts(
2345 &buffer_address,
2346 &buffer_address,
2347 &upgrade_authority_address,
2348 &elf_orig,
2349 &elf_new,
2350 );
2351 process_instruction(
2352 transaction_accounts,
2353 instruction_accounts,
2354 Err(InstructionError::IncorrectAuthority),
2355 );
2356
2357 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2359 &buffer_address,
2360 &buffer_address,
2361 &upgrade_authority_address,
2362 &elf_orig,
2363 &elf_new,
2364 );
2365 transaction_accounts
2366 .get_mut(2)
2367 .unwrap()
2368 .1
2369 .set_state(&UpgradeableLoaderState::Buffer {
2370 authority_address: None,
2371 })
2372 .unwrap();
2373 process_instruction(
2374 transaction_accounts,
2375 instruction_accounts,
2376 Err(InstructionError::IncorrectAuthority),
2377 );
2378
2379 let (mut transaction_accounts, instruction_accounts) = get_accounts(
2381 &buffer_address,
2382 &buffer_address,
2383 &upgrade_authority_address,
2384 &elf_orig,
2385 &elf_new,
2386 );
2387 transaction_accounts
2388 .get_mut(0)
2389 .unwrap()
2390 .1
2391 .set_state(&UpgradeableLoaderState::ProgramData {
2392 slot: SLOT,
2393 upgrade_authority_address: None,
2394 })
2395 .unwrap();
2396 transaction_accounts
2397 .get_mut(2)
2398 .unwrap()
2399 .1
2400 .set_state(&UpgradeableLoaderState::Buffer {
2401 authority_address: None,
2402 })
2403 .unwrap();
2404 process_instruction(
2405 transaction_accounts,
2406 instruction_accounts,
2407 Err(InstructionError::IncorrectAuthority),
2408 );
2409
2410 let mut file =
2412 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
2413 let mut elf_new = Vec::new();
2414 file.read_to_end(&mut elf_new).unwrap();
2415 let (transaction_accounts, instruction_accounts) = get_accounts(
2416 &buffer_address,
2417 &upgrade_authority_address,
2418 &upgrade_authority_address,
2419 &elf_orig,
2420 &elf_new,
2421 );
2422 process_instruction(
2423 transaction_accounts,
2424 instruction_accounts,
2425 Err(InstructionError::InvalidAccountData),
2426 );
2427 }
2428
2429 #[test]
2430 fn test_bpf_loader_upgradeable_upgrade_simd_0433() {
2431 let mut file = File::open("test_elfs/out/sbpfv3_return_err.so").expect("file open failed");
2432 let mut elf_small = Vec::new();
2433 file.read_to_end(&mut elf_small).unwrap();
2434 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
2435 let mut elf_large = Vec::new();
2436 file.read_to_end(&mut elf_large).unwrap();
2437 assert!(elf_small.len() < elf_large.len());
2438 const SLOT: u64 = 42;
2439 let upgrade_authority_address = Pubkey::new_unique();
2440
2441 fn get_accounts(
2442 upgrade_authority_address: &Pubkey,
2443 elf_orig: &[u8],
2444 elf_new: &[u8],
2445 programdata_len: usize,
2446 programdata_lamports: u64,
2447 buffer_len: usize,
2448 buffer_lamports: u64,
2449 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
2450 assert!(programdata_len >= UpgradeableLoaderState::size_of_programdata(elf_orig.len()));
2451 assert!(buffer_len >= UpgradeableLoaderState::size_of_buffer(elf_new.len()));
2452 let loader_id = bpf_loader_upgradeable::id();
2453 let program_address = Pubkey::new_unique();
2454 let buffer_address = Pubkey::new_unique();
2455 let spill_address = Pubkey::new_unique();
2456 let rent = Rent::default();
2457 let (programdata_address, _) =
2458 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
2459
2460 let mut buffer_account =
2461 AccountSharedData::new(buffer_lamports, buffer_len, &loader_id);
2462 buffer_account
2463 .set_state(&UpgradeableLoaderState::Buffer {
2464 authority_address: Some(*upgrade_authority_address),
2465 })
2466 .unwrap();
2467 let buffer_data_offset = UpgradeableLoaderState::size_of_buffer_metadata();
2468 buffer_account
2469 .data_as_mut_slice()
2470 .get_mut(buffer_data_offset..buffer_data_offset.saturating_add(elf_new.len()))
2471 .unwrap()
2472 .copy_from_slice(elf_new);
2473
2474 let mut programdata_account =
2475 AccountSharedData::new(programdata_lamports, programdata_len, &loader_id);
2476 programdata_account
2477 .set_state(&UpgradeableLoaderState::ProgramData {
2478 slot: SLOT,
2479 upgrade_authority_address: Some(*upgrade_authority_address),
2480 })
2481 .unwrap();
2482 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
2483 programdata_account
2484 .data_as_mut_slice()
2485 .get_mut(
2486 programdata_data_offset..programdata_data_offset.saturating_add(elf_orig.len()),
2487 )
2488 .unwrap()
2489 .copy_from_slice(elf_orig);
2490
2491 let mut program_account = AccountSharedData::new(
2492 rent.minimum_balance(UpgradeableLoaderState::size_of_program()),
2493 UpgradeableLoaderState::size_of_program(),
2494 &loader_id,
2495 );
2496 program_account.set_executable(true);
2497 program_account
2498 .set_state(&UpgradeableLoaderState::Program {
2499 programdata_address,
2500 })
2501 .unwrap();
2502
2503 let spill_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
2504 let rent_account = create_sysvar_account(&rent);
2505 let clock_account = create_sysvar_account(&Clock {
2506 slot: SLOT.saturating_add(1),
2507 ..Clock::default()
2508 });
2509 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2510 let transaction_accounts = vec![
2511 (programdata_address, programdata_account),
2512 (program_address, program_account),
2513 (buffer_address, buffer_account),
2514 (spill_address, spill_account),
2515 (sysvar::rent::id(), rent_account),
2516 (sysvar::clock::id(), clock_account),
2517 (*upgrade_authority_address, upgrade_authority_account),
2518 ];
2519 let instruction_accounts = vec![
2520 AccountMeta {
2521 pubkey: programdata_address,
2522 is_signer: false,
2523 is_writable: true,
2524 },
2525 AccountMeta {
2526 pubkey: program_address,
2527 is_signer: false,
2528 is_writable: true,
2529 },
2530 AccountMeta {
2531 pubkey: buffer_address,
2532 is_signer: false,
2533 is_writable: true,
2534 },
2535 AccountMeta {
2536 pubkey: spill_address,
2537 is_signer: false,
2538 is_writable: true,
2539 },
2540 AccountMeta {
2541 pubkey: sysvar::rent::id(),
2542 is_signer: false,
2543 is_writable: false,
2544 },
2545 AccountMeta {
2546 pubkey: sysvar::clock::id(),
2547 is_signer: false,
2548 is_writable: false,
2549 },
2550 AccountMeta {
2551 pubkey: *upgrade_authority_address,
2552 is_signer: true,
2553 is_writable: false,
2554 },
2555 ];
2556 (transaction_accounts, instruction_accounts)
2557 }
2558
2559 let process_instruction =
2560 |transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
2561 instruction_accounts: Vec<AccountMeta>,
2562 expected_result: Result<(), InstructionError>| {
2563 let instruction_data =
2564 bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap();
2565 process_instruction_with_setup(
2566 &bpf_loader_upgradeable::id(),
2567 &instruction_data,
2568 transaction_accounts,
2569 instruction_accounts,
2570 LoaderV3Features {
2571 set_programdata_to_elf_length: true,
2572 },
2573 expected_result,
2574 |_invoke_context| {},
2575 )
2576 };
2577
2578 let rent = Rent::default();
2579 let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
2580 let small_len = UpgradeableLoaderState::size_of_programdata(elf_small.len());
2581 let large_len = UpgradeableLoaderState::size_of_programdata(elf_large.len());
2582 let small_balance = rent.minimum_balance(small_len);
2583 let large_balance = rent.minimum_balance(large_len);
2584
2585 let assert_upgraded =
2586 |accounts: &[AccountSharedData], elf_new: &[u8], expected_len: usize| {
2587 let programdata = accounts.first().unwrap();
2588 assert_eq!(expected_len, programdata.data().len());
2590 assert_eq!(rent.minimum_balance(expected_len), programdata.lamports());
2592 assert_eq!(
2594 elf_new,
2595 programdata
2596 .data()
2597 .get(
2598 programdata_data_offset
2599 ..programdata_data_offset.saturating_add(elf_new.len())
2600 )
2601 .unwrap()
2602 );
2603 let state: UpgradeableLoaderState = programdata.state().unwrap();
2605 assert_eq!(
2606 UpgradeableLoaderState::ProgramData {
2607 slot: SLOT.saturating_add(1),
2608 upgrade_authority_address: Some(upgrade_authority_address),
2609 },
2610 state
2611 );
2612 let buffer = accounts.get(2).unwrap();
2614 assert_eq!(0, buffer.lamports());
2615 assert_eq!(
2616 UpgradeableLoaderState::size_of_buffer(0),
2617 buffer.data().len()
2618 );
2619 };
2620
2621 let (transaction_accounts, instruction_accounts) = get_accounts(
2623 &upgrade_authority_address,
2624 &elf_large,
2625 &elf_small,
2626 large_len,
2627 large_balance,
2628 UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2629 1,
2630 );
2631 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2632 assert_upgraded(&accounts, &elf_small, small_len);
2633 assert_eq!(
2634 large_balance
2635 .saturating_sub(small_balance)
2636 .saturating_add(1),
2637 accounts.get(3).unwrap().lamports()
2638 );
2639
2640 let extended_len = large_len.saturating_add(4096);
2642 let extended_balance = rent.minimum_balance(extended_len);
2643 let (transaction_accounts, instruction_accounts) = get_accounts(
2644 &upgrade_authority_address,
2645 &elf_large,
2646 &elf_small,
2647 extended_len,
2648 extended_balance,
2649 UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2650 1,
2651 );
2652 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2653 assert_upgraded(&accounts, &elf_small, small_len);
2654 assert_eq!(
2655 extended_balance
2656 .saturating_sub(small_balance)
2657 .saturating_add(1),
2658 accounts.get(3).unwrap().lamports()
2659 );
2660
2661 let extended_len = large_len.saturating_add(4096);
2666 let extended_balance = rent.minimum_balance(extended_len);
2667 let (transaction_accounts, instruction_accounts) = get_accounts(
2668 &upgrade_authority_address,
2669 &elf_small,
2670 &elf_large,
2671 extended_len,
2672 extended_balance,
2673 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2674 1,
2675 );
2676 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2677 assert_upgraded(&accounts, &elf_large, large_len);
2678 assert!(small_len < large_len && large_len < extended_len);
2679 assert_eq!(
2680 extended_balance
2681 .saturating_sub(large_balance)
2682 .saturating_add(1),
2683 accounts.get(3).unwrap().lamports()
2684 );
2685
2686 let padded_buffer_len =
2688 UpgradeableLoaderState::size_of_buffer(elf_small.len()).saturating_add(32);
2689 let padded_len = small_len.saturating_add(32);
2690 let padded_balance = rent.minimum_balance(padded_len);
2691 assert!(padded_len < large_len);
2692 let (transaction_accounts, instruction_accounts) = get_accounts(
2693 &upgrade_authority_address,
2694 &elf_large,
2695 &elf_small,
2696 large_len,
2697 large_balance,
2698 padded_buffer_len,
2699 1,
2700 );
2701 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2702 assert_upgraded(&accounts, &elf_small, padded_len);
2703 assert!(
2705 accounts
2706 .first()
2707 .unwrap()
2708 .data()
2709 .get(programdata_data_offset.saturating_add(elf_small.len())..)
2710 .unwrap()
2711 .iter()
2712 .all(|byte| *byte == 0)
2713 );
2714 assert_eq!(
2715 large_balance
2716 .saturating_sub(padded_balance)
2717 .saturating_add(1),
2718 accounts.get(3).unwrap().lamports()
2719 );
2720
2721 let (transaction_accounts, instruction_accounts) = get_accounts(
2723 &upgrade_authority_address,
2724 &elf_large,
2725 &elf_small,
2726 large_len,
2727 small_balance, UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2729 0,
2730 );
2731 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2732 assert_upgraded(&accounts, &elf_small, small_len);
2733 assert_eq!(0, accounts.get(3).unwrap().lamports());
2734
2735 let (transaction_accounts, instruction_accounts) = get_accounts(
2738 &upgrade_authority_address,
2739 &elf_large,
2740 &elf_small,
2741 large_len,
2742 small_balance.saturating_sub(1),
2743 UpgradeableLoaderState::size_of_buffer(elf_small.len()),
2744 0,
2745 );
2746 process_instruction(
2747 transaction_accounts,
2748 instruction_accounts,
2749 Err(InstructionError::InsufficientFunds),
2750 );
2751
2752 let (transaction_accounts, instruction_accounts) = get_accounts(
2754 &upgrade_authority_address,
2755 &elf_small,
2756 &elf_large,
2757 small_len,
2758 small_balance,
2759 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2760 large_balance,
2761 );
2762 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2763 assert_upgraded(&accounts, &elf_large, large_len);
2764 assert_eq!(small_balance, accounts.get(3).unwrap().lamports());
2767
2768 let extended_len = small_len.saturating_add(50);
2770 let extended_balance = rent.minimum_balance(extended_len);
2771 assert!(extended_len < large_len);
2772 let (transaction_accounts, instruction_accounts) = get_accounts(
2773 &upgrade_authority_address,
2774 &elf_small,
2775 &elf_large,
2776 extended_len,
2777 extended_balance,
2778 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2779 large_balance,
2780 );
2781 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2782 assert_upgraded(&accounts, &elf_large, large_len);
2783 assert_eq!(extended_balance, accounts.get(3).unwrap().lamports());
2787
2788 let padded_buffer_len =
2790 UpgradeableLoaderState::size_of_buffer(elf_large.len()).saturating_add(64);
2791 let padded_len = large_len.saturating_add(64);
2792 let padded_balance = rent.minimum_balance(padded_len);
2793 let (transaction_accounts, instruction_accounts) = get_accounts(
2794 &upgrade_authority_address,
2795 &elf_small,
2796 &elf_large,
2797 small_len,
2798 padded_balance,
2799 padded_buffer_len,
2800 0,
2801 );
2802 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2803 assert_upgraded(&accounts, &elf_large, padded_len);
2804 assert!(
2805 accounts
2806 .first()
2807 .unwrap()
2808 .data()
2809 .get(programdata_data_offset.saturating_add(elf_large.len())..)
2810 .unwrap()
2811 .iter()
2812 .all(|byte| *byte == 0)
2813 );
2814 assert_eq!(0, accounts.get(3).unwrap().lamports());
2815
2816 let (transaction_accounts, instruction_accounts) = get_accounts(
2818 &upgrade_authority_address,
2819 &elf_small,
2820 &elf_large,
2821 small_len,
2822 large_balance,
2823 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2824 0,
2825 );
2826 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2827 assert_upgraded(&accounts, &elf_large, large_len);
2828 assert_eq!(0, accounts.get(3).unwrap().lamports());
2830
2831 let deficit = large_balance.saturating_sub(small_balance);
2833 let (transaction_accounts, instruction_accounts) = get_accounts(
2834 &upgrade_authority_address,
2835 &elf_small,
2836 &elf_large,
2837 small_len,
2838 small_balance,
2839 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2840 deficit.saturating_sub(1), );
2842 process_instruction(
2843 transaction_accounts,
2844 instruction_accounts,
2845 Err(InstructionError::InsufficientFunds),
2846 );
2847
2848 let (transaction_accounts, instruction_accounts) = get_accounts(
2850 &upgrade_authority_address,
2851 &elf_large,
2852 &elf_large,
2853 large_len,
2854 large_balance,
2855 UpgradeableLoaderState::size_of_buffer(elf_large.len()),
2856 1,
2857 );
2858 let accounts = process_instruction(transaction_accounts, instruction_accounts, Ok(()));
2859 assert_upgraded(&accounts, &elf_large, large_len);
2860 assert_eq!(1, accounts.get(3).unwrap().lamports());
2862
2863 let (transaction_accounts, instruction_accounts) = get_accounts(
2865 &upgrade_authority_address,
2866 &elf_large,
2867 &[],
2868 large_len,
2869 large_balance,
2870 UpgradeableLoaderState::size_of_buffer(0),
2871 1,
2872 );
2873 process_instruction(
2874 transaction_accounts,
2875 instruction_accounts,
2876 Err(InstructionError::InvalidAccountData),
2877 );
2878
2879 let oversized_elf_len = (MAX_PERMITTED_DATA_LENGTH as usize)
2881 .saturating_sub(UpgradeableLoaderState::size_of_buffer_metadata());
2882 let mut oversized_elf = elf_large.clone();
2883 oversized_elf.resize(oversized_elf_len, 0);
2884 assert!(
2885 UpgradeableLoaderState::size_of_programdata(oversized_elf.len())
2886 > MAX_PERMITTED_DATA_LENGTH as usize
2887 );
2888 let (transaction_accounts, instruction_accounts) = get_accounts(
2889 &upgrade_authority_address,
2890 &elf_small,
2891 &oversized_elf,
2892 small_len,
2893 u64::MAX / 2,
2894 UpgradeableLoaderState::size_of_buffer(oversized_elf.len()),
2895 0,
2896 );
2897 process_instruction(
2898 transaction_accounts,
2899 instruction_accounts,
2900 Err(InstructionError::InvalidAccountData),
2901 );
2902 }
2903
2904 #[test]
2905 fn test_bpf_loader_upgradeable_deploy_with_max_data_len() {
2906 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
2907 let mut elf = Vec::new();
2908 file.read_to_end(&mut elf).unwrap();
2909 const SLOT: u64 = 42;
2910 let payer_address = Pubkey::new_unique();
2911 let buffer_address = Pubkey::new_unique();
2912 let upgrade_authority_address = Pubkey::new_unique();
2913
2914 fn get_accounts(
2915 payer_address: &Pubkey,
2916 buffer_address: &Pubkey,
2917 buffer_authority: &Pubkey,
2918 upgrade_authority_address: &Pubkey,
2919 elf: &[u8],
2920 ) -> (Vec<(Pubkey, AccountSharedData)>, Vec<AccountMeta>) {
2921 let loader_id = bpf_loader_upgradeable::id();
2922 let program_address = Pubkey::new_unique();
2923 let rent = Rent::default();
2924 let min_program_balance =
2925 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_program()));
2926 let min_programdata_balance =
2927 1.max(rent.minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len())));
2928 let (programdata_address, _) =
2929 Pubkey::find_program_address(&[program_address.as_ref()], &loader_id);
2930 let mut buffer_account = AccountSharedData::new(
2931 1,
2932 UpgradeableLoaderState::size_of_buffer(elf.len()),
2933 &bpf_loader_upgradeable::id(),
2934 );
2935 buffer_account
2936 .set_state(&UpgradeableLoaderState::Buffer {
2937 authority_address: Some(*buffer_authority),
2938 })
2939 .unwrap();
2940 buffer_account
2941 .data_as_mut_slice()
2942 .get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
2943 .unwrap()
2944 .copy_from_slice(elf);
2945 let programdata_account = AccountSharedData::new(0, 0, &system_program::id());
2946 let mut program_account = AccountSharedData::new(
2947 min_program_balance,
2948 UpgradeableLoaderState::size_of_program(),
2949 &bpf_loader_upgradeable::id(),
2950 );
2951 program_account
2952 .set_state(&UpgradeableLoaderState::Uninitialized)
2953 .unwrap();
2954 let payer_account = AccountSharedData::new(
2955 min_programdata_balance.saturating_add(1),
2956 0,
2957 &system_program::id(),
2958 );
2959 let rent_account = create_sysvar_account(&rent);
2960 let clock_account = create_sysvar_account(&Clock {
2961 slot: SLOT,
2962 ..Clock::default()
2963 });
2964 let system_program_account = AccountSharedData::new(0, 0, &native_loader::id());
2965 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
2966 let transaction_accounts = vec![
2967 (*payer_address, payer_account),
2968 (programdata_address, programdata_account),
2969 (program_address, program_account),
2970 (*buffer_address, buffer_account),
2971 (sysvar::rent::id(), rent_account),
2972 (sysvar::clock::id(), clock_account),
2973 (system_program::id(), system_program_account),
2974 (*upgrade_authority_address, upgrade_authority_account),
2975 ];
2976 let instruction_accounts = vec![
2977 AccountMeta {
2978 pubkey: *payer_address,
2979 is_signer: true,
2980 is_writable: true,
2981 },
2982 AccountMeta {
2983 pubkey: programdata_address,
2984 is_signer: false,
2985 is_writable: true,
2986 },
2987 AccountMeta {
2988 pubkey: program_address,
2989 is_signer: false,
2990 is_writable: true,
2991 },
2992 AccountMeta {
2993 pubkey: *buffer_address,
2994 is_signer: false,
2995 is_writable: true,
2996 },
2997 AccountMeta {
2998 pubkey: sysvar::rent::id(),
2999 is_signer: false,
3000 is_writable: false,
3001 },
3002 AccountMeta {
3003 pubkey: sysvar::clock::id(),
3004 is_signer: false,
3005 is_writable: false,
3006 },
3007 AccountMeta {
3008 pubkey: system_program::id(),
3009 is_signer: false,
3010 is_writable: false,
3011 },
3012 AccountMeta {
3013 pubkey: *upgrade_authority_address,
3014 is_signer: true,
3015 is_writable: false,
3016 },
3017 ];
3018 (transaction_accounts, instruction_accounts)
3019 }
3020
3021 fn process_instruction(
3022 max_data_len: usize,
3023 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
3024 instruction_accounts: Vec<AccountMeta>,
3025 expected_result: Result<(), InstructionError>,
3026 ) -> Vec<AccountSharedData> {
3027 let instruction_data =
3028 bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
3029 max_data_len,
3030 })
3031 .unwrap();
3032 process_instruction_with_setup(
3033 &bpf_loader_upgradeable::id(),
3034 &instruction_data,
3035 transaction_accounts,
3036 instruction_accounts,
3037 LoaderV3Features::all_enabled(),
3038 expected_result,
3039 |invoke_context| {
3040 invoke_context.program_cache_for_tx_batch.replenish(
3042 system_program::id(),
3043 Arc::new(ProgramCacheEntry::new_builtin(
3044 solana_system_program::system_processor::Entrypoint::register,
3045 )),
3046 );
3047 },
3048 )
3049 }
3050
3051 let (transaction_accounts, instruction_accounts) = get_accounts(
3053 &payer_address,
3054 &buffer_address,
3055 &upgrade_authority_address,
3056 &upgrade_authority_address,
3057 &elf,
3058 );
3059 let programdata_address = instruction_accounts.get(1).unwrap().pubkey;
3060 let accounts = process_instruction(
3061 elf.len(),
3062 transaction_accounts,
3063 instruction_accounts,
3064 Ok(()),
3065 );
3066 let min_programdata_balance =
3067 Rent::default().minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len()));
3068 assert_eq!(min_programdata_balance, accounts.get(1).unwrap().lamports());
3069 assert_eq!(2, accounts.first().unwrap().lamports());
3070 assert_eq!(0, accounts.get(3).unwrap().lamports());
3071 assert_eq!(
3072 UpgradeableLoaderState::size_of_buffer(0),
3073 accounts.get(3).unwrap().data().len()
3074 );
3075 let state: UpgradeableLoaderState = accounts.get(1).unwrap().state().unwrap();
3076 assert_eq!(
3077 state,
3078 UpgradeableLoaderState::ProgramData {
3079 slot: SLOT,
3080 upgrade_authority_address: Some(upgrade_authority_address),
3081 }
3082 );
3083 for (i, byte) in accounts
3084 .get(1)
3085 .unwrap()
3086 .data()
3087 .get(
3088 UpgradeableLoaderState::size_of_programdata_metadata()
3089 ..UpgradeableLoaderState::size_of_programdata(elf.len()),
3090 )
3091 .unwrap()
3092 .iter()
3093 .enumerate()
3094 {
3095 assert_eq!(*elf.get(i).unwrap(), *byte);
3096 }
3097 let state: UpgradeableLoaderState = accounts.get(2).unwrap().state().unwrap();
3098 assert_eq!(
3099 state,
3100 UpgradeableLoaderState::Program {
3101 programdata_address,
3102 }
3103 );
3104 assert!(accounts.get(2).unwrap().executable());
3105
3106 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
3108 &payer_address,
3109 &buffer_address,
3110 &upgrade_authority_address,
3111 &upgrade_authority_address,
3112 &elf,
3113 );
3114 let invalid_upgrade_authority_address = Pubkey::new_unique();
3115 transaction_accounts.get_mut(7).unwrap().0 = invalid_upgrade_authority_address;
3116 instruction_accounts.get_mut(7).unwrap().pubkey = invalid_upgrade_authority_address;
3117 process_instruction(
3118 elf.len(),
3119 transaction_accounts,
3120 instruction_accounts,
3121 Err(InstructionError::IncorrectAuthority),
3122 );
3123
3124 let (transaction_accounts, mut instruction_accounts) = get_accounts(
3126 &payer_address,
3127 &buffer_address,
3128 &upgrade_authority_address,
3129 &upgrade_authority_address,
3130 &elf,
3131 );
3132 instruction_accounts.get_mut(7).unwrap().is_signer = false;
3133 process_instruction(
3134 elf.len(),
3135 transaction_accounts,
3136 instruction_accounts,
3137 Err(InstructionError::MissingRequiredSignature),
3138 );
3139
3140 let (transaction_accounts, mut instruction_accounts) = get_accounts(
3142 &payer_address,
3143 &buffer_address,
3144 &upgrade_authority_address,
3145 &upgrade_authority_address,
3146 &elf,
3147 );
3148 *instruction_accounts.get_mut(0).unwrap() = instruction_accounts.get(3).unwrap().clone();
3149 process_instruction(
3150 elf.len(),
3151 transaction_accounts,
3152 instruction_accounts,
3153 Err(InstructionError::AccountBorrowFailed),
3154 );
3155
3156 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3165 &payer_address,
3166 &buffer_address,
3167 &upgrade_authority_address,
3168 &upgrade_authority_address,
3169 &elf,
3170 );
3171 transaction_accounts
3172 .get_mut(2)
3173 .unwrap()
3174 .1
3175 .set_owner(Pubkey::new_unique());
3176 process_instruction(
3177 elf.len(),
3178 transaction_accounts,
3179 instruction_accounts,
3180 Err(InstructionError::ExternalAccountDataModified),
3181 );
3182
3183 let (transaction_accounts, mut instruction_accounts) = get_accounts(
3190 &payer_address,
3191 &buffer_address,
3192 &upgrade_authority_address,
3193 &upgrade_authority_address,
3194 &elf,
3195 );
3196 instruction_accounts.get_mut(2).unwrap().is_writable = false;
3197 process_instruction(
3198 elf.len(),
3199 transaction_accounts,
3200 instruction_accounts,
3201 Err(InstructionError::ReadonlyDataModified),
3202 );
3203
3204 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3206 &payer_address,
3207 &buffer_address,
3208 &upgrade_authority_address,
3209 &upgrade_authority_address,
3210 &elf,
3211 );
3212 transaction_accounts
3213 .get_mut(2)
3214 .unwrap()
3215 .1
3216 .set_state(&UpgradeableLoaderState::Program {
3217 programdata_address: Pubkey::new_unique(),
3218 })
3219 .unwrap();
3220 process_instruction(
3221 elf.len(),
3222 transaction_accounts,
3223 instruction_accounts,
3224 Err(InstructionError::AccountAlreadyInitialized),
3225 );
3226
3227 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3229 &payer_address,
3230 &buffer_address,
3231 &upgrade_authority_address,
3232 &upgrade_authority_address,
3233 &elf,
3234 );
3235 truncate_data(&mut transaction_accounts.get_mut(2).unwrap().1, 5);
3236 process_instruction(
3237 elf.len(),
3238 transaction_accounts,
3239 instruction_accounts,
3240 Err(InstructionError::AccountDataTooSmall),
3241 );
3242
3243 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3245 &payer_address,
3246 &buffer_address,
3247 &upgrade_authority_address,
3248 &upgrade_authority_address,
3249 &elf,
3250 );
3251 transaction_accounts.get_mut(2).unwrap().1.set_lamports(1);
3252 process_instruction(
3253 elf.len(),
3254 transaction_accounts,
3255 instruction_accounts,
3256 Err(InstructionError::ExecutableAccountNotRentExempt),
3257 );
3258
3259 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
3261 &payer_address,
3262 &buffer_address,
3263 &upgrade_authority_address,
3264 &upgrade_authority_address,
3265 &elf,
3266 );
3267 let invalid_programdata_address = Pubkey::new_unique();
3268 transaction_accounts.get_mut(1).unwrap().0 = invalid_programdata_address;
3269 instruction_accounts.get_mut(1).unwrap().pubkey = invalid_programdata_address;
3270 process_instruction(
3271 elf.len(),
3272 transaction_accounts,
3273 instruction_accounts,
3274 Err(InstructionError::InvalidArgument),
3275 );
3276
3277 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3279 &payer_address,
3280 &buffer_address,
3281 &upgrade_authority_address,
3282 &upgrade_authority_address,
3283 &elf,
3284 );
3285 transaction_accounts
3286 .get_mut(3)
3287 .unwrap()
3288 .1
3289 .set_state(&UpgradeableLoaderState::Uninitialized)
3290 .unwrap();
3291 process_instruction(
3292 elf.len(),
3293 transaction_accounts,
3294 instruction_accounts,
3295 Err(InstructionError::InvalidArgument),
3296 );
3297
3298 for buffer_balance in [0, 1_000_000, 15 * 1_000_000_000] {
3300 let (mut transaction_accounts, mut instruction_accounts) = get_accounts(
3301 &payer_address,
3302 &buffer_address,
3303 &upgrade_authority_address,
3304 &upgrade_authority_address,
3305 &elf,
3306 );
3307 transaction_accounts
3308 .get_mut(3)
3309 .unwrap()
3310 .1
3311 .set_lamports(buffer_balance);
3312 instruction_accounts.get_mut(3).unwrap().is_writable = false;
3313 process_instruction(
3314 elf.len(),
3315 transaction_accounts,
3316 instruction_accounts,
3317 Err(InstructionError::InvalidArgument),
3318 );
3319 }
3320
3321 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3327 &payer_address,
3328 &buffer_address,
3329 &upgrade_authority_address,
3330 &upgrade_authority_address,
3331 &elf,
3332 );
3333 {
3334 let required_rent = Rent::default()
3336 .minimum_balance(UpgradeableLoaderState::size_of_programdata(elf.len()));
3337 let programdata = &transaction_accounts.get(1).unwrap().1;
3338 assert!(programdata.lamports() < required_rent);
3339 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
3340 buffer.set_owner(Pubkey::new_unique());
3341 buffer.set_lamports(required_rent);
3342 }
3343 process_instruction(
3344 elf.len(),
3345 transaction_accounts,
3346 instruction_accounts,
3347 Err(InstructionError::IncorrectProgramId),
3348 );
3349
3350 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3355 &payer_address,
3356 &buffer_address,
3357 &upgrade_authority_address,
3358 &upgrade_authority_address,
3359 &elf,
3360 );
3361 {
3362 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
3364 buffer.set_owner(Pubkey::new_unique());
3365 buffer.set_lamports(0);
3366 }
3367 process_instruction(
3368 elf.len(),
3369 transaction_accounts,
3370 instruction_accounts,
3371 Err(InstructionError::IncorrectProgramId),
3372 );
3373
3374 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3380 &payer_address,
3381 &buffer_address,
3382 &upgrade_authority_address,
3383 &upgrade_authority_address,
3384 &elf,
3385 );
3386 {
3387 let buffer = &mut transaction_accounts.get_mut(3).unwrap().1;
3389 buffer.set_owner(Pubkey::new_unique());
3390 buffer.set_lamports(0);
3391 truncate_data(buffer, UpgradeableLoaderState::size_of_buffer(0));
3392 }
3393 process_instruction(
3394 elf.len(),
3395 transaction_accounts,
3396 instruction_accounts,
3397 Err(InstructionError::IncorrectProgramId),
3398 );
3399
3400 let (transaction_accounts, instruction_accounts) = get_accounts(
3402 &payer_address,
3403 &buffer_address,
3404 &upgrade_authority_address,
3405 &upgrade_authority_address,
3406 &elf,
3407 );
3408 process_instruction(
3409 elf.len().saturating_sub(1),
3410 transaction_accounts,
3411 instruction_accounts,
3412 Err(InstructionError::AccountDataTooSmall),
3413 );
3414
3415 let (transaction_accounts, instruction_accounts) = get_accounts(
3417 &payer_address,
3418 &buffer_address,
3419 &upgrade_authority_address,
3420 &upgrade_authority_address,
3421 &elf,
3422 );
3423 process_instruction(
3424 MAX_PERMITTED_DATA_LENGTH as usize,
3425 transaction_accounts,
3426 instruction_accounts,
3427 Err(InstructionError::InvalidArgument),
3428 );
3429
3430 let (transaction_accounts, instruction_accounts) = get_accounts(
3432 &payer_address,
3433 &buffer_address,
3434 &buffer_address,
3435 &upgrade_authority_address,
3436 &elf,
3437 );
3438 process_instruction(
3439 elf.len(),
3440 transaction_accounts,
3441 instruction_accounts,
3442 Err(InstructionError::IncorrectAuthority),
3443 );
3444
3445 let (mut transaction_accounts, instruction_accounts) = get_accounts(
3447 &payer_address,
3448 &buffer_address,
3449 &buffer_address,
3450 &upgrade_authority_address,
3451 &elf,
3452 );
3453 transaction_accounts
3454 .get_mut(3)
3455 .unwrap()
3456 .1
3457 .set_state(&UpgradeableLoaderState::Buffer {
3458 authority_address: None,
3459 })
3460 .unwrap();
3461 process_instruction(
3462 elf.len(),
3463 transaction_accounts,
3464 instruction_accounts,
3465 Err(InstructionError::IncorrectAuthority),
3466 );
3467
3468 let mut file =
3470 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
3471 let mut elf = Vec::new();
3472 file.read_to_end(&mut elf).unwrap();
3473 let (transaction_accounts, instruction_accounts) = get_accounts(
3474 &payer_address,
3475 &buffer_address,
3476 &upgrade_authority_address,
3477 &upgrade_authority_address,
3478 &elf,
3479 );
3480 process_instruction(
3481 elf.len(),
3482 transaction_accounts,
3483 instruction_accounts,
3484 Err(InstructionError::InvalidAccountData),
3485 );
3486 }
3487
3488 #[test]
3489 fn test_bpf_loader_upgradeable_set_upgrade_authority() {
3490 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap();
3491 let loader_id = bpf_loader_upgradeable::id();
3492 let slot = 0;
3493 let upgrade_authority_address = Pubkey::new_unique();
3494 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3495 let new_upgrade_authority_address = Pubkey::new_unique();
3496 let new_upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3497 let program_address = Pubkey::new_unique();
3498 let (programdata_address, _) = Pubkey::find_program_address(
3499 &[program_address.as_ref()],
3500 &bpf_loader_upgradeable::id(),
3501 );
3502 let mut programdata_account = AccountSharedData::new(
3503 1,
3504 UpgradeableLoaderState::size_of_programdata(0),
3505 &bpf_loader_upgradeable::id(),
3506 );
3507 programdata_account
3508 .set_state(&UpgradeableLoaderState::ProgramData {
3509 slot,
3510 upgrade_authority_address: Some(upgrade_authority_address),
3511 })
3512 .unwrap();
3513 let programdata_meta = AccountMeta {
3514 pubkey: programdata_address,
3515 is_signer: false,
3516 is_writable: true,
3517 };
3518 let upgrade_authority_meta = AccountMeta {
3519 pubkey: upgrade_authority_address,
3520 is_signer: true,
3521 is_writable: false,
3522 };
3523 let new_upgrade_authority_meta = AccountMeta {
3524 pubkey: new_upgrade_authority_address,
3525 is_signer: false,
3526 is_writable: false,
3527 };
3528
3529 let accounts = process_instruction(
3531 &loader_id,
3532 &instruction,
3533 vec![
3534 (programdata_address, programdata_account.clone()),
3535 (upgrade_authority_address, upgrade_authority_account.clone()),
3536 (
3537 new_upgrade_authority_address,
3538 new_upgrade_authority_account.clone(),
3539 ),
3540 ],
3541 vec![
3542 programdata_meta.clone(),
3543 upgrade_authority_meta.clone(),
3544 new_upgrade_authority_meta.clone(),
3545 ],
3546 Ok(()),
3547 );
3548 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3549 assert_eq!(
3550 state,
3551 UpgradeableLoaderState::ProgramData {
3552 slot,
3553 upgrade_authority_address: Some(new_upgrade_authority_address),
3554 }
3555 );
3556
3557 let accounts = process_instruction(
3559 &loader_id,
3560 &instruction,
3561 vec![
3562 (programdata_address, programdata_account.clone()),
3563 (upgrade_authority_address, upgrade_authority_account.clone()),
3564 ],
3565 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3566 Ok(()),
3567 );
3568 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3569 assert_eq!(
3570 state,
3571 UpgradeableLoaderState::ProgramData {
3572 slot,
3573 upgrade_authority_address: None,
3574 }
3575 );
3576
3577 let mut file =
3579 File::open("test_elfs/out/sbpfv0_verifier_err.so").expect("file open failed");
3580 let mut elf = Vec::new();
3581 file.read_to_end(&mut elf).unwrap();
3582 programdata_account.resize(UpgradeableLoaderState::size_of_programdata(elf.len()), 0);
3583 programdata_account
3584 .data_as_mut_slice()
3585 .get_mut(UpgradeableLoaderState::size_of_programdata_metadata()..)
3586 .unwrap()
3587 .copy_from_slice(&elf);
3588 process_instruction(
3589 &loader_id,
3590 &instruction,
3591 vec![
3592 (programdata_address, programdata_account.clone()),
3593 (upgrade_authority_address, upgrade_authority_account.clone()),
3594 ],
3595 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3596 Err(InstructionError::InvalidAccountData),
3597 );
3598
3599 process_instruction(
3601 &loader_id,
3602 &instruction,
3603 vec![
3604 (programdata_address, programdata_account.clone()),
3605 (upgrade_authority_address, upgrade_authority_account.clone()),
3606 ],
3607 vec![
3608 programdata_meta.clone(),
3609 AccountMeta {
3610 pubkey: upgrade_authority_address,
3611 is_signer: false,
3612 is_writable: false,
3613 },
3614 ],
3615 Err(InstructionError::MissingRequiredSignature),
3616 );
3617
3618 let invalid_upgrade_authority_address = Pubkey::new_unique();
3620 process_instruction(
3621 &loader_id,
3622 &instruction,
3623 vec![
3624 (programdata_address, programdata_account.clone()),
3625 (
3626 invalid_upgrade_authority_address,
3627 upgrade_authority_account.clone(),
3628 ),
3629 (new_upgrade_authority_address, new_upgrade_authority_account),
3630 ],
3631 vec![
3632 programdata_meta.clone(),
3633 AccountMeta {
3634 pubkey: invalid_upgrade_authority_address,
3635 is_signer: true,
3636 is_writable: false,
3637 },
3638 new_upgrade_authority_meta,
3639 ],
3640 Err(InstructionError::IncorrectAuthority),
3641 );
3642
3643 programdata_account
3645 .set_state(&UpgradeableLoaderState::ProgramData {
3646 slot,
3647 upgrade_authority_address: None,
3648 })
3649 .unwrap();
3650 process_instruction(
3651 &loader_id,
3652 &instruction,
3653 vec![
3654 (programdata_address, programdata_account.clone()),
3655 (upgrade_authority_address, upgrade_authority_account.clone()),
3656 ],
3657 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3658 Err(InstructionError::Immutable),
3659 );
3660
3661 programdata_account
3663 .set_state(&UpgradeableLoaderState::Program {
3664 programdata_address: Pubkey::new_unique(),
3665 })
3666 .unwrap();
3667 process_instruction(
3668 &loader_id,
3669 &instruction,
3670 vec![
3671 (programdata_address, programdata_account.clone()),
3672 (upgrade_authority_address, upgrade_authority_account),
3673 ],
3674 vec![programdata_meta, upgrade_authority_meta],
3675 Err(InstructionError::InvalidArgument),
3676 );
3677 }
3678
3679 #[test]
3680 fn test_bpf_loader_upgradeable_set_upgrade_authority_checked() {
3681 let instruction =
3682 bincode::serialize(&UpgradeableLoaderInstruction::SetAuthorityChecked).unwrap();
3683 let loader_id = bpf_loader_upgradeable::id();
3684 let slot = 0;
3685 let upgrade_authority_address = Pubkey::new_unique();
3686 let upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3687 let new_upgrade_authority_address = Pubkey::new_unique();
3688 let new_upgrade_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3689 let program_address = Pubkey::new_unique();
3690 let (programdata_address, _) = Pubkey::find_program_address(
3691 &[program_address.as_ref()],
3692 &bpf_loader_upgradeable::id(),
3693 );
3694 let mut programdata_account = AccountSharedData::new(
3695 1,
3696 UpgradeableLoaderState::size_of_programdata(0),
3697 &bpf_loader_upgradeable::id(),
3698 );
3699 programdata_account
3700 .set_state(&UpgradeableLoaderState::ProgramData {
3701 slot,
3702 upgrade_authority_address: Some(upgrade_authority_address),
3703 })
3704 .unwrap();
3705 let programdata_meta = AccountMeta {
3706 pubkey: programdata_address,
3707 is_signer: false,
3708 is_writable: true,
3709 };
3710 let upgrade_authority_meta = AccountMeta {
3711 pubkey: upgrade_authority_address,
3712 is_signer: true,
3713 is_writable: false,
3714 };
3715 let new_upgrade_authority_meta = AccountMeta {
3716 pubkey: new_upgrade_authority_address,
3717 is_signer: true,
3718 is_writable: false,
3719 };
3720
3721 let accounts = process_instruction(
3723 &loader_id,
3724 &instruction,
3725 vec![
3726 (programdata_address, programdata_account.clone()),
3727 (upgrade_authority_address, upgrade_authority_account.clone()),
3728 (
3729 new_upgrade_authority_address,
3730 new_upgrade_authority_account.clone(),
3731 ),
3732 ],
3733 vec![
3734 programdata_meta.clone(),
3735 upgrade_authority_meta.clone(),
3736 new_upgrade_authority_meta.clone(),
3737 ],
3738 Ok(()),
3739 );
3740
3741 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3742 assert_eq!(
3743 state,
3744 UpgradeableLoaderState::ProgramData {
3745 slot,
3746 upgrade_authority_address: Some(new_upgrade_authority_address),
3747 }
3748 );
3749
3750 process_instruction(
3752 &loader_id,
3753 &instruction,
3754 vec![
3755 (programdata_address, programdata_account.clone()),
3756 (upgrade_authority_address, upgrade_authority_account.clone()),
3757 ],
3758 vec![
3759 programdata_meta.clone(),
3760 upgrade_authority_meta.clone(),
3761 upgrade_authority_meta.clone(),
3762 ],
3763 Ok(()),
3764 );
3765
3766 process_instruction(
3768 &loader_id,
3769 &instruction,
3770 vec![
3771 (programdata_address, programdata_account.clone()),
3772 (upgrade_authority_address, upgrade_authority_account.clone()),
3773 (
3774 new_upgrade_authority_address,
3775 new_upgrade_authority_account.clone(),
3776 ),
3777 ],
3778 vec![programdata_meta.clone(), new_upgrade_authority_meta.clone()],
3779 Err(InstructionError::MissingAccount),
3780 );
3781
3782 process_instruction(
3784 &loader_id,
3785 &instruction,
3786 vec![
3787 (programdata_address, programdata_account.clone()),
3788 (upgrade_authority_address, upgrade_authority_account.clone()),
3789 (
3790 new_upgrade_authority_address,
3791 new_upgrade_authority_account.clone(),
3792 ),
3793 ],
3794 vec![programdata_meta.clone(), upgrade_authority_meta.clone()],
3795 Err(InstructionError::MissingAccount),
3796 );
3797
3798 process_instruction(
3800 &loader_id,
3801 &instruction,
3802 vec![
3803 (programdata_address, programdata_account.clone()),
3804 (upgrade_authority_address, upgrade_authority_account.clone()),
3805 (
3806 new_upgrade_authority_address,
3807 new_upgrade_authority_account.clone(),
3808 ),
3809 ],
3810 vec![
3811 programdata_meta.clone(),
3812 AccountMeta {
3813 pubkey: upgrade_authority_address,
3814 is_signer: false,
3815 is_writable: false,
3816 },
3817 new_upgrade_authority_meta.clone(),
3818 ],
3819 Err(InstructionError::MissingRequiredSignature),
3820 );
3821
3822 process_instruction(
3824 &loader_id,
3825 &instruction,
3826 vec![
3827 (programdata_address, programdata_account.clone()),
3828 (upgrade_authority_address, upgrade_authority_account.clone()),
3829 (
3830 new_upgrade_authority_address,
3831 new_upgrade_authority_account.clone(),
3832 ),
3833 ],
3834 vec![
3835 programdata_meta.clone(),
3836 upgrade_authority_meta.clone(),
3837 AccountMeta {
3838 pubkey: new_upgrade_authority_address,
3839 is_signer: false,
3840 is_writable: false,
3841 },
3842 ],
3843 Err(InstructionError::MissingRequiredSignature),
3844 );
3845
3846 let invalid_upgrade_authority_address = Pubkey::new_unique();
3848 process_instruction(
3849 &loader_id,
3850 &instruction,
3851 vec![
3852 (programdata_address, programdata_account.clone()),
3853 (
3854 invalid_upgrade_authority_address,
3855 upgrade_authority_account.clone(),
3856 ),
3857 (new_upgrade_authority_address, new_upgrade_authority_account),
3858 ],
3859 vec![
3860 programdata_meta.clone(),
3861 AccountMeta {
3862 pubkey: invalid_upgrade_authority_address,
3863 is_signer: true,
3864 is_writable: false,
3865 },
3866 new_upgrade_authority_meta.clone(),
3867 ],
3868 Err(InstructionError::IncorrectAuthority),
3869 );
3870
3871 programdata_account
3873 .set_state(&UpgradeableLoaderState::ProgramData {
3874 slot,
3875 upgrade_authority_address: None,
3876 })
3877 .unwrap();
3878 process_instruction(
3879 &loader_id,
3880 &instruction,
3881 vec![
3882 (programdata_address, programdata_account.clone()),
3883 (upgrade_authority_address, upgrade_authority_account.clone()),
3884 ],
3885 vec![
3886 programdata_meta.clone(),
3887 upgrade_authority_meta.clone(),
3888 new_upgrade_authority_meta.clone(),
3889 ],
3890 Err(InstructionError::Immutable),
3891 );
3892
3893 programdata_account
3895 .set_state(&UpgradeableLoaderState::Program {
3896 programdata_address: Pubkey::new_unique(),
3897 })
3898 .unwrap();
3899 process_instruction(
3900 &loader_id,
3901 &instruction,
3902 vec![
3903 (programdata_address, programdata_account.clone()),
3904 (upgrade_authority_address, upgrade_authority_account),
3905 ],
3906 vec![
3907 programdata_meta,
3908 upgrade_authority_meta,
3909 new_upgrade_authority_meta,
3910 ],
3911 Err(InstructionError::InvalidArgument),
3912 );
3913 }
3914
3915 #[test]
3916 fn test_bpf_loader_upgradeable_set_buffer_authority() {
3917 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap();
3918 let loader_id = bpf_loader_upgradeable::id();
3919 let invalid_authority_address = Pubkey::new_unique();
3920 let authority_address = Pubkey::new_unique();
3921 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3922 let new_authority_address = Pubkey::new_unique();
3923 let new_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
3924 let buffer_address = Pubkey::new_unique();
3925 let mut buffer_account =
3926 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(0), &loader_id);
3927 buffer_account
3928 .set_state(&UpgradeableLoaderState::Buffer {
3929 authority_address: Some(authority_address),
3930 })
3931 .unwrap();
3932 let mut transaction_accounts = vec![
3933 (buffer_address, buffer_account.clone()),
3934 (authority_address, authority_account.clone()),
3935 (new_authority_address, new_authority_account.clone()),
3936 ];
3937 let buffer_meta = AccountMeta {
3938 pubkey: buffer_address,
3939 is_signer: false,
3940 is_writable: true,
3941 };
3942 let authority_meta = AccountMeta {
3943 pubkey: authority_address,
3944 is_signer: true,
3945 is_writable: false,
3946 };
3947 let new_authority_meta = AccountMeta {
3948 pubkey: new_authority_address,
3949 is_signer: false,
3950 is_writable: false,
3951 };
3952
3953 let accounts = process_instruction(
3955 &loader_id,
3956 &instruction,
3957 transaction_accounts.clone(),
3958 vec![buffer_meta.clone(), authority_meta.clone()],
3959 Err(InstructionError::IncorrectAuthority),
3960 );
3961 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3962 assert_eq!(
3963 state,
3964 UpgradeableLoaderState::Buffer {
3965 authority_address: Some(authority_address),
3966 }
3967 );
3968
3969 buffer_account
3971 .set_state(&UpgradeableLoaderState::Buffer {
3972 authority_address: Some(authority_address),
3973 })
3974 .unwrap();
3975 let accounts = process_instruction(
3976 &loader_id,
3977 &instruction,
3978 transaction_accounts.clone(),
3979 vec![
3980 buffer_meta.clone(),
3981 authority_meta.clone(),
3982 new_authority_meta.clone(),
3983 ],
3984 Ok(()),
3985 );
3986 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
3987 assert_eq!(
3988 state,
3989 UpgradeableLoaderState::Buffer {
3990 authority_address: Some(new_authority_address),
3991 }
3992 );
3993
3994 process_instruction(
3996 &loader_id,
3997 &instruction,
3998 transaction_accounts.clone(),
3999 vec![
4000 buffer_meta.clone(),
4001 AccountMeta {
4002 pubkey: authority_address,
4003 is_signer: false,
4004 is_writable: false,
4005 },
4006 new_authority_meta.clone(),
4007 ],
4008 Err(InstructionError::MissingRequiredSignature),
4009 );
4010
4011 process_instruction(
4013 &loader_id,
4014 &instruction,
4015 vec![
4016 (buffer_address, buffer_account.clone()),
4017 (invalid_authority_address, authority_account),
4018 (new_authority_address, new_authority_account),
4019 ],
4020 vec![
4021 buffer_meta.clone(),
4022 AccountMeta {
4023 pubkey: invalid_authority_address,
4024 is_signer: true,
4025 is_writable: false,
4026 },
4027 new_authority_meta.clone(),
4028 ],
4029 Err(InstructionError::IncorrectAuthority),
4030 );
4031
4032 process_instruction(
4034 &loader_id,
4035 &instruction,
4036 transaction_accounts.clone(),
4037 vec![buffer_meta.clone(), authority_meta.clone()],
4038 Err(InstructionError::IncorrectAuthority),
4039 );
4040
4041 transaction_accounts
4043 .get_mut(0)
4044 .unwrap()
4045 .1
4046 .set_state(&UpgradeableLoaderState::Buffer {
4047 authority_address: None,
4048 })
4049 .unwrap();
4050 process_instruction(
4051 &loader_id,
4052 &instruction,
4053 transaction_accounts.clone(),
4054 vec![
4055 buffer_meta.clone(),
4056 authority_meta.clone(),
4057 new_authority_meta.clone(),
4058 ],
4059 Err(InstructionError::Immutable),
4060 );
4061
4062 transaction_accounts
4064 .get_mut(0)
4065 .unwrap()
4066 .1
4067 .set_state(&UpgradeableLoaderState::Program {
4068 programdata_address: Pubkey::new_unique(),
4069 })
4070 .unwrap();
4071 process_instruction(
4072 &loader_id,
4073 &instruction,
4074 transaction_accounts.clone(),
4075 vec![buffer_meta, authority_meta, new_authority_meta],
4076 Err(InstructionError::InvalidArgument),
4077 );
4078 }
4079
4080 #[test]
4081 fn test_bpf_loader_upgradeable_set_buffer_authority_checked() {
4082 let instruction =
4083 bincode::serialize(&UpgradeableLoaderInstruction::SetAuthorityChecked).unwrap();
4084 let loader_id = bpf_loader_upgradeable::id();
4085 let invalid_authority_address = Pubkey::new_unique();
4086 let authority_address = Pubkey::new_unique();
4087 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4088 let new_authority_address = Pubkey::new_unique();
4089 let new_authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4090 let buffer_address = Pubkey::new_unique();
4091 let mut buffer_account =
4092 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(0), &loader_id);
4093 buffer_account
4094 .set_state(&UpgradeableLoaderState::Buffer {
4095 authority_address: Some(authority_address),
4096 })
4097 .unwrap();
4098 let mut transaction_accounts = vec![
4099 (buffer_address, buffer_account.clone()),
4100 (authority_address, authority_account.clone()),
4101 (new_authority_address, new_authority_account.clone()),
4102 ];
4103 let buffer_meta = AccountMeta {
4104 pubkey: buffer_address,
4105 is_signer: false,
4106 is_writable: true,
4107 };
4108 let authority_meta = AccountMeta {
4109 pubkey: authority_address,
4110 is_signer: true,
4111 is_writable: false,
4112 };
4113 let new_authority_meta = AccountMeta {
4114 pubkey: new_authority_address,
4115 is_signer: true,
4116 is_writable: false,
4117 };
4118
4119 buffer_account
4121 .set_state(&UpgradeableLoaderState::Buffer {
4122 authority_address: Some(authority_address),
4123 })
4124 .unwrap();
4125 let accounts = process_instruction(
4126 &loader_id,
4127 &instruction,
4128 transaction_accounts.clone(),
4129 vec![
4130 buffer_meta.clone(),
4131 authority_meta.clone(),
4132 new_authority_meta.clone(),
4133 ],
4134 Ok(()),
4135 );
4136 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4137 assert_eq!(
4138 state,
4139 UpgradeableLoaderState::Buffer {
4140 authority_address: Some(new_authority_address),
4141 }
4142 );
4143
4144 process_instruction(
4146 &loader_id,
4147 &instruction,
4148 transaction_accounts.clone(),
4149 vec![
4150 buffer_meta.clone(),
4151 authority_meta.clone(),
4152 authority_meta.clone(),
4153 ],
4154 Ok(()),
4155 );
4156
4157 process_instruction(
4159 &loader_id,
4160 &instruction,
4161 transaction_accounts.clone(),
4162 vec![buffer_meta.clone(), new_authority_meta.clone()],
4163 Err(InstructionError::MissingAccount),
4164 );
4165
4166 process_instruction(
4168 &loader_id,
4169 &instruction,
4170 transaction_accounts.clone(),
4171 vec![buffer_meta.clone(), authority_meta.clone()],
4172 Err(InstructionError::MissingAccount),
4173 );
4174
4175 process_instruction(
4177 &loader_id,
4178 &instruction,
4179 vec![
4180 (buffer_address, buffer_account.clone()),
4181 (invalid_authority_address, authority_account),
4182 (new_authority_address, new_authority_account),
4183 ],
4184 vec![
4185 buffer_meta.clone(),
4186 AccountMeta {
4187 pubkey: invalid_authority_address,
4188 is_signer: true,
4189 is_writable: false,
4190 },
4191 new_authority_meta.clone(),
4192 ],
4193 Err(InstructionError::IncorrectAuthority),
4194 );
4195
4196 process_instruction(
4198 &loader_id,
4199 &instruction,
4200 transaction_accounts.clone(),
4201 vec![
4202 buffer_meta.clone(),
4203 AccountMeta {
4204 pubkey: authority_address,
4205 is_signer: false,
4206 is_writable: false,
4207 },
4208 new_authority_meta.clone(),
4209 ],
4210 Err(InstructionError::MissingRequiredSignature),
4211 );
4212
4213 process_instruction(
4215 &loader_id,
4216 &instruction,
4217 transaction_accounts.clone(),
4218 vec![
4219 buffer_meta.clone(),
4220 authority_meta.clone(),
4221 AccountMeta {
4222 pubkey: new_authority_address,
4223 is_signer: false,
4224 is_writable: false,
4225 },
4226 ],
4227 Err(InstructionError::MissingRequiredSignature),
4228 );
4229
4230 transaction_accounts
4232 .get_mut(0)
4233 .unwrap()
4234 .1
4235 .set_state(&UpgradeableLoaderState::Program {
4236 programdata_address: Pubkey::new_unique(),
4237 })
4238 .unwrap();
4239 process_instruction(
4240 &loader_id,
4241 &instruction,
4242 transaction_accounts.clone(),
4243 vec![
4244 buffer_meta.clone(),
4245 authority_meta.clone(),
4246 new_authority_meta.clone(),
4247 ],
4248 Err(InstructionError::InvalidArgument),
4249 );
4250
4251 transaction_accounts
4253 .get_mut(0)
4254 .unwrap()
4255 .1
4256 .set_state(&UpgradeableLoaderState::Buffer {
4257 authority_address: None,
4258 })
4259 .unwrap();
4260 process_instruction(
4261 &loader_id,
4262 &instruction,
4263 transaction_accounts.clone(),
4264 vec![buffer_meta, authority_meta, new_authority_meta],
4265 Err(InstructionError::Immutable),
4266 );
4267 }
4268
4269 #[test]
4270 fn test_bpf_loader_upgradeable_close() {
4271 let instruction = bincode::serialize(&UpgradeableLoaderInstruction::Close).unwrap();
4272 let loader_id = bpf_loader_upgradeable::id();
4273 let invalid_authority_address = Pubkey::new_unique();
4274 let authority_address = Pubkey::new_unique();
4275 let authority_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4276 let recipient_address = Pubkey::new_unique();
4277 let recipient_account = AccountSharedData::new(1, 0, &Pubkey::new_unique());
4278 let buffer_address = Pubkey::new_unique();
4279 let mut buffer_account =
4280 AccountSharedData::new(1, UpgradeableLoaderState::size_of_buffer(128), &loader_id);
4281 buffer_account
4282 .set_state(&UpgradeableLoaderState::Buffer {
4283 authority_address: Some(authority_address),
4284 })
4285 .unwrap();
4286 let uninitialized_address = Pubkey::new_unique();
4287 let mut uninitialized_account = AccountSharedData::new(
4288 1,
4289 UpgradeableLoaderState::size_of_programdata(0),
4290 &loader_id,
4291 );
4292 uninitialized_account
4293 .set_state(&UpgradeableLoaderState::Uninitialized)
4294 .unwrap();
4295 let programdata_address = Pubkey::new_unique();
4296 let mut programdata_account = AccountSharedData::new(
4297 1,
4298 UpgradeableLoaderState::size_of_programdata(128),
4299 &loader_id,
4300 );
4301 programdata_account
4302 .set_state(&UpgradeableLoaderState::ProgramData {
4303 slot: 0,
4304 upgrade_authority_address: Some(authority_address),
4305 })
4306 .unwrap();
4307 let program_address = Pubkey::new_unique();
4308 let mut program_account =
4309 AccountSharedData::new(1, UpgradeableLoaderState::size_of_program(), &loader_id);
4310 program_account.set_executable(true);
4311 program_account
4312 .set_state(&UpgradeableLoaderState::Program {
4313 programdata_address,
4314 })
4315 .unwrap();
4316 let clock_account = create_sysvar_account(&Clock {
4317 slot: 1,
4318 ..Clock::default()
4319 });
4320 let transaction_accounts = vec![
4321 (buffer_address, buffer_account.clone()),
4322 (recipient_address, recipient_account.clone()),
4323 (authority_address, authority_account.clone()),
4324 ];
4325 let buffer_meta = AccountMeta {
4326 pubkey: buffer_address,
4327 is_signer: false,
4328 is_writable: true,
4329 };
4330 let recipient_meta = AccountMeta {
4331 pubkey: recipient_address,
4332 is_signer: false,
4333 is_writable: true,
4334 };
4335 let authority_meta = AccountMeta {
4336 pubkey: authority_address,
4337 is_signer: true,
4338 is_writable: false,
4339 };
4340
4341 let accounts = process_instruction(
4343 &loader_id,
4344 &instruction,
4345 transaction_accounts,
4346 vec![
4347 buffer_meta.clone(),
4348 recipient_meta.clone(),
4349 authority_meta.clone(),
4350 ],
4351 Ok(()),
4352 );
4353 assert_eq!(0, accounts.first().unwrap().lamports());
4354 assert_eq!(2, accounts.get(1).unwrap().lamports());
4355 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4356 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
4357 assert_eq!(
4358 UpgradeableLoaderState::size_of_uninitialized(),
4359 accounts.first().unwrap().data().len()
4360 );
4361
4362 process_instruction(
4364 &loader_id,
4365 &instruction,
4366 vec![
4367 (buffer_address, buffer_account.clone()),
4368 (recipient_address, recipient_account.clone()),
4369 (invalid_authority_address, authority_account.clone()),
4370 ],
4371 vec![
4372 buffer_meta,
4373 recipient_meta.clone(),
4374 AccountMeta {
4375 pubkey: invalid_authority_address,
4376 is_signer: true,
4377 is_writable: false,
4378 },
4379 ],
4380 Err(InstructionError::IncorrectAuthority),
4381 );
4382
4383 let accounts = process_instruction(
4385 &loader_id,
4386 &instruction,
4387 vec![
4388 (uninitialized_address, uninitialized_account.clone()),
4389 (recipient_address, recipient_account.clone()),
4390 (invalid_authority_address, authority_account.clone()),
4391 ],
4392 vec![
4393 AccountMeta {
4394 pubkey: uninitialized_address,
4395 is_signer: false,
4396 is_writable: true,
4397 },
4398 recipient_meta.clone(),
4399 authority_meta.clone(),
4400 ],
4401 Ok(()),
4402 );
4403 assert_eq!(0, accounts.first().unwrap().lamports());
4404 assert_eq!(2, accounts.get(1).unwrap().lamports());
4405 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4406 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
4407 assert_eq!(
4408 UpgradeableLoaderState::size_of_uninitialized(),
4409 accounts.first().unwrap().data().len()
4410 );
4411
4412 process_instruction(
4414 &loader_id,
4415 &instruction,
4416 vec![
4417 (programdata_address, programdata_account.clone()),
4418 (recipient_address, recipient_account.clone()),
4419 (authority_address, authority_account.clone()),
4420 (program_address, program_account.clone()),
4421 (sysvar::clock::id(), clock_account.clone()),
4422 ],
4423 vec![
4424 AccountMeta {
4425 pubkey: programdata_address,
4426 is_signer: false,
4427 is_writable: true,
4428 },
4429 recipient_meta.clone(),
4430 authority_meta.clone(),
4431 AccountMeta {
4432 pubkey: program_address,
4433 is_signer: false,
4434 is_writable: false,
4435 },
4436 ],
4437 Err(InstructionError::InvalidArgument),
4438 );
4439
4440 let accounts = process_instruction(
4442 &loader_id,
4443 &instruction,
4444 vec![
4445 (programdata_address, programdata_account.clone()),
4446 (recipient_address, recipient_account.clone()),
4447 (authority_address, authority_account.clone()),
4448 (program_address, program_account.clone()),
4449 (sysvar::clock::id(), clock_account.clone()),
4450 ],
4451 vec![
4452 AccountMeta {
4453 pubkey: programdata_address,
4454 is_signer: false,
4455 is_writable: true,
4456 },
4457 recipient_meta,
4458 authority_meta,
4459 AccountMeta {
4460 pubkey: program_address,
4461 is_signer: false,
4462 is_writable: true,
4463 },
4464 ],
4465 Ok(()),
4466 );
4467 assert_eq!(0, accounts.first().unwrap().lamports());
4468 assert_eq!(2, accounts.get(1).unwrap().lamports());
4469 let state: UpgradeableLoaderState = accounts.first().unwrap().state().unwrap();
4470 assert_eq!(state, UpgradeableLoaderState::Uninitialized);
4471 assert_eq!(
4472 UpgradeableLoaderState::size_of_uninitialized(),
4473 accounts.first().unwrap().data().len()
4474 );
4475
4476 programdata_account = accounts.first().unwrap().clone();
4478 program_account = accounts.get(3).unwrap().clone();
4479 process_instruction(
4480 &program_address,
4481 &[],
4482 vec![
4483 (programdata_address, programdata_account.clone()),
4484 (program_address, program_account.clone()),
4485 ],
4486 Vec::new(),
4487 Err(InstructionError::UnsupportedProgramId),
4488 );
4489
4490 process_instruction(
4492 &loader_id,
4493 &bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
4494 max_data_len: 0,
4495 })
4496 .unwrap(),
4497 vec![
4498 (recipient_address, recipient_account),
4499 (programdata_address, programdata_account),
4500 (program_address, program_account),
4501 (buffer_address, buffer_account),
4502 (sysvar::rent::id(), create_sysvar_account(&Rent::default())),
4503 (sysvar::clock::id(), clock_account),
4504 (
4505 system_program::id(),
4506 AccountSharedData::new(0, 0, &system_program::id()),
4507 ),
4508 (authority_address, authority_account),
4509 ],
4510 vec![
4511 AccountMeta {
4512 pubkey: recipient_address,
4513 is_signer: true,
4514 is_writable: true,
4515 },
4516 AccountMeta {
4517 pubkey: programdata_address,
4518 is_signer: false,
4519 is_writable: true,
4520 },
4521 AccountMeta {
4522 pubkey: program_address,
4523 is_signer: false,
4524 is_writable: true,
4525 },
4526 AccountMeta {
4527 pubkey: buffer_address,
4528 is_signer: false,
4529 is_writable: false,
4530 },
4531 AccountMeta {
4532 pubkey: sysvar::rent::id(),
4533 is_signer: false,
4534 is_writable: false,
4535 },
4536 AccountMeta {
4537 pubkey: sysvar::clock::id(),
4538 is_signer: false,
4539 is_writable: false,
4540 },
4541 AccountMeta {
4542 pubkey: system_program::id(),
4543 is_signer: false,
4544 is_writable: false,
4545 },
4546 AccountMeta {
4547 pubkey: authority_address,
4548 is_signer: false,
4549 is_writable: false,
4550 },
4551 ],
4552 Err(InstructionError::AccountAlreadyInitialized),
4553 );
4554 }
4555
4556 fn fuzz<F>(
4558 bytes: &[u8],
4559 outer_iters: usize,
4560 inner_iters: usize,
4561 offset: Range<usize>,
4562 value: Range<u8>,
4563 work: F,
4564 ) where
4565 F: Fn(&mut [u8]),
4566 {
4567 let mut rng = rand::rng();
4568 for _ in 0..outer_iters {
4569 let mut mangled_bytes = bytes.to_vec();
4570 for _ in 0..inner_iters {
4571 let offset = rng.random_range(offset.start..offset.end);
4572 let value = rng.random_range(value.start..value.end);
4573 *mangled_bytes.get_mut(offset).unwrap() = value;
4574 work(&mut mangled_bytes);
4575 }
4576 }
4577 }
4578
4579 #[test]
4580 #[ignore]
4581 fn test_fuzz() {
4582 let loader_id = bpf_loader::id();
4583 let program_id = Pubkey::new_unique();
4584
4585 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
4587 let mut elf = Vec::new();
4588 file.read_to_end(&mut elf).unwrap();
4589
4590 fuzz(
4592 &elf,
4593 1_000_000_000,
4594 100,
4595 0..elf.len(),
4596 0..255,
4597 |bytes: &mut [u8]| {
4598 let mut program_account = AccountSharedData::new(1, 0, &loader_id);
4599 program_account.set_data_from_slice(bytes);
4600 program_account.set_executable(true);
4601 process_instruction(
4602 &program_id,
4603 &[],
4604 vec![(program_id, program_account)],
4605 Vec::new(),
4606 Ok(()),
4607 );
4608 },
4609 );
4610 }
4611
4612 #[test]
4613 fn test_calculate_heap_cost() {
4614 let heap_cost = 8_u64;
4615
4616 assert_eq!(0, calculate_heap_cost(31 * 1024, heap_cost));
4620
4621 assert_eq!(0, calculate_heap_cost(32 * 1024, heap_cost));
4623
4624 assert_eq!(heap_cost, calculate_heap_cost(33 * 1024, heap_cost));
4626
4627 assert_eq!(heap_cost, calculate_heap_cost(64 * 1024, heap_cost));
4629 }
4630
4631 fn deploy_test_program(
4632 invoke_context: &mut InvokeContext,
4633 program_id: Pubkey,
4634 ) -> Result<(), InstructionError> {
4635 let mut file = File::open("test_elfs/out/sbpfv3_return_ok.so").expect("file open failed");
4636 let mut elf = Vec::new();
4637 file.read_to_end(&mut elf).unwrap();
4638 deploy_program!(
4639 invoke_context,
4640 &program_id,
4641 &bpf_loader_upgradeable::id(),
4642 &elf,
4643 2_u64,
4644 true, );
4646 Ok(())
4647 }
4648
4649 #[cfg(feature = "shuttle-test")]
4668 const PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS: usize = 100;
4669
4670 #[test]
4671 fn test_program_usage_count_on_upgrade() {
4672 #[cfg(feature = "shuttle-test")]
4673 shuttle::check_random(
4674 do_test_program_usage_count_on_upgrade,
4675 PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS,
4676 );
4677 #[cfg(not(feature = "shuttle-test"))]
4678 do_test_program_usage_count_on_upgrade();
4679 }
4680
4681 fn do_test_program_usage_count_on_upgrade() {
4682 let transaction_accounts = vec![(
4683 sysvar::epoch_schedule::id(),
4684 create_sysvar_account(&EpochSchedule::default()),
4685 )];
4686 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4687 let program_id = Pubkey::new_unique();
4688 let env = ProgramRuntimeEnvironment::from(BuiltinProgram::new_mock());
4689 let stats = ProgramStatistics {
4690 uses: 100.into(),
4691 ..Default::default()
4692 };
4693 let program = ProgramCacheEntry {
4694 program: ProgramCacheEntryType::Unloaded(env),
4695 account_owner: ProgramCacheEntryOwner::LoaderV2,
4696 deployment_slot: 0,
4697 stats: stats.into(),
4698 latest_access_slot: AtomicU64::new(0),
4699 };
4700 invoke_context
4701 .program_cache_for_tx_batch
4702 .replenish(program_id, Arc::new(program));
4703 invoke_context
4704 .program_cache_for_tx_batch
4705 .set_slot_for_tests(2);
4706
4707 assert_matches!(
4708 deploy_test_program(&mut invoke_context, program_id,),
4709 Ok(())
4710 );
4711
4712 let updated_program = invoke_context
4713 .program_cache_for_tx_batch
4714 .find(&program_id)
4715 .expect("Didn't find upgraded program in the cache");
4716
4717 assert_eq!(updated_program.deployment_slot, 2);
4718 assert_eq!(updated_program.stats.uses.load(Ordering::Relaxed), 100);
4719 }
4720
4721 #[test]
4722 fn test_program_usage_count_on_non_upgrade() {
4723 #[cfg(feature = "shuttle-test")]
4724 shuttle::check_random(
4725 do_test_program_usage_count_on_non_upgrade,
4726 PROGRAM_USAGE_COUNT_RANDOM_ITERATIONS,
4727 );
4728 #[cfg(not(feature = "shuttle-test"))]
4729 do_test_program_usage_count_on_non_upgrade();
4730 }
4731
4732 fn do_test_program_usage_count_on_non_upgrade() {
4733 let transaction_accounts = vec![(
4734 sysvar::epoch_schedule::id(),
4735 create_sysvar_account(&EpochSchedule::default()),
4736 )];
4737 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4738 let program_id = Pubkey::new_unique();
4739 let env = ProgramRuntimeEnvironment::from(BuiltinProgram::new_mock());
4740 let stats = ProgramStatistics {
4741 uses: 100.into(),
4742 ..Default::default()
4743 };
4744 let program = ProgramCacheEntry {
4745 program: ProgramCacheEntryType::Unloaded(env),
4746 account_owner: ProgramCacheEntryOwner::LoaderV2,
4747 deployment_slot: 0,
4748 stats: stats.into(),
4749 latest_access_slot: AtomicU64::new(0),
4750 };
4751 invoke_context
4752 .program_cache_for_tx_batch
4753 .replenish(program_id, Arc::new(program));
4754 invoke_context
4755 .program_cache_for_tx_batch
4756 .set_slot_for_tests(2);
4757
4758 let program_id2 = Pubkey::new_unique();
4759 assert_matches!(
4760 deploy_test_program(&mut invoke_context, program_id2),
4761 Ok(())
4762 );
4763
4764 let program2 = invoke_context
4765 .program_cache_for_tx_batch
4766 .find(&program_id2)
4767 .expect("Didn't find upgraded program in the cache");
4768
4769 assert_eq!(program2.deployment_slot, 2);
4770 assert_eq!(program2.stats.uses.load(Ordering::Relaxed), 0);
4771 }
4772}