solana_bpf_loader_program/
lib.rs

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