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