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