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