clone_solana_bpf_loader_program/
lib.rs

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