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