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