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