gemachain_bpf_loader_program/
lib.rs

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