solana_bpf_loader_program/
lib.rs

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