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