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