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