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