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