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