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