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