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