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