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