solana_bpf_loader_program/
lib.rs

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