solana_bpf_loader_program/
lib.rs

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