1#![cfg(feature = "agave-unstable-api")]
2pub use self::{
3 cpi::{SyscallInvokeSignedC, SyscallInvokeSignedRust},
4 logging::{
5 SyscallLog, SyscallLogBpfComputeUnits, SyscallLogData, SyscallLogPubkey, SyscallLogU64,
6 },
7 mem_ops::{SyscallMemcmp, SyscallMemcpy, SyscallMemmove, SyscallMemset},
8 sysvar::{
9 SyscallGetClockSysvar, SyscallGetEpochRewardsSysvar, SyscallGetEpochScheduleSysvar,
10 SyscallGetFeesSysvar, SyscallGetLastRestartSlotSysvar, SyscallGetRentSysvar,
11 SyscallGetSysvar,
12 },
13};
14use {
15 crate::mem_ops::is_nonoverlapping,
16 solana_big_mod_exp::{
17 BIG_MOD_EXP_MAX_BYTES, BIG_MOD_EXP_MIN_EXPONENT_LENGTH,
18 BIG_MOD_EXP_MOD_REDUCTION_COMPLEXITY_FACTOR, BigModExpParams, big_mod_exp,
19 },
20 solana_blake3_hasher as blake3,
21 solana_cpi::MAX_RETURN_DATA,
22 solana_hash::Hash,
23 solana_hash_512::Hash512,
24 solana_instruction::{AccountMeta, ProcessedSiblingInstruction, error::InstructionError},
25 solana_keccak_hasher as keccak, solana_poseidon as poseidon,
26 solana_program_entrypoint::{BPF_ALIGN_OF_U128, SUCCESS},
27 solana_program_runtime::{
28 cpi::CpiError,
29 execution_budget::{SVMTransactionExecutionBudget, SVMTransactionExecutionCost},
30 invoke_context::InvokeContext,
31 loaded_programs::ProgramRuntimeEnvironment,
32 memory::{MemoryTranslationError, translate_vm_slice},
33 stable_log, translate_inner, translate_slice_inner, translate_type_inner,
34 },
35 solana_pubkey::{MAX_SEED_LEN, MAX_SEEDS, PUBKEY_BYTES, Pubkey, PubkeyError},
36 solana_sbpf::{
37 declare_builtin_function,
38 memory_region::{AccessType, MemoryMapping},
39 program::{BuiltinFunctionDefinition, BuiltinProgram, SBPFVersion},
40 vm::Config,
41 },
42 solana_secp256k1_recover::{
43 SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH, Secp256k1RecoverError,
44 },
45 solana_sha256_hasher::Hasher,
46 solana_sha512_hasher as sha512,
47 solana_svm_feature_set::SVMFeatureSet,
48 solana_svm_log_collector::{ic_logger_msg, ic_msg},
49 solana_svm_type_overrides::sync::Arc,
50 solana_sysvar::SysvarSerialize,
51 solana_transaction_context::vm_slice::VmSlice,
52 std::{
53 alloc::Layout,
54 mem::{MaybeUninit, align_of, size_of},
55 str::{Utf8Error, from_utf8},
56 },
57 thiserror::Error as ThisError,
58};
59
60mod cpi;
61mod logging;
62mod mem_ops;
63mod sysvar;
64
65#[derive(Debug, ThisError, PartialEq, Eq)]
69#[repr(u64)]
70pub enum SyscallError {
71 #[error("{0}: {1:?}")]
72 InvalidString(Utf8Error, Vec<u8>),
73 #[error("SBF program panicked")]
74 Abort,
75 #[error("SBF program Panicked in {0} at {1}:{2}")]
76 Panic(String, u64, u64),
77 #[error("Cannot borrow invoke context")]
78 InvokeContextBorrowFailed,
79 #[error("Malformed signer seed: {0}: {1:?}")]
80 MalformedSignerSeed(Utf8Error, Vec<u8>),
81 #[error("Could not create program address with signer seeds: {0}")]
82 BadSeeds(PubkeyError),
83 #[error("Program {0} not supported by inner instructions")]
84 ProgramNotSupported(Pubkey),
85 #[error("Unaligned pointer")]
86 UnalignedPointer,
87 #[error("Too many signers")]
88 TooManySigners,
89 #[error("Instruction passed to inner instruction is too large ({0} > {1})")]
90 InstructionTooLarge(usize, usize),
91 #[error("Too many accounts passed to inner instruction")]
92 TooManyAccounts,
93 #[error("Overlapping copy")]
94 CopyOverlapping,
95 #[error("Return data too large ({0} > {1})")]
96 ReturnDataTooLarge(u64, u64),
97 #[error("Hashing too many sequences")]
98 TooManySlices,
99 #[error("InvalidLength")]
100 InvalidLength,
101 #[error("Invoked an instruction with data that is too large ({data_len} > {max_data_len})")]
102 MaxInstructionDataLenExceeded { data_len: u64, max_data_len: u64 },
103 #[error("Invoked an instruction with too many accounts ({num_accounts} > {max_accounts})")]
104 MaxInstructionAccountsExceeded {
105 num_accounts: u64,
106 max_accounts: u64,
107 },
108 #[error(
109 "Invoked an instruction with too many account info's ({num_account_infos} > \
110 {max_account_infos})"
111 )]
112 MaxInstructionAccountInfosExceeded {
113 num_account_infos: u64,
114 max_account_infos: u64,
115 },
116 #[error("InvalidAttribute")]
117 InvalidAttribute,
118 #[error("Invalid pointer")]
119 InvalidPointer,
120 #[error("Arithmetic overflow")]
121 ArithmeticOverflow,
122}
123
124impl SyscallError {
125 pub fn discriminant(&self) -> u64 {
129 unsafe { *std::ptr::addr_of!(*self).cast::<u64>() }
130 }
131}
132
133impl From<MemoryTranslationError> for SyscallError {
134 fn from(error: MemoryTranslationError) -> Self {
135 match error {
136 MemoryTranslationError::UnalignedPointer => SyscallError::UnalignedPointer,
137 MemoryTranslationError::InvalidLength => SyscallError::InvalidLength,
138 }
139 }
140}
141
142impl From<CpiError> for SyscallError {
143 fn from(error: CpiError) -> Self {
144 match error {
145 CpiError::InvalidPointer => SyscallError::InvalidPointer,
146 CpiError::TooManySigners => SyscallError::TooManySigners,
147 CpiError::BadSeeds(e) => SyscallError::BadSeeds(e),
148 CpiError::InvalidLength => SyscallError::InvalidLength,
149 CpiError::MaxInstructionAccountsExceeded {
150 num_accounts,
151 max_accounts,
152 } => SyscallError::MaxInstructionAccountsExceeded {
153 num_accounts,
154 max_accounts,
155 },
156 CpiError::MaxInstructionDataLenExceeded {
157 data_len,
158 max_data_len,
159 } => SyscallError::MaxInstructionDataLenExceeded {
160 data_len,
161 max_data_len,
162 },
163 CpiError::MaxInstructionAccountInfosExceeded {
164 num_account_infos,
165 max_account_infos,
166 } => SyscallError::MaxInstructionAccountInfosExceeded {
167 num_account_infos,
168 max_account_infos,
169 },
170 CpiError::ProgramNotSupported(pubkey) => SyscallError::ProgramNotSupported(pubkey),
171 }
172 }
173}
174
175type Error = Box<dyn std::error::Error>;
176
177trait HasherImpl {
178 const NAME: &'static str;
179 type Output: AsRef<[u8]>;
180
181 fn create_hasher() -> Self;
182 fn hash(&mut self, val: &[u8]);
183 fn result(self) -> Self::Output;
184 fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64;
185 fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64;
186 fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64;
187}
188
189struct Sha256Hasher(Hasher);
190struct Blake3Hasher(blake3::Hasher);
191struct Keccak256Hasher(keccak::Hasher);
192struct Sha512Hasher(sha512::Hasher);
193
194impl HasherImpl for Sha256Hasher {
195 const NAME: &'static str = "Sha256";
196 type Output = Hash;
197
198 fn create_hasher() -> Self {
199 Sha256Hasher(Hasher::default())
200 }
201
202 fn hash(&mut self, val: &[u8]) {
203 self.0.hash(val);
204 }
205
206 fn result(self) -> Self::Output {
207 self.0.result()
208 }
209
210 fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
211 compute_cost.sha256_base_cost
212 }
213 fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
214 compute_cost.sha256_byte_cost
215 }
216 fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
217 compute_budget.sha256_max_slices
218 }
219}
220
221impl HasherImpl for Blake3Hasher {
222 const NAME: &'static str = "Blake3";
223 type Output = blake3::Hash;
224
225 fn create_hasher() -> Self {
226 Blake3Hasher(blake3::Hasher::default())
227 }
228
229 fn hash(&mut self, val: &[u8]) {
230 self.0.hash(val);
231 }
232
233 fn result(self) -> Self::Output {
234 self.0.result()
235 }
236
237 fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
238 compute_cost.sha256_base_cost
239 }
240 fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
241 compute_cost.sha256_byte_cost
242 }
243 fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
244 compute_budget.sha256_max_slices
245 }
246}
247
248impl HasherImpl for Keccak256Hasher {
249 const NAME: &'static str = "Keccak256";
250 type Output = keccak::Hash;
251
252 fn create_hasher() -> Self {
253 Keccak256Hasher(keccak::Hasher::default())
254 }
255
256 fn hash(&mut self, val: &[u8]) {
257 self.0.hash(val);
258 }
259
260 fn result(self) -> Self::Output {
261 self.0.result()
262 }
263
264 fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
265 compute_cost.sha256_base_cost
266 }
267 fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
268 compute_cost.sha256_byte_cost
269 }
270 fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
271 compute_budget.sha256_max_slices
272 }
273}
274
275impl HasherImpl for Sha512Hasher {
276 const NAME: &'static str = "Sha512";
277 type Output = Hash512;
278
279 fn create_hasher() -> Self {
280 Sha512Hasher(sha512::Hasher::default())
281 }
282
283 fn hash(&mut self, val: &[u8]) {
284 self.0.hash(val);
285 }
286
287 fn result(self) -> Self::Output {
288 self.0.result()
289 }
290
291 fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
292 compute_cost.sha256_base_cost
293 }
294 fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
295 compute_cost.sha256_byte_cost
296 }
297 fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
298 compute_budget.sha256_max_slices
299 }
300}
301
302mod bls12_381_curve_id {
305 pub(crate) const BLS12_381_LE: u64 = 4;
307 pub(crate) const BLS12_381_BE: u64 = 4 | 0x80;
308
309 pub(crate) const BLS12_381_G1_LE: u64 = 5;
311 pub(crate) const BLS12_381_G1_BE: u64 = 5 | 0x80;
312
313 pub(crate) const BLS12_381_G2_LE: u64 = 6;
315 pub(crate) const BLS12_381_G2_BE: u64 = 6 | 0x80;
316}
317
318macro_rules! register_feature_gated_function {
322 ($result:expr, $is_feature_active:expr, $name:expr, $call:ty $(,)?) => {
323 if $is_feature_active {
324 <$call>::register(&mut $result, $name)
325 } else {
326 Ok(())
327 }
328 };
329}
330
331pub fn create_program_runtime_environment(
332 feature_set: &SVMFeatureSet,
333 compute_budget: &SVMTransactionExecutionBudget,
334 reject_deployment_of_broken_elfs: bool,
335 debugging_features: bool,
336) -> Result<ProgramRuntimeEnvironment, Error> {
337 let enable_alt_bn128_syscall = feature_set.enable_alt_bn128_syscall;
338 let enable_alt_bn128_compression_syscall = feature_set.enable_alt_bn128_compression_syscall;
339 let enable_big_mod_exp_syscall = feature_set.enable_big_mod_exp_syscall;
340 let blake3_syscall_enabled = feature_set.blake3_syscall_enabled;
341 let curve25519_syscall_enabled = feature_set.curve25519_syscall_enabled;
342 let enable_bls12_381_syscall = feature_set.enable_bls12_381_syscall;
343 let enable_sha512_syscall = feature_set.enable_sha512_syscall;
344 let disable_fees_sysvar = feature_set.disable_fees_sysvar;
345 let last_restart_slot_syscall_enabled = feature_set.last_restart_slot_sysvar;
346 let enable_poseidon_syscall = feature_set.enable_poseidon_syscall;
347 let remaining_compute_units_syscall_enabled =
348 feature_set.remaining_compute_units_syscall_enabled;
349 let get_sysvar_syscall_enabled = feature_set.get_sysvar_syscall_enabled;
350 let enable_get_epoch_stake_syscall = feature_set.enable_get_epoch_stake_syscall;
351 let min_sbpf_version =
352 if !feature_set.disable_sbpf_v0_execution || feature_set.reenable_sbpf_v0_execution {
353 SBPFVersion::V0
354 } else {
355 SBPFVersion::V3
356 };
357 let max_sbpf_version = SBPFVersion::V3;
358 debug_assert!(min_sbpf_version <= max_sbpf_version);
359
360 let config = Config {
361 max_call_depth: compute_budget.max_call_depth,
362 stack_frame_size: compute_budget.stack_frame_size,
363 enable_address_translation: true,
364 enable_stack_frame_gaps: !feature_set.virtual_address_space_adjustments,
365 instruction_meter_checkpoint_distance: 10000,
366 enable_instruction_meter: true,
367 enable_register_tracing: debugging_features,
368 enable_symbol_and_section_labels: debugging_features,
369 reject_broken_elfs: reject_deployment_of_broken_elfs,
370 noop_instruction_rate: 256,
371 sanitize_user_provided_values: true,
372 enabled_sbpf_versions: min_sbpf_version..=max_sbpf_version,
373 optimize_rodata: false,
374 aligned_memory_mapping: !feature_set.virtual_address_space_adjustments,
375 allow_memory_region_zero: true,
376 };
378
379 let mut result = BuiltinProgram::new_loader(config);
383
384 SyscallAbort::register(&mut result, "abort")?;
386
387 SyscallPanic::register(&mut result, "sol_panic_")?;
389
390 SyscallLog::register(&mut result, "sol_log_")?;
392 SyscallLogU64::register(&mut result, "sol_log_64_")?;
393 SyscallLogPubkey::register(&mut result, "sol_log_pubkey")?;
394 SyscallLogBpfComputeUnits::register(&mut result, "sol_log_compute_units_")?;
395
396 SyscallCreateProgramAddress::register(&mut result, "sol_create_program_address")?;
398 SyscallTryFindProgramAddress::register(&mut result, "sol_try_find_program_address")?;
399
400 SyscallHash::<Sha256Hasher>::register(&mut result, "sol_sha256")?;
402
403 SyscallHash::<Keccak256Hasher>::register(&mut result, "sol_keccak256")?;
405
406 SyscallSecp256k1Recover::register(&mut result, "sol_secp256k1_recover")?;
408
409 register_feature_gated_function!(
411 result,
412 blake3_syscall_enabled,
413 "sol_blake3",
414 SyscallHash::<Blake3Hasher>
415 )?;
416
417 register_feature_gated_function!(
419 result,
420 enable_sha512_syscall,
421 "sol_sha512",
422 SyscallHash::<Sha512Hasher>
423 )?;
424
425 register_feature_gated_function!(
427 result,
428 curve25519_syscall_enabled,
429 "sol_curve_validate_point",
430 SyscallCurvePointValidation
431 )?;
432 register_feature_gated_function!(
433 result,
434 curve25519_syscall_enabled,
435 "sol_curve_group_op",
436 SyscallCurveGroupOps
437 )?;
438 register_feature_gated_function!(
439 result,
440 curve25519_syscall_enabled,
441 "sol_curve_multiscalar_mul",
442 SyscallCurveMultiscalarMultiplication
443 )?;
444 register_feature_gated_function!(
445 result,
446 enable_bls12_381_syscall,
447 "sol_curve_decompress",
448 SyscallCurveDecompress
449 )?;
450 register_feature_gated_function!(
451 result,
452 enable_bls12_381_syscall,
453 "sol_curve_pairing_map",
454 SyscallCurvePairingMap
455 )?;
456
457 SyscallGetClockSysvar::register(&mut result, "sol_get_clock_sysvar")?;
459 SyscallGetEpochScheduleSysvar::register(&mut result, "sol_get_epoch_schedule_sysvar")?;
460 register_feature_gated_function!(
461 result,
462 !disable_fees_sysvar,
463 "sol_get_fees_sysvar",
464 SyscallGetFeesSysvar
465 )?;
466 SyscallGetRentSysvar::register(&mut result, "sol_get_rent_sysvar")?;
467
468 register_feature_gated_function!(
469 result,
470 last_restart_slot_syscall_enabled,
471 "sol_get_last_restart_slot",
472 SyscallGetLastRestartSlotSysvar
473 )?;
474
475 SyscallGetEpochRewardsSysvar::register(&mut result, "sol_get_epoch_rewards_sysvar")?;
476
477 SyscallMemcpy::register(&mut result, "sol_memcpy_")?;
479 SyscallMemmove::register(&mut result, "sol_memmove_")?;
480 SyscallMemset::register(&mut result, "sol_memset_")?;
481 SyscallMemcmp::register(&mut result, "sol_memcmp_")?;
482
483 SyscallGetProcessedSiblingInstruction::register(
485 &mut result,
486 "sol_get_processed_sibling_instruction",
487 )?;
488
489 SyscallGetStackHeight::register(&mut result, "sol_get_stack_height")?;
491
492 SyscallSetReturnData::register(&mut result, "sol_set_return_data")?;
494 SyscallGetReturnData::register(&mut result, "sol_get_return_data")?;
495
496 SyscallInvokeSignedC::register(&mut result, "sol_invoke_signed_c")?;
498 SyscallInvokeSignedRust::register(&mut result, "sol_invoke_signed_rust")?;
499
500 register_feature_gated_function!(
502 result,
503 !reject_deployment_of_broken_elfs,
504 "sol_alloc_free_",
505 SyscallAllocFree
506 )?;
507
508 register_feature_gated_function!(
510 result,
511 enable_alt_bn128_syscall,
512 "sol_alt_bn128_group_op",
513 SyscallAltBn128
514 )?;
515
516 register_feature_gated_function!(
518 result,
519 enable_big_mod_exp_syscall,
520 "sol_big_mod_exp",
521 SyscallBigModExp
522 )?;
523
524 register_feature_gated_function!(
526 result,
527 enable_poseidon_syscall,
528 "sol_poseidon",
529 SyscallPoseidon
530 )?;
531
532 register_feature_gated_function!(
534 result,
535 remaining_compute_units_syscall_enabled,
536 "sol_remaining_compute_units",
537 SyscallRemainingComputeUnits
538 )?;
539
540 register_feature_gated_function!(
542 result,
543 enable_alt_bn128_compression_syscall,
544 "sol_alt_bn128_compression",
545 SyscallAltBn128Compression
546 )?;
547
548 register_feature_gated_function!(
550 result,
551 get_sysvar_syscall_enabled,
552 "sol_get_sysvar",
553 SyscallGetSysvar
554 )?;
555
556 register_feature_gated_function!(
558 result,
559 enable_get_epoch_stake_syscall,
560 "sol_get_epoch_stake",
561 SyscallGetEpochStake
562 )?;
563
564 SyscallLogData::register(&mut result, "sol_log_data")?;
566
567 Ok(ProgramRuntimeEnvironment::from(result))
568}
569
570fn translate_type<T>(
571 memory_mapping: &MemoryMapping,
572 vm_addr: u64,
573 check_aligned: bool,
574) -> Result<&T, Error> {
575 translate_type_inner!(memory_mapping, AccessType::Load, vm_addr, T, check_aligned)
576}
577fn translate_slice<T>(
578 memory_mapping: &MemoryMapping,
579 vm_addr: u64,
580 len: u64,
581 check_aligned: bool,
582) -> Result<&[T], Error> {
583 translate_slice_inner!(
584 memory_mapping,
585 AccessType::Load,
586 vm_addr,
587 len,
588 T,
589 check_aligned,
590 )
591 .map(|value| unsafe {
592 &*value
596 })
597}
598
599fn translate_string_and_do(
602 memory_mapping: &MemoryMapping,
603 addr: u64,
604 len: u64,
605 check_aligned: bool,
606 work: &mut dyn FnMut(&str) -> Result<u64, Error>,
607) -> Result<u64, Error> {
608 let buf = translate_slice::<u8>(memory_mapping, addr, len, check_aligned)?;
609 match from_utf8(buf) {
610 Ok(message) => work(message),
611 Err(err) => Err(SyscallError::InvalidString(err, buf.to_vec()).into()),
612 }
613}
614
615#[expect(clippy::mut_from_ref)]
617fn translate_type_mut<T>(
618 memory_mapping: &MemoryMapping,
619 vm_addr: u64,
620 check_aligned: bool,
621) -> Result<&mut T, Error> {
622 translate_type_inner!(memory_mapping, AccessType::Store, vm_addr, T, check_aligned)
623}
624#[expect(clippy::mut_from_ref)]
626fn translate_slice_mut<T>(
627 memory_mapping: &MemoryMapping,
628 vm_addr: u64,
629 len: u64,
630 check_aligned: bool,
631) -> Result<&mut [T], Error> {
632 translate_slice_inner!(
633 memory_mapping,
634 AccessType::Store,
635 vm_addr,
636 len,
637 T,
638 check_aligned,
639 )
640 .map(|p| unsafe {
641 &mut *p
645 })
646}
647
648fn touch_type_mut<T>(memory_mapping: &mut MemoryMapping, vm_addr: u64) -> Result<(), Error> {
649 translate_inner!(
650 memory_mapping,
651 map_with_access_violation_handler,
652 AccessType::Store,
653 vm_addr,
654 size_of::<T>() as u64,
655 )
656 .map(|_| ())
657}
658fn touch_slice_mut<T>(
659 memory_mapping: &mut MemoryMapping,
660 vm_addr: u64,
661 element_count: u64,
662) -> Result<(), Error> {
663 if element_count == 0 {
664 return Ok(());
665 }
666 translate_inner!(
667 memory_mapping,
668 map_with_access_violation_handler,
669 AccessType::Store,
670 vm_addr,
671 element_count.saturating_mul(size_of::<T>() as u64),
672 )
673 .map(|_| ())
674}
675
676#[macro_export]
680macro_rules! translate_mut {
681 (internal, $memory_mapping:expr, &mut [$T:ty], $vm_addr_and_element_count:expr) => {
682 touch_slice_mut::<$T>(
683 $memory_mapping,
684 $vm_addr_and_element_count.0,
685 $vm_addr_and_element_count.1,
686 )?
687 };
688 (internal, $memory_mapping:expr, &mut $T:ty, $vm_addr:expr) => {
689 touch_type_mut::<$T>(
690 $memory_mapping,
691 $vm_addr,
692 )?
693 };
694 (internal, $memory_mapping:expr, $check_aligned:expr, &mut [$T:ty], $vm_addr_and_element_count:expr) => {{
695 let slice = translate_slice_mut::<$T>(
696 $memory_mapping,
697 $vm_addr_and_element_count.0,
698 $vm_addr_and_element_count.1,
699 $check_aligned,
700 )?;
701 let host_addr = slice.as_ptr().addr();
702 (slice, host_addr, std::mem::size_of::<$T>().saturating_mul($vm_addr_and_element_count.1 as usize))
703 }};
704 (internal, $memory_mapping:expr, $check_aligned:expr, &mut $T:ty, $vm_addr:expr) => {{
705 let reference = translate_type_mut::<$T>(
706 $memory_mapping,
707 $vm_addr,
708 $check_aligned,
709 )?;
710 let host_addr = reference as *const _ as usize;
711 (reference, host_addr, std::mem::size_of::<$T>())
712 }};
713 ($memory_mapping:expr, $check_aligned:expr, $(let $binding:ident : (&mut $($T:tt)+) = map($vm_addr:expr $(, $element_count:expr)?) $try:tt;)+) => {
714 $(let $binding = ($vm_addr $(, $element_count)?);)+
716 $(translate_mut!(internal, $memory_mapping, &mut $($T)+, $binding);)+
718 $(let $binding = translate_mut!(internal, $memory_mapping, $check_aligned, &mut $($T)+, $binding);)+
719 let host_ranges = [
720 $(($binding.1, $binding.2),)+
721 ];
722 for (index, range_a) in host_ranges.get(..host_ranges.len().saturating_sub(1)).unwrap().iter().enumerate() {
723 for range_b in host_ranges.get(index.saturating_add(1)..).unwrap().iter() {
724 if !is_nonoverlapping(range_a.0, range_a.1, range_b.0, range_b.1) {
725 return Err(SyscallError::CopyOverlapping.into());
726 }
727 }
728 }
729 $(let $binding = $binding.0;)+
730 };
731}
732
733declare_builtin_function!(
734 SyscallAbort,
739 fn rust(
740 _invoke_context: &mut InvokeContext<'_, '_>,
741 _arg1: u64,
742 _arg2: u64,
743 _arg3: u64,
744 _arg4: u64,
745 _arg5: u64,
746 ) -> Result<u64, Error> {
747 Err(SyscallError::Abort.into())
748 }
749);
750
751declare_builtin_function!(
752 SyscallPanic,
755 fn rust(
756 invoke_context: &mut InvokeContext<'_, '_>,
757 file: u64,
758 len: u64,
759 line: u64,
760 column: u64,
761 _arg5: u64,
762 ) -> Result<u64, Error> {
763 invoke_context.compute_meter.consume_checked(len)?;
764
765 let check_aligned = invoke_context.get_check_aligned();
766 translate_string_and_do(
767 invoke_context.memory_contexts.memory_mapping()?,
768 file,
769 len,
770 check_aligned,
771 &mut |string: &str| Err(SyscallError::Panic(string.to_string(), line, column).into()),
772 )
773 }
774);
775
776declare_builtin_function!(
777 SyscallAllocFree,
784 fn rust(
785 invoke_context: &mut InvokeContext<'_, '_>,
786 size: u64,
787 free_addr: u64,
788 _arg3: u64,
789 _arg4: u64,
790 _arg5: u64,
791 ) -> Result<u64, Error> {
792 let align = if invoke_context.get_check_aligned() {
793 BPF_ALIGN_OF_U128
794 } else {
795 align_of::<u8>()
796 };
797 let Ok(layout) = Layout::from_size_align(size as usize, align) else {
798 return Ok(0);
799 };
800 let allocator = &mut invoke_context.memory_contexts.memory_context_mut_abi_v1()?.allocator;
801 if free_addr == 0 {
802 match allocator.alloc(layout) {
803 Ok(addr) => Ok(addr),
804 Err(_) => Ok(0),
805 }
806 } else {
807 Ok(0)
809 }
810 }
811);
812
813fn translate_and_check_program_address_inputs(
814 seeds_addr: u64,
815 seeds_len: u64,
816 program_id_addr: u64,
817 memory_mapping: &mut MemoryMapping,
818 check_aligned: bool,
819) -> Result<(Vec<&[u8]>, &Pubkey), Error> {
820 let untranslated_seeds =
821 translate_slice::<VmSlice<u8>>(memory_mapping, seeds_addr, seeds_len, check_aligned)?;
822 if untranslated_seeds.len() > MAX_SEEDS {
823 return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
824 }
825 let seeds = untranslated_seeds
826 .iter()
827 .map(|untranslated_seed| {
828 if untranslated_seed.len() > MAX_SEED_LEN as u64 {
829 return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
830 }
831 translate_vm_slice(untranslated_seed, memory_mapping, check_aligned)
832 })
833 .collect::<Result<Vec<_>, Error>>()?;
834 let program_id = translate_type::<Pubkey>(memory_mapping, program_id_addr, check_aligned)?;
835 Ok((seeds, program_id))
836}
837
838declare_builtin_function!(
839 SyscallCreateProgramAddress,
841 fn rust(
842 invoke_context: &mut InvokeContext<'_, '_>,
843 seeds_addr: u64,
844 seeds_len: u64,
845 program_id_addr: u64,
846 address_addr: u64,
847 _arg5: u64,
848 ) -> Result<u64, Error> {
849 let cost = invoke_context
850 .get_execution_cost()
851 .create_program_address_units;
852 invoke_context.compute_meter.consume_checked(cost)?;
853
854 let check_aligned = invoke_context.get_check_aligned();
855 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
856 let (seeds, program_id) = translate_and_check_program_address_inputs(
857 seeds_addr,
858 seeds_len,
859 program_id_addr,
860 memory_mapping,
861 check_aligned,
862 )?;
863
864 let Ok(new_address) = Pubkey::create_program_address(&seeds, program_id) else {
865 return Ok(1);
866 };
867 translate_mut!(
868 memory_mapping,
869 check_aligned,
870 let address: (&mut [MaybeUninit<u8>]) = map(address_addr, std::mem::size_of::<Pubkey>() as u64)?;
871 );
872 address.write_copy_of_slice(new_address.as_ref());
873 Ok(0)
874 }
875);
876
877declare_builtin_function!(
878 SyscallTryFindProgramAddress,
880 fn rust(
881 invoke_context: &mut InvokeContext<'_, '_>,
882 seeds_addr: u64,
883 seeds_len: u64,
884 program_id_addr: u64,
885 address_addr: u64,
886 bump_seed_addr: u64,
887 ) -> Result<u64, Error> {
888 let cost = invoke_context
889 .get_execution_cost()
890 .create_program_address_units;
891 invoke_context.compute_meter.consume_checked(cost)?;
892
893 let check_aligned = invoke_context.get_check_aligned();
894 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
895 let (seeds, program_id) = translate_and_check_program_address_inputs(
896 seeds_addr,
897 seeds_len,
898 program_id_addr,
899 memory_mapping,
900 check_aligned,
901 )?;
902
903 let mut bump_seed = [u8::MAX];
904 for _ in 0..u8::MAX {
905 {
906 let mut seeds_with_bump = seeds.to_vec();
907 seeds_with_bump.push(&bump_seed);
908
909 if let Ok(new_address) =
910 Pubkey::create_program_address(&seeds_with_bump, program_id)
911 {
912 translate_mut!(
913 memory_mapping,
914 check_aligned,
915 let bump_seed_ref: (&mut MaybeUninit<u8>) = map(bump_seed_addr)?;
916 let address: (&mut [MaybeUninit<u8>]) = map(address_addr, std::mem::size_of::<Pubkey>() as u64)?;
917 );
918 bump_seed_ref.write(bump_seed[0]);
919 address.write_copy_of_slice(new_address.as_ref());
920 return Ok(0);
921 }
922 }
923 bump_seed[0] = bump_seed[0].saturating_sub(1);
924 invoke_context.compute_meter.consume_checked(cost)?;
925 }
926 Ok(1)
927 }
928);
929
930declare_builtin_function!(
931 SyscallSecp256k1Recover,
933 fn rust(
934 invoke_context: &mut InvokeContext<'_, '_>,
935 hash_addr: u64,
936 recovery_id_val: u64,
937 signature_addr: u64,
938 result_addr: u64,
939 _arg5: u64,
940 ) -> Result<u64, Error> {
941 let cost = invoke_context.get_execution_cost().secp256k1_recover_cost;
942 invoke_context.compute_meter.consume_checked(cost)?;
943
944 let check_aligned = invoke_context.get_check_aligned();
945 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
946
947 {
948 translate_mut!(
950 memory_mapping,
951 check_aligned,
952 let _result: (&mut [MaybeUninit<u8>]) =
953 map(result_addr, SECP256K1_PUBLIC_KEY_LENGTH as u64)?;
954 );
955 }
956 let hash = translate_slice::<u8>(
957 memory_mapping,
958 hash_addr,
959 keccak::HASH_BYTES as u64,
960 check_aligned,
961 )?;
962 let signature = translate_slice::<u8>(
963 memory_mapping,
964 signature_addr,
965 SECP256K1_SIGNATURE_LENGTH as u64,
966 check_aligned,
967 )?;
968
969 let Ok(message) = libsecp256k1::Message::parse_slice(hash) else {
970 return Ok(Secp256k1RecoverError::InvalidHash.into());
971 };
972 let Ok(adjusted_recover_id_val) = recovery_id_val.try_into() else {
973 return Ok(Secp256k1RecoverError::InvalidRecoveryId.into());
974 };
975 let Ok(recovery_id) = libsecp256k1::RecoveryId::parse(adjusted_recover_id_val) else {
976 return Ok(Secp256k1RecoverError::InvalidRecoveryId.into());
977 };
978 let Ok(signature) = libsecp256k1::Signature::parse_standard_slice(signature) else {
979 return Ok(Secp256k1RecoverError::InvalidSignature.into());
980 };
981 let public_key = match libsecp256k1::recover(&message, &signature, &recovery_id) {
982 Ok(key) => key.serialize(),
983 Err(_) => {
984 return Ok(Secp256k1RecoverError::InvalidSignature.into());
985 }
986 };
987
988 translate_mut!(
989 memory_mapping,
990 check_aligned,
991 let result: (&mut [MaybeUninit<u8>]) =
992 map(result_addr, SECP256K1_PUBLIC_KEY_LENGTH as u64)?;
993 );
994 result.write_copy_of_slice(&public_key[1..65]);
995 Ok(SUCCESS)
996 }
997);
998
999declare_builtin_function!(
1000 SyscallCurvePointValidation,
1006 fn rust(
1007 invoke_context: &mut InvokeContext<'_, '_>,
1008 curve_id: u64,
1009 point_addr: u64,
1010 _arg3: u64,
1011 _arg4: u64,
1012 _arg5: u64,
1013 ) -> Result<u64, Error> {
1014 use {
1015 crate::bls12_381_curve_id::*,
1016 solana_curve25519::{curve_syscall_traits::*, edwards, ristretto},
1017 };
1018
1019 if !invoke_context.get_feature_set().enable_bls12_381_syscall
1021 && matches!(
1022 curve_id,
1023 BLS12_381_G1_BE | BLS12_381_G1_LE | BLS12_381_G2_BE | BLS12_381_G2_LE
1024 )
1025 {
1026 return Err(SyscallError::InvalidAttribute.into());
1027 }
1028
1029 let check_aligned = invoke_context.get_check_aligned();
1030 let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
1031 match curve_id {
1032 CURVE25519_EDWARDS => {
1033 let cost = invoke_context
1034 .get_execution_cost()
1035 .curve25519_edwards_validate_point_cost;
1036 invoke_context.compute_meter.consume_checked(cost)?;
1037
1038 let point = translate_type::<edwards::PodEdwardsPoint>(
1039 memory_mapping,
1040 point_addr,
1041 check_aligned,
1042 )?;
1043
1044 if edwards::validate_edwards(point) {
1045 Ok(0)
1046 } else {
1047 Ok(1)
1048 }
1049 }
1050 CURVE25519_RISTRETTO => {
1051 let cost = invoke_context
1052 .get_execution_cost()
1053 .curve25519_ristretto_validate_point_cost;
1054 invoke_context.compute_meter.consume_checked(cost)?;
1055
1056 let point = translate_type::<ristretto::PodRistrettoPoint>(
1057 memory_mapping,
1058 point_addr,
1059 check_aligned,
1060 )?;
1061
1062 if ristretto::validate_ristretto(point) {
1063 Ok(0)
1064 } else {
1065 Ok(1)
1066 }
1067 }
1068 BLS12_381_G1_LE | BLS12_381_G1_BE => {
1069 let cost = invoke_context
1070 .get_execution_cost()
1071 .bls12_381_g1_validate_cost;
1072 invoke_context.compute_meter.consume_checked(cost)?;
1073
1074 let point = translate_type::<solana_bls12_381_syscall::PodG1Point>(
1075 memory_mapping,
1076 point_addr,
1077 check_aligned,
1078 )?;
1079
1080 let endianness = if curve_id == BLS12_381_G1_LE {
1081 solana_bls12_381_syscall::Endianness::LE
1082 } else {
1083 solana_bls12_381_syscall::Endianness::BE
1084 };
1085
1086 if solana_bls12_381_syscall::bls12_381_g1_point_validation(
1087 solana_bls12_381_syscall::Version::V0,
1088 point,
1089 endianness,
1090 ) {
1091 Ok(SUCCESS)
1092 } else {
1093 Ok(1)
1094 }
1095 }
1096 BLS12_381_G2_LE | BLS12_381_G2_BE => {
1097 let cost = invoke_context
1098 .get_execution_cost()
1099 .bls12_381_g2_validate_cost;
1100 invoke_context.compute_meter.consume_checked(cost)?;
1101
1102 let point = translate_type::<solana_bls12_381_syscall::PodG2Point>(
1103 memory_mapping,
1104 point_addr,
1105 check_aligned,
1106 )?;
1107
1108 let endianness = if curve_id == BLS12_381_G2_LE {
1109 solana_bls12_381_syscall::Endianness::LE
1110 } else {
1111 solana_bls12_381_syscall::Endianness::BE
1112 };
1113
1114 if solana_bls12_381_syscall::bls12_381_g2_point_validation(
1115 solana_bls12_381_syscall::Version::V0,
1116 point,
1117 endianness,
1118 ) {
1119 Ok(SUCCESS)
1120 } else {
1121 Ok(1)
1122 }
1123 }
1124 _ => {
1125 if invoke_context.get_feature_set().abort_on_invalid_curve {
1126 Err(SyscallError::InvalidAttribute.into())
1127 } else {
1128 Ok(1)
1129 }
1130 }
1131 }
1132 }
1133);
1134
1135declare_builtin_function!(
1136 SyscallCurveDecompress,
1141 fn rust(
1142 invoke_context: &mut InvokeContext<'_, '_>,
1143 curve_id: u64,
1144 point_addr: u64,
1145 result_addr: u64,
1146 _arg4: u64,
1147 _arg5: u64,
1148 ) -> Result<u64, Error> {
1149 use {
1150 crate::bls12_381_curve_id::*,
1151 solana_bls12_381_syscall::{
1152 PodG1Compressed as PodBLSG1Compressed, PodG1Point as PodBLSG1Point,
1153 PodG2Compressed as PodBLSG2Compressed, PodG2Point as PodBLSG2Point,
1154 },
1155 };
1156
1157 let check_aligned = invoke_context.get_check_aligned();
1158 match curve_id {
1159 BLS12_381_G1_LE | BLS12_381_G1_BE => {
1160 let cost = invoke_context
1161 .get_execution_cost()
1162 .bls12_381_g1_decompress_cost;
1163 invoke_context.compute_meter.consume_checked(cost)?;
1164
1165 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1166 let compressed_point = translate_type::<PodBLSG1Compressed>(
1167 memory_mapping,
1168 point_addr,
1169 check_aligned,
1170 )?;
1171
1172 let endianness = if curve_id == BLS12_381_G1_LE {
1173 solana_bls12_381_syscall::Endianness::LE
1174 } else {
1175 solana_bls12_381_syscall::Endianness::BE
1176 };
1177
1178 if let Some(affine_point) = solana_bls12_381_syscall::bls12_381_g1_decompress(
1179 solana_bls12_381_syscall::Version::V0,
1180 compressed_point,
1181 endianness,
1182 ) {
1183 translate_mut!(
1184 memory_mapping,
1185 check_aligned,
1186 let result_ref_mut: (&mut MaybeUninit<PodBLSG1Point>) = map(result_addr)?;
1187 );
1188 result_ref_mut.write(affine_point);
1189 Ok(SUCCESS)
1190 } else {
1191 Ok(1)
1192 }
1193 }
1194 BLS12_381_G2_LE | BLS12_381_G2_BE => {
1195 let cost = invoke_context
1196 .get_execution_cost()
1197 .bls12_381_g2_decompress_cost;
1198 invoke_context.compute_meter.consume_checked(cost)?;
1199
1200 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1201 let compressed_point = translate_type::<PodBLSG2Compressed>(
1202 memory_mapping,
1203 point_addr,
1204 check_aligned,
1205 )?;
1206
1207 let endianness = if curve_id == BLS12_381_G2_LE {
1208 solana_bls12_381_syscall::Endianness::LE
1209 } else {
1210 solana_bls12_381_syscall::Endianness::BE
1211 };
1212
1213 if let Some(affine_point) = solana_bls12_381_syscall::bls12_381_g2_decompress(
1214 solana_bls12_381_syscall::Version::V0,
1215 compressed_point,
1216 endianness,
1217 ) {
1218 translate_mut!(
1219 memory_mapping,
1220 check_aligned,
1221 let result_ref_mut: (&mut MaybeUninit<PodBLSG2Point>) = map(result_addr)?;
1222 );
1223 result_ref_mut.write(affine_point);
1224 Ok(SUCCESS)
1225 } else {
1226 Ok(1)
1227 }
1228 }
1229 _ => Err(SyscallError::InvalidAttribute.into()),
1230 }
1231 }
1232);
1233
1234declare_builtin_function!(
1235 SyscallCurveGroupOps,
1241 fn rust(
1242 invoke_context: &mut InvokeContext<'_, '_>,
1243 curve_id: u64,
1244 group_op: u64,
1245 left_input_addr: u64,
1246 right_input_addr: u64,
1247 result_point_addr: u64,
1248 ) -> Result<u64, Error> {
1249 use {
1250 crate::bls12_381_curve_id::*,
1251 solana_bls12_381_syscall::{
1252 PodG1Point as PodBLSG1Point, PodG2Point as PodBLSG2Point, PodScalar as PodBLSScalar,
1253 },
1254 solana_curve25519::{
1255 curve_syscall_traits::*,
1256 edwards::{self, PodEdwardsPoint},
1257 ristretto::{self, PodRistrettoPoint},
1258 scalar,
1259 },
1260 };
1261
1262 if !invoke_context.get_feature_set().enable_bls12_381_syscall
1263 && matches!(
1264 curve_id,
1265 BLS12_381_G1_BE | BLS12_381_G1_LE | BLS12_381_G2_BE | BLS12_381_G2_LE
1266 )
1267 {
1268 return Err(SyscallError::InvalidAttribute.into());
1269 }
1270
1271 let check_aligned = invoke_context.get_check_aligned();
1272 match curve_id {
1273 CURVE25519_EDWARDS => match group_op {
1274 ADD => {
1275 let cost = invoke_context
1276 .get_execution_cost()
1277 .curve25519_edwards_add_cost;
1278 invoke_context.compute_meter.consume_checked(cost)?;
1279
1280 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1281 let left_point = translate_type::<PodEdwardsPoint>(
1282 memory_mapping,
1283 left_input_addr,
1284 check_aligned,
1285 )?;
1286 let right_point = translate_type::<PodEdwardsPoint>(
1287 memory_mapping,
1288 right_input_addr,
1289 check_aligned,
1290 )?;
1291
1292 if let Some(result_point) = edwards::add_edwards(left_point, right_point) {
1293 translate_mut!(
1294 memory_mapping,
1295 check_aligned,
1296 let result_point_ref_mut: (&mut MaybeUninit<PodEdwardsPoint>) = map(result_point_addr)?;
1297 );
1298 result_point_ref_mut.write(result_point);
1299 Ok(0)
1300 } else {
1301 Ok(1)
1302 }
1303 }
1304 SUB => {
1305 let cost = invoke_context
1306 .get_execution_cost()
1307 .curve25519_edwards_subtract_cost;
1308 invoke_context.compute_meter.consume_checked(cost)?;
1309
1310 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1311 let left_point = translate_type::<PodEdwardsPoint>(
1312 memory_mapping,
1313 left_input_addr,
1314 check_aligned,
1315 )?;
1316 let right_point = translate_type::<PodEdwardsPoint>(
1317 memory_mapping,
1318 right_input_addr,
1319 check_aligned,
1320 )?;
1321
1322 if let Some(result_point) = edwards::subtract_edwards(left_point, right_point) {
1323 translate_mut!(
1324 memory_mapping,
1325 check_aligned,
1326 let result_point_ref_mut: (&mut MaybeUninit<PodEdwardsPoint>) = map(result_point_addr)?;
1327 );
1328 result_point_ref_mut.write(result_point);
1329 Ok(0)
1330 } else {
1331 Ok(1)
1332 }
1333 }
1334 MUL => {
1335 let cost = invoke_context
1336 .get_execution_cost()
1337 .curve25519_edwards_multiply_cost;
1338 invoke_context.compute_meter.consume_checked(cost)?;
1339
1340 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1341 let scalar = translate_type::<scalar::PodScalar>(
1342 memory_mapping,
1343 left_input_addr,
1344 check_aligned,
1345 )?;
1346 let input_point = translate_type::<PodEdwardsPoint>(
1347 memory_mapping,
1348 right_input_addr,
1349 check_aligned,
1350 )?;
1351
1352 if let Some(result_point) = edwards::multiply_edwards(scalar, input_point) {
1353 translate_mut!(
1354 memory_mapping,
1355 check_aligned,
1356 let result_point_ref_mut: (&mut MaybeUninit<PodEdwardsPoint>) = map(result_point_addr)?;
1357 );
1358 result_point_ref_mut.write(result_point);
1359 Ok(0)
1360 } else {
1361 Ok(1)
1362 }
1363 }
1364 _ => {
1365 if invoke_context.get_feature_set().abort_on_invalid_curve {
1366 Err(SyscallError::InvalidAttribute.into())
1367 } else {
1368 Ok(1)
1369 }
1370 }
1371 },
1372
1373 CURVE25519_RISTRETTO => match group_op {
1374 ADD => {
1375 let cost = invoke_context
1376 .get_execution_cost()
1377 .curve25519_ristretto_add_cost;
1378 invoke_context.compute_meter.consume_checked(cost)?;
1379
1380 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1381 let left_point = translate_type::<PodRistrettoPoint>(
1382 memory_mapping,
1383 left_input_addr,
1384 check_aligned,
1385 )?;
1386 let right_point = translate_type::<PodRistrettoPoint>(
1387 memory_mapping,
1388 right_input_addr,
1389 check_aligned,
1390 )?;
1391
1392 if let Some(result_point) = ristretto::add_ristretto(left_point, right_point) {
1393 translate_mut!(
1394 memory_mapping,
1395 check_aligned,
1396 let result_point_ref_mut: (&mut MaybeUninit<PodRistrettoPoint>) = map(result_point_addr)?;
1397 );
1398 result_point_ref_mut.write(result_point);
1399 Ok(0)
1400 } else {
1401 Ok(1)
1402 }
1403 }
1404 SUB => {
1405 let cost = invoke_context
1406 .get_execution_cost()
1407 .curve25519_ristretto_subtract_cost;
1408 invoke_context.compute_meter.consume_checked(cost)?;
1409
1410 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1411 let left_point = translate_type::<PodRistrettoPoint>(
1412 memory_mapping,
1413 left_input_addr,
1414 check_aligned,
1415 )?;
1416 let right_point = translate_type::<PodRistrettoPoint>(
1417 memory_mapping,
1418 right_input_addr,
1419 check_aligned,
1420 )?;
1421
1422 if let Some(result_point) =
1423 ristretto::subtract_ristretto(left_point, right_point)
1424 {
1425 translate_mut!(
1426 memory_mapping,
1427 check_aligned,
1428 let result_point_ref_mut: (&mut MaybeUninit<PodRistrettoPoint>) = map(result_point_addr)?;
1429 );
1430 result_point_ref_mut.write(result_point);
1431 Ok(0)
1432 } else {
1433 Ok(1)
1434 }
1435 }
1436 MUL => {
1437 let cost = invoke_context
1438 .get_execution_cost()
1439 .curve25519_ristretto_multiply_cost;
1440 invoke_context.compute_meter.consume_checked(cost)?;
1441
1442 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1443 let scalar = translate_type::<scalar::PodScalar>(
1444 memory_mapping,
1445 left_input_addr,
1446 check_aligned,
1447 )?;
1448 let input_point = translate_type::<PodRistrettoPoint>(
1449 memory_mapping,
1450 right_input_addr,
1451 check_aligned,
1452 )?;
1453
1454 if let Some(result_point) = ristretto::multiply_ristretto(scalar, input_point) {
1455 translate_mut!(
1456 memory_mapping,
1457 check_aligned,
1458 let result_point_ref_mut: (&mut MaybeUninit<PodRistrettoPoint>) = map(result_point_addr)?;
1459 );
1460 result_point_ref_mut.write(result_point);
1461 Ok(0)
1462 } else {
1463 Ok(1)
1464 }
1465 }
1466 _ => {
1467 if invoke_context.get_feature_set().abort_on_invalid_curve {
1468 Err(SyscallError::InvalidAttribute.into())
1469 } else {
1470 Ok(1)
1471 }
1472 }
1473 },
1474
1475 BLS12_381_G1_LE | BLS12_381_G1_BE => {
1476 let endianness = if curve_id == BLS12_381_G1_LE {
1477 solana_bls12_381_syscall::Endianness::LE
1478 } else {
1479 solana_bls12_381_syscall::Endianness::BE
1480 };
1481
1482 match group_op {
1483 ADD => {
1484 let cost = invoke_context.get_execution_cost().bls12_381_g1_add_cost;
1485 invoke_context.compute_meter.consume_checked(cost)?;
1486
1487 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1488 let left_point = translate_type::<PodBLSG1Point>(
1489 memory_mapping,
1490 left_input_addr,
1491 check_aligned,
1492 )?;
1493 let right_point = translate_type::<PodBLSG1Point>(
1494 memory_mapping,
1495 right_input_addr,
1496 check_aligned,
1497 )?;
1498
1499 if let Some(result_point) =
1500 solana_bls12_381_syscall::bls12_381_g1_addition_unchecked(
1501 solana_bls12_381_syscall::Version::V0,
1502 left_point,
1503 right_point,
1504 endianness,
1505 )
1506 {
1507 translate_mut!(
1508 memory_mapping,
1509 check_aligned,
1510 let result_point_ref_mut: (&mut MaybeUninit<PodBLSG1Point>) = map(result_point_addr)?;
1511 );
1512 result_point_ref_mut.write(result_point);
1513 Ok(SUCCESS)
1514 } else {
1515 Ok(1)
1516 }
1517 }
1518 SUB => {
1519 let cost = invoke_context
1520 .get_execution_cost()
1521 .bls12_381_g1_subtract_cost;
1522 invoke_context.compute_meter.consume_checked(cost)?;
1523
1524 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1525 let left_point = translate_type::<PodBLSG1Point>(
1526 memory_mapping,
1527 left_input_addr,
1528 check_aligned,
1529 )?;
1530 let right_point = translate_type::<PodBLSG1Point>(
1531 memory_mapping,
1532 right_input_addr,
1533 check_aligned,
1534 )?;
1535
1536 if let Some(result_point) =
1537 solana_bls12_381_syscall::bls12_381_g1_subtraction_unchecked(
1538 solana_bls12_381_syscall::Version::V0,
1539 left_point,
1540 right_point,
1541 endianness,
1542 )
1543 {
1544 translate_mut!(
1545 memory_mapping,
1546 check_aligned,
1547 let result_point_ref_mut: (&mut MaybeUninit<PodBLSG1Point>) = map(result_point_addr)?;
1548 );
1549 result_point_ref_mut.write(result_point);
1550 Ok(SUCCESS)
1551 } else {
1552 Ok(1)
1553 }
1554 }
1555 MUL => {
1556 let cost = invoke_context
1557 .get_execution_cost()
1558 .bls12_381_g1_multiply_cost;
1559 invoke_context.compute_meter.consume_checked(cost)?;
1560
1561 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1562 let scalar = translate_type::<PodBLSScalar>(
1563 memory_mapping,
1564 left_input_addr,
1565 check_aligned,
1566 )?;
1567 let point = translate_type::<PodBLSG1Point>(
1568 memory_mapping,
1569 right_input_addr,
1570 check_aligned,
1571 )?;
1572
1573 if let Some(result_point) =
1574 solana_bls12_381_syscall::bls12_381_g1_multiplication(
1575 solana_bls12_381_syscall::Version::V0,
1576 point,
1577 scalar,
1578 endianness,
1579 )
1580 {
1581 translate_mut!(
1582 memory_mapping,
1583 check_aligned,
1584 let result_point_ref_mut: (&mut MaybeUninit<PodBLSG1Point>) = map(result_point_addr)?;
1585 );
1586 result_point_ref_mut.write(result_point);
1587 Ok(SUCCESS)
1588 } else {
1589 Ok(1)
1590 }
1591 }
1592 _ => Err(SyscallError::InvalidAttribute.into()),
1593 }
1594 }
1595
1596 BLS12_381_G2_LE | BLS12_381_G2_BE => {
1598 let endianness = if curve_id == BLS12_381_G2_LE {
1599 solana_bls12_381_syscall::Endianness::LE
1600 } else {
1601 solana_bls12_381_syscall::Endianness::BE
1602 };
1603
1604 match group_op {
1605 ADD => {
1606 let cost = invoke_context.get_execution_cost().bls12_381_g2_add_cost;
1607 invoke_context.compute_meter.consume_checked(cost)?;
1608
1609 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1610 let left_point = translate_type::<PodBLSG2Point>(
1611 memory_mapping,
1612 left_input_addr,
1613 check_aligned,
1614 )?;
1615 let right_point = translate_type::<PodBLSG2Point>(
1616 memory_mapping,
1617 right_input_addr,
1618 check_aligned,
1619 )?;
1620
1621 if let Some(result_point) =
1622 solana_bls12_381_syscall::bls12_381_g2_addition_unchecked(
1623 solana_bls12_381_syscall::Version::V0,
1624 left_point,
1625 right_point,
1626 endianness,
1627 )
1628 {
1629 translate_mut!(
1630 memory_mapping,
1631 check_aligned,
1632 let result_point_ref_mut: (&mut MaybeUninit<PodBLSG2Point>) = map(result_point_addr)?;
1633 );
1634 result_point_ref_mut.write(result_point);
1635 Ok(SUCCESS)
1636 } else {
1637 Ok(1)
1638 }
1639 }
1640 SUB => {
1641 let cost = invoke_context
1642 .get_execution_cost()
1643 .bls12_381_g2_subtract_cost;
1644 invoke_context.compute_meter.consume_checked(cost)?;
1645
1646 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1647 let left_point = translate_type::<PodBLSG2Point>(
1648 memory_mapping,
1649 left_input_addr,
1650 check_aligned,
1651 )?;
1652 let right_point = translate_type::<PodBLSG2Point>(
1653 memory_mapping,
1654 right_input_addr,
1655 check_aligned,
1656 )?;
1657
1658 if let Some(result_point) =
1659 solana_bls12_381_syscall::bls12_381_g2_subtraction_unchecked(
1660 solana_bls12_381_syscall::Version::V0,
1661 left_point,
1662 right_point,
1663 endianness,
1664 )
1665 {
1666 translate_mut!(
1667 memory_mapping,
1668 check_aligned,
1669 let result_point_ref_mut: (&mut MaybeUninit<PodBLSG2Point>) = map(result_point_addr)?;
1670 );
1671 result_point_ref_mut.write(result_point);
1672 Ok(SUCCESS)
1673 } else {
1674 Ok(1)
1675 }
1676 }
1677 MUL => {
1678 let cost = invoke_context
1679 .get_execution_cost()
1680 .bls12_381_g2_multiply_cost;
1681 invoke_context.compute_meter.consume_checked(cost)?;
1682
1683 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1684 let scalar = translate_type::<PodBLSScalar>(
1685 memory_mapping,
1686 left_input_addr,
1687 check_aligned,
1688 )?;
1689 let point = translate_type::<PodBLSG2Point>(
1690 memory_mapping,
1691 right_input_addr,
1692 check_aligned,
1693 )?;
1694
1695 if let Some(result_point) =
1696 solana_bls12_381_syscall::bls12_381_g2_multiplication(
1697 solana_bls12_381_syscall::Version::V0,
1698 point,
1699 scalar,
1700 endianness,
1701 )
1702 {
1703 translate_mut!(
1704 memory_mapping,
1705 check_aligned,
1706 let result_point_ref_mut: (&mut MaybeUninit<PodBLSG2Point>) = map(result_point_addr)?;
1707 );
1708 result_point_ref_mut.write(result_point);
1709 Ok(SUCCESS)
1710 } else {
1711 Ok(1)
1712 }
1713 }
1714 _ => Err(SyscallError::InvalidAttribute.into()),
1715 }
1716 }
1717
1718 _ => {
1719 if invoke_context.get_feature_set().abort_on_invalid_curve {
1720 Err(SyscallError::InvalidAttribute.into())
1721 } else {
1722 Ok(1)
1723 }
1724 }
1725 }
1726 }
1727);
1728
1729declare_builtin_function!(
1730 SyscallCurveMultiscalarMultiplication,
1735 fn rust(
1736 invoke_context: &mut InvokeContext<'_, '_>,
1737 curve_id: u64,
1738 scalars_addr: u64,
1739 points_addr: u64,
1740 points_len: u64,
1741 result_point_addr: u64,
1742 ) -> Result<u64, Error> {
1743 use solana_curve25519::{
1744 curve_syscall_traits::*,
1745 edwards::{self, PodEdwardsPoint},
1746 ristretto::{self, PodRistrettoPoint},
1747 scalar,
1748 };
1749
1750 if points_len > 512 {
1751 return Err(Box::new(SyscallError::InvalidLength));
1752 }
1753
1754 let check_aligned = invoke_context.get_check_aligned();
1755 match curve_id {
1756 CURVE25519_EDWARDS => {
1757 let cost = invoke_context
1758 .get_execution_cost()
1759 .curve25519_edwards_msm_base_cost
1760 .saturating_add(
1761 invoke_context
1762 .get_execution_cost()
1763 .curve25519_edwards_msm_incremental_cost
1764 .saturating_mul(points_len.saturating_sub(1)),
1765 );
1766 invoke_context.compute_meter.consume_checked(cost)?;
1767
1768 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1769 let scalars = translate_slice::<scalar::PodScalar>(
1770 memory_mapping,
1771 scalars_addr,
1772 points_len,
1773 check_aligned,
1774 )?;
1775
1776 let points = translate_slice::<PodEdwardsPoint>(
1777 memory_mapping,
1778 points_addr,
1779 points_len,
1780 check_aligned,
1781 )?;
1782
1783 if let Some(result_point) = edwards::multiscalar_multiply_edwards(scalars, points) {
1784 translate_mut!(
1785 memory_mapping,
1786 check_aligned,
1787 let result_point_ref_mut: (&mut MaybeUninit<PodEdwardsPoint>) = map(result_point_addr)?;
1788 );
1789 result_point_ref_mut.write(result_point);
1790 Ok(0)
1791 } else {
1792 Ok(1)
1793 }
1794 }
1795
1796 CURVE25519_RISTRETTO => {
1797 let cost = invoke_context
1798 .get_execution_cost()
1799 .curve25519_ristretto_msm_base_cost
1800 .saturating_add(
1801 invoke_context
1802 .get_execution_cost()
1803 .curve25519_ristretto_msm_incremental_cost
1804 .saturating_mul(points_len.saturating_sub(1)),
1805 );
1806 invoke_context.compute_meter.consume_checked(cost)?;
1807
1808 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1809 let scalars = translate_slice::<scalar::PodScalar>(
1810 memory_mapping,
1811 scalars_addr,
1812 points_len,
1813 check_aligned,
1814 )?;
1815
1816 let points = translate_slice::<PodRistrettoPoint>(
1817 memory_mapping,
1818 points_addr,
1819 points_len,
1820 check_aligned,
1821 )?;
1822
1823 if let Some(result_point) =
1824 ristretto::multiscalar_multiply_ristretto(scalars, points)
1825 {
1826 translate_mut!(
1827 memory_mapping,
1828 check_aligned,
1829 let result_point_ref_mut: (&mut MaybeUninit<PodRistrettoPoint>) = map(result_point_addr)?;
1830 );
1831 result_point_ref_mut.write(result_point);
1832 Ok(0)
1833 } else {
1834 Ok(1)
1835 }
1836 }
1837
1838 _ => {
1839 if invoke_context.get_feature_set().abort_on_invalid_curve {
1840 Err(SyscallError::InvalidAttribute.into())
1841 } else {
1842 Ok(1)
1843 }
1844 }
1845 }
1846 }
1847);
1848
1849declare_builtin_function!(
1850 SyscallCurvePairingMap,
1855 fn rust(
1856 invoke_context: &mut InvokeContext<'_, '_>,
1857 curve_id: u64,
1858 num_pairs: u64,
1859 g1_points_addr: u64,
1860 g2_points_addr: u64,
1861 result_addr: u64,
1862 ) -> Result<u64, Error> {
1863 use {
1864 crate::bls12_381_curve_id::*,
1865 solana_bls12_381_syscall::{
1866 PodG1Point as PodBLSG1Point, PodG2Point as PodBLSG2Point,
1867 PodGtElement as PodBLSGtElement,
1868 },
1869 };
1870
1871 let check_aligned = invoke_context.get_check_aligned();
1872 match curve_id {
1873 BLS12_381_LE | BLS12_381_BE => {
1874 let execution_cost = invoke_context.get_execution_cost();
1875 let cost = execution_cost
1876 .bls12_381_one_pair_cost
1877 .saturating_add(
1878 execution_cost
1879 .bls12_381_additional_pair_cost
1880 .saturating_mul(num_pairs.saturating_sub(1)),
1881 );
1882 invoke_context.compute_meter.consume_checked(cost)?;
1883
1884 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
1885 let g1_points = translate_slice::<PodBLSG1Point>(
1886 memory_mapping,
1887 g1_points_addr,
1888 num_pairs,
1889 check_aligned,
1890 )?;
1891
1892 let g2_points = translate_slice::<PodBLSG2Point>(
1893 memory_mapping,
1894 g2_points_addr,
1895 num_pairs,
1896 check_aligned,
1897 )?;
1898
1899 let endianness = if curve_id == BLS12_381_LE {
1900 solana_bls12_381_syscall::Endianness::LE
1901 } else {
1902 solana_bls12_381_syscall::Endianness::BE
1903 };
1904
1905 if let Some(gt_element) = solana_bls12_381_syscall::bls12_381_pairing_map(
1906 solana_bls12_381_syscall::Version::V0,
1907 g1_points,
1908 g2_points,
1909 endianness,
1910 ) {
1911 translate_mut!(
1912 memory_mapping,
1913 check_aligned,
1914 let result_ref_mut: (&mut MaybeUninit<PodBLSGtElement>) = map(result_addr)?;
1915 );
1916 result_ref_mut.write(gt_element);
1917 Ok(SUCCESS)
1918 } else {
1919 Ok(1)
1920 }
1921 }
1922 _ => {
1923 Err(SyscallError::InvalidAttribute.into())
1924 }
1925 }
1926 }
1927);
1928
1929declare_builtin_function!(
1930 SyscallSetReturnData,
1932 fn rust(
1933 invoke_context: &mut InvokeContext<'_, '_>,
1934 addr: u64,
1935 len: u64,
1936 _arg3: u64,
1937 _arg4: u64,
1938 _arg5: u64,
1939 ) -> Result<u64, Error> {
1940 let execution_cost = invoke_context.get_execution_cost();
1941
1942 let cost = len
1943 .checked_div(execution_cost.cpi_bytes_per_unit)
1944 .unwrap_or(u64::MAX)
1945 .saturating_add(execution_cost.syscall_base_cost);
1946 invoke_context.compute_meter.consume_checked(cost)?;
1947
1948 if len > MAX_RETURN_DATA as u64 {
1949 return Err(SyscallError::ReturnDataTooLarge(len, MAX_RETURN_DATA as u64).into());
1950 }
1951
1952 let return_data = if len == 0 {
1953 Vec::new()
1954 } else {
1955 let check_aligned = invoke_context.get_check_aligned();
1956 let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
1957 translate_slice::<u8>(
1958 memory_mapping,
1959 addr,
1960 len,
1961 check_aligned,
1962 )?
1963 .to_vec()
1964 };
1965 let transaction_context = &mut invoke_context.transaction_context;
1966 let program_id = *transaction_context
1967 .get_current_instruction_context()
1968 .and_then(|instruction_context| {
1969 instruction_context.get_program_key()
1970 })?;
1971
1972 transaction_context.set_return_data(program_id, return_data)?;
1973
1974 Ok(0)
1975 }
1976);
1977
1978declare_builtin_function!(
1979 SyscallGetReturnData,
1981 fn rust(
1982 invoke_context: &mut InvokeContext<'_, '_>,
1983 return_data_addr: u64,
1984 length: u64,
1985 program_id_addr: u64,
1986 _arg4: u64,
1987 _arg5: u64,
1988 ) -> Result<u64, Error> {
1989 let execution_cost = invoke_context.get_execution_cost();
1990
1991 invoke_context.compute_meter.consume_checked(execution_cost.syscall_base_cost)?;
1992
1993 let (program_id, return_data) = invoke_context.transaction_context.get_return_data();
1994 let length = length.min(return_data.len() as u64);
1995 if length != 0 {
1996 let cost = length
1997 .saturating_add(size_of::<Pubkey>() as u64)
1998 .checked_div(execution_cost.cpi_bytes_per_unit)
1999 .unwrap_or(u64::MAX);
2000 invoke_context.compute_meter.consume_checked(cost)?;
2001 let check_aligned = invoke_context.get_check_aligned();
2002 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2003 translate_mut!(
2004 memory_mapping,
2005 check_aligned,
2006 let to_slice: (&mut [MaybeUninit<u8>]) = map(return_data_addr, length)?;
2007 let program_id_result: (&mut MaybeUninit<Pubkey>) = map(program_id_addr)?;
2008 );
2009
2010 let from_slice = return_data
2011 .get(..length as usize)
2012 .ok_or(SyscallError::InvokeContextBorrowFailed)?;
2013 if to_slice.len() != from_slice.len() {
2014 return Err(SyscallError::InvalidLength.into());
2015 }
2016 to_slice.write_copy_of_slice(from_slice);
2017 program_id_result.write(*program_id);
2018 }
2019
2020 Ok(return_data.len() as u64)
2022 }
2023);
2024
2025declare_builtin_function!(
2026 SyscallGetProcessedSiblingInstruction,
2028 fn rust(
2029 invoke_context: &mut InvokeContext<'_, '_>,
2030 index: u64,
2031 meta_addr: u64,
2032 program_id_addr: u64,
2033 data_addr: u64,
2034 accounts_addr: u64,
2035 ) -> Result<u64, Error> {
2036 let execution_cost = invoke_context.get_execution_cost();
2037
2038 invoke_context.compute_meter.consume_checked(execution_cost.syscall_base_cost)?;
2039
2040 let stack_height = invoke_context.get_stack_height();
2041 let mut reverse_index_at_stack_height = 0;
2042 let mut found_instruction_context = None;
2043 let current_ix_caller = invoke_context.transaction_context.get_current_instruction_context()?.get_index_of_caller();
2044
2045 let range = if stack_height == 1 {
2047 0..invoke_context.transaction_context.next_top_level_instruction_index()
2048 } else {
2049 let end = invoke_context.transaction_context.get_instruction_trace_length();
2050 let start = end.saturating_sub(invoke_context.transaction_context.number_of_cpis_in_trace());
2051 start..end
2052 };
2053
2054 for index_in_trace in range.rev() {
2055 let instruction_context = invoke_context
2056 .transaction_context
2057 .get_instruction_context_at_index_in_trace(index_in_trace)?;
2058 if instruction_context.get_index_of_caller() != current_ix_caller {
2061 continue;
2062 }
2063
2064 if instruction_context.get_stack_height() < stack_height {
2065 break;
2066 }
2067 if instruction_context.get_stack_height() == stack_height {
2068 if index.saturating_add(1) == reverse_index_at_stack_height {
2069 found_instruction_context = Some(instruction_context);
2070 break;
2071 }
2072 reverse_index_at_stack_height = reverse_index_at_stack_height.saturating_add(1);
2073 }
2074 }
2075
2076 let check_aligned = invoke_context.get_check_aligned();
2077 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2078 if let Some(instruction_context) = found_instruction_context {
2079 translate_mut!(
2080 memory_mapping,
2081 check_aligned,
2082 let result_header: (&mut ProcessedSiblingInstruction) = map(meta_addr)?;
2083 );
2084
2085 if result_header.data_len == (instruction_context.get_instruction_data().len() as u64)
2086 && result_header.accounts_len
2087 == (instruction_context.get_number_of_instruction_accounts() as u64)
2088 {
2089 translate_mut!(
2090 memory_mapping,
2091 check_aligned,
2092 let program_id: (&mut MaybeUninit<Pubkey>) = map(program_id_addr)?;
2093 let data: (&mut [MaybeUninit<u8>]) = map(data_addr, result_header.data_len)?;
2094 let accounts: (&mut [MaybeUninit<AccountMeta>]) = map(accounts_addr, result_header.accounts_len)?;
2095 let result_header: (&mut ProcessedSiblingInstruction) = map(meta_addr)?;
2096 );
2097 let _ = result_header;
2099
2100 program_id.write(*instruction_context.get_program_key()?);
2101 data.write_copy_of_slice(instruction_context.get_instruction_data());
2102 let account_metas = (0..instruction_context.get_number_of_instruction_accounts())
2103 .map(|instruction_account_index| {
2104 Ok(AccountMeta {
2105 pubkey: *instruction_context.get_key_of_instruction_account(instruction_account_index)?,
2106 is_signer: instruction_context
2107 .is_instruction_account_signer(instruction_account_index)?,
2108 is_writable: instruction_context
2109 .is_instruction_account_writable(instruction_account_index)?,
2110 })
2111 })
2112 .collect::<Result<Vec<_>, InstructionError>>()?;
2113 accounts.write_clone_of_slice(account_metas.as_slice());
2114 } else {
2115 result_header.data_len = instruction_context.get_instruction_data().len() as u64;
2116 result_header.accounts_len =
2117 instruction_context.get_number_of_instruction_accounts() as u64;
2118 }
2119 return Ok(true as u64);
2120 }
2121 Ok(false as u64)
2122 }
2123);
2124
2125declare_builtin_function!(
2126 SyscallGetStackHeight,
2128 fn rust(
2129 invoke_context: &mut InvokeContext<'_, '_>,
2130 _arg1: u64,
2131 _arg2: u64,
2132 _arg3: u64,
2133 _arg4: u64,
2134 _arg5: u64,
2135 ) -> Result<u64, Error> {
2136 let execution_cost = invoke_context.get_execution_cost();
2137
2138 invoke_context.compute_meter.consume_checked(execution_cost.syscall_base_cost)?;
2139
2140 Ok(invoke_context.get_stack_height() as u64)
2141 }
2142);
2143
2144declare_builtin_function!(
2145 SyscallAltBn128,
2147 fn rust(
2148 invoke_context: &mut InvokeContext<'_, '_>,
2149 group_op: u64,
2150 input_addr: u64,
2151 input_size: u64,
2152 result_addr: u64,
2153 _arg5: u64,
2154 ) -> Result<u64, Error> {
2155 use solana_bn254::versioned::{
2156 alt_bn128_versioned_g1_addition, alt_bn128_versioned_g1_multiplication,
2157 alt_bn128_versioned_g2_addition, alt_bn128_versioned_g2_multiplication,
2158 alt_bn128_versioned_pairing, Endianness, VersionedG1Addition,
2159 VersionedG1Multiplication, VersionedG2Addition, VersionedG2Multiplication,
2160 VersionedPairing, ALT_BN128_G1_POINT_SIZE, ALT_BN128_G2_POINT_SIZE,
2161 ALT_BN128_G1_ADD_BE, ALT_BN128_G1_MUL_BE, ALT_BN128_PAIRING_BE,
2162 ALT_BN128_PAIRING_ELEMENT_SIZE, ALT_BN128_PAIRING_OUTPUT_SIZE, ALT_BN128_G1_ADD_LE,
2163 ALT_BN128_G1_MUL_LE, ALT_BN128_PAIRING_LE, ALT_BN128_G2_ADD_BE, ALT_BN128_G2_ADD_LE,
2164 ALT_BN128_G2_MUL_BE, ALT_BN128_G2_MUL_LE,
2165 };
2166
2167 if !invoke_context.get_feature_set().alt_bn128_little_endian &&
2169 matches!(
2170 group_op,
2171 ALT_BN128_G1_ADD_LE
2172 | ALT_BN128_G1_MUL_LE
2173 | ALT_BN128_PAIRING_LE
2174 )
2175 {
2176 return Err(SyscallError::InvalidAttribute.into());
2177 }
2178
2179 if !invoke_context.get_feature_set().enable_alt_bn128_g2_syscalls &&
2181 matches!(
2182 group_op,
2183 ALT_BN128_G2_ADD_BE
2184 | ALT_BN128_G2_ADD_LE
2185 | ALT_BN128_G2_MUL_BE
2186 | ALT_BN128_G2_MUL_LE
2187 )
2188 {
2189 return Err(SyscallError::InvalidAttribute.into());
2190 }
2191
2192 let execution_cost = invoke_context.get_execution_cost();
2193 let (cost, output): (u64, usize) = match group_op {
2194 ALT_BN128_G1_ADD_BE | ALT_BN128_G1_ADD_LE => (
2195 execution_cost.alt_bn128_g1_addition_cost,
2196 ALT_BN128_G1_POINT_SIZE,
2197 ),
2198 ALT_BN128_G2_ADD_BE | ALT_BN128_G2_ADD_LE => (
2199 execution_cost.alt_bn128_g2_addition_cost,
2200 ALT_BN128_G2_POINT_SIZE,
2201 ),
2202 ALT_BN128_G1_MUL_BE | ALT_BN128_G1_MUL_LE => (
2203 execution_cost.alt_bn128_g1_multiplication_cost,
2204 ALT_BN128_G1_POINT_SIZE,
2205 ),
2206 ALT_BN128_G2_MUL_BE | ALT_BN128_G2_MUL_LE => (
2207 execution_cost.alt_bn128_g2_multiplication_cost,
2208 ALT_BN128_G2_POINT_SIZE,
2209 ),
2210 ALT_BN128_PAIRING_BE | ALT_BN128_PAIRING_LE => {
2211 let ele_len = input_size
2212 .checked_div(ALT_BN128_PAIRING_ELEMENT_SIZE as u64)
2213 .expect("div by non-zero constant");
2214 let cost = execution_cost
2215 .alt_bn128_pairing_one_pair_cost_first
2216 .saturating_add(
2217 execution_cost
2218 .alt_bn128_pairing_one_pair_cost_other
2219 .saturating_mul(ele_len.saturating_sub(1)),
2220 )
2221 .saturating_add(execution_cost.sha256_base_cost)
2222 .saturating_add(input_size)
2223 .saturating_add(ALT_BN128_PAIRING_OUTPUT_SIZE as u64);
2224 (cost, ALT_BN128_PAIRING_OUTPUT_SIZE)
2225 }
2226 _ => {
2227 return Err(SyscallError::InvalidAttribute.into());
2228 }
2229 };
2230
2231 invoke_context.compute_meter.consume_checked(cost)?;
2232
2233 let check_aligned = invoke_context.get_check_aligned();
2234 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2235 {
2236 translate_mut!(
2238 memory_mapping,
2239 check_aligned,
2240 let _result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2241 );
2242 }
2243 let input = translate_slice::<u8>(
2244 memory_mapping,
2245 input_addr,
2246 input_size,
2247 check_aligned,
2248 )?;
2249
2250 let result_point = match group_op {
2251 ALT_BN128_G1_ADD_BE => {
2252 alt_bn128_versioned_g1_addition(VersionedG1Addition::V0, input, Endianness::BE)
2253 }
2254 ALT_BN128_G1_ADD_LE => {
2255 alt_bn128_versioned_g1_addition(VersionedG1Addition::V0, input, Endianness::LE)
2256 }
2257 ALT_BN128_G2_ADD_BE => {
2258 alt_bn128_versioned_g2_addition(VersionedG2Addition::V0, input, Endianness::BE)
2259 }
2260 ALT_BN128_G2_ADD_LE => {
2261 alt_bn128_versioned_g2_addition(VersionedG2Addition::V0, input, Endianness::LE)
2262 }
2263 ALT_BN128_G1_MUL_BE => {
2264 alt_bn128_versioned_g1_multiplication(
2265 VersionedG1Multiplication::V1,
2266 input,
2267 Endianness::BE
2268 )
2269 }
2270 ALT_BN128_G1_MUL_LE => {
2271 alt_bn128_versioned_g1_multiplication(
2272 VersionedG1Multiplication::V1,
2273 input,
2274 Endianness::LE
2275 )
2276 }
2277 ALT_BN128_G2_MUL_BE => {
2278 alt_bn128_versioned_g2_multiplication(
2279 VersionedG2Multiplication::V0,
2280 input,
2281 Endianness::BE
2282 )
2283 }
2284 ALT_BN128_G2_MUL_LE => {
2285 alt_bn128_versioned_g2_multiplication(
2286 VersionedG2Multiplication::V0,
2287 input,
2288 Endianness::LE
2289 )
2290 }
2291 ALT_BN128_PAIRING_BE => {
2292 alt_bn128_versioned_pairing(VersionedPairing::V1, input, Endianness::BE)
2293 }
2294 ALT_BN128_PAIRING_LE => {
2295 alt_bn128_versioned_pairing(VersionedPairing::V1, input, Endianness::LE)
2296 }
2297 _ => {
2298 return Err(SyscallError::InvalidAttribute.into());
2299 }
2300 };
2301
2302 match result_point {
2303 Ok(point) => {
2304 translate_mut!(
2305 memory_mapping,
2306 check_aligned,
2307 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2308 );
2309 result.write_copy_of_slice(&point);
2310 Ok(SUCCESS)
2311 }
2312 Err(_) => {
2313 Ok(1)
2314 }
2315 }
2316 }
2317);
2318
2319fn big_mod_exp_mult_complexity(input_len: u64) -> Option<u128> {
2320 let input_len = input_len as u128;
2321 let input_len_squared = input_len.checked_mul(input_len)?;
2322 if input_len <= 64 {
2323 Some(input_len_squared)
2324 } else if input_len <= 1024 {
2325 input_len_squared
2326 .checked_div(4)?
2327 .checked_add(96_u128.checked_mul(input_len)?)?
2328 .checked_sub(3_072)
2329 } else {
2330 input_len_squared
2331 .checked_div(16)?
2332 .checked_add(480_u128.checked_mul(input_len)?)?
2333 .checked_sub(199_680)
2334 }
2335}
2336
2337fn big_mod_exp_highest_set_bit_index_le(bytes: &[u8]) -> Option<u64> {
2338 bytes.iter().enumerate().rev().find_map(|(index, byte)| {
2339 (*byte != 0).then(|| {
2340 (index as u64)
2341 .saturating_mul(u64::from(u8::BITS))
2342 .saturating_add(u64::from(7_u32.saturating_sub(byte.leading_zeros())))
2343 })
2344 })
2345}
2346
2347fn big_mod_exp_adjusted_exponent_length(exponent: &[u8]) -> u64 {
2348 if exponent.len() <= 32 {
2349 big_mod_exp_highest_set_bit_index_le(exponent).unwrap_or(0)
2350 } else {
2351 let trailing_bytes = exponent.len().saturating_sub(32);
2352 let most_significant_32_bytes = &exponent[trailing_bytes..];
2353 (trailing_bytes as u64)
2354 .saturating_mul(u64::from(u8::BITS))
2355 .saturating_add(
2356 big_mod_exp_highest_set_bit_index_le(most_significant_32_bytes).unwrap_or(0),
2357 )
2358 }
2359}
2360
2361fn big_mod_exp_is_one_le(bytes: &[u8]) -> bool {
2362 matches!(bytes.first(), Some(1)) && bytes[1..].iter().all(|byte| *byte == 0)
2363}
2364
2365fn big_mod_exp_operation_cost(
2368 cost_divisor: u64,
2369 params: &BigModExpParams,
2370 exponent: &[u8],
2371) -> Option<u64> {
2372 let input_len = params.base_len.max(params.modulus_len);
2373 let mult_complexity = big_mod_exp_mult_complexity(input_len)?;
2374 let operation_complexity = if big_mod_exp_is_one_le(exponent) {
2375 mult_complexity.checked_mul(u128::from(BIG_MOD_EXP_MOD_REDUCTION_COMPLEXITY_FACTOR))?
2376 } else {
2377 let adjusted_exponent_length =
2378 big_mod_exp_adjusted_exponent_length(exponent).max(BIG_MOD_EXP_MIN_EXPONENT_LENGTH);
2379 mult_complexity.checked_mul(u128::from(adjusted_exponent_length))?
2380 };
2381 let divisor = u128::from(cost_divisor);
2382 if divisor == 0 {
2383 return None;
2384 }
2385
2386 let operation_cost = operation_complexity
2387 .checked_add(divisor.checked_sub(1)?)?
2388 .checked_div(divisor)?;
2389 u64::try_from(operation_cost).ok()
2390}
2391
2392declare_builtin_function!(
2393 SyscallBigModExp,
2395 fn rust(
2396 invoke_context: &mut InvokeContext<'_, '_>,
2397 params_addr: u64,
2398 result_addr: u64,
2399 _arg3: u64,
2400 _arg4: u64,
2401 _arg5: u64,
2402 ) -> Result<u64, Error> {
2403 let check_aligned = invoke_context.get_check_aligned();
2404
2405 let execution_cost = invoke_context.get_execution_cost();
2408 let base_cost = execution_cost.big_modular_exponentiation_base_cost;
2409 let cost_divisor = execution_cost.big_modular_exponentiation_cost_divisor;
2410 invoke_context.compute_meter.consume_checked(base_cost)?;
2411
2412 let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
2413 let params =
2414 *translate_type::<BigModExpParams>(memory_mapping, params_addr, check_aligned)?;
2415
2416 if params.base_len > BIG_MOD_EXP_MAX_BYTES
2417 || params.exponent_len > BIG_MOD_EXP_MAX_BYTES
2418 || params.modulus_len > BIG_MOD_EXP_MAX_BYTES
2419 {
2420 return Err(SyscallError::InvalidLength.into());
2421 }
2422
2423 let exponent = translate_slice::<u8>(
2427 memory_mapping,
2428 params.exponent,
2429 params.exponent_len,
2430 check_aligned,
2431 )?;
2432 let Some(cost) = big_mod_exp_operation_cost(cost_divisor, ¶ms, exponent) else {
2433 invoke_context.compute_meter.consume_checked(u64::MAX)?;
2436 return Err(Box::new(InstructionError::ComputationalBudgetExceeded));
2437 };
2438 invoke_context.compute_meter.consume_checked(cost)?;
2439
2440 let base = translate_slice::<u8>(
2441 memory_mapping,
2442 params.base,
2443 params.base_len,
2444 check_aligned,
2445 )?;
2446 let modulus = translate_slice::<u8>(
2447 memory_mapping,
2448 params.modulus,
2449 params.modulus_len,
2450 check_aligned,
2451 )?;
2452
2453 let Some(value) = big_mod_exp(base, exponent, modulus) else {
2454 return Err(SyscallError::InvalidAttribute.into());
2455 };
2456
2457 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2458 translate_mut!(
2459 memory_mapping,
2460 check_aligned,
2461 let result_ref_mut: (&mut [MaybeUninit<u8>]) = map(result_addr, params.modulus_len)?;
2462 );
2463 result_ref_mut.write_copy_of_slice(value.as_slice());
2464
2465 Ok(SUCCESS)
2466 }
2467);
2468
2469declare_builtin_function!(
2470 SyscallPoseidon,
2472 fn rust(
2473 invoke_context: &mut InvokeContext<'_, '_>,
2474 parameters: u64,
2475 endianness: u64,
2476 vals_addr: u64,
2477 vals_len: u64,
2478 result_addr: u64,
2479 ) -> Result<u64, Error> {
2480 let parameters: poseidon::Parameters = parameters.try_into()?;
2481 let endianness: poseidon::Endianness = endianness.try_into()?;
2482
2483 if vals_len > 12 {
2484 ic_msg!(
2485 invoke_context,
2486 "Poseidon hashing {} sequences is not supported",
2487 vals_len,
2488 );
2489 return Err(SyscallError::InvalidLength.into());
2490 }
2491
2492 let execution_cost = invoke_context.get_execution_cost();
2493 let Some(cost) = execution_cost.poseidon_cost(vals_len) else {
2494 ic_msg!(
2495 invoke_context,
2496 "Overflow while calculating the compute cost"
2497 );
2498 return Err(SyscallError::ArithmeticOverflow.into());
2499 };
2500 invoke_context
2501 .compute_meter
2502 .consume_checked(cost.to_owned())?;
2503
2504 let check_aligned = invoke_context.get_check_aligned();
2505 let poseidon_enforce_padding = invoke_context.get_feature_set().poseidon_enforce_padding;
2506 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2507 {
2508 translate_mut!(
2510 memory_mapping,
2511 check_aligned,
2512 let _result: (&mut [MaybeUninit<u8>]) =
2513 map(result_addr, poseidon::HASH_BYTES as u64)?;
2514 );
2515 }
2516 let inputs =
2517 translate_slice::<VmSlice<u8>>(memory_mapping, vals_addr, vals_len, check_aligned)?;
2518 let inputs = inputs
2519 .iter()
2520 .map(|input| translate_vm_slice(input, memory_mapping, check_aligned))
2521 .collect::<Result<Vec<_>, Error>>()?;
2522
2523 let result = if poseidon_enforce_padding {
2524 poseidon::hashv(parameters, endianness, inputs.as_slice())
2525 } else {
2526 poseidon::legacy::hashv(parameters, endianness, inputs.as_slice())
2527 };
2528 let Ok(hash) = result else {
2529 return Ok(1);
2530 };
2531 drop(inputs);
2532
2533 translate_mut!(
2534 memory_mapping,
2535 check_aligned,
2536 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, poseidon::HASH_BYTES as u64)?;
2537 );
2538 result.write_copy_of_slice(&hash.to_bytes());
2539
2540 Ok(SUCCESS)
2541 }
2542);
2543
2544declare_builtin_function!(
2545 SyscallRemainingComputeUnits,
2547 fn rust(
2548 invoke_context: &mut InvokeContext<'_, '_>,
2549 _arg1: u64,
2550 _arg2: u64,
2551 _arg3: u64,
2552 _arg4: u64,
2553 _arg5: u64,
2554 ) -> Result<u64, Error> {
2555 let execution_cost = invoke_context.get_execution_cost();
2556 invoke_context.compute_meter.consume_checked(execution_cost.syscall_base_cost)?;
2557
2558 use solana_sbpf::vm::ContextObject;
2559 Ok(invoke_context.get_remaining())
2560 }
2561);
2562
2563declare_builtin_function!(
2564 SyscallAltBn128Compression,
2566 fn rust(
2567 invoke_context: &mut InvokeContext<'_, '_>,
2568 op: u64,
2569 input_addr: u64,
2570 input_size: u64,
2571 result_addr: u64,
2572 _arg5: u64,
2573 ) -> Result<u64, Error> {
2574 use solana_bn254::{
2575 prelude::{ALT_BN128_G1_POINT_SIZE, ALT_BN128_G2_POINT_SIZE},
2576 compression::prelude::{
2577 alt_bn128_g1_compress_be, alt_bn128_g1_decompress_be,
2578 alt_bn128_g2_compress_be, alt_bn128_g2_decompress_be,
2579 alt_bn128_g1_compress_le, alt_bn128_g1_decompress_le,
2580 alt_bn128_g2_compress_le, alt_bn128_g2_decompress_le,
2581 ALT_BN128_G1_COMPRESS_BE, ALT_BN128_G1_DECOMPRESS_BE,
2582 ALT_BN128_G2_COMPRESS_BE, ALT_BN128_G2_DECOMPRESS_BE,
2583 ALT_BN128_G1_COMPRESSED_POINT_SIZE, ALT_BN128_G2_COMPRESSED_POINT_SIZE,
2584 ALT_BN128_G1_COMPRESS_LE, ALT_BN128_G2_COMPRESS_LE,
2585 ALT_BN128_G1_DECOMPRESS_LE, ALT_BN128_G2_DECOMPRESS_LE,
2586 }
2587 };
2588
2589 if !invoke_context.get_feature_set().alt_bn128_little_endian &&
2591 matches!(
2592 op,
2593 ALT_BN128_G1_COMPRESS_LE
2594 | ALT_BN128_G2_COMPRESS_LE
2595 | ALT_BN128_G1_DECOMPRESS_LE
2596 | ALT_BN128_G2_DECOMPRESS_LE
2597 )
2598 {
2599 return Err(SyscallError::InvalidAttribute.into());
2600 }
2601
2602 let execution_cost = invoke_context.get_execution_cost();
2603 let base_cost = execution_cost.syscall_base_cost;
2604 let (cost, output): (u64, usize) = match op {
2605 ALT_BN128_G1_COMPRESS_BE | ALT_BN128_G1_COMPRESS_LE => (
2606 base_cost.saturating_add(execution_cost.alt_bn128_g1_compress),
2607 ALT_BN128_G1_COMPRESSED_POINT_SIZE,
2608 ),
2609 ALT_BN128_G1_DECOMPRESS_BE | ALT_BN128_G1_DECOMPRESS_LE => {
2610 (base_cost.saturating_add(execution_cost.alt_bn128_g1_decompress), ALT_BN128_G1_POINT_SIZE)
2611 }
2612 ALT_BN128_G2_COMPRESS_BE | ALT_BN128_G2_COMPRESS_LE => (
2613 base_cost.saturating_add(execution_cost.alt_bn128_g2_compress),
2614 ALT_BN128_G2_COMPRESSED_POINT_SIZE,
2615 ),
2616 ALT_BN128_G2_DECOMPRESS_BE | ALT_BN128_G2_DECOMPRESS_LE => {
2617 (base_cost.saturating_add(execution_cost.alt_bn128_g2_decompress), ALT_BN128_G2_POINT_SIZE)
2618 }
2619 _ => {
2620 return Err(SyscallError::InvalidAttribute.into());
2621 }
2622 };
2623
2624 invoke_context.compute_meter.consume_checked(cost)?;
2625
2626 let check_aligned = invoke_context.get_check_aligned();
2627 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2628 {
2629 translate_mut!(
2631 memory_mapping,
2632 check_aligned,
2633 let _result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2634 );
2635 }
2636 let input = translate_slice::<u8>(
2637 memory_mapping,
2638 input_addr,
2639 input_size,
2640 check_aligned,
2641 )?;
2642
2643 match op {
2644 ALT_BN128_G1_COMPRESS_BE => {
2645 let Ok(result_point) = alt_bn128_g1_compress_be(input) else {
2646 return Ok(1);
2647 };
2648 translate_mut!(
2649 memory_mapping,
2650 check_aligned,
2651 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2652 );
2653 result.write_copy_of_slice(&result_point);
2654 }
2655 ALT_BN128_G1_COMPRESS_LE => {
2656 let Ok(result_point) = alt_bn128_g1_compress_le(input) else {
2657 return Ok(1);
2658 };
2659 translate_mut!(
2660 memory_mapping,
2661 check_aligned,
2662 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2663 );
2664 result.write_copy_of_slice(&result_point);
2665 }
2666 ALT_BN128_G1_DECOMPRESS_BE => {
2667 let Ok(result_point) = alt_bn128_g1_decompress_be(input) else {
2668 return Ok(1);
2669 };
2670 translate_mut!(
2671 memory_mapping,
2672 check_aligned,
2673 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2674 );
2675 result.write_copy_of_slice(&result_point);
2676 }
2677 ALT_BN128_G1_DECOMPRESS_LE => {
2678 let Ok(result_point) = alt_bn128_g1_decompress_le(input) else {
2679 return Ok(1);
2680 };
2681 translate_mut!(
2682 memory_mapping,
2683 check_aligned,
2684 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2685 );
2686 result.write_copy_of_slice(&result_point);
2687 }
2688 ALT_BN128_G2_COMPRESS_BE => {
2689 let Ok(result_point) = alt_bn128_g2_compress_be(input) else {
2690 return Ok(1);
2691 };
2692 translate_mut!(
2693 memory_mapping,
2694 check_aligned,
2695 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2696 );
2697 result.write_copy_of_slice(&result_point);
2698 }
2699 ALT_BN128_G2_COMPRESS_LE => {
2700 let Ok(result_point) = alt_bn128_g2_compress_le(input) else {
2701 return Ok(1);
2702 };
2703 translate_mut!(
2704 memory_mapping,
2705 check_aligned,
2706 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2707 );
2708 result.write_copy_of_slice(&result_point);
2709 }
2710 ALT_BN128_G2_DECOMPRESS_BE => {
2711 let Ok(result_point) = alt_bn128_g2_decompress_be(input) else {
2712 return Ok(1);
2713 };
2714 translate_mut!(
2715 memory_mapping,
2716 check_aligned,
2717 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2718 );
2719 result.write_copy_of_slice(&result_point);
2720 }
2721 ALT_BN128_G2_DECOMPRESS_LE => {
2722 let Ok(result_point) = alt_bn128_g2_decompress_le(input) else {
2723 return Ok(1);
2724 };
2725 translate_mut!(
2726 memory_mapping,
2727 check_aligned,
2728 let result: (&mut [MaybeUninit<u8>]) = map(result_addr, output as u64)?;
2729 );
2730 result.write_copy_of_slice(&result_point);
2731 }
2732 _ => return Err(SyscallError::InvalidAttribute.into()),
2733 }
2734
2735 Ok(SUCCESS)
2736 }
2737);
2738
2739declare_builtin_function!(
2740 SyscallHash<H: HasherImpl>,
2742 fn rust(
2743 invoke_context: &mut InvokeContext<'_, '_>,
2744 vals_addr: u64,
2745 vals_len: u64,
2746 result_addr: u64,
2747 _arg4: u64,
2748 _arg5: u64,
2749 ) -> Result<u64, Error> {
2750 let compute_budget = invoke_context.get_compute_budget();
2751 let compute_cost = invoke_context.get_execution_cost();
2752 let hash_base_cost = H::get_base_cost(compute_cost);
2753 let hash_byte_cost = H::get_byte_cost(compute_cost);
2754 let hash_max_slices = H::get_max_slices(compute_budget);
2755 if hash_max_slices < vals_len {
2756 ic_msg!(
2757 invoke_context,
2758 "{} Hashing {} sequences in one syscall is over the limit {}",
2759 H::NAME,
2760 vals_len,
2761 hash_max_slices,
2762 );
2763 return Err(SyscallError::TooManySlices.into());
2764 }
2765
2766 invoke_context.compute_meter.consume_checked(hash_base_cost)?;
2767 let check_aligned = invoke_context.get_check_aligned();
2768 let mem_op_base_cost = compute_cost.mem_op_base_cost;
2769 let memory_mapping = invoke_context.memory_contexts.memory_mapping_mut()?;
2770 {
2771 translate_mut!(
2773 memory_mapping,
2774 check_aligned,
2775 let _result: (&mut [MaybeUninit<u8>]) =
2776 map(result_addr, std::mem::size_of::<H::Output>() as u64)?;
2777 );
2778 }
2779 let mut hasher = H::create_hasher();
2780 if vals_len > 0 {
2781 let vals = translate_slice::<VmSlice<u8>>(
2782 memory_mapping,
2783 vals_addr,
2784 vals_len,
2785 check_aligned,
2786 )?;
2787
2788 for val in vals.iter() {
2789 let bytes = translate_vm_slice(val, memory_mapping, check_aligned)?;
2790 let cost = mem_op_base_cost.max(
2791 hash_byte_cost.saturating_mul(
2792 val.len()
2793 .checked_div(2)
2794 .expect("div by non-zero literal"),
2795 ),
2796 );
2797 invoke_context.compute_meter.consume_checked(cost)?;
2798 hasher.hash(bytes);
2799 }
2800 }
2801 translate_mut!(
2802 memory_mapping,
2803 check_aligned,
2804 let result: (&mut [MaybeUninit<u8>]) =
2805 map(result_addr, std::mem::size_of::<H::Output>() as u64)?;
2806 );
2807 result.write_copy_of_slice(hasher.result().as_ref());
2808 Ok(0)
2809 }
2810);
2811
2812declare_builtin_function!(
2813 SyscallGetEpochStake,
2815 fn rust(
2816 invoke_context: &mut InvokeContext<'_, '_>,
2817 var_addr: u64,
2818 _arg2: u64,
2819 _arg3: u64,
2820 _arg4: u64,
2821 _arg5: u64,
2822 ) -> Result<u64, Error> {
2823 let compute_cost = invoke_context.get_execution_cost();
2824
2825 if var_addr == 0 {
2826 let compute_units = compute_cost.syscall_base_cost;
2834 invoke_context
2835 .compute_meter
2836 .consume_checked(compute_units)?;
2837 Ok(invoke_context.get_epoch_stake())
2845 } else {
2846 let compute_units = compute_cost
2854 .syscall_base_cost
2855 .saturating_add(
2856 (PUBKEY_BYTES as u64)
2857 .checked_div(compute_cost.cpi_bytes_per_unit)
2858 .unwrap_or(u64::MAX),
2859 )
2860 .saturating_add(compute_cost.mem_op_base_cost);
2861 invoke_context
2862 .compute_meter
2863 .consume_checked(compute_units)?;
2864 let check_aligned = invoke_context.get_check_aligned();
2876 let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
2877 let vote_address = translate_type::<Pubkey>(memory_mapping, var_addr, check_aligned)?;
2878
2879 Ok(invoke_context.get_epoch_stake_for_vote_account(vote_address))
2880 }
2881 }
2882);
2883
2884#[cfg(test)]
2885#[allow(clippy::arithmetic_side_effects)]
2886#[allow(clippy::indexing_slicing)]
2887mod tests {
2888 #[allow(deprecated)]
2889 use solana_sysvar::fees::Fees;
2890 use {
2891 super::*,
2892 assert_matches::assert_matches,
2893 core::slice,
2894 solana_account::{AccountSharedData, create_account_shared_data_for_test},
2895 solana_account_info::AccountInfo,
2896 solana_clock::Clock,
2897 solana_epoch_rewards::EpochRewards,
2898 solana_epoch_schedule::EpochSchedule,
2899 solana_fee_calculator::FeeCalculator,
2900 solana_hash::HASH_BYTES,
2901 solana_instruction::Instruction,
2902 solana_last_restart_slot::LastRestartSlot,
2903 solana_program::program::check_type_assumptions,
2904 solana_program_runtime::{
2905 execution_budget::MAX_HEAP_FRAME_BYTES,
2906 invoke_context::{BpfAllocator, InvokeContext},
2907 memory_context::MemoryContext,
2908 with_mock_invoke_context, with_mock_invoke_context_with_feature_set,
2909 },
2910 solana_sbpf::{
2911 aligned_memory::AlignedMemory,
2912 ebpf::{self, HOST_ALIGN},
2913 error::EbpfError,
2914 memory_region::{MemoryMapping, MemoryRegion},
2915 program::SBPFVersion,
2916 vm::Config,
2917 },
2918 solana_sdk_ids::{
2919 bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, native_loader, sysvar,
2920 },
2921 solana_sha256_hasher::hashv,
2922 solana_slot_hashes::{self as slot_hashes, SlotHashes},
2923 solana_stable_layout::stable_instruction::StableInstruction,
2924 solana_stake_history::{
2925 SIZE as STAKE_HISTORY_ACCOUNT_SIZE, StakeHistory, StakeHistoryEntry,
2926 },
2927 solana_sysvar_id::SysvarId,
2928 solana_transaction_context::instruction_accounts::InstructionAccount,
2929 std::{
2930 hash::{DefaultHasher, Hash, Hasher},
2931 mem,
2932 str::FromStr,
2933 },
2934 test_case::test_case,
2935 };
2936
2937 fn create_stake_history_account_for_test(stake_history: &StakeHistory) -> AccountSharedData {
2938 let data_len = STAKE_HISTORY_ACCOUNT_SIZE
2939 .max(bincode::serialized_size(stake_history).unwrap() as usize);
2940 let mut account = AccountSharedData::new(1, data_len, &sysvar::id());
2941 account.serialize_data(stake_history).unwrap();
2942 account
2943 }
2944
2945 macro_rules! assert_access_violation {
2946 ($result:expr, $va:expr, $len:expr) => {
2947 match $result.unwrap_err().downcast_ref::<EbpfError>().unwrap() {
2948 EbpfError::AccessViolation(_, va, len, _) if $va == *va && $len == *len => {}
2949 EbpfError::StackAccessViolation(_, va, len, _) if $va == *va && $len == *len => {}
2950 _ => panic!(),
2951 }
2952 };
2953 }
2954
2955 macro_rules! prepare_mockup {
2956 ($invoke_context:ident,
2957 $program_key:ident,
2958 $loader_key:expr $(,)?) => {
2959 let $program_key = Pubkey::new_unique();
2960 let transaction_accounts = vec![
2961 (
2962 $loader_key,
2963 AccountSharedData::new(0, 0, &native_loader::id()),
2964 ),
2965 ($program_key, AccountSharedData::new(0, 0, &$loader_key)),
2966 ];
2967 with_mock_invoke_context!($invoke_context, transaction_context, transaction_accounts);
2968 $invoke_context
2969 .transaction_context
2970 .configure_top_level_instruction_for_tests(1, vec![], vec![])
2971 .unwrap();
2972 $invoke_context.push().unwrap();
2973 };
2974 }
2975
2976 macro_rules! prepare_mock_with_feature_set {
2977 ($invoke_context:ident,
2978 $program_key:ident,
2979 $loader_key:expr,
2980 $feature_set:ident $(,)?) => {
2981 let $program_key = Pubkey::new_unique();
2982 let transaction_accounts = vec![
2983 (
2984 $loader_key,
2985 AccountSharedData::new(0, 0, &native_loader::id()),
2986 ),
2987 ($program_key, AccountSharedData::new(0, 0, &$loader_key)),
2988 ];
2989 with_mock_invoke_context_with_feature_set!(
2990 $invoke_context,
2991 transaction_context,
2992 $feature_set,
2993 transaction_accounts
2994 );
2995 $invoke_context
2996 .transaction_context
2997 .configure_top_level_instruction_for_tests(1, vec![], vec![])
2998 .unwrap();
2999 $invoke_context.push().unwrap();
3000 };
3001 }
3002
3003 #[allow(dead_code)]
3004 struct MockSlice {
3005 vm_addr: u64,
3006 len: usize,
3007 }
3008
3009 #[test]
3010 fn test_translate() {
3011 const START: u64 = 0x100000000;
3012 const LENGTH: u64 = 1000;
3013
3014 let data = vec![0u8; LENGTH as usize];
3015 let addr = data.as_ptr().addr();
3016 let config = Config::default();
3017 let memory_mapping = unsafe {
3018 MemoryMapping::new(
3019 vec![MemoryRegion::new(&raw const data[..], START)],
3020 &config,
3021 SBPFVersion::V3,
3022 )
3023 .unwrap()
3024 };
3025
3026 let cases = vec![
3027 (true, START, 0, addr),
3028 (true, START, 1, addr),
3029 (true, START, LENGTH, addr),
3030 (true, START + 1, LENGTH - 1, addr + 1),
3031 (false, START + 1, LENGTH, 0),
3032 (true, START + LENGTH - 1, 1, addr + LENGTH as usize - 1),
3033 (true, START + LENGTH, 0, addr + LENGTH as usize),
3034 (false, START + LENGTH, 1, 0),
3035 (false, START, LENGTH + 1, 0),
3036 (false, 0, 0, 0),
3037 (false, 0, 1, 0),
3038 (false, START - 1, 0, 0),
3039 (false, START - 1, 1, 0),
3040 (
3041 true,
3042 START + LENGTH / 2,
3043 LENGTH / 2,
3044 addr + LENGTH as usize / 2,
3045 ),
3046 ];
3047 for (ok, start, length, value) in cases {
3048 if ok {
3049 assert_eq!(
3050 translate_inner!(&memory_mapping, map, AccessType::Load, start, length)
3051 .unwrap()
3052 .ptr()
3053 .addr(),
3054 value
3055 )
3056 } else {
3057 assert!(
3058 translate_inner!(&memory_mapping, map, AccessType::Load, start, length)
3059 .is_err()
3060 )
3061 }
3062 }
3063 }
3064
3065 #[test]
3066 fn test_translate_type() {
3067 let config = Config::default();
3068
3069 let pubkey = solana_pubkey::new_rand();
3071 let memory_mapping = unsafe {
3072 MemoryMapping::new(
3073 vec![MemoryRegion::new(bytes_of(&pubkey), 0x100000000)],
3074 &config,
3075 SBPFVersion::V3,
3076 )
3077 .unwrap()
3078 };
3079 let translated_pubkey =
3080 translate_type::<Pubkey>(&memory_mapping, 0x100000000, true).unwrap();
3081 assert_eq!(pubkey, *translated_pubkey);
3082
3083 let instruction = Instruction::new_with_bincode(
3085 solana_pubkey::new_rand(),
3086 &"foobar",
3087 vec![AccountMeta::new(solana_pubkey::new_rand(), false)],
3088 );
3089 let instruction = StableInstruction::from(instruction);
3090 let memory_region = MemoryRegion::new(bytes_of(&instruction), 0x100000000);
3091 let memory_mapping =
3092 unsafe { MemoryMapping::new(vec![memory_region], &config, SBPFVersion::V3).unwrap() };
3093 let translated_instruction =
3094 translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).unwrap();
3095 assert_eq!(instruction, *translated_instruction);
3096
3097 let memory_mapping = unsafe {
3098 let instruction_byte =
3099 core::ptr::slice_from_raw_parts::<u8>((&raw const instruction).cast(), 1);
3100 let memory_region = MemoryRegion::new(instruction_byte, 0x100000000);
3101 MemoryMapping::new(vec![memory_region], &config, SBPFVersion::V3).unwrap()
3102 };
3103 assert!(translate_type::<Instruction>(&memory_mapping, 0x100000000, true).is_err());
3104 }
3105
3106 #[test]
3107 fn test_translate_slice() {
3108 let config = Config::default();
3109
3110 let good_data = [1u8, 2, 3, 4, 5];
3112 let data: Vec<u8> = vec![];
3113 assert_eq!(std::ptr::dangling::<u8>(), data.as_ptr());
3114 let memory_mapping = unsafe {
3115 MemoryMapping::new(
3116 vec![MemoryRegion::new(&raw const good_data, 0x100000000)],
3117 &config,
3118 SBPFVersion::V3,
3119 )
3120 .unwrap()
3121 };
3122 let translated_data =
3123 translate_slice::<u8>(&memory_mapping, data.as_ptr() as u64, 0, true).unwrap();
3124 assert_eq!(data, translated_data);
3125 assert_eq!(0, translated_data.len());
3126
3127 let mut data = vec![1u8, 2, 3, 4, 5];
3129 let memory_mapping = unsafe {
3130 MemoryMapping::new(
3131 vec![MemoryRegion::new(&raw const data[..], 0x100000000)],
3132 &config,
3133 SBPFVersion::V3,
3134 )
3135 .unwrap()
3136 };
3137 let translated_data =
3138 translate_slice::<u8>(&memory_mapping, 0x100000000, data.len() as u64, true).unwrap();
3139 assert_eq!(data, translated_data);
3140 *data.first_mut().unwrap() = 10;
3141 assert_eq!(data, translated_data);
3142 assert!(
3143 translate_slice::<u8>(&memory_mapping, data.as_ptr() as u64, u64::MAX, true).is_err()
3144 );
3145
3146 assert!(
3147 translate_slice::<u8>(&memory_mapping, 0x100000000 - 1, data.len() as u64, true,)
3148 .is_err()
3149 );
3150
3151 let mut data = vec![1u64, 2, 3, 4, 5];
3153 let memory_mapping = unsafe {
3154 MemoryMapping::new(
3155 vec![MemoryRegion::new(bytes_of_slice(&data), 0x100000000)],
3156 &config,
3157 SBPFVersion::V3,
3158 )
3159 .unwrap()
3160 };
3161 let translated_data =
3162 translate_slice::<u64>(&memory_mapping, 0x100000000, data.len() as u64, true).unwrap();
3163 assert_eq!(data, translated_data);
3164 *data.first_mut().unwrap() = 10;
3165 assert_eq!(data, translated_data);
3166 assert!(translate_slice::<u64>(&memory_mapping, 0x100000000, u64::MAX, true).is_err());
3167
3168 let mut data = vec![solana_pubkey::new_rand(); 5];
3170 let memory_mapping = unsafe {
3171 MemoryMapping::new(
3172 vec![MemoryRegion::new(
3173 core::ptr::slice_from_raw_parts(
3174 data.as_ptr() as *const u8,
3175 mem::size_of::<Pubkey>() * 5,
3176 ),
3177 0x100000000,
3178 )],
3179 &config,
3180 SBPFVersion::V3,
3181 )
3182 .unwrap()
3183 };
3184 let translated_data =
3185 translate_slice::<Pubkey>(&memory_mapping, 0x100000000, data.len() as u64, true)
3186 .unwrap();
3187 assert_eq!(data, translated_data);
3188 *data.first_mut().unwrap() = solana_pubkey::new_rand(); assert_eq!(data, translated_data);
3190 }
3191
3192 #[test]
3193 fn test_translate_string_and_do() {
3194 let string = "Gaggablaghblagh!";
3195 let config = Config::default();
3196 let memory_mapping = unsafe {
3197 MemoryMapping::new(
3198 vec![MemoryRegion::new(
3199 &raw const *string.as_bytes(),
3200 0x100000000,
3201 )],
3202 &config,
3203 SBPFVersion::V3,
3204 )
3205 .unwrap()
3206 };
3207 assert_eq!(
3208 42,
3209 translate_string_and_do(
3210 &memory_mapping,
3211 0x100000000,
3212 string.len() as u64,
3213 true,
3214 &mut |string: &str| {
3215 assert_eq!(string, "Gaggablaghblagh!");
3216 Ok(42)
3217 }
3218 )
3219 .unwrap()
3220 );
3221 }
3222
3223 #[test]
3224 #[should_panic(expected = "Abort")]
3225 fn test_syscall_abort() {
3226 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3227 let config = Config::default();
3228 let memory_mapping =
3229 unsafe { MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap() };
3230 invoke_context
3231 .memory_contexts
3232 .mock_set_mapping_abi_v1(memory_mapping);
3233 let result = SyscallAbort::rust(&mut invoke_context, 0, 0, 0, 0, 0);
3234 result.unwrap();
3235 }
3236
3237 #[test]
3238 #[should_panic(expected = "Panic(\"Gaggablaghblagh!\", 42, 84)")]
3239 fn test_syscall_sol_panic() {
3240 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3241
3242 let string = "Gaggablaghblagh!";
3243 let config = Config::default();
3244 let memory_mapping = unsafe {
3245 MemoryMapping::new(
3246 vec![MemoryRegion::new(
3247 &raw const *string.as_bytes(),
3248 0x100000000,
3249 )],
3250 &config,
3251 SBPFVersion::V3,
3252 )
3253 .unwrap()
3254 };
3255 invoke_context
3256 .memory_contexts
3257 .mock_set_mapping_abi_v1(memory_mapping);
3258 invoke_context
3259 .compute_meter
3260 .mock_set_remaining(string.len() as u64 - 1);
3261 let result = SyscallPanic::rust(
3262 &mut invoke_context,
3263 0x100000000,
3264 string.len() as u64,
3265 42,
3266 84,
3267 0,
3268 );
3269 assert_matches!(
3270 result,
3271 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3272 );
3273
3274 invoke_context
3275 .compute_meter
3276 .mock_set_remaining(string.len() as u64);
3277 let result = SyscallPanic::rust(
3278 &mut invoke_context,
3279 0x100000000,
3280 string.len() as u64,
3281 42,
3282 84,
3283 0,
3284 );
3285 result.unwrap();
3286 }
3287
3288 #[test]
3289 fn test_syscall_sol_log() {
3290 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3291
3292 let string = "Gaggablaghblagh!";
3293 let config = Config::default();
3294 let memory_mapping = unsafe {
3295 MemoryMapping::new(
3296 vec![MemoryRegion::new(
3297 &raw const *string.as_bytes(),
3298 0x100000000,
3299 )],
3300 &config,
3301 SBPFVersion::V3,
3302 )
3303 .unwrap()
3304 };
3305 invoke_context
3306 .memory_contexts
3307 .mock_set_mapping_abi_v1(memory_mapping);
3308 invoke_context.compute_meter.mock_set_remaining(400 - 1);
3309 let result = SyscallLog::rust(
3310 &mut invoke_context,
3311 0x100000001, string.len() as u64,
3313 0,
3314 0,
3315 0,
3316 );
3317 assert_access_violation!(result, 0x100000001, string.len() as u64);
3318 let result = SyscallLog::rust(
3319 &mut invoke_context,
3320 0x100000000,
3321 string.len() as u64 * 2, 0,
3323 0,
3324 0,
3325 );
3326 assert_access_violation!(result, 0x100000000, string.len() as u64 * 2);
3327
3328 let result = SyscallLog::rust(
3329 &mut invoke_context,
3330 0x100000000,
3331 string.len() as u64,
3332 0,
3333 0,
3334 0,
3335 );
3336 result.unwrap();
3337 let result = SyscallLog::rust(
3338 &mut invoke_context,
3339 0x100000000,
3340 string.len() as u64,
3341 0,
3342 0,
3343 0,
3344 );
3345 assert_matches!(
3346 result,
3347 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3348 );
3349
3350 assert_eq!(
3351 invoke_context
3352 .get_log_collector()
3353 .unwrap()
3354 .borrow()
3355 .get_recorded_content(),
3356 &["Program log: Gaggablaghblagh!".to_string()]
3357 );
3358 }
3359
3360 #[test]
3361 fn test_syscall_sol_log_u64() {
3362 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3363 let cost = invoke_context.get_execution_cost().log_64_units;
3364
3365 invoke_context.compute_meter.mock_set_remaining(cost);
3366 let config = Config::default();
3367 let memory_mapping =
3368 unsafe { MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap() };
3369 invoke_context
3370 .memory_contexts
3371 .mock_set_mapping_abi_v1(memory_mapping);
3372 let result = SyscallLogU64::rust(&mut invoke_context, 1, 2, 3, 4, 5);
3373 result.unwrap();
3374
3375 assert_eq!(
3376 invoke_context
3377 .get_log_collector()
3378 .unwrap()
3379 .borrow()
3380 .get_recorded_content(),
3381 &["Program log: 0x1, 0x2, 0x3, 0x4, 0x5".to_string()]
3382 );
3383 }
3384
3385 #[test]
3386 fn test_syscall_sol_pubkey() {
3387 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3388 let cost = invoke_context.get_execution_cost().log_pubkey_units;
3389
3390 let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap();
3391 let config = Config::default();
3392 let memory_mapping = unsafe {
3393 MemoryMapping::new(
3394 vec![MemoryRegion::new(bytes_of(&pubkey), 0x100000000)],
3395 &config,
3396 SBPFVersion::V3,
3397 )
3398 .unwrap()
3399 };
3400 invoke_context
3401 .memory_contexts
3402 .mock_set_mapping_abi_v1(memory_mapping);
3403
3404 let result = SyscallLogPubkey::rust(
3405 &mut invoke_context,
3406 0x100000001, 32,
3408 0,
3409 0,
3410 0,
3411 );
3412 assert_access_violation!(result, 0x100000001, 32);
3413
3414 invoke_context.compute_meter.mock_set_remaining(1);
3415 let result = SyscallLogPubkey::rust(&mut invoke_context, 100, 32, 0, 0, 0);
3416 assert_matches!(
3417 result,
3418 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3419 );
3420
3421 invoke_context.compute_meter.mock_set_remaining(cost);
3422 let result = SyscallLogPubkey::rust(&mut invoke_context, 0x100000000, 0, 0, 0, 0);
3423 result.unwrap();
3424
3425 assert_eq!(
3426 invoke_context
3427 .get_log_collector()
3428 .unwrap()
3429 .borrow()
3430 .get_recorded_content(),
3431 &["Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN".to_string()]
3432 );
3433 }
3434
3435 macro_rules! setup_alloc_test {
3436 ($invoke_context:ident, $heap:ident) => {
3437 prepare_mockup!($invoke_context, program_id, bpf_loader::id());
3438 let config = Config {
3439 aligned_memory_mapping: false,
3440 ..Config::default()
3441 };
3442 let mut $heap =
3443 AlignedMemory::<{ HOST_ALIGN }>::zero_filled(MAX_HEAP_FRAME_BYTES as usize);
3444 let regions = vec![MemoryRegion::new(&mut $heap, ebpf::MM_HEAP_START)];
3445 let mapping = unsafe { MemoryMapping::new(regions, &config, SBPFVersion::V3).unwrap() };
3446 $invoke_context
3447 .memory_contexts
3448 .set_memory_context_abi_v1(MemoryContext::new(
3449 BpfAllocator::new(solana_program_entrypoint::HEAP_LENGTH as u64),
3450 Vec::new(),
3451 mapping,
3452 ))
3453 .unwrap();
3454 };
3455 }
3456
3457 #[test]
3458 fn test_syscall_sol_alloc_free() {
3459 {
3461 setup_alloc_test!(invoke_context, heap);
3462 let result = SyscallAllocFree::rust(
3463 &mut invoke_context,
3464 solana_program_entrypoint::HEAP_LENGTH as u64,
3465 0,
3466 0,
3467 0,
3468 0,
3469 );
3470 assert_ne!(result.unwrap(), 0);
3471 let result = SyscallAllocFree::rust(
3472 &mut invoke_context,
3473 solana_program_entrypoint::HEAP_LENGTH as u64,
3474 0,
3475 0,
3476 0,
3477 0,
3478 );
3479 assert_eq!(result.unwrap(), 0);
3480 let result = SyscallAllocFree::rust(&mut invoke_context, u64::MAX, 0, 0, 0, 0);
3481 assert_eq!(result.unwrap(), 0);
3482 }
3483
3484 {
3486 setup_alloc_test!(invoke_context, heap);
3487 for _ in 0..100 {
3488 let result = SyscallAllocFree::rust(&mut invoke_context, 1, 0, 0, 0, 0);
3489 assert_ne!(result.unwrap(), 0);
3490 }
3491 let result = SyscallAllocFree::rust(
3492 &mut invoke_context,
3493 solana_program_entrypoint::HEAP_LENGTH as u64,
3494 0,
3495 0,
3496 0,
3497 0,
3498 );
3499 assert_eq!(result.unwrap(), 0);
3500 }
3501
3502 {
3504 setup_alloc_test!(invoke_context, heap);
3505 for _ in 0..12 {
3506 let result = SyscallAllocFree::rust(&mut invoke_context, 1, 0, 0, 0, 0);
3507 assert_ne!(result.unwrap(), 0);
3508 }
3509 let result = SyscallAllocFree::rust(
3510 &mut invoke_context,
3511 solana_program_entrypoint::HEAP_LENGTH as u64,
3512 0,
3513 0,
3514 0,
3515 0,
3516 );
3517 assert_eq!(result.unwrap(), 0);
3518 }
3519
3520 fn aligned<T>() {
3523 setup_alloc_test!(invoke_context, heap);
3524 let result =
3525 SyscallAllocFree::rust(&mut invoke_context, size_of::<T>() as u64, 0, 0, 0, 0);
3526 let address = result.unwrap();
3527 let align = align_of::<T>() as u64;
3528 assert_ne!(address, 0);
3529 assert!((address % align) == 0);
3530 }
3531 aligned::<u8>();
3532 aligned::<u16>();
3533 aligned::<u32>();
3534 aligned::<u64>();
3535 aligned::<u128>();
3536 }
3537
3538 #[test]
3539 fn test_syscall_sha256() {
3540 let config = Config::default();
3541 prepare_mockup!(invoke_context, program_id, bpf_loader_deprecated::id());
3542
3543 let bytes1 = "Gaggablaghblagh!";
3544 let bytes2 = "flurbos";
3545
3546 let mock_slice1 = MockSlice {
3547 vm_addr: 0x300000000,
3548 len: bytes1.len(),
3549 };
3550 let mock_slice2 = MockSlice {
3551 vm_addr: 0x400000000,
3552 len: bytes2.len(),
3553 };
3554 let bytes_to_hash = [mock_slice1, mock_slice2];
3555 let mut hash_result = [0; HASH_BYTES];
3556 let ro_len = bytes_to_hash.len() as u64;
3557 let ro_va = 0x100000000;
3558 let rw_va = 0x200000000;
3559 let memory_mapping = unsafe {
3560 MemoryMapping::new(
3561 vec![
3562 MemoryRegion::new(bytes_of_slice(&bytes_to_hash), ro_va),
3563 MemoryRegion::new(bytes_of_slice_mut(&mut hash_result), rw_va),
3564 MemoryRegion::new(&raw const *bytes1.as_bytes(), bytes_to_hash[0].vm_addr),
3565 MemoryRegion::new(&raw const *bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
3566 ],
3567 &config,
3568 SBPFVersion::V3,
3569 )
3570 .unwrap()
3571 };
3572 invoke_context
3573 .memory_contexts
3574 .mock_set_mapping_abi_v1(memory_mapping);
3575 invoke_context.compute_meter.mock_set_remaining(
3576 (invoke_context.get_execution_cost().sha256_base_cost
3577 + invoke_context.get_execution_cost().mem_op_base_cost.max(
3578 invoke_context
3579 .get_execution_cost()
3580 .sha256_byte_cost
3581 .saturating_mul((bytes1.len() + bytes2.len()) as u64 / 2),
3582 ))
3583 * 4,
3584 );
3585
3586 let result =
3587 SyscallHash::<Sha256Hasher>::rust(&mut invoke_context, ro_va, ro_len, rw_va, 0, 0);
3588 result.unwrap();
3589
3590 let hash_local = hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes();
3591 assert_eq!(hash_result, hash_local);
3592 let result = SyscallHash::<Sha256Hasher>::rust(
3593 &mut invoke_context,
3594 ro_va - 1, ro_len,
3596 rw_va,
3597 0,
3598 0,
3599 );
3600 assert_access_violation!(result, ro_va - 1, 32);
3601 let result = SyscallHash::<Sha256Hasher>::rust(
3602 &mut invoke_context,
3603 ro_va,
3604 ro_len + 1, rw_va,
3606 0,
3607 0,
3608 );
3609 assert_access_violation!(result, ro_va, 48);
3610 let result = SyscallHash::<Sha256Hasher>::rust(
3611 &mut invoke_context,
3612 ro_va,
3613 ro_len,
3614 rw_va - 1, 0,
3616 0,
3617 );
3618 assert_access_violation!(result, rw_va - 1, HASH_BYTES as u64);
3619 let result =
3620 SyscallHash::<Sha256Hasher>::rust(&mut invoke_context, ro_va, ro_len, rw_va, 0, 0);
3621 assert_matches!(
3622 result,
3623 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3624 );
3625 }
3626
3627 #[test]
3628 fn test_syscall_edwards_curve_point_validation() {
3629 use solana_curve25519::curve_syscall_traits::CURVE25519_EDWARDS;
3630
3631 let config = Config::default();
3632 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3633
3634 let valid_bytes: [u8; 32] = [
3635 201, 179, 241, 122, 180, 185, 239, 50, 183, 52, 221, 0, 153, 195, 43, 18, 22, 38, 187,
3636 206, 179, 192, 210, 58, 53, 45, 150, 98, 89, 17, 158, 11,
3637 ];
3638 let valid_bytes_va = 0x100000000;
3639
3640 let invalid_bytes: [u8; 32] = [
3641 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
3642 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
3643 ];
3644 let invalid_bytes_va = 0x200000000;
3645
3646 let memory_mapping = unsafe {
3647 MemoryMapping::new(
3648 vec![
3649 MemoryRegion::new(&raw const valid_bytes, valid_bytes_va),
3650 MemoryRegion::new(&raw const invalid_bytes, invalid_bytes_va),
3651 ],
3652 &config,
3653 SBPFVersion::V3,
3654 )
3655 .unwrap()
3656 };
3657
3658 invoke_context
3659 .memory_contexts
3660 .mock_set_mapping_abi_v1(memory_mapping);
3661 invoke_context.compute_meter.mock_set_remaining(
3662 (invoke_context
3663 .get_execution_cost()
3664 .curve25519_edwards_validate_point_cost)
3665 * 2,
3666 );
3667
3668 let result = SyscallCurvePointValidation::rust(
3669 &mut invoke_context,
3670 CURVE25519_EDWARDS,
3671 valid_bytes_va,
3672 0,
3673 0,
3674 0,
3675 );
3676 assert_eq!(0, result.unwrap());
3677
3678 let result = SyscallCurvePointValidation::rust(
3679 &mut invoke_context,
3680 CURVE25519_EDWARDS,
3681 invalid_bytes_va,
3682 0,
3683 0,
3684 0,
3685 );
3686 assert_eq!(1, result.unwrap());
3687
3688 let result = SyscallCurvePointValidation::rust(
3689 &mut invoke_context,
3690 CURVE25519_EDWARDS,
3691 valid_bytes_va,
3692 0,
3693 0,
3694 0,
3695 );
3696 assert_matches!(
3697 result,
3698 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3699 );
3700 }
3701
3702 #[test]
3703 fn test_syscall_ristretto_curve_point_validation() {
3704 use solana_curve25519::curve_syscall_traits::CURVE25519_RISTRETTO;
3705
3706 let config = Config::default();
3707 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3708
3709 let valid_bytes: [u8; 32] = [
3710 226, 242, 174, 10, 106, 188, 78, 113, 168, 132, 169, 97, 197, 0, 81, 95, 88, 227, 11,
3711 106, 165, 130, 221, 141, 182, 166, 89, 69, 224, 141, 45, 118,
3712 ];
3713 let valid_bytes_va = 0x100000000;
3714
3715 let invalid_bytes: [u8; 32] = [
3716 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
3717 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
3718 ];
3719 let invalid_bytes_va = 0x200000000;
3720
3721 let memory_mapping = unsafe {
3722 MemoryMapping::new(
3723 vec![
3724 MemoryRegion::new(&raw const valid_bytes, valid_bytes_va),
3725 MemoryRegion::new(&raw const invalid_bytes, invalid_bytes_va),
3726 ],
3727 &config,
3728 SBPFVersion::V3,
3729 )
3730 .unwrap()
3731 };
3732
3733 invoke_context
3734 .memory_contexts
3735 .mock_set_mapping_abi_v1(memory_mapping);
3736 invoke_context.compute_meter.mock_set_remaining(
3737 (invoke_context
3738 .get_execution_cost()
3739 .curve25519_ristretto_validate_point_cost)
3740 * 2,
3741 );
3742
3743 let result = SyscallCurvePointValidation::rust(
3744 &mut invoke_context,
3745 CURVE25519_RISTRETTO,
3746 valid_bytes_va,
3747 0,
3748 0,
3749 0,
3750 );
3751 assert_eq!(0, result.unwrap());
3752
3753 let result = SyscallCurvePointValidation::rust(
3754 &mut invoke_context,
3755 CURVE25519_RISTRETTO,
3756 invalid_bytes_va,
3757 0,
3758 0,
3759 0,
3760 );
3761 assert_eq!(1, result.unwrap());
3762
3763 let result = SyscallCurvePointValidation::rust(
3764 &mut invoke_context,
3765 CURVE25519_RISTRETTO,
3766 valid_bytes_va,
3767 0,
3768 0,
3769 0,
3770 );
3771 assert_matches!(
3772 result,
3773 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3774 );
3775 }
3776
3777 #[test]
3778 fn test_syscall_edwards_curve_group_ops() {
3779 use solana_curve25519::curve_syscall_traits::{ADD, CURVE25519_EDWARDS, MUL, SUB};
3780
3781 let config = Config::default();
3782 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3783
3784 let left_point: [u8; 32] = [
3785 33, 124, 71, 170, 117, 69, 151, 247, 59, 12, 95, 125, 133, 166, 64, 5, 2, 27, 90, 27,
3786 200, 167, 59, 164, 52, 54, 52, 200, 29, 13, 34, 213,
3787 ];
3788 let left_point_va = 0x100000000;
3789 let right_point: [u8; 32] = [
3790 70, 222, 137, 221, 253, 204, 71, 51, 78, 8, 124, 1, 67, 200, 102, 225, 122, 228, 111,
3791 183, 129, 14, 131, 210, 212, 95, 109, 246, 55, 10, 159, 91,
3792 ];
3793 let right_point_va = 0x200000000;
3794 let scalar: [u8; 32] = [
3795 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
3796 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
3797 ];
3798 let scalar_va = 0x300000000;
3799 let invalid_point: [u8; 32] = [
3800 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
3801 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
3802 ];
3803 let invalid_point_va = 0x400000000;
3804 let mut result_point: [u8; 32] = [0; 32];
3805 let result_point_va = 0x500000000;
3806
3807 let memory_mapping = unsafe {
3808 MemoryMapping::new(
3809 vec![
3810 MemoryRegion::new(bytes_of_slice(&left_point), left_point_va),
3811 MemoryRegion::new(bytes_of_slice(&right_point), right_point_va),
3812 MemoryRegion::new(bytes_of_slice(&scalar), scalar_va),
3813 MemoryRegion::new(bytes_of_slice(&invalid_point), invalid_point_va),
3814 MemoryRegion::new(bytes_of_slice_mut(&mut result_point), result_point_va),
3815 ],
3816 &config,
3817 SBPFVersion::V3,
3818 )
3819 .unwrap()
3820 };
3821
3822 invoke_context
3823 .memory_contexts
3824 .mock_set_mapping_abi_v1(memory_mapping);
3825 invoke_context.compute_meter.mock_set_remaining(
3826 (invoke_context
3827 .get_execution_cost()
3828 .curve25519_edwards_add_cost
3829 + invoke_context
3830 .get_execution_cost()
3831 .curve25519_edwards_subtract_cost
3832 + invoke_context
3833 .get_execution_cost()
3834 .curve25519_edwards_multiply_cost)
3835 * 2,
3836 );
3837
3838 let result = SyscallCurveGroupOps::rust(
3839 &mut invoke_context,
3840 CURVE25519_EDWARDS,
3841 ADD,
3842 left_point_va,
3843 right_point_va,
3844 result_point_va,
3845 );
3846
3847 assert_eq!(0, result.unwrap());
3848 let expected_sum = [
3849 7, 251, 187, 86, 186, 232, 57, 242, 193, 236, 49, 200, 90, 29, 254, 82, 46, 80, 83, 70,
3850 244, 153, 23, 156, 2, 138, 207, 51, 165, 38, 200, 85,
3851 ];
3852 assert_eq!(expected_sum, result_point);
3853
3854 let result = SyscallCurveGroupOps::rust(
3855 &mut invoke_context,
3856 CURVE25519_EDWARDS,
3857 ADD,
3858 invalid_point_va,
3859 right_point_va,
3860 result_point_va,
3861 );
3862 assert_eq!(1, result.unwrap());
3863
3864 let result = SyscallCurveGroupOps::rust(
3865 &mut invoke_context,
3866 CURVE25519_EDWARDS,
3867 SUB,
3868 left_point_va,
3869 right_point_va,
3870 result_point_va,
3871 );
3872
3873 assert_eq!(0, result.unwrap());
3874 let expected_difference = [
3875 60, 87, 90, 68, 232, 25, 7, 172, 247, 120, 158, 104, 52, 127, 94, 244, 5, 79, 253, 15,
3876 48, 69, 82, 134, 155, 70, 188, 81, 108, 95, 212, 9,
3877 ];
3878 assert_eq!(expected_difference, result_point);
3879
3880 let result = SyscallCurveGroupOps::rust(
3881 &mut invoke_context,
3882 CURVE25519_EDWARDS,
3883 SUB,
3884 invalid_point_va,
3885 right_point_va,
3886 result_point_va,
3887 );
3888 assert_eq!(1, result.unwrap());
3889
3890 let result = SyscallCurveGroupOps::rust(
3891 &mut invoke_context,
3892 CURVE25519_EDWARDS,
3893 MUL,
3894 scalar_va,
3895 right_point_va,
3896 result_point_va,
3897 );
3898
3899 result.unwrap();
3900 let expected_product = [
3901 64, 150, 40, 55, 80, 49, 217, 209, 105, 229, 181, 65, 241, 68, 2, 106, 220, 234, 211,
3902 71, 159, 76, 156, 114, 242, 68, 147, 31, 243, 211, 191, 124,
3903 ];
3904 assert_eq!(expected_product, result_point);
3905
3906 let result = SyscallCurveGroupOps::rust(
3907 &mut invoke_context,
3908 CURVE25519_EDWARDS,
3909 MUL,
3910 scalar_va,
3911 invalid_point_va,
3912 result_point_va,
3913 );
3914 assert_eq!(1, result.unwrap());
3915
3916 let result = SyscallCurveGroupOps::rust(
3917 &mut invoke_context,
3918 CURVE25519_EDWARDS,
3919 MUL,
3920 scalar_va,
3921 invalid_point_va,
3922 result_point_va,
3923 );
3924 assert_matches!(
3925 result,
3926 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
3927 );
3928 }
3929
3930 #[test]
3931 fn test_syscall_ristretto_curve_group_ops() {
3932 use solana_curve25519::curve_syscall_traits::{ADD, CURVE25519_RISTRETTO, MUL, SUB};
3933
3934 let config = Config::default();
3935 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
3936
3937 let left_point: [u8; 32] = [
3938 208, 165, 125, 204, 2, 100, 218, 17, 170, 194, 23, 9, 102, 156, 134, 136, 217, 190, 98,
3939 34, 183, 194, 228, 153, 92, 11, 108, 103, 28, 57, 88, 15,
3940 ];
3941 let left_point_va = 0x100000000;
3942 let right_point: [u8; 32] = [
3943 208, 241, 72, 163, 73, 53, 32, 174, 54, 194, 71, 8, 70, 181, 244, 199, 93, 147, 99,
3944 231, 162, 127, 25, 40, 39, 19, 140, 132, 112, 212, 145, 108,
3945 ];
3946 let right_point_va = 0x200000000;
3947 let scalar: [u8; 32] = [
3948 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
3949 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
3950 ];
3951 let scalar_va = 0x300000000;
3952 let invalid_point: [u8; 32] = [
3953 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
3954 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
3955 ];
3956 let invalid_point_va = 0x400000000;
3957 let mut result_point: [u8; 32] = [0; 32];
3958 let result_point_va = 0x500000000;
3959
3960 let memory_mapping = unsafe {
3961 MemoryMapping::new(
3962 vec![
3963 MemoryRegion::new(bytes_of_slice(&left_point), left_point_va),
3964 MemoryRegion::new(bytes_of_slice(&right_point), right_point_va),
3965 MemoryRegion::new(bytes_of_slice(&scalar), scalar_va),
3966 MemoryRegion::new(bytes_of_slice(&invalid_point), invalid_point_va),
3967 MemoryRegion::new(bytes_of_slice_mut(&mut result_point), result_point_va),
3968 ],
3969 &config,
3970 SBPFVersion::V3,
3971 )
3972 .unwrap()
3973 };
3974
3975 invoke_context
3976 .memory_contexts
3977 .mock_set_mapping_abi_v1(memory_mapping);
3978 invoke_context.compute_meter.mock_set_remaining(
3979 (invoke_context
3980 .get_execution_cost()
3981 .curve25519_ristretto_add_cost
3982 + invoke_context
3983 .get_execution_cost()
3984 .curve25519_ristretto_subtract_cost
3985 + invoke_context
3986 .get_execution_cost()
3987 .curve25519_ristretto_multiply_cost)
3988 * 2,
3989 );
3990
3991 let result = SyscallCurveGroupOps::rust(
3992 &mut invoke_context,
3993 CURVE25519_RISTRETTO,
3994 ADD,
3995 left_point_va,
3996 right_point_va,
3997 result_point_va,
3998 );
3999
4000 assert_eq!(0, result.unwrap());
4001 let expected_sum = [
4002 78, 173, 9, 241, 180, 224, 31, 107, 176, 210, 144, 240, 118, 73, 70, 191, 128, 119,
4003 141, 113, 125, 215, 161, 71, 49, 176, 87, 38, 180, 177, 39, 78,
4004 ];
4005 assert_eq!(expected_sum, result_point);
4006
4007 let result = SyscallCurveGroupOps::rust(
4008 &mut invoke_context,
4009 CURVE25519_RISTRETTO,
4010 ADD,
4011 invalid_point_va,
4012 right_point_va,
4013 result_point_va,
4014 );
4015 assert_eq!(1, result.unwrap());
4016
4017 let result = SyscallCurveGroupOps::rust(
4018 &mut invoke_context,
4019 CURVE25519_RISTRETTO,
4020 SUB,
4021 left_point_va,
4022 right_point_va,
4023 result_point_va,
4024 );
4025
4026 assert_eq!(0, result.unwrap());
4027 let expected_difference = [
4028 150, 72, 222, 61, 148, 79, 96, 130, 151, 176, 29, 217, 231, 211, 0, 215, 76, 86, 212,
4029 146, 110, 128, 24, 151, 187, 144, 108, 233, 221, 208, 157, 52,
4030 ];
4031 assert_eq!(expected_difference, result_point);
4032
4033 let result = SyscallCurveGroupOps::rust(
4034 &mut invoke_context,
4035 CURVE25519_RISTRETTO,
4036 SUB,
4037 invalid_point_va,
4038 right_point_va,
4039 result_point_va,
4040 );
4041
4042 assert_eq!(1, result.unwrap());
4043
4044 let result = SyscallCurveGroupOps::rust(
4045 &mut invoke_context,
4046 CURVE25519_RISTRETTO,
4047 MUL,
4048 scalar_va,
4049 right_point_va,
4050 result_point_va,
4051 );
4052
4053 result.unwrap();
4054 let expected_product = [
4055 4, 16, 46, 2, 53, 151, 201, 133, 117, 149, 232, 164, 119, 109, 136, 20, 153, 24, 124,
4056 21, 101, 124, 80, 19, 119, 100, 77, 108, 65, 187, 228, 5,
4057 ];
4058 assert_eq!(expected_product, result_point);
4059
4060 let result = SyscallCurveGroupOps::rust(
4061 &mut invoke_context,
4062 CURVE25519_RISTRETTO,
4063 MUL,
4064 scalar_va,
4065 invalid_point_va,
4066 result_point_va,
4067 );
4068
4069 assert_eq!(1, result.unwrap());
4070
4071 let result = SyscallCurveGroupOps::rust(
4072 &mut invoke_context,
4073 CURVE25519_RISTRETTO,
4074 MUL,
4075 scalar_va,
4076 invalid_point_va,
4077 result_point_va,
4078 );
4079 assert_matches!(
4080 result,
4081 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
4082 );
4083 }
4084
4085 #[test]
4086 fn test_syscall_multiscalar_multiplication() {
4087 use solana_curve25519::curve_syscall_traits::{CURVE25519_EDWARDS, CURVE25519_RISTRETTO};
4088
4089 let config = Config::default();
4090 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
4091
4092 let scalar_a: [u8; 32] = [
4093 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
4094 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
4095 ];
4096 let scalar_b: [u8; 32] = [
4097 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
4098 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
4099 ];
4100
4101 let scalars = [scalar_a, scalar_b];
4102 let scalars_va = 0x100000000;
4103
4104 let edwards_point_x: [u8; 32] = [
4105 252, 31, 230, 46, 173, 95, 144, 148, 158, 157, 63, 10, 8, 68, 58, 176, 142, 192, 168,
4106 53, 61, 105, 194, 166, 43, 56, 246, 236, 28, 146, 114, 133,
4107 ];
4108 let edwards_point_y: [u8; 32] = [
4109 10, 111, 8, 236, 97, 189, 124, 69, 89, 176, 222, 39, 199, 253, 111, 11, 248, 186, 128,
4110 90, 120, 128, 248, 210, 232, 183, 93, 104, 111, 150, 7, 241,
4111 ];
4112 let edwards_points = [edwards_point_x, edwards_point_y];
4113 let edwards_points_va = 0x200000000;
4114
4115 let ristretto_point_x: [u8; 32] = [
4116 130, 35, 97, 25, 18, 199, 33, 239, 85, 143, 119, 111, 49, 51, 224, 40, 167, 185, 240,
4117 179, 25, 194, 213, 41, 14, 155, 104, 18, 181, 197, 15, 112,
4118 ];
4119 let ristretto_point_y: [u8; 32] = [
4120 152, 156, 155, 197, 152, 232, 92, 206, 219, 159, 193, 134, 121, 128, 139, 36, 56, 191,
4121 51, 143, 72, 204, 87, 76, 110, 124, 101, 96, 238, 158, 42, 108,
4122 ];
4123 let ristretto_points = [ristretto_point_x, ristretto_point_y];
4124 let ristretto_points_va = 0x300000000;
4125
4126 let mut result_point: [u8; 32] = [0; 32];
4127 let result_point_va = 0x400000000;
4128
4129 let memory_mapping = unsafe {
4130 MemoryMapping::new(
4131 vec![
4132 MemoryRegion::new(bytes_of_slice(&scalars), scalars_va),
4133 MemoryRegion::new(bytes_of_slice(&edwards_points), edwards_points_va),
4134 MemoryRegion::new(bytes_of_slice(&ristretto_points), ristretto_points_va),
4135 MemoryRegion::new(bytes_of_slice_mut(&mut result_point), result_point_va),
4136 ],
4137 &config,
4138 SBPFVersion::V3,
4139 )
4140 .unwrap()
4141 };
4142
4143 invoke_context
4144 .memory_contexts
4145 .mock_set_mapping_abi_v1(memory_mapping);
4146 invoke_context.compute_meter.mock_set_remaining(
4147 invoke_context
4148 .get_execution_cost()
4149 .curve25519_edwards_msm_base_cost
4150 + invoke_context
4151 .get_execution_cost()
4152 .curve25519_edwards_msm_incremental_cost
4153 + invoke_context
4154 .get_execution_cost()
4155 .curve25519_ristretto_msm_base_cost
4156 + invoke_context
4157 .get_execution_cost()
4158 .curve25519_ristretto_msm_incremental_cost,
4159 );
4160
4161 let result = SyscallCurveMultiscalarMultiplication::rust(
4162 &mut invoke_context,
4163 CURVE25519_EDWARDS,
4164 scalars_va,
4165 edwards_points_va,
4166 2,
4167 result_point_va,
4168 );
4169
4170 assert_eq!(0, result.unwrap());
4171 let expected_product = [
4172 30, 174, 168, 34, 160, 70, 63, 166, 236, 18, 74, 144, 185, 222, 208, 243, 5, 54, 223,
4173 172, 185, 75, 244, 26, 70, 18, 248, 46, 207, 184, 235, 60,
4174 ];
4175 assert_eq!(expected_product, result_point);
4176
4177 let result = SyscallCurveMultiscalarMultiplication::rust(
4178 &mut invoke_context,
4179 CURVE25519_RISTRETTO,
4180 scalars_va,
4181 ristretto_points_va,
4182 2,
4183 result_point_va,
4184 );
4185
4186 assert_eq!(0, result.unwrap());
4187 let expected_product = [
4188 78, 120, 86, 111, 152, 64, 146, 84, 14, 236, 77, 147, 237, 190, 251, 241, 136, 167, 21,
4189 94, 84, 118, 92, 140, 120, 81, 30, 246, 173, 140, 195, 86,
4190 ];
4191 assert_eq!(expected_product, result_point);
4192 }
4193
4194 #[test]
4195 fn test_syscall_multiscalar_multiplication_maximum_length_exceeded() {
4196 use solana_curve25519::curve_syscall_traits::{CURVE25519_EDWARDS, CURVE25519_RISTRETTO};
4197
4198 let config = Config::default();
4199 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
4200
4201 let scalar: [u8; 32] = [
4202 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
4203 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
4204 ];
4205 let scalars = [scalar; 513];
4206 let scalars_va = 0x100000000;
4207
4208 let edwards_point: [u8; 32] = [
4209 252, 31, 230, 46, 173, 95, 144, 148, 158, 157, 63, 10, 8, 68, 58, 176, 142, 192, 168,
4210 53, 61, 105, 194, 166, 43, 56, 246, 236, 28, 146, 114, 133,
4211 ];
4212 let edwards_points = [edwards_point; 513];
4213 let edwards_points_va = 0x200000000;
4214
4215 let ristretto_point: [u8; 32] = [
4216 130, 35, 97, 25, 18, 199, 33, 239, 85, 143, 119, 111, 49, 51, 224, 40, 167, 185, 240,
4217 179, 25, 194, 213, 41, 14, 155, 104, 18, 181, 197, 15, 112,
4218 ];
4219 let ristretto_points = [ristretto_point; 513];
4220 let ristretto_points_va = 0x300000000;
4221
4222 let mut result_point: [u8; 32] = [0; 32];
4223 let result_point_va = 0x400000000;
4224
4225 let memory_mapping = unsafe {
4226 MemoryMapping::new(
4227 vec![
4228 MemoryRegion::new(bytes_of_slice(&scalars), scalars_va),
4229 MemoryRegion::new(bytes_of_slice(&edwards_points), edwards_points_va),
4230 MemoryRegion::new(bytes_of_slice(&ristretto_points), ristretto_points_va),
4231 MemoryRegion::new(bytes_of_slice_mut(&mut result_point), result_point_va),
4232 ],
4233 &config,
4234 SBPFVersion::V3,
4235 )
4236 .unwrap()
4237 };
4238
4239 invoke_context
4241 .memory_contexts
4242 .mock_set_mapping_abi_v1(memory_mapping);
4243 invoke_context.compute_meter.mock_set_remaining(500_000);
4244 let result = SyscallCurveMultiscalarMultiplication::rust(
4245 &mut invoke_context,
4246 CURVE25519_EDWARDS,
4247 scalars_va,
4248 edwards_points_va,
4249 512, result_point_va,
4251 );
4252
4253 assert_eq!(0, result.unwrap());
4254 let expected_product = [
4255 20, 146, 226, 37, 22, 61, 86, 249, 208, 40, 38, 11, 126, 101, 10, 82, 81, 77, 88, 209,
4256 15, 76, 82, 251, 180, 133, 84, 243, 162, 0, 11, 145,
4257 ];
4258 assert_eq!(expected_product, result_point);
4259
4260 invoke_context.compute_meter.mock_set_remaining(500_000);
4261 let result = SyscallCurveMultiscalarMultiplication::rust(
4262 &mut invoke_context,
4263 CURVE25519_EDWARDS,
4264 scalars_va,
4265 edwards_points_va,
4266 513, result_point_va,
4268 )
4269 .unwrap_err()
4270 .downcast::<SyscallError>()
4271 .unwrap();
4272
4273 assert_eq!(*result, SyscallError::InvalidLength);
4274
4275 invoke_context.compute_meter.mock_set_remaining(500_000);
4277 let result = SyscallCurveMultiscalarMultiplication::rust(
4278 &mut invoke_context,
4279 CURVE25519_RISTRETTO,
4280 scalars_va,
4281 ristretto_points_va,
4282 512, result_point_va,
4284 );
4285
4286 assert_eq!(0, result.unwrap());
4287 let expected_product = [
4288 146, 224, 127, 193, 252, 64, 196, 181, 246, 104, 27, 116, 183, 52, 200, 239, 2, 108,
4289 21, 27, 97, 44, 95, 65, 26, 218, 223, 39, 197, 132, 51, 49,
4290 ];
4291 assert_eq!(expected_product, result_point);
4292
4293 invoke_context.compute_meter.mock_set_remaining(500_000);
4294 let result = SyscallCurveMultiscalarMultiplication::rust(
4295 &mut invoke_context,
4296 CURVE25519_RISTRETTO,
4297 scalars_va,
4298 ristretto_points_va,
4299 513, result_point_va,
4301 )
4302 .unwrap_err()
4303 .downcast::<SyscallError>()
4304 .unwrap();
4305
4306 assert_eq!(*result, SyscallError::InvalidLength);
4307 }
4308
4309 fn create_filled_type<T: Default>(zero_init: bool) -> T {
4310 let mut val = T::default();
4311 let p = &mut val as *mut _ as *mut u8;
4312 for i in 0..(size_of::<T>() as isize) {
4313 unsafe {
4314 *p.offset(i) = if zero_init { 0 } else { i as u8 };
4315 }
4316 }
4317 val
4318 }
4319
4320 fn are_bytes_equal<T>(first: &T, second: &T) -> bool {
4321 let p_first = first as *const _ as *const u8;
4322 let p_second = second as *const _ as *const u8;
4323
4324 for i in 0..(size_of::<T>() as isize) {
4325 unsafe {
4326 if *p_first.offset(i) != *p_second.offset(i) {
4327 return false;
4328 }
4329 }
4330 }
4331 true
4332 }
4333
4334 #[test]
4335 #[expect(deprecated)]
4336 #[expect(clippy::redundant_clone)]
4337 fn test_syscall_get_sysvar() {
4338 let config = Config::default();
4339
4340 let mut src_clock = create_filled_type::<Clock>(false);
4341 src_clock.slot = 1;
4342 src_clock.epoch_start_timestamp = 2;
4343 src_clock.epoch = 3;
4344 src_clock.leader_schedule_epoch = 4;
4345 src_clock.unix_timestamp = 5;
4346
4347 let mut src_epochschedule = create_filled_type::<EpochSchedule>(false);
4348 src_epochschedule.slots_per_epoch = 1;
4349 src_epochschedule.leader_schedule_slot_offset = 2;
4350 src_epochschedule.warmup = false;
4351 src_epochschedule.first_normal_epoch = 3;
4352 src_epochschedule.first_normal_slot = 4;
4353
4354 let mut src_fees = create_filled_type::<Fees>(false);
4355 src_fees.fee_calculator = FeeCalculator {
4356 lamports_per_signature: 1,
4357 };
4358
4359 let mut src_rent = create_filled_type::<Rent>(false);
4360 src_rent.lamports_per_byte = 1;
4361 src_rent.exemption_threshold = 1.0f64.to_le_bytes();
4362 src_rent.burn_percent = 3;
4363
4364 let mut src_rewards = create_filled_type::<EpochRewards>(false);
4365 src_rewards.distribution_starting_block_height = 42;
4366 src_rewards.num_partitions = 2;
4367 src_rewards.parent_blockhash = Hash::new_from_array([3; 32]);
4368 src_rewards.total_points = 4;
4369 src_rewards.total_rewards = 100;
4370 src_rewards.distributed_rewards = 10;
4371 src_rewards.active = true;
4372
4373 let mut src_restart = create_filled_type::<LastRestartSlot>(false);
4374 src_restart.last_restart_slot = 1;
4375
4376 let transaction_accounts = vec![
4377 (
4378 sysvar::clock::id(),
4379 create_account_shared_data_for_test(&src_clock),
4380 ),
4381 (
4382 sysvar::epoch_schedule::id(),
4383 create_account_shared_data_for_test(&src_epochschedule),
4384 ),
4385 (
4386 sysvar::fees::id(),
4387 create_account_shared_data_for_test(&src_fees),
4388 ),
4389 (
4390 sysvar::rent::id(),
4391 create_account_shared_data_for_test(&src_rent),
4392 ),
4393 (
4394 sysvar::epoch_rewards::id(),
4395 create_account_shared_data_for_test(&src_rewards),
4396 ),
4397 (
4398 sysvar::last_restart_slot::id(),
4399 create_account_shared_data_for_test(&src_restart),
4400 ),
4401 ];
4402 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4403
4404 {
4406 let mut got_clock_obj = Clock::default();
4407 let got_clock_obj_va = 0x100000000;
4408
4409 let mut got_clock_buf = vec![0; Clock::size_of()];
4410 let got_clock_buf_va = 0x200000000;
4411 let clock_id_va = 0x300000000;
4412 let clock_id = Clock::id().to_bytes();
4413
4414 let memory_mapping = unsafe {
4415 MemoryMapping::new(
4416 vec![
4417 MemoryRegion::new(bytes_of_mut(&mut got_clock_obj), got_clock_obj_va),
4418 MemoryRegion::new(&raw mut got_clock_buf[..], got_clock_buf_va),
4419 MemoryRegion::new(&raw const clock_id, clock_id_va),
4420 ],
4421 &config,
4422 SBPFVersion::V3,
4423 )
4424 .unwrap()
4425 };
4426 invoke_context
4427 .memory_contexts
4428 .mock_set_mapping_abi_v1(memory_mapping);
4429
4430 let result =
4431 SyscallGetClockSysvar::rust(&mut invoke_context, got_clock_obj_va, 0, 0, 0, 0);
4432 assert_eq!(result.unwrap(), 0);
4433 assert_eq!(got_clock_obj, src_clock);
4434
4435 let mut clean_clock = create_filled_type::<Clock>(true);
4436 clean_clock.slot = src_clock.slot;
4437 clean_clock.epoch_start_timestamp = src_clock.epoch_start_timestamp;
4438 clean_clock.epoch = src_clock.epoch;
4439 clean_clock.leader_schedule_epoch = src_clock.leader_schedule_epoch;
4440 clean_clock.unix_timestamp = src_clock.unix_timestamp;
4441 assert!(are_bytes_equal(&got_clock_obj, &clean_clock));
4442
4443 let result = SyscallGetSysvar::rust(
4444 &mut invoke_context,
4445 clock_id_va,
4446 got_clock_buf_va,
4447 0,
4448 Clock::size_of() as u64,
4449 0,
4450 );
4451 assert_eq!(result.unwrap(), 0);
4452
4453 let clock_from_buf = bincode::deserialize::<Clock>(&got_clock_buf).unwrap();
4454
4455 assert_eq!(clock_from_buf, src_clock);
4456 assert!(are_bytes_equal(&clock_from_buf, &clean_clock));
4457 }
4458
4459 {
4461 let mut got_epochschedule_obj = EpochSchedule::default();
4462 let got_epochschedule_obj_va = 0x100000000;
4463
4464 let mut got_epochschedule_buf = vec![0; EpochSchedule::size_of()];
4465 let got_epochschedule_buf_va = 0x200000000;
4466 let epochschedule_id_va = 0x300000000;
4467 let epochschedule_id = EpochSchedule::id().to_bytes();
4468
4469 let memory_mapping = unsafe {
4470 MemoryMapping::new(
4471 vec![
4472 MemoryRegion::new(
4473 bytes_of_mut(&mut got_epochschedule_obj),
4474 got_epochschedule_obj_va,
4475 ),
4476 MemoryRegion::new(
4477 &raw mut got_epochschedule_buf[..],
4478 got_epochschedule_buf_va,
4479 ),
4480 MemoryRegion::new(&raw const epochschedule_id, epochschedule_id_va),
4481 ],
4482 &config,
4483 SBPFVersion::V3,
4484 )
4485 .unwrap()
4486 };
4487 invoke_context
4488 .memory_contexts
4489 .mock_set_mapping_abi_v1(memory_mapping);
4490
4491 let result = SyscallGetEpochScheduleSysvar::rust(
4492 &mut invoke_context,
4493 got_epochschedule_obj_va,
4494 0,
4495 0,
4496 0,
4497 0,
4498 );
4499 assert_eq!(result.unwrap(), 0);
4500 assert_eq!(got_epochschedule_obj, src_epochschedule);
4501
4502 let mut clean_epochschedule = create_filled_type::<EpochSchedule>(true);
4503 clean_epochschedule.slots_per_epoch = src_epochschedule.slots_per_epoch;
4504 clean_epochschedule.leader_schedule_slot_offset =
4505 src_epochschedule.leader_schedule_slot_offset;
4506 clean_epochschedule.warmup = src_epochschedule.warmup;
4507 clean_epochschedule.first_normal_epoch = src_epochschedule.first_normal_epoch;
4508 clean_epochschedule.first_normal_slot = src_epochschedule.first_normal_slot;
4509 assert!(are_bytes_equal(
4510 &got_epochschedule_obj,
4511 &clean_epochschedule
4512 ));
4513
4514 let result = SyscallGetSysvar::rust(
4515 &mut invoke_context,
4516 epochschedule_id_va,
4517 got_epochschedule_buf_va,
4518 0,
4519 EpochSchedule::size_of() as u64,
4520 0,
4521 );
4522 assert_eq!(result.unwrap(), 0);
4523
4524 let epochschedule_from_buf =
4525 bincode::deserialize::<EpochSchedule>(&got_epochschedule_buf).unwrap();
4526
4527 assert_eq!(epochschedule_from_buf, src_epochschedule);
4528
4529 assert!(are_bytes_equal(
4531 &epochschedule_from_buf.clone(),
4532 &clean_epochschedule
4533 ));
4534 }
4535
4536 {
4538 let mut got_fees = Fees::default();
4539 let got_fees_va = 0x100000000;
4540
4541 let memory_mapping = unsafe {
4542 MemoryMapping::new(
4543 vec![MemoryRegion::new(bytes_of_mut(&mut got_fees), got_fees_va)],
4544 &config,
4545 SBPFVersion::V3,
4546 )
4547 .unwrap()
4548 };
4549 invoke_context
4550 .memory_contexts
4551 .mock_set_mapping_abi_v1(memory_mapping);
4552
4553 let result = SyscallGetFeesSysvar::rust(&mut invoke_context, got_fees_va, 0, 0, 0, 0);
4554 assert_eq!(result.unwrap(), 0);
4555 assert_eq!(got_fees, src_fees);
4556
4557 let mut clean_fees = create_filled_type::<Fees>(true);
4558 clean_fees.fee_calculator = src_fees.fee_calculator;
4559 assert!(are_bytes_equal(&got_fees, &clean_fees));
4560
4561 }
4563
4564 {
4566 let mut got_rent_obj = create_filled_type::<Rent>(true);
4567 let got_rent_obj_va = 0x100000000;
4568
4569 let mut got_rent_buf = vec![0; Rent::size_of()];
4570 let got_rent_buf_va = 0x200000000;
4571 let rent_id_va = 0x300000000;
4572 let rent_id = Rent::id().to_bytes();
4573
4574 let memory_mapping = unsafe {
4575 MemoryMapping::new(
4576 vec![
4577 MemoryRegion::new(bytes_of_mut(&mut got_rent_obj), got_rent_obj_va),
4578 MemoryRegion::new(&raw mut got_rent_buf[..], got_rent_buf_va),
4579 MemoryRegion::new(&raw const rent_id, rent_id_va),
4580 ],
4581 &config,
4582 SBPFVersion::V3,
4583 )
4584 .unwrap()
4585 };
4586 invoke_context
4587 .memory_contexts
4588 .mock_set_mapping_abi_v1(memory_mapping);
4589
4590 let result =
4591 SyscallGetRentSysvar::rust(&mut invoke_context, got_rent_obj_va, 0, 0, 0, 0);
4592 assert_eq!(result.unwrap(), 0);
4593 assert_eq!(got_rent_obj, src_rent);
4594
4595 let mut clean_rent = create_filled_type::<Rent>(true);
4596 clean_rent.lamports_per_byte = src_rent.lamports_per_byte;
4597 clean_rent.exemption_threshold = src_rent.exemption_threshold;
4598 clean_rent.burn_percent = src_rent.burn_percent;
4599 assert!(are_bytes_equal(&got_rent_obj, &clean_rent));
4600
4601 let result = SyscallGetSysvar::rust(
4602 &mut invoke_context,
4603 rent_id_va,
4604 got_rent_buf_va,
4605 0,
4606 Rent::size_of() as u64,
4607 0,
4608 );
4609 assert_eq!(result.unwrap(), 0);
4610
4611 let rent_from_buf = bincode::deserialize::<Rent>(&got_rent_buf).unwrap();
4612
4613 assert_eq!(rent_from_buf, src_rent);
4614
4615 assert!(are_bytes_equal(&rent_from_buf.clone(), &clean_rent));
4617 }
4618
4619 {
4621 let mut got_rewards_obj = create_filled_type::<EpochRewards>(true);
4622 let got_rewards_obj_va = 0x100000000;
4623
4624 let mut got_rewards_buf = vec![0; EpochRewards::size_of()];
4625 let got_rewards_buf_va = 0x200000000;
4626 let rewards_id_va = 0x300000000;
4627 let rewards_id = EpochRewards::id().to_bytes();
4628
4629 let memory_mapping = unsafe {
4630 MemoryMapping::new(
4631 vec![
4632 MemoryRegion::new(bytes_of_mut(&mut got_rewards_obj), got_rewards_obj_va),
4633 MemoryRegion::new(&raw mut got_rewards_buf[..], got_rewards_buf_va),
4634 MemoryRegion::new(&raw const rewards_id, rewards_id_va),
4635 ],
4636 &config,
4637 SBPFVersion::V3,
4638 )
4639 .unwrap()
4640 };
4641 invoke_context
4642 .memory_contexts
4643 .mock_set_mapping_abi_v1(memory_mapping);
4644
4645 let result = SyscallGetEpochRewardsSysvar::rust(
4646 &mut invoke_context,
4647 got_rewards_obj_va,
4648 0,
4649 0,
4650 0,
4651 0,
4652 );
4653 assert_eq!(result.unwrap(), 0);
4654 assert_eq!(got_rewards_obj, src_rewards);
4655
4656 let mut clean_rewards = create_filled_type::<EpochRewards>(true);
4657 clean_rewards.distribution_starting_block_height =
4658 src_rewards.distribution_starting_block_height;
4659 clean_rewards.num_partitions = src_rewards.num_partitions;
4660 clean_rewards.parent_blockhash = src_rewards.parent_blockhash;
4661 clean_rewards.total_points = src_rewards.total_points;
4662 clean_rewards.total_rewards = src_rewards.total_rewards;
4663 clean_rewards.distributed_rewards = src_rewards.distributed_rewards;
4664 clean_rewards.active = src_rewards.active;
4665 assert!(are_bytes_equal(&got_rewards_obj, &clean_rewards));
4666
4667 let result = SyscallGetSysvar::rust(
4668 &mut invoke_context,
4669 rewards_id_va,
4670 got_rewards_buf_va,
4671 0,
4672 EpochRewards::size_of() as u64,
4673 0,
4674 );
4675 assert_eq!(result.unwrap(), 0);
4676
4677 let rewards_from_buf = bincode::deserialize::<EpochRewards>(&got_rewards_buf).unwrap();
4678
4679 assert_eq!(rewards_from_buf, src_rewards);
4680
4681 assert!(are_bytes_equal(&rewards_from_buf.clone(), &clean_rewards));
4683 }
4684
4685 {
4687 let mut got_restart_obj = LastRestartSlot::default();
4688 let got_restart_obj_va = 0x100000000;
4689
4690 let mut got_restart_buf = vec![0; LastRestartSlot::size_of()];
4691 let got_restart_buf_va = 0x200000000;
4692 let restart_id_va = 0x300000000;
4693 let restart_id = LastRestartSlot::id().to_bytes();
4694
4695 let memory_mapping = unsafe {
4696 MemoryMapping::new(
4697 vec![
4698 MemoryRegion::new(bytes_of_mut(&mut got_restart_obj), got_restart_obj_va),
4699 MemoryRegion::new(&raw mut got_restart_buf[..], got_restart_buf_va),
4700 MemoryRegion::new(&raw const restart_id, restart_id_va),
4701 ],
4702 &config,
4703 SBPFVersion::V3,
4704 )
4705 .unwrap()
4706 };
4707 invoke_context
4708 .memory_contexts
4709 .mock_set_mapping_abi_v1(memory_mapping);
4710
4711 let result = SyscallGetLastRestartSlotSysvar::rust(
4712 &mut invoke_context,
4713 got_restart_obj_va,
4714 0,
4715 0,
4716 0,
4717 0,
4718 );
4719 assert_eq!(result.unwrap(), 0);
4720 assert_eq!(got_restart_obj, src_restart);
4721
4722 let mut clean_restart = create_filled_type::<LastRestartSlot>(true);
4723 clean_restart.last_restart_slot = src_restart.last_restart_slot;
4724 assert!(are_bytes_equal(&got_restart_obj, &clean_restart));
4725
4726 let result = SyscallGetSysvar::rust(
4727 &mut invoke_context,
4728 restart_id_va,
4729 got_restart_buf_va,
4730 0,
4731 LastRestartSlot::size_of() as u64,
4732 0,
4733 );
4734 assert_eq!(result.unwrap(), 0);
4735
4736 let restart_from_buf =
4737 bincode::deserialize::<LastRestartSlot>(&got_restart_buf).unwrap();
4738
4739 assert_eq!(restart_from_buf, src_restart);
4740 assert!(are_bytes_equal(&restart_from_buf, &clean_restart));
4741 }
4742 }
4743
4744 #[test_case(false; "partial")]
4745 #[test_case(true; "full")]
4746 fn test_syscall_get_stake_history(filled: bool) {
4747 let config = Config::default();
4748
4749 let mut src_history = StakeHistory::default();
4750
4751 let epochs = if filled {
4752 solana_stake_history::MAX_ENTRIES + 1
4753 } else {
4754 solana_stake_history::MAX_ENTRIES / 2
4755 } as u64;
4756
4757 for epoch in 1..epochs {
4758 src_history.add(
4759 epoch,
4760 StakeHistoryEntry {
4761 effective: epoch * 2,
4762 activating: epoch * 3,
4763 deactivating: epoch * 5,
4764 },
4765 );
4766 }
4767
4768 let src_history = src_history;
4769
4770 let mut src_history_buf = vec![0; STAKE_HISTORY_ACCOUNT_SIZE];
4771 bincode::serialize_into(&mut src_history_buf, &src_history).unwrap();
4772
4773 let transaction_accounts = vec![(
4774 sysvar::stake_history::id(),
4775 create_stake_history_account_for_test(&src_history),
4776 )];
4777 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4778
4779 {
4780 let mut got_history_buf = vec![0; STAKE_HISTORY_ACCOUNT_SIZE];
4781 let got_history_buf_va = 0x100000000;
4782 let history_id_va = 0x200000000;
4783 let history_id = StakeHistory::id().to_bytes();
4784
4785 let memory_mapping = unsafe {
4786 MemoryMapping::new(
4787 vec![
4788 MemoryRegion::new(&raw mut got_history_buf[..], got_history_buf_va),
4789 MemoryRegion::new(&raw const history_id, history_id_va),
4790 ],
4791 &config,
4792 SBPFVersion::V3,
4793 )
4794 .unwrap()
4795 };
4796 invoke_context
4797 .memory_contexts
4798 .mock_set_mapping_abi_v1(memory_mapping);
4799
4800 let result = SyscallGetSysvar::rust(
4801 &mut invoke_context,
4802 history_id_va,
4803 got_history_buf_va,
4804 0,
4805 STAKE_HISTORY_ACCOUNT_SIZE as u64,
4806 0,
4807 );
4808 assert_eq!(result.unwrap(), 0);
4809
4810 let history_from_buf = bincode::deserialize::<StakeHistory>(&got_history_buf).unwrap();
4811 assert_eq!(history_from_buf, src_history);
4812 }
4813 }
4814
4815 #[test_case(false; "partial")]
4816 #[test_case(true; "full")]
4817 fn test_syscall_get_slot_hashes(filled: bool) {
4818 let config = Config::default();
4819
4820 let mut src_hashes = SlotHashes::default();
4821
4822 let slots = if filled {
4823 slot_hashes::MAX_ENTRIES + 1
4824 } else {
4825 slot_hashes::MAX_ENTRIES / 2
4826 } as u64;
4827
4828 for slot in 1..slots {
4829 src_hashes.add(slot, hashv(&[&slot.to_le_bytes()]));
4830 }
4831
4832 let src_hashes = src_hashes;
4833
4834 let mut src_hashes_buf = vec![0; SlotHashes::size_of()];
4835 wincode::serialize_into(&mut src_hashes_buf, &src_hashes).unwrap();
4836
4837 let transaction_accounts = vec![(
4838 sysvar::slot_hashes::id(),
4839 create_account_shared_data_for_test(&src_hashes),
4840 )];
4841 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4842
4843 {
4844 let mut got_hashes_buf = vec![0; SlotHashes::size_of()];
4845 let got_hashes_buf_va = 0x100000000;
4846 let hashes_id_va = 0x200000000;
4847 let hashes_id = SlotHashes::id().to_bytes();
4848
4849 let memory_mapping = unsafe {
4850 MemoryMapping::new(
4851 vec![
4852 MemoryRegion::new(&raw mut got_hashes_buf[..], got_hashes_buf_va),
4853 MemoryRegion::new(&raw const hashes_id, hashes_id_va),
4854 ],
4855 &config,
4856 SBPFVersion::V3,
4857 )
4858 .unwrap()
4859 };
4860 invoke_context
4861 .memory_contexts
4862 .mock_set_mapping_abi_v1(memory_mapping);
4863
4864 let result = SyscallGetSysvar::rust(
4865 &mut invoke_context,
4866 hashes_id_va,
4867 got_hashes_buf_va,
4868 0,
4869 SlotHashes::size_of() as u64,
4870 0,
4871 );
4872 assert_eq!(result.unwrap(), 0);
4873
4874 let hashes_from_buf = wincode::deserialize::<SlotHashes>(&got_hashes_buf).unwrap();
4875 assert_eq!(hashes_from_buf, src_hashes);
4876 }
4877 }
4878
4879 #[test]
4880 fn test_syscall_get_sysvar_errors() {
4881 let config = Config::default();
4882
4883 let mut src_clock = create_filled_type::<Clock>(false);
4884 src_clock.slot = 1;
4885 src_clock.epoch_start_timestamp = 2;
4886 src_clock.epoch = 3;
4887 src_clock.leader_schedule_epoch = 4;
4888 src_clock.unix_timestamp = 5;
4889
4890 let clock_id_va = 0x300000000;
4891 let clock_id = Clock::id().to_bytes();
4892
4893 let mut got_clock_buf_rw = vec![0; Clock::size_of()];
4894 let got_clock_buf_rw_va = 0x400000000;
4895
4896 let got_clock_buf_ro = vec![0; Clock::size_of()];
4897 let got_clock_buf_ro_va = 0x500000000;
4898
4899 let access_violation_err =
4900 std::mem::discriminant(&EbpfError::AccessViolation(AccessType::Load, 0, 0, ""));
4901
4902 let got_clock_empty = vec![0; Clock::size_of()];
4903
4904 {
4905 with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
4907 let memory_mapping = unsafe {
4908 MemoryMapping::new(
4909 vec![
4910 MemoryRegion::new(&raw const clock_id, clock_id_va),
4911 MemoryRegion::new(&raw mut got_clock_buf_rw[..], got_clock_buf_rw_va),
4912 MemoryRegion::new(&raw const got_clock_buf_ro[..], got_clock_buf_ro_va),
4913 ],
4914 &config,
4915 SBPFVersion::V3,
4916 )
4917 .unwrap()
4918 };
4919 invoke_context
4920 .memory_contexts
4921 .mock_set_mapping_abi_v1(memory_mapping);
4922
4923 let e = SyscallGetSysvar::rust(
4925 &mut invoke_context,
4926 clock_id_va + 1,
4927 got_clock_buf_rw_va,
4928 0,
4929 Clock::size_of() as u64,
4930 0,
4931 )
4932 .unwrap_err();
4933
4934 assert_eq!(
4935 std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
4936 access_violation_err,
4937 );
4938 assert_eq!(got_clock_buf_rw, got_clock_empty);
4939
4940 let e = SyscallGetSysvar::rust(
4942 &mut invoke_context,
4943 clock_id_va,
4944 got_clock_buf_rw_va + 1,
4945 0,
4946 Clock::size_of() as u64,
4947 0,
4948 )
4949 .unwrap_err();
4950
4951 assert_eq!(
4952 std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
4953 access_violation_err,
4954 );
4955 assert_eq!(got_clock_buf_rw, got_clock_empty);
4956
4957 let e = SyscallGetSysvar::rust(
4958 &mut invoke_context,
4959 clock_id_va,
4960 got_clock_buf_ro_va,
4961 0,
4962 Clock::size_of() as u64,
4963 0,
4964 )
4965 .unwrap_err();
4966
4967 assert_eq!(
4968 std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
4969 access_violation_err,
4970 );
4971 assert_eq!(got_clock_buf_rw, got_clock_empty);
4972
4973 let e = SyscallGetSysvar::rust(
4975 &mut invoke_context,
4976 clock_id_va,
4977 got_clock_buf_rw_va,
4978 u64::MAX - Clock::size_of() as u64 / 2,
4979 Clock::size_of() as u64,
4980 0,
4981 )
4982 .unwrap_err();
4983
4984 assert_eq!(
4985 *e.downcast_ref::<InstructionError>().unwrap(),
4986 InstructionError::ArithmeticOverflow,
4987 );
4988 assert_eq!(got_clock_buf_rw, got_clock_empty);
4989
4990 let result = SyscallGetSysvar::rust(
4995 &mut invoke_context,
4996 clock_id_va,
4997 got_clock_buf_rw_va,
4998 0,
4999 Clock::size_of() as u64,
5000 0,
5001 )
5002 .unwrap();
5003
5004 assert_eq!(result, 2);
5005 assert_eq!(got_clock_buf_rw, got_clock_empty);
5006 }
5007
5008 {
5009 let transaction_accounts = vec![(
5010 sysvar::clock::id(),
5011 create_account_shared_data_for_test(&src_clock),
5012 )];
5013 let memory_mapping = unsafe {
5014 MemoryMapping::new(
5015 vec![
5016 MemoryRegion::new(&raw const clock_id, clock_id_va),
5017 MemoryRegion::new(&raw mut got_clock_buf_rw[..], got_clock_buf_rw_va),
5018 MemoryRegion::new(&raw const got_clock_buf_ro[..], got_clock_buf_ro_va),
5019 ],
5020 &config,
5021 SBPFVersion::V3,
5022 )
5023 .unwrap()
5024 };
5025 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
5026 invoke_context
5027 .memory_contexts
5028 .mock_set_mapping_abi_v1(memory_mapping);
5029
5030 let result = SyscallGetSysvar::rust(
5032 &mut invoke_context,
5033 clock_id_va,
5034 got_clock_buf_rw_va,
5035 1,
5036 Clock::size_of() as u64,
5037 0,
5038 )
5039 .unwrap();
5040
5041 assert_eq!(result, 1);
5042 assert_eq!(got_clock_buf_rw, got_clock_empty);
5043
5044 SyscallGetSysvar::rust(
5046 &mut invoke_context,
5047 clock_id_va,
5048 got_clock_buf_rw_va,
5049 0,
5050 Clock::size_of() as u64,
5051 0,
5052 )
5053 .unwrap();
5054
5055 let clock_from_buf = bincode::deserialize::<Clock>(&got_clock_buf_rw).unwrap();
5056
5057 assert_eq!(clock_from_buf, src_clock);
5058 }
5059 }
5060
5061 type BuiltinFunctionRustInterface<'a> = fn(
5062 &mut InvokeContext<'a, 'a>,
5063 u64,
5064 u64,
5065 u64,
5066 u64,
5067 u64,
5068 ) -> Result<u64, Box<dyn std::error::Error>>;
5069
5070 fn call_program_address_common<'a, 'b: 'a>(
5071 invoke_context: &'a mut InvokeContext<'b, 'b>,
5072 seeds: &[&[u8]],
5073 program_id: &Pubkey,
5074 overlap_outputs: bool,
5075 syscall: BuiltinFunctionRustInterface<'b>,
5076 ) -> Result<(Pubkey, u8), Error> {
5077 const SEEDS_VA: u64 = 0x100000000;
5078 const PROGRAM_ID_VA: u64 = 0x200000000;
5079 const ADDRESS_VA: u64 = 0x300000000;
5080 const BUMP_SEED_VA: u64 = 0x400000000;
5081 const SEED_VA: u64 = 0x500000000;
5082
5083 let config = Config::default();
5084 let mut address = Pubkey::default();
5085 let mut bump_seed = 0;
5086 let mut regions = vec![
5087 MemoryRegion::new(bytes_of(program_id), PROGRAM_ID_VA),
5088 MemoryRegion::new(bytes_of_mut(&mut address), ADDRESS_VA),
5089 MemoryRegion::new(bytes_of_mut(&mut bump_seed), BUMP_SEED_VA),
5090 ];
5091
5092 let mut mock_slices = Vec::with_capacity(seeds.len());
5093 for (i, seed) in seeds.iter().enumerate() {
5094 let vm_addr = SEED_VA.saturating_add((i as u64).saturating_mul(0x100000000));
5095 let mock_slice = MockSlice {
5096 vm_addr,
5097 len: seed.len(),
5098 };
5099 mock_slices.push(mock_slice);
5100 regions.push(MemoryRegion::new(bytes_of_slice(seed), vm_addr));
5101 }
5102 regions.push(MemoryRegion::new(bytes_of_slice(&mock_slices), SEEDS_VA));
5103 let memory_mapping =
5104 unsafe { MemoryMapping::new(regions, &config, SBPFVersion::V3).unwrap() };
5105 invoke_context
5106 .memory_contexts
5107 .mock_set_mapping_abi_v1(memory_mapping);
5108
5109 let result = syscall(
5110 invoke_context,
5111 SEEDS_VA,
5112 seeds.len() as u64,
5113 PROGRAM_ID_VA,
5114 ADDRESS_VA,
5115 if overlap_outputs {
5116 ADDRESS_VA
5117 } else {
5118 BUMP_SEED_VA
5119 },
5120 );
5121 result.map(|_| (address, bump_seed))
5122 }
5123
5124 fn create_program_address<'a>(
5125 invoke_context: &mut InvokeContext<'a, 'a>,
5126 seeds: &[&[u8]],
5127 address: &Pubkey,
5128 ) -> Result<Pubkey, Error> {
5129 let (address, _) = call_program_address_common(
5130 invoke_context,
5131 seeds,
5132 address,
5133 false,
5134 SyscallCreateProgramAddress::rust,
5135 )?;
5136 Ok(address)
5137 }
5138
5139 fn try_find_program_address<'a>(
5140 invoke_context: &mut InvokeContext<'a, 'a>,
5141 seeds: &[&[u8]],
5142 address: &Pubkey,
5143 ) -> Result<(Pubkey, u8), Error> {
5144 call_program_address_common(
5145 invoke_context,
5146 seeds,
5147 address,
5148 false,
5149 SyscallTryFindProgramAddress::rust,
5150 )
5151 }
5152
5153 #[test]
5154 fn test_set_and_get_return_data() {
5155 const SRC_VA: u64 = 0x100000000;
5156 const DST_VA: u64 = 0x200000000;
5157 const PROGRAM_ID_VA: u64 = 0x300000000;
5158 let data = [42; 24];
5159 let mut data_buffer = vec![0; 16];
5160 let mut id_buffer = vec![0; 32];
5161
5162 let config = Config::default();
5163 let memory_mapping = unsafe {
5164 MemoryMapping::new(
5165 vec![
5166 MemoryRegion::new(&raw const data, SRC_VA),
5167 MemoryRegion::new(&raw mut data_buffer[..], DST_VA),
5168 MemoryRegion::new(&raw mut id_buffer[..], PROGRAM_ID_VA),
5169 ],
5170 &config,
5171 SBPFVersion::V3,
5172 )
5173 .unwrap()
5174 };
5175
5176 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
5177 invoke_context
5178 .memory_contexts
5179 .mock_set_mapping_abi_v1(memory_mapping);
5180
5181 let result =
5182 SyscallSetReturnData::rust(&mut invoke_context, SRC_VA, data.len() as u64, 0, 0, 0);
5183 assert_eq!(result.unwrap(), 0);
5184
5185 let result = SyscallGetReturnData::rust(
5186 &mut invoke_context,
5187 DST_VA,
5188 data_buffer.len() as u64,
5189 PROGRAM_ID_VA,
5190 0,
5191 0,
5192 );
5193 assert_eq!(result.unwrap() as usize, data.len());
5194 assert_eq!(data.get(0..data_buffer.len()).unwrap(), data_buffer);
5195 assert_eq!(id_buffer, program_id.to_bytes());
5196
5197 let result = SyscallGetReturnData::rust(
5198 &mut invoke_context,
5199 PROGRAM_ID_VA,
5200 data_buffer.len() as u64,
5201 PROGRAM_ID_VA,
5202 0,
5203 0,
5204 );
5205 assert_matches!(
5206 result,
5207 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
5208 );
5209 }
5210
5211 #[test]
5212 fn test_syscall_sol_get_processed_sibling_instruction_top_level() {
5213 let transaction_accounts = (0..9)
5214 .map(|_| {
5215 (
5216 Pubkey::new_unique(),
5217 AccountSharedData::new(0, 0, &bpf_loader::id()),
5218 )
5219 })
5220 .collect::<Vec<_>>();
5221 with_mock_invoke_context!(invoke_context, transaction_context, 4, transaction_accounts);
5222
5223 let ixs = *b"ABCD";
5236 for (idx, ix) in ixs.iter().enumerate() {
5237 invoke_context
5238 .transaction_context
5239 .configure_top_level_instruction_for_tests(
5240 0,
5241 vec![InstructionAccount::new(idx as u16, false, false)],
5242 vec![*ix],
5243 )
5244 .unwrap();
5245 }
5246
5247 invoke_context.transaction_context.push().unwrap();
5255 invoke_context.transaction_context.pop().unwrap();
5256
5257 invoke_context.transaction_context.push().unwrap();
5259 invoke_context
5261 .transaction_context
5262 .configure_next_cpi_for_tests(
5263 1,
5264 vec![InstructionAccount::new(4, false, false)],
5265 vec![b'B', 1],
5266 )
5267 .unwrap();
5268 invoke_context.transaction_context.push().unwrap();
5269 invoke_context.transaction_context.pop().unwrap();
5270 invoke_context.transaction_context.pop().unwrap();
5271
5272 invoke_context.transaction_context.push().unwrap();
5274
5275 const VM_BASE_ADDRESS: u64 = 0x100000000;
5276 const META_OFFSET: usize = 0;
5277 const PROGRAM_ID_OFFSET: usize =
5278 META_OFFSET + std::mem::size_of::<ProcessedSiblingInstruction>();
5279 const DATA_OFFSET: usize = PROGRAM_ID_OFFSET + std::mem::size_of::<Pubkey>();
5280 const ACCOUNTS_OFFSET: usize = DATA_OFFSET + 0x100;
5281 const END_OFFSET: usize = ACCOUNTS_OFFSET + std::mem::size_of::<AccountInfo>() * 4;
5282 let mut memory = [0u8; END_OFFSET];
5283 let config = Config::default();
5284 let memory_mapping = unsafe {
5285 MemoryMapping::new(
5286 vec![MemoryRegion::new(&raw mut memory, VM_BASE_ADDRESS)],
5287 &config,
5288 SBPFVersion::V3,
5289 )
5290 .unwrap()
5291 };
5292 invoke_context
5293 .memory_contexts
5294 .mock_set_mapping_abi_v1(memory_mapping);
5295 let processed_sibling_instruction =
5296 unsafe { &mut *memory.as_mut_ptr().cast::<ProcessedSiblingInstruction>() };
5297 processed_sibling_instruction.data_len = 1;
5298 processed_sibling_instruction.accounts_len = 1;
5299
5300 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5301 invoke_context
5302 .compute_meter
5303 .mock_set_remaining(syscall_base_cost);
5304 let result = SyscallGetProcessedSiblingInstruction::rust(
5305 &mut invoke_context,
5306 0,
5307 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5308 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5309 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5310 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5311 );
5312 assert_eq!(result.unwrap(), 1);
5313 {
5314 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5315 let program_id = translate_type::<Pubkey>(
5316 memory_mapping,
5317 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5318 true,
5319 )
5320 .unwrap();
5321 let data = translate_slice::<u8>(
5322 memory_mapping,
5323 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5324 processed_sibling_instruction.data_len,
5325 true,
5326 )
5327 .unwrap();
5328 let accounts = translate_slice::<AccountMeta>(
5329 memory_mapping,
5330 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5331 processed_sibling_instruction.accounts_len,
5332 true,
5333 )
5334 .unwrap();
5335 let transaction_context = &invoke_context.transaction_context;
5336 assert_eq!(processed_sibling_instruction.data_len, 1);
5337 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5338 assert_eq!(
5339 program_id,
5340 transaction_context.get_key_of_account_at_index(0).unwrap(),
5341 );
5342 assert_eq!(data, b"B");
5343 assert_eq!(
5344 accounts,
5345 &[AccountMeta {
5346 pubkey: *transaction_context.get_key_of_account_at_index(1).unwrap(),
5347 is_signer: false,
5348 is_writable: false
5349 }]
5350 );
5351 }
5352
5353 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5354 invoke_context
5355 .compute_meter
5356 .mock_set_remaining(syscall_base_cost);
5357 let result = SyscallGetProcessedSiblingInstruction::rust(
5358 &mut invoke_context,
5359 1,
5360 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5361 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5362 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5363 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5364 );
5365
5366 assert_eq!(result.unwrap(), 1);
5367 {
5368 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5369 let program_id = translate_type::<Pubkey>(
5370 memory_mapping,
5371 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5372 true,
5373 )
5374 .unwrap();
5375 let data = translate_slice::<u8>(
5376 memory_mapping,
5377 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5378 processed_sibling_instruction.data_len,
5379 true,
5380 )
5381 .unwrap();
5382 let accounts = translate_slice::<AccountMeta>(
5383 memory_mapping,
5384 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5385 processed_sibling_instruction.accounts_len,
5386 true,
5387 )
5388 .unwrap();
5389 let transaction_context = &invoke_context.transaction_context;
5390 assert_eq!(processed_sibling_instruction.data_len, 1);
5391 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5392 assert_eq!(
5393 program_id,
5394 transaction_context.get_key_of_account_at_index(0).unwrap(),
5395 );
5396 assert_eq!(data, b"A");
5397 assert_eq!(
5398 accounts,
5399 &[AccountMeta {
5400 pubkey: *transaction_context.get_key_of_account_at_index(0).unwrap(),
5401 is_signer: false,
5402 is_writable: false
5403 }]
5404 );
5405 }
5406
5407 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5408 invoke_context
5409 .compute_meter
5410 .mock_set_remaining(syscall_base_cost);
5411 let result = SyscallGetProcessedSiblingInstruction::rust(
5412 &mut invoke_context,
5413 2,
5414 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5415 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5416 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5417 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5418 );
5419
5420 assert_eq!(result.unwrap(), 0);
5421
5422 invoke_context
5423 .compute_meter
5424 .mock_set_remaining(syscall_base_cost);
5425 let result = SyscallGetProcessedSiblingInstruction::rust(
5426 &mut invoke_context,
5427 0,
5428 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5429 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5430 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5431 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5432 );
5433 assert_matches!(
5434 result,
5435 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
5436 );
5437 }
5438
5439 #[test]
5440 fn test_syscall_sol_get_processed_sibling_instruction_cpi() {
5441 let transaction_accounts = (0..9)
5442 .map(|_| {
5443 (
5444 Pubkey::new_unique(),
5445 AccountSharedData::new(0, 0, &bpf_loader::id()),
5446 )
5447 })
5448 .collect::<Vec<_>>();
5449 with_mock_invoke_context!(invoke_context, transaction_context, 3, transaction_accounts);
5450
5451 const VM_BASE_ADDRESS: u64 = 0x100000000;
5452 const META_OFFSET: usize = 0;
5453 const PROGRAM_ID_OFFSET: usize =
5454 META_OFFSET + std::mem::size_of::<ProcessedSiblingInstruction>();
5455 const DATA_OFFSET: usize = PROGRAM_ID_OFFSET + std::mem::size_of::<Pubkey>();
5456 const ACCOUNTS_OFFSET: usize = DATA_OFFSET + 0x100;
5457 const END_OFFSET: usize = ACCOUNTS_OFFSET + std::mem::size_of::<AccountInfo>() * 4;
5458 let mut memory = [0u8; END_OFFSET];
5459 let config = Config::default();
5460 let memory_mapping = unsafe {
5461 MemoryMapping::new(
5462 vec![MemoryRegion::new(&raw mut memory, VM_BASE_ADDRESS)],
5463 &config,
5464 SBPFVersion::V3,
5465 )
5466 .unwrap()
5467 };
5468 invoke_context
5469 .memory_contexts
5470 .mock_set_mapping_abi_v1(memory_mapping);
5471 let processed_sibling_instruction =
5472 unsafe { &mut *memory.as_mut_ptr().cast::<ProcessedSiblingInstruction>() };
5473 processed_sibling_instruction.data_len = 2;
5474 processed_sibling_instruction.accounts_len = 1;
5475 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5476
5477 let top_level = *b"ABC";
5500 for (idx, ix) in top_level.iter().enumerate() {
5501 invoke_context
5502 .transaction_context
5503 .configure_top_level_instruction_for_tests(
5504 0,
5505 vec![InstructionAccount::new(idx as u16, false, false)],
5506 vec![*ix],
5507 )
5508 .unwrap();
5509 }
5510
5511 invoke_context.transaction_context.push().unwrap();
5519 invoke_context.transaction_context.pop().unwrap();
5520 invoke_context.transaction_context.push().unwrap();
5522 invoke_context
5524 .transaction_context
5525 .configure_next_cpi_for_tests(
5526 1,
5527 vec![InstructionAccount::new(1, false, false)],
5528 vec![b'B', 1],
5529 )
5530 .unwrap();
5531 invoke_context.transaction_context.push().unwrap();
5532 invoke_context
5534 .transaction_context
5535 .configure_next_cpi_for_tests(
5536 1,
5537 vec![InstructionAccount::new(2, false, false)],
5538 vec![b'B', 2],
5539 )
5540 .unwrap();
5541 invoke_context.transaction_context.push().unwrap();
5542 invoke_context.transaction_context.pop().unwrap();
5544 invoke_context.transaction_context.pop().unwrap();
5545 invoke_context
5547 .transaction_context
5548 .configure_next_cpi_for_tests(
5549 1,
5550 vec![InstructionAccount::new(3, false, false)],
5551 vec![b'B', 3],
5552 )
5553 .unwrap();
5554 invoke_context.transaction_context.push().unwrap();
5555 invoke_context.transaction_context.pop().unwrap();
5557 invoke_context
5559 .transaction_context
5560 .configure_next_cpi_for_tests(
5561 1,
5562 vec![InstructionAccount::new(4, false, false)],
5563 vec![b'B', 4],
5564 )
5565 .unwrap();
5566 invoke_context.transaction_context.push().unwrap();
5567 invoke_context
5569 .transaction_context
5570 .configure_next_cpi_for_tests(
5571 1,
5572 vec![InstructionAccount::new(5, false, false)],
5573 vec![b'B', 5],
5574 )
5575 .unwrap();
5576 invoke_context.transaction_context.push().unwrap();
5577
5578 invoke_context
5580 .compute_meter
5581 .mock_set_remaining(syscall_base_cost);
5582 let result = SyscallGetProcessedSiblingInstruction::rust(
5583 &mut invoke_context,
5584 0,
5585 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5586 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5587 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5588 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5589 );
5590 assert_eq!(result.unwrap(), 0);
5591
5592 invoke_context.transaction_context.pop().unwrap();
5594 invoke_context
5596 .transaction_context
5597 .configure_next_cpi_for_tests(
5598 2,
5599 vec![InstructionAccount::new(6, false, false)],
5600 vec![b'B', 6],
5601 )
5602 .unwrap();
5603 invoke_context.transaction_context.push().unwrap();
5604 invoke_context
5606 .transaction_context
5607 .configure_next_cpi_for_tests(
5608 1,
5609 vec![InstructionAccount::new(6, false, false)],
5610 vec![b'B', 7],
5611 )
5612 .unwrap();
5613 invoke_context.transaction_context.push().unwrap();
5614 invoke_context.transaction_context.pop().unwrap();
5616
5617 invoke_context
5619 .compute_meter
5620 .mock_set_remaining(syscall_base_cost);
5621 let result = SyscallGetProcessedSiblingInstruction::rust(
5622 &mut invoke_context,
5623 0,
5624 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5625 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5626 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5627 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5628 );
5629
5630 assert_eq!(result.unwrap(), 1);
5631 {
5632 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5633 let program_id = translate_type::<Pubkey>(
5634 memory_mapping,
5635 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5636 true,
5637 )
5638 .unwrap();
5639 let data = translate_slice::<u8>(
5640 memory_mapping,
5641 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5642 processed_sibling_instruction.data_len,
5643 true,
5644 )
5645 .unwrap();
5646 let accounts = translate_slice::<AccountMeta>(
5647 memory_mapping,
5648 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5649 processed_sibling_instruction.accounts_len,
5650 true,
5651 )
5652 .unwrap();
5653 let transaction_context = &invoke_context.transaction_context;
5654 assert_eq!(processed_sibling_instruction.data_len, 2);
5655 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5656 assert_eq!(
5657 program_id,
5658 transaction_context.get_key_of_account_at_index(1).unwrap(),
5659 );
5660 assert_eq!(data, &[b'B', 5]);
5661 assert_eq!(
5662 accounts,
5663 &[AccountMeta {
5664 pubkey: *transaction_context.get_key_of_account_at_index(5).unwrap(),
5665 is_signer: false,
5666 is_writable: false
5667 }]
5668 );
5669 }
5670
5671 invoke_context
5673 .compute_meter
5674 .mock_set_remaining(syscall_base_cost);
5675 let result = SyscallGetProcessedSiblingInstruction::rust(
5676 &mut invoke_context,
5677 1,
5678 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5679 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5680 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5681 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5682 );
5683 assert_eq!(result.unwrap(), 0);
5684
5685 invoke_context.transaction_context.pop().unwrap();
5687
5688 invoke_context
5690 .transaction_context
5691 .configure_next_cpi_for_tests(
5692 3,
5693 vec![InstructionAccount::new(8, false, false)],
5694 vec![b'B', 8],
5695 )
5696 .unwrap();
5697 invoke_context.transaction_context.push().unwrap();
5698
5699 invoke_context
5701 .compute_meter
5702 .mock_set_remaining(syscall_base_cost);
5703 let result = SyscallGetProcessedSiblingInstruction::rust(
5704 &mut invoke_context,
5705 0,
5706 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5707 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5708 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5709 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5710 );
5711
5712 assert_eq!(result.unwrap(), 1);
5713 {
5714 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5715 let program_id = translate_type::<Pubkey>(
5716 memory_mapping,
5717 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5718 true,
5719 )
5720 .unwrap();
5721 let data = translate_slice::<u8>(
5722 memory_mapping,
5723 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5724 processed_sibling_instruction.data_len,
5725 true,
5726 )
5727 .unwrap();
5728 let accounts = translate_slice::<AccountMeta>(
5729 memory_mapping,
5730 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5731 processed_sibling_instruction.accounts_len,
5732 true,
5733 )
5734 .unwrap();
5735 let transaction_context = &invoke_context.transaction_context;
5736 assert_eq!(processed_sibling_instruction.data_len, 2);
5737 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5738 assert_eq!(
5739 program_id,
5740 transaction_context.get_key_of_account_at_index(2).unwrap(),
5741 );
5742 assert_eq!(data, &[b'B', 6]);
5743 assert_eq!(
5744 accounts,
5745 &[AccountMeta {
5746 pubkey: *transaction_context.get_key_of_account_at_index(6).unwrap(),
5747 is_signer: false,
5748 is_writable: false
5749 }]
5750 );
5751 }
5752
5753 invoke_context
5755 .compute_meter
5756 .mock_set_remaining(syscall_base_cost);
5757 let result = SyscallGetProcessedSiblingInstruction::rust(
5758 &mut invoke_context,
5759 1,
5760 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5761 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5762 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5763 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5764 );
5765
5766 assert_eq!(result.unwrap(), 1);
5767 {
5768 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5769 let program_id = translate_type::<Pubkey>(
5770 memory_mapping,
5771 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5772 true,
5773 )
5774 .unwrap();
5775 let data = translate_slice::<u8>(
5776 memory_mapping,
5777 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5778 processed_sibling_instruction.data_len,
5779 true,
5780 )
5781 .unwrap();
5782 let accounts = translate_slice::<AccountMeta>(
5783 memory_mapping,
5784 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5785 processed_sibling_instruction.accounts_len,
5786 true,
5787 )
5788 .unwrap();
5789 let transaction_context = &invoke_context.transaction_context;
5790 assert_eq!(processed_sibling_instruction.data_len, 2);
5791 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5792 assert_eq!(
5793 program_id,
5794 transaction_context.get_key_of_account_at_index(1).unwrap(),
5795 );
5796 assert_eq!(data, &[b'B', 5]);
5797 assert_eq!(
5798 accounts,
5799 &[AccountMeta {
5800 pubkey: *transaction_context.get_key_of_account_at_index(5).unwrap(),
5801 is_signer: false,
5802 is_writable: false
5803 }]
5804 );
5805 }
5806
5807 invoke_context
5809 .compute_meter
5810 .mock_set_remaining(syscall_base_cost);
5811 let result = SyscallGetProcessedSiblingInstruction::rust(
5812 &mut invoke_context,
5813 2,
5814 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5815 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5816 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5817 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5818 );
5819 assert_eq!(result.unwrap(), 0);
5820
5821 invoke_context.transaction_context.pop().unwrap();
5823 invoke_context.transaction_context.pop().unwrap();
5825 invoke_context.transaction_context.pop().unwrap();
5827
5828 invoke_context.transaction_context.push().unwrap();
5830
5831 invoke_context
5833 .compute_meter
5834 .mock_set_remaining(syscall_base_cost);
5835 processed_sibling_instruction.data_len = 1;
5836 let result = SyscallGetProcessedSiblingInstruction::rust(
5837 &mut invoke_context,
5838 0,
5839 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5840 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5841 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5842 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5843 );
5844
5845 assert_eq!(result.unwrap(), 1);
5846 {
5847 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5848 let program_id = translate_type::<Pubkey>(
5849 memory_mapping,
5850 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5851 true,
5852 )
5853 .unwrap();
5854 let data = translate_slice::<u8>(
5855 memory_mapping,
5856 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5857 processed_sibling_instruction.data_len,
5858 true,
5859 )
5860 .unwrap();
5861 let accounts = translate_slice::<AccountMeta>(
5862 memory_mapping,
5863 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5864 processed_sibling_instruction.accounts_len,
5865 true,
5866 )
5867 .unwrap();
5868 let transaction_context = &invoke_context.transaction_context;
5869 assert_eq!(processed_sibling_instruction.data_len, 1);
5870 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5871 assert_eq!(
5872 program_id,
5873 transaction_context.get_key_of_account_at_index(0).unwrap(),
5874 );
5875 assert_eq!(data, b"B");
5876 assert_eq!(
5877 accounts,
5878 &[AccountMeta {
5879 pubkey: *transaction_context.get_key_of_account_at_index(1).unwrap(),
5880 is_signer: false,
5881 is_writable: false
5882 }]
5883 );
5884 }
5885
5886 invoke_context
5888 .transaction_context
5889 .configure_next_cpi_for_tests(
5890 2,
5891 vec![InstructionAccount::new(7, false, false)],
5892 vec![b'C', 1],
5893 )
5894 .unwrap();
5895 invoke_context.transaction_context.push().unwrap();
5896
5897 invoke_context
5899 .compute_meter
5900 .mock_set_remaining(syscall_base_cost);
5901 let result = SyscallGetProcessedSiblingInstruction::rust(
5902 &mut invoke_context,
5903 0,
5904 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5905 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5906 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5907 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5908 );
5909 assert_eq!(result.unwrap(), 0);
5910
5911 invoke_context.transaction_context.pop().unwrap();
5913 invoke_context
5915 .transaction_context
5916 .configure_next_cpi_for_tests(
5917 2,
5918 vec![InstructionAccount::new(7, false, false)],
5919 vec![b'C', 2],
5920 )
5921 .unwrap();
5922 invoke_context.transaction_context.push().unwrap();
5923
5924 invoke_context
5926 .compute_meter
5927 .mock_set_remaining(syscall_base_cost);
5928 processed_sibling_instruction.data_len = 2;
5929 let result = SyscallGetProcessedSiblingInstruction::rust(
5930 &mut invoke_context,
5931 0,
5932 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5933 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5934 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5935 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5936 );
5937
5938 assert_eq!(result.unwrap(), 1);
5939 {
5940 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5941 let program_id = translate_type::<Pubkey>(
5942 memory_mapping,
5943 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5944 true,
5945 )
5946 .unwrap();
5947 let data = translate_slice::<u8>(
5948 memory_mapping,
5949 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5950 processed_sibling_instruction.data_len,
5951 true,
5952 )
5953 .unwrap();
5954 let accounts = translate_slice::<AccountMeta>(
5955 memory_mapping,
5956 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5957 processed_sibling_instruction.accounts_len,
5958 true,
5959 )
5960 .unwrap();
5961 let transaction_context = &invoke_context.transaction_context;
5962 assert_eq!(processed_sibling_instruction.data_len, 2);
5963 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5964 assert_eq!(
5965 program_id,
5966 transaction_context.get_key_of_account_at_index(2).unwrap(),
5967 );
5968 assert_eq!(data, &[b'C', 1]);
5969 assert_eq!(
5970 accounts,
5971 &[AccountMeta {
5972 pubkey: *transaction_context.get_key_of_account_at_index(7).unwrap(),
5973 is_signer: false,
5974 is_writable: false
5975 }]
5976 );
5977 }
5978
5979 invoke_context
5981 .compute_meter
5982 .mock_set_remaining(syscall_base_cost);
5983 let result = SyscallGetProcessedSiblingInstruction::rust(
5984 &mut invoke_context,
5985 1,
5986 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5987 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5988 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5989 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5990 );
5991 assert_eq!(result.unwrap(), 0);
5992 }
5993
5994 #[test]
5995 fn test_create_program_address() {
5996 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
5999 let address = bpf_loader_upgradeable::id();
6000
6001 let exceeded_seed = &[127; MAX_SEED_LEN + 1];
6002 assert_matches!(
6003 create_program_address(&mut invoke_context, &[exceeded_seed], &address),
6004 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6005 );
6006 assert_matches!(
6007 create_program_address(
6008 &mut invoke_context,
6009 &[b"short_seed", exceeded_seed],
6010 &address,
6011 ),
6012 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6013 );
6014 let max_seed = &[0; MAX_SEED_LEN];
6015 assert!(create_program_address(&mut invoke_context, &[max_seed], &address).is_ok());
6016 let exceeded_seeds: &[&[u8]] = &[
6017 &[1],
6018 &[2],
6019 &[3],
6020 &[4],
6021 &[5],
6022 &[6],
6023 &[7],
6024 &[8],
6025 &[9],
6026 &[10],
6027 &[11],
6028 &[12],
6029 &[13],
6030 &[14],
6031 &[15],
6032 &[16],
6033 ];
6034 assert!(create_program_address(&mut invoke_context, exceeded_seeds, &address).is_ok());
6035 let max_seeds: &[&[u8]] = &[
6036 &[1],
6037 &[2],
6038 &[3],
6039 &[4],
6040 &[5],
6041 &[6],
6042 &[7],
6043 &[8],
6044 &[9],
6045 &[10],
6046 &[11],
6047 &[12],
6048 &[13],
6049 &[14],
6050 &[15],
6051 &[16],
6052 &[17],
6053 ];
6054 assert_matches!(
6055 create_program_address(&mut invoke_context, max_seeds, &address),
6056 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6057 );
6058 assert_eq!(
6059 create_program_address(&mut invoke_context, &[b"", &[1]], &address).unwrap(),
6060 "BwqrghZA2htAcqq8dzP1WDAhTXYTYWj7CHxF5j7TDBAe"
6061 .parse()
6062 .unwrap(),
6063 );
6064 assert_eq!(
6065 create_program_address(&mut invoke_context, &["☉".as_ref(), &[0]], &address).unwrap(),
6066 "13yWmRpaTR4r5nAktwLqMpRNr28tnVUZw26rTvPSSB19"
6067 .parse()
6068 .unwrap(),
6069 );
6070 assert_eq!(
6071 create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
6072 .unwrap(),
6073 "2fnQrngrQT4SeLcdToJAD96phoEjNL2man2kfRLCASVk"
6074 .parse()
6075 .unwrap(),
6076 );
6077 let public_key = Pubkey::from_str("SeedPubey1111111111111111111111111111111111").unwrap();
6078 assert_eq!(
6079 create_program_address(&mut invoke_context, &[public_key.as_ref(), &[1]], &address)
6080 .unwrap(),
6081 "976ymqVnfE32QFe6NfGDctSvVa36LWnvYxhU6G2232YL"
6082 .parse()
6083 .unwrap(),
6084 );
6085 assert_ne!(
6086 create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
6087 .unwrap(),
6088 create_program_address(&mut invoke_context, &[b"Talking"], &address).unwrap(),
6089 );
6090 invoke_context.compute_meter.mock_set_remaining(0);
6091 assert_matches!(
6092 create_program_address(&mut invoke_context, &[b"", &[1]], &address),
6093 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
6094 );
6095 }
6096
6097 #[test]
6098 fn test_find_program_address() {
6099 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6100 let cost = invoke_context
6101 .get_execution_cost()
6102 .create_program_address_units;
6103 let address = bpf_loader_upgradeable::id();
6104 let max_tries = 256; for _ in 0..1_000 {
6107 let address = Pubkey::new_unique();
6108 invoke_context
6109 .compute_meter
6110 .mock_set_remaining(cost * max_tries);
6111 let (found_address, bump_seed) =
6112 try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address)
6113 .unwrap();
6114 assert_eq!(
6115 found_address,
6116 create_program_address(
6117 &mut invoke_context,
6118 &[b"Lil'", b"Bits", &[bump_seed]],
6119 &address,
6120 )
6121 .unwrap()
6122 );
6123 }
6124
6125 let seeds: &[&[u8]] = &[b""];
6126 invoke_context
6127 .compute_meter
6128 .mock_set_remaining(cost * max_tries);
6129 let (_, bump_seed) =
6130 try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
6131 invoke_context
6132 .compute_meter
6133 .mock_set_remaining(cost * (max_tries - bump_seed as u64));
6134 try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
6135 invoke_context
6136 .compute_meter
6137 .mock_set_remaining(cost * (max_tries - bump_seed as u64 - 1));
6138 assert_matches!(
6139 try_find_program_address(&mut invoke_context, seeds, &address),
6140 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
6141 );
6142
6143 let exceeded_seed = &[127; MAX_SEED_LEN + 1];
6144 invoke_context
6145 .compute_meter
6146 .mock_set_remaining(cost * (max_tries - 1));
6147 assert_matches!(
6148 try_find_program_address(&mut invoke_context, &[exceeded_seed], &address),
6149 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6150 );
6151 let exceeded_seeds: &[&[u8]] = &[
6152 &[1],
6153 &[2],
6154 &[3],
6155 &[4],
6156 &[5],
6157 &[6],
6158 &[7],
6159 &[8],
6160 &[9],
6161 &[10],
6162 &[11],
6163 &[12],
6164 &[13],
6165 &[14],
6166 &[15],
6167 &[16],
6168 &[17],
6169 ];
6170 invoke_context
6171 .compute_meter
6172 .mock_set_remaining(cost * (max_tries - 1));
6173 assert_matches!(
6174 try_find_program_address(&mut invoke_context, exceeded_seeds, &address),
6175 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6176 );
6177
6178 assert_matches!(
6179 call_program_address_common(
6180 &mut invoke_context,
6181 seeds,
6182 &address,
6183 true,
6184 SyscallTryFindProgramAddress::rust,
6185 ),
6186 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
6187 );
6188 }
6189
6190 #[test]
6191 fn test_syscall_big_mod_exp() {
6192 let config = Config::default();
6193 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6194
6195 const VADDR_PARAMS: u64 = 0x100000000;
6196 const VADDR_BASE: u64 = 0x200000000;
6197 const VADDR_EXPONENT: u64 = 0x300000000;
6198 const VADDR_MODULUS: u64 = 0x400000000;
6199 const VADDR_OUT: u64 = 0x500000000;
6200
6201 let base = [0x03];
6202 let exponent = [
6203 0x2e, 0xfc, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6204 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6205 0xff, 0xff, 0xff, 0xff,
6206 ];
6207 let modulus = [
6208 0x2f, 0xfc, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6210 0xff, 0xff, 0xff, 0xff,
6211 ];
6212 let mut data_out = [0u8; 32];
6213 let mut expected = [0u8; 32];
6214 expected[0] = 1;
6215 assert_eq!(
6216 big_mod_exp(&base, &exponent, &modulus),
6217 Some(expected.to_vec())
6218 );
6219 let params = BigModExpParams {
6220 base: VADDR_BASE,
6221 base_len: base.len() as u64,
6222 exponent: VADDR_EXPONENT,
6223 exponent_len: exponent.len() as u64,
6224 modulus: VADDR_MODULUS,
6225 modulus_len: modulus.len() as u64,
6226 };
6227
6228 let memory_mapping = unsafe {
6229 MemoryMapping::new(
6230 vec![
6231 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6232 MemoryRegion::new(bytes_of_slice(&base), VADDR_BASE),
6233 MemoryRegion::new(bytes_of_slice(&exponent), VADDR_EXPONENT),
6234 MemoryRegion::new(bytes_of_slice(&modulus), VADDR_MODULUS),
6235 MemoryRegion::new(bytes_of_slice_mut(&mut data_out), VADDR_OUT),
6236 ],
6237 &config,
6238 SBPFVersion::V3,
6239 )
6240 .unwrap()
6241 };
6242 invoke_context
6243 .memory_contexts
6244 .mock_set_mapping_abi_v1(memory_mapping);
6245 let budget = invoke_context.get_execution_cost();
6246 let cost = budget.big_modular_exponentiation_base_cost
6247 + big_mod_exp_operation_cost(
6248 budget.big_modular_exponentiation_cost_divisor,
6249 ¶ms,
6250 &exponent,
6251 )
6252 .unwrap();
6253 invoke_context.compute_meter.mock_set_remaining(cost);
6254
6255 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_OUT, 0, 0, 0);
6256
6257 assert_eq!(result.unwrap(), SUCCESS);
6258 assert_eq!(data_out, expected);
6259 }
6260
6261 #[test]
6262 fn test_syscall_big_mod_exp_invalid_modulus() {
6263 let config = Config::default();
6264 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6265
6266 const VADDR_PARAMS: u64 = 0x100000000;
6267 const VADDR_BASE: u64 = 0x200000000;
6268 const VADDR_EXPONENT: u64 = 0x300000000;
6269 const VADDR_MODULUS: u64 = 0x400000000;
6270 const VADDR_OUT: u64 = 0x500000000;
6271
6272 let base = [0x05];
6273 let exponent = [0x02];
6274 let modulus = [0x02];
6275 let mut data_out = [0u8; 1];
6276 let params = BigModExpParams {
6277 base: VADDR_BASE,
6278 base_len: base.len() as u64,
6279 exponent: VADDR_EXPONENT,
6280 exponent_len: exponent.len() as u64,
6281 modulus: VADDR_MODULUS,
6282 modulus_len: modulus.len() as u64,
6283 };
6284
6285 let memory_mapping = unsafe {
6286 MemoryMapping::new(
6287 vec![
6288 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6289 MemoryRegion::new(bytes_of_slice(&base), VADDR_BASE),
6290 MemoryRegion::new(bytes_of_slice(&exponent), VADDR_EXPONENT),
6291 MemoryRegion::new(bytes_of_slice(&modulus), VADDR_MODULUS),
6292 MemoryRegion::new(bytes_of_slice_mut(&mut data_out), VADDR_OUT),
6293 ],
6294 &config,
6295 SBPFVersion::V3,
6296 )
6297 .unwrap()
6298 };
6299 invoke_context
6300 .memory_contexts
6301 .mock_set_mapping_abi_v1(memory_mapping);
6302 let budget = invoke_context.get_execution_cost();
6303 let cost = budget.big_modular_exponentiation_base_cost
6304 + big_mod_exp_operation_cost(
6305 budget.big_modular_exponentiation_cost_divisor,
6306 ¶ms,
6307 &exponent,
6308 )
6309 .unwrap();
6310 invoke_context.compute_meter.mock_set_remaining(cost);
6311
6312 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_OUT, 0, 0, 0);
6313
6314 assert_matches!(
6315 result,
6316 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::InvalidAttribute
6317 );
6318 assert_eq!(data_out, [0x00]);
6319 }
6320
6321 #[test]
6322 fn test_syscall_big_mod_exp_overlapping_result() {
6323 let config = Config::default();
6324 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6325
6326 const VADDR_PARAMS: u64 = 0x100000000;
6327 const VADDR_BASE: u64 = 0x200000000;
6328 const VADDR_EXPONENT: u64 = 0x300000000;
6329 const VADDR_MODULUS: u64 = 0x400000000;
6330 let mut base = [0x05];
6331 let exponent = [0x02];
6332 let modulus = [0x07];
6333 assert_eq!(big_mod_exp(&[0x05], &[0x02], &[0x07]), Some(vec![0x04]));
6334 let params = BigModExpParams {
6335 base: VADDR_BASE,
6336 base_len: 1,
6337 exponent: VADDR_EXPONENT,
6338 exponent_len: 1,
6339 modulus: VADDR_MODULUS,
6340 modulus_len: 1,
6341 };
6342
6343 let memory_mapping = unsafe {
6344 MemoryMapping::new(
6345 vec![
6346 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6347 MemoryRegion::new(bytes_of_slice_mut(&mut base), VADDR_BASE),
6348 MemoryRegion::new(bytes_of_slice(&exponent), VADDR_EXPONENT),
6349 MemoryRegion::new(bytes_of_slice(&modulus), VADDR_MODULUS),
6350 ],
6351 &config,
6352 SBPFVersion::V3,
6353 )
6354 .unwrap()
6355 };
6356 invoke_context
6357 .memory_contexts
6358 .mock_set_mapping_abi_v1(memory_mapping);
6359 let budget = invoke_context.get_execution_cost();
6360 let cost = budget.big_modular_exponentiation_base_cost
6361 + big_mod_exp_operation_cost(
6362 budget.big_modular_exponentiation_cost_divisor,
6363 ¶ms,
6364 &exponent,
6365 )
6366 .unwrap();
6367 invoke_context.compute_meter.mock_set_remaining(cost);
6368
6369 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_BASE, 0, 0, 0);
6370
6371 assert_eq!(result.unwrap(), SUCCESS);
6372 assert_eq!(base, [0x04]);
6373 }
6374
6375 #[test]
6376 fn test_syscall_big_mod_exp_abort_conditions() {
6377 let config = Config::default();
6378 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6379
6380 const VADDR_PARAMS: u64 = 0x100000000;
6381 const VADDR_DATA: u64 = 0x200000000;
6382 const VADDR_OUT: u64 = 0x300000000;
6383 let data = [0u8; 1];
6384 let mut data_out = [0u8; 1];
6385 let params = BigModExpParams {
6386 base: VADDR_DATA,
6387 base_len: BIG_MOD_EXP_MAX_BYTES + 1,
6388 exponent: VADDR_DATA,
6389 exponent_len: 0,
6390 modulus: VADDR_DATA,
6391 modulus_len: 1,
6392 };
6393
6394 let memory_mapping = unsafe {
6395 MemoryMapping::new(
6396 vec![
6397 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6398 MemoryRegion::new(bytes_of_slice(&data), VADDR_DATA),
6399 MemoryRegion::new(bytes_of_slice_mut(&mut data_out), VADDR_OUT),
6400 ],
6401 &config,
6402 SBPFVersion::V3,
6403 )
6404 .unwrap()
6405 };
6406 invoke_context
6407 .memory_contexts
6408 .mock_set_mapping_abi_v1(memory_mapping);
6409
6410 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_OUT, 0, 0, 0);
6411 assert_matches!(
6412 result,
6413 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::InvalidLength
6414 );
6415 }
6416
6417 #[test]
6418 fn test_syscall_get_epoch_stake_total_stake() {
6419 let config = Config::default();
6420 let compute_cost = SVMTransactionExecutionCost::default();
6421 let mut compute_budget = SVMTransactionExecutionBudget::default();
6422 let sysvar_cache = Arc::<SysvarCache>::default();
6423
6424 const EXPECTED_TOTAL_STAKE: u64 = 200_000_000_000_000;
6425
6426 struct MockCallback {}
6427 impl InvokeContextCallback for MockCallback {
6428 fn get_epoch_stake(&self) -> u64 {
6429 EXPECTED_TOTAL_STAKE
6430 }
6431 }
6433
6434 let expected_cus = compute_cost.syscall_base_cost;
6437
6438 compute_budget.compute_unit_limit = expected_cus;
6441
6442 with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
6443 let feature_set = SVMFeatureSet::default();
6444 let program_runtime_environments = ProgramRuntimeEnvironments::mock();
6445 invoke_context.environment_config = EnvironmentConfig::new(
6446 Hash::default(),
6447 0,
6448 false,
6449 &MockCallback {},
6450 &feature_set,
6451 &program_runtime_environments,
6452 &sysvar_cache,
6453 );
6454 invoke_context
6455 .compute_meter
6456 .mock_set_remaining(compute_budget.compute_unit_limit);
6457
6458 let null_pointer_var = std::ptr::null::<Pubkey>() as u64;
6459
6460 let memory_mapping =
6461 unsafe { MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap() };
6462 invoke_context
6463 .memory_contexts
6464 .mock_set_mapping_abi_v1(memory_mapping);
6465
6466 let result =
6467 SyscallGetEpochStake::rust(&mut invoke_context, null_pointer_var, 0, 0, 0, 0).unwrap();
6468
6469 assert_eq!(result, EXPECTED_TOTAL_STAKE);
6470 }
6471
6472 #[test]
6473 fn test_syscall_get_epoch_stake_vote_account_stake() {
6474 let config = Config::default();
6475 let mut compute_budget = SVMTransactionExecutionBudget::default();
6476 let compute_cost = SVMTransactionExecutionCost::default();
6477 let sysvar_cache = Arc::<SysvarCache>::default();
6478
6479 const TARGET_VOTE_ADDRESS: Pubkey = Pubkey::new_from_array([2; 32]);
6480 const EXPECTED_EPOCH_STAKE: u64 = 55_000_000_000;
6481
6482 struct MockCallback {}
6483 impl InvokeContextCallback for MockCallback {
6484 fn get_epoch_stake_for_vote_account(&self, vote_address: &Pubkey) -> u64 {
6486 if *vote_address == TARGET_VOTE_ADDRESS {
6487 EXPECTED_EPOCH_STAKE
6488 } else {
6489 0
6490 }
6491 }
6492 }
6493
6494 let expected_cus = compute_cost.syscall_base_cost
6499 + (PUBKEY_BYTES as u64) / compute_cost.cpi_bytes_per_unit
6500 + compute_cost.mem_op_base_cost;
6501
6502 compute_budget.compute_unit_limit = expected_cus;
6505
6506 with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
6507 let feature_set = SVMFeatureSet::default();
6508 let program_runtime_environments = ProgramRuntimeEnvironments::mock();
6509 invoke_context.environment_config = EnvironmentConfig::new(
6510 Hash::default(),
6511 0,
6512 false,
6513 &MockCallback {},
6514 &feature_set,
6515 &program_runtime_environments,
6516 &sysvar_cache,
6517 );
6518
6519 {
6520 let vote_address_var = 0x100000000;
6523 let memory = [2; 31];
6524
6525 let memory_mapping = unsafe {
6526 MemoryMapping::new(
6527 vec![
6528 MemoryRegion::new(&raw const memory, vote_address_var),
6530 ],
6531 &config,
6532 SBPFVersion::V3,
6533 )
6534 .unwrap()
6535 };
6536 invoke_context
6537 .memory_contexts
6538 .mock_set_mapping_abi_v1(memory_mapping);
6539
6540 let result =
6541 SyscallGetEpochStake::rust(&mut invoke_context, vote_address_var, 0, 0, 0, 0);
6542
6543 assert_access_violation!(result, vote_address_var, 32);
6544 }
6545
6546 invoke_context
6547 .compute_meter
6548 .mock_set_remaining(compute_budget.compute_unit_limit);
6549 {
6550 let vote_address_var = 0x100000000;
6554
6555 let memory_mapping = unsafe {
6556 MemoryMapping::new(
6557 vec![MemoryRegion::new(
6558 bytes_of(&TARGET_VOTE_ADDRESS),
6559 vote_address_var,
6560 )],
6561 &config,
6562 SBPFVersion::V3,
6563 )
6564 .unwrap()
6565 };
6566 invoke_context
6567 .memory_contexts
6568 .mock_set_mapping_abi_v1(memory_mapping);
6569
6570 let result =
6571 SyscallGetEpochStake::rust(&mut invoke_context, vote_address_var, 0, 0, 0, 0)
6572 .unwrap();
6573
6574 assert_eq!(result, EXPECTED_EPOCH_STAKE);
6575 }
6576
6577 invoke_context
6578 .compute_meter
6579 .mock_set_remaining(compute_budget.compute_unit_limit);
6580 {
6581 let vote_address_var = 0x100000000;
6585 let not_a_vote_address = Pubkey::new_unique(); let memory_mapping = unsafe {
6588 MemoryMapping::new(
6589 vec![MemoryRegion::new(
6590 bytes_of(¬_a_vote_address),
6591 vote_address_var,
6592 )],
6593 &config,
6594 SBPFVersion::V3,
6595 )
6596 .unwrap()
6597 };
6598 invoke_context
6599 .memory_contexts
6600 .mock_set_mapping_abi_v1(memory_mapping);
6601
6602 let result =
6603 SyscallGetEpochStake::rust(&mut invoke_context, vote_address_var, 0, 0, 0, 0)
6604 .unwrap();
6605
6606 assert_eq!(result, 0); }
6608 }
6609
6610 #[test]
6611 fn test_check_type_assumptions() {
6612 check_type_assumptions();
6613 }
6614
6615 fn bytes_of<T>(val: &T) -> *const [u8] {
6616 let size = mem::size_of::<T>();
6617 core::ptr::slice_from_raw_parts(std::slice::from_ref(val).as_ptr().cast(), size)
6618 }
6619
6620 fn bytes_of_mut<T>(val: &mut T) -> *mut [u8] {
6621 let size = mem::size_of::<T>();
6622 core::ptr::slice_from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size)
6623 }
6624
6625 fn bytes_of_slice<T>(val: &[T]) -> *const [u8] {
6626 let size = val.len().wrapping_mul(mem::size_of::<T>());
6627 core::ptr::slice_from_raw_parts(val.as_ptr().cast(), size)
6628 }
6629
6630 fn bytes_of_slice_mut<T>(val: &mut [T]) -> *mut [u8] {
6631 let size = val.len().wrapping_mul(mem::size_of::<T>());
6632 core::ptr::slice_from_raw_parts_mut(val.as_mut_ptr().cast(), size)
6633 }
6634
6635 #[test_case(0x100000004, 0x100000004, &[0x00, 0x00, 0x00, 0x00])] #[test_case(0x100000003, 0x100000004, &[0xFF, 0xFF, 0xFF, 0xFF])] #[test_case(0x100000005, 0x100000004, &[0x01, 0x00, 0x00, 0x00])] #[test_case(0x100000004, 0x200000004, &[0x00, 0x00, 0x00, 0x00])] #[test_case(0x100000003, 0x200000004, &[0xFF, 0xFF, 0xFF, 0xFF])] #[test_case(0x100000005, 0x200000004, &[0x01, 0x00, 0x00, 0x00])] fn test_memcmp_success(src_a: u64, src_b: u64, expected_result: &[u8; 4]) {
6642 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6643 let mem = (0..12).collect::<Vec<u8>>();
6644 let mut result_mem = vec![0; 4];
6645 let config = Config::default();
6646 let memory_mapping = unsafe {
6647 MemoryMapping::new(
6648 vec![
6649 MemoryRegion::new(&raw const mem[..], 0x100000000),
6650 MemoryRegion::new(&raw const mem[..], 0x200000000),
6651 MemoryRegion::new(&raw mut result_mem[..], 0x300000000),
6652 ],
6653 &config,
6654 SBPFVersion::V3,
6655 )
6656 .unwrap()
6657 };
6658 invoke_context
6659 .memory_contexts
6660 .mock_set_mapping_abi_v1(memory_mapping);
6661
6662 let result = SyscallMemcmp::rust(&mut invoke_context, src_a, src_b, 4, 0x300000000, 0);
6663 result.unwrap();
6664 assert_eq!(result_mem, expected_result);
6665 }
6666
6667 #[test_case(0x100000002, 0x100000004, 18245498089483734664)] #[test_case(0x100000004, 0x100000002, 6092969436446403628)] #[test_case(0x100000002, 0x100000006, 16598193894146733116)] #[test_case(0x100000006, 0x100000002, 8940776276357560353)] #[test_case(0x100000000, 0x100000008, 1288053912680171784)] #[test_case(0x100000008, 0x100000000, 4652742827052033592)] #[test_case(0x100000004, 0x200000004, 8833460765081683332)] #[test_case(0x200000004, 0x100000004, 11837649335115988407)] fn test_memmove_success(dst: u64, src: u64, expected_hash: u64) {
6676 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6677 let mut mem = (0..24).collect::<Vec<u8>>();
6678 let config = Config::default();
6679 let memory_mapping = unsafe {
6680 MemoryMapping::new(
6681 vec![
6682 MemoryRegion::new(&raw mut mem[..12], 0x100000000),
6683 MemoryRegion::new(&raw mut mem[12..], 0x200000000),
6684 ],
6685 &config,
6686 SBPFVersion::V3,
6687 )
6688 .unwrap()
6689 };
6690 invoke_context
6691 .memory_contexts
6692 .mock_set_mapping_abi_v1(memory_mapping);
6693
6694 let result = SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0);
6695 result.unwrap();
6696 let mut hasher = DefaultHasher::new();
6697 mem.hash(&mut hasher);
6698 assert_eq!(hasher.finish(), expected_hash);
6699 }
6700
6701 #[test_case(0x100000002, 0x00, 6070675560359421890)]
6702 #[test_case(0x100000002, 0xFF, 3413209638111181029)]
6703 fn test_memset_success(dst: u64, value: u64, expected_hash: u64) {
6704 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6705 let mut mem = (0..12).collect::<Vec<u8>>();
6706 let config = Config::default();
6707 let memory_mapping = unsafe {
6708 MemoryMapping::new(
6709 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6710 &config,
6711 SBPFVersion::V3,
6712 )
6713 .unwrap()
6714 };
6715 invoke_context
6716 .memory_contexts
6717 .mock_set_mapping_abi_v1(memory_mapping);
6718
6719 let result = SyscallMemset::rust(&mut invoke_context, dst, value, 4, 0, 0);
6720 result.unwrap();
6721 let mut hasher = DefaultHasher::new();
6722 mem.hash(&mut hasher);
6723 assert_eq!(hasher.finish(), expected_hash);
6724 }
6725
6726 #[test_case(0x100000002, 0x100000004)] #[test_case(0x100000004, 0x100000002)] fn test_memcpy_overlapping(dst: u64, src: u64) {
6729 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6730 let mut mem = (0..12).collect::<Vec<u8>>();
6731 let config = Config::default();
6732 let memory_mapping = unsafe {
6733 MemoryMapping::new(
6734 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6735 &config,
6736 SBPFVersion::V3,
6737 )
6738 .unwrap()
6739 };
6740 invoke_context
6741 .memory_contexts
6742 .mock_set_mapping_abi_v1(memory_mapping);
6743
6744 let result = SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0);
6745 assert_matches!(
6746 result,
6747 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
6748 );
6749 }
6750
6751 #[test_case(0xFFFFFFFFF, 0x100000006, 0xFFFFFFFFF)] #[test_case(0x100000010, 0x100000006, 0x100000010)] #[test_case(0x100000002, 0xFFFFFFFFF, 0xFFFFFFFFF)] #[test_case(0x100000002, 0x100000010, 0x100000010)] fn test_memops_access_violation(dst: u64, src: u64, fault_address: u64) {
6756 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6757 let mut mem = (0..12).collect::<Vec<u8>>();
6758 let config = Config::default();
6759 let memory_mapping = unsafe {
6760 MemoryMapping::new(
6761 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6762 &config,
6763 SBPFVersion::V3,
6764 )
6765 .unwrap()
6766 };
6767 invoke_context
6768 .memory_contexts
6769 .mock_set_mapping_abi_v1(memory_mapping);
6770
6771 let result = SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0);
6772 assert_access_violation!(result, fault_address, 4);
6773 let result = SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0);
6774 assert_access_violation!(result, fault_address, 4);
6775 let result = SyscallMemcmp::rust(&mut invoke_context, dst, src, 4, 0, 0);
6776 assert_access_violation!(result, fault_address, 4);
6777 }
6778
6779 #[test_case(0xFFFFFFFFF)] #[test_case(0x100000010)] fn test_memset_access_violation(dst: u64) {
6782 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6783 let mut mem = (0..12).collect::<Vec<u8>>();
6784 let config = Config::default();
6785 let memory_mapping = unsafe {
6786 MemoryMapping::new(
6787 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6788 &config,
6789 SBPFVersion::V3,
6790 )
6791 .unwrap()
6792 };
6793 invoke_context
6794 .memory_contexts
6795 .mock_set_mapping_abi_v1(memory_mapping);
6796
6797 let result = SyscallMemset::rust(&mut invoke_context, dst, 0, 4, 0, 0);
6798 assert_access_violation!(result, dst, 4);
6799 }
6800
6801 #[test]
6802 fn test_memcmp_result_access_violation() {
6803 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6804 let mem = (0..12).collect::<Vec<u8>>();
6805 let config = Config::default();
6806 let memory_mapping = unsafe {
6807 MemoryMapping::new(
6808 vec![MemoryRegion::new(&raw const mem[..], 0x100000000)],
6809 &config,
6810 SBPFVersion::V3,
6811 )
6812 .unwrap()
6813 };
6814 invoke_context
6815 .memory_contexts
6816 .mock_set_mapping_abi_v1(memory_mapping);
6817
6818 let result = SyscallMemcmp::rust(
6819 &mut invoke_context,
6820 0x100000000,
6821 0x100000000,
6822 4,
6823 0x100000000,
6824 0,
6825 );
6826 assert_access_violation!(result, 0x100000000, 4);
6827 }
6828
6829 #[test]
6830 fn test_syscall_bls12_381_g1_add() {
6831 use {
6832 crate::bls12_381_curve_id::{BLS12_381_G1_BE, BLS12_381_G1_LE},
6833 solana_curve25519::curve_syscall_traits::ADD,
6834 };
6835
6836 let config = Config::default();
6837 let feature_set = SVMFeatureSet {
6838 enable_bls12_381_syscall: true,
6839 ..Default::default()
6840 };
6841 let feature_set = &feature_set;
6842 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
6843
6844 let p1_bytes_be: [u8; 96] = [
6845 9, 86, 169, 212, 236, 245, 17, 101, 127, 183, 56, 13, 99, 100, 183, 133, 57, 107, 96,
6846 220, 198, 197, 2, 215, 225, 175, 212, 57, 168, 143, 104, 127, 117, 242, 180, 200, 162,
6847 135, 72, 155, 88, 154, 58, 90, 58, 46, 248, 176, 10, 206, 25, 112, 240, 1, 57, 89, 10,
6848 30, 165, 94, 164, 252, 219, 225, 133, 214, 161, 4, 118, 177, 123, 53, 57, 53, 233, 255,
6849 112, 117, 241, 247, 185, 195, 232, 36, 123, 31, 221, 6, 57, 176, 251, 163, 195, 39, 35,
6850 175,
6851 ];
6852 let p2_bytes_be: [u8; 96] = [
6853 13, 32, 61, 215, 83, 124, 186, 189, 82, 0, 79, 244, 67, 167, 21, 50, 48, 229, 8, 107,
6854 51, 15, 19, 47, 75, 77, 246, 185, 63, 66, 143, 109, 237, 211, 153, 146, 163, 175, 74,
6855 69, 50, 198, 235, 218, 9, 170, 225, 46, 22, 211, 116, 84, 32, 115, 130, 224, 106, 250,
6856 205, 143, 238, 115, 74, 207, 238, 193, 232, 16, 59, 140, 20, 252, 7, 34, 144, 47, 137,
6857 56, 190, 170, 235, 189, 238, 45, 97, 58, 199, 202, 45, 164, 139, 200, 190, 215, 9, 59,
6858 ];
6859 let expected_sum_be: [u8; 96] = [
6860 23, 62, 255, 137, 157, 188, 98, 86, 192, 102, 136, 171, 187, 49, 155, 83, 204, 133,
6861 217, 144, 137, 103, 15, 4, 116, 75, 127, 65, 29, 89, 223, 147, 32, 161, 91, 104, 96,
6862 211, 239, 102, 233, 95, 48, 130, 207, 154, 19, 189, 18, 112, 102, 145, 36, 73, 17, 27,
6863 47, 96, 116, 45, 56, 25, 16, 191, 56, 21, 86, 216, 133, 245, 207, 71, 158, 31, 29, 51,
6864 84, 185, 134, 138, 64, 68, 55, 161, 55, 153, 214, 155, 250, 21, 233, 4, 3, 117, 41,
6865 239,
6866 ];
6867 let p1_bytes_le: [u8; 96] = [
6868 176, 248, 46, 58, 90, 58, 154, 88, 155, 72, 135, 162, 200, 180, 242, 117, 127, 104,
6869 143, 168, 57, 212, 175, 225, 215, 2, 197, 198, 220, 96, 107, 57, 133, 183, 100, 99, 13,
6870 56, 183, 127, 101, 17, 245, 236, 212, 169, 86, 9, 175, 35, 39, 195, 163, 251, 176, 57,
6871 6, 221, 31, 123, 36, 232, 195, 185, 247, 241, 117, 112, 255, 233, 53, 57, 53, 123, 177,
6872 118, 4, 161, 214, 133, 225, 219, 252, 164, 94, 165, 30, 10, 89, 57, 1, 240, 112, 25,
6873 206, 10,
6874 ];
6875 let p2_bytes_le: [u8; 96] = [
6876 46, 225, 170, 9, 218, 235, 198, 50, 69, 74, 175, 163, 146, 153, 211, 237, 109, 143, 66,
6877 63, 185, 246, 77, 75, 47, 19, 15, 51, 107, 8, 229, 48, 50, 21, 167, 67, 244, 79, 0, 82,
6878 189, 186, 124, 83, 215, 61, 32, 13, 59, 9, 215, 190, 200, 139, 164, 45, 202, 199, 58,
6879 97, 45, 238, 189, 235, 170, 190, 56, 137, 47, 144, 34, 7, 252, 20, 140, 59, 16, 232,
6880 193, 238, 207, 74, 115, 238, 143, 205, 250, 106, 224, 130, 115, 32, 84, 116, 211, 22,
6881 ];
6882 let expected_sum_le: [u8; 96] = [
6883 189, 19, 154, 207, 130, 48, 95, 233, 102, 239, 211, 96, 104, 91, 161, 32, 147, 223, 89,
6884 29, 65, 127, 75, 116, 4, 15, 103, 137, 144, 217, 133, 204, 83, 155, 49, 187, 171, 136,
6885 102, 192, 86, 98, 188, 157, 137, 255, 62, 23, 239, 41, 117, 3, 4, 233, 21, 250, 155,
6886 214, 153, 55, 161, 55, 68, 64, 138, 134, 185, 84, 51, 29, 31, 158, 71, 207, 245, 133,
6887 216, 86, 21, 56, 191, 16, 25, 56, 45, 116, 96, 47, 27, 17, 73, 36, 145, 102, 112, 18,
6888 ];
6889
6890 let p1_be_va = 0x100000000;
6891 let p2_be_va = 0x200000000;
6892 let p1_le_va = 0x300000000;
6893 let p2_le_va = 0x400000000;
6894 let result_be_va = 0x500000000;
6895 let result_le_va = 0x600000000;
6896
6897 let mut result_be_buf = [0u8; 96];
6898 let mut result_le_buf = [0u8; 96];
6899
6900 let memory_mapping = unsafe {
6901 MemoryMapping::new(
6902 vec![
6903 MemoryRegion::new(&raw const p1_bytes_be, p1_be_va),
6904 MemoryRegion::new(&raw const p2_bytes_be, p2_be_va),
6905 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
6906 MemoryRegion::new(&raw const p1_bytes_le, p1_le_va),
6907 MemoryRegion::new(&raw const p2_bytes_le, p2_le_va),
6908 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
6909 ],
6910 &config,
6911 SBPFVersion::V3,
6912 )
6913 .unwrap()
6914 };
6915 invoke_context
6916 .memory_contexts
6917 .mock_set_mapping_abi_v1(memory_mapping);
6918
6919 let bls12_381_g1_add_cost = invoke_context.get_execution_cost().bls12_381_g1_add_cost;
6920 invoke_context
6921 .compute_meter
6922 .mock_set_remaining(2 * bls12_381_g1_add_cost);
6923
6924 let result = SyscallCurveGroupOps::rust(
6925 &mut invoke_context,
6926 BLS12_381_G1_BE,
6927 ADD,
6928 p1_be_va,
6929 p2_be_va,
6930 result_be_va,
6931 );
6932
6933 assert_eq!(0, result.unwrap());
6934 assert_eq!(result_be_buf, expected_sum_be);
6935
6936 let result = SyscallCurveGroupOps::rust(
6937 &mut invoke_context,
6938 BLS12_381_G1_LE,
6939 ADD,
6940 p1_le_va,
6941 p2_le_va,
6942 result_le_va,
6943 );
6944
6945 assert_eq!(0, result.unwrap());
6946 assert_eq!(result_le_buf, expected_sum_le);
6947 }
6948
6949 #[test]
6950 fn test_syscall_bls12_381_g1_sub() {
6951 use {
6952 crate::bls12_381_curve_id::{BLS12_381_G1_BE, BLS12_381_G1_LE},
6953 solana_curve25519::curve_syscall_traits::SUB,
6954 };
6955
6956 let config = Config::default();
6957 let feature_set = SVMFeatureSet {
6958 enable_bls12_381_syscall: true,
6959 ..Default::default()
6960 };
6961 let feature_set = &feature_set;
6962 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
6963
6964 let sub_p1_be: [u8; 96] = [
6965 6, 126, 67, 177, 221, 168, 219, 147, 17, 32, 109, 112, 204, 95, 207, 179, 227, 202, 32,
6966 250, 118, 43, 195, 105, 176, 47, 188, 43, 181, 226, 123, 119, 132, 240, 97, 172, 225,
6967 247, 180, 76, 58, 229, 188, 121, 247, 28, 245, 198, 17, 128, 94, 239, 206, 10, 10, 20,
6968 148, 186, 226, 202, 12, 196, 71, 72, 167, 44, 87, 64, 24, 214, 238, 218, 6, 166, 113,
6969 165, 178, 8, 221, 0, 21, 154, 72, 160, 158, 70, 46, 244, 127, 4, 250, 158, 31, 2, 130,
6970 152,
6971 ];
6972 let sub_p2_be: [u8; 96] = [
6973 12, 173, 131, 106, 17, 172, 169, 46, 205, 228, 83, 25, 204, 216, 118, 223, 16, 102, 52,
6974 235, 202, 255, 183, 91, 99, 78, 141, 169, 14, 244, 161, 28, 240, 32, 214, 46, 0, 93,
6975 106, 73, 41, 176, 220, 160, 251, 37, 18, 110, 15, 86, 67, 210, 137, 114, 71, 220, 167,
6976 121, 177, 224, 142, 151, 152, 29, 206, 12, 35, 6, 46, 60, 53, 127, 84, 78, 231, 88, 49,
6977 95, 219, 36, 224, 182, 0, 253, 136, 115, 59, 15, 80, 229, 136, 103, 27, 211, 120, 90,
6978 ];
6979 let expected_sub_be: [u8; 96] = [
6980 13, 144, 131, 116, 67, 229, 136, 165, 135, 146, 181, 191, 197, 215, 68, 126, 103, 158,
6981 231, 50, 49, 105, 8, 243, 53, 209, 99, 16, 39, 177, 211, 99, 128, 164, 37, 101, 139,
6982 186, 14, 225, 84, 210, 120, 16, 203, 115, 160, 49, 10, 243, 68, 241, 87, 193, 186, 179,
6983 87, 214, 88, 39, 123, 126, 136, 31, 178, 134, 203, 222, 127, 206, 218, 240, 135, 183,
6984 93, 145, 136, 148, 174, 238, 159, 0, 117, 212, 171, 247, 148, 197, 206, 7, 225, 81,
6985 114, 74, 63, 201,
6986 ];
6987 let sub_p1_le: [u8; 96] = [
6988 198, 245, 28, 247, 121, 188, 229, 58, 76, 180, 247, 225, 172, 97, 240, 132, 119, 123,
6989 226, 181, 43, 188, 47, 176, 105, 195, 43, 118, 250, 32, 202, 227, 179, 207, 95, 204,
6990 112, 109, 32, 17, 147, 219, 168, 221, 177, 67, 126, 6, 152, 130, 2, 31, 158, 250, 4,
6991 127, 244, 46, 70, 158, 160, 72, 154, 21, 0, 221, 8, 178, 165, 113, 166, 6, 218, 238,
6992 214, 24, 64, 87, 44, 167, 72, 71, 196, 12, 202, 226, 186, 148, 20, 10, 10, 206, 239,
6993 94, 128, 17,
6994 ];
6995 let sub_p2_le: [u8; 96] = [
6996 110, 18, 37, 251, 160, 220, 176, 41, 73, 106, 93, 0, 46, 214, 32, 240, 28, 161, 244,
6997 14, 169, 141, 78, 99, 91, 183, 255, 202, 235, 52, 102, 16, 223, 118, 216, 204, 25, 83,
6998 228, 205, 46, 169, 172, 17, 106, 131, 173, 12, 90, 120, 211, 27, 103, 136, 229, 80, 15,
6999 59, 115, 136, 253, 0, 182, 224, 36, 219, 95, 49, 88, 231, 78, 84, 127, 53, 60, 46, 6,
7000 35, 12, 206, 29, 152, 151, 142, 224, 177, 121, 167, 220, 71, 114, 137, 210, 67, 86, 15,
7001 ];
7002 let expected_sub_le: [u8; 96] = [
7003 49, 160, 115, 203, 16, 120, 210, 84, 225, 14, 186, 139, 101, 37, 164, 128, 99, 211,
7004 177, 39, 16, 99, 209, 53, 243, 8, 105, 49, 50, 231, 158, 103, 126, 68, 215, 197, 191,
7005 181, 146, 135, 165, 136, 229, 67, 116, 131, 144, 13, 201, 63, 74, 114, 81, 225, 7, 206,
7006 197, 148, 247, 171, 212, 117, 0, 159, 238, 174, 148, 136, 145, 93, 183, 135, 240, 218,
7007 206, 127, 222, 203, 134, 178, 31, 136, 126, 123, 39, 88, 214, 87, 179, 186, 193, 87,
7008 241, 68, 243, 10,
7009 ];
7010
7011 let p1_be_va = 0x100000000;
7012 let p2_be_va = 0x200000000;
7013 let p1_le_va = 0x300000000;
7014 let p2_le_va = 0x400000000;
7015 let result_be_va = 0x500000000;
7016 let result_le_va = 0x600000000;
7017
7018 let mut result_be_buf = [0u8; 96];
7019 let mut result_le_buf = [0u8; 96];
7020
7021 let memory_mapping = unsafe {
7022 MemoryMapping::new(
7023 vec![
7024 MemoryRegion::new(&raw const sub_p1_be, p1_be_va),
7025 MemoryRegion::new(&raw const sub_p2_be, p2_be_va),
7026 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7027 MemoryRegion::new(&raw const sub_p1_le, p1_le_va),
7028 MemoryRegion::new(&raw const sub_p2_le, p2_le_va),
7029 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7030 ],
7031 &config,
7032 SBPFVersion::V3,
7033 )
7034 .unwrap()
7035 };
7036 invoke_context
7037 .memory_contexts
7038 .mock_set_mapping_abi_v1(memory_mapping);
7039
7040 let bls12_381_g1_subtract_cost = invoke_context
7041 .get_execution_cost()
7042 .bls12_381_g1_subtract_cost;
7043 invoke_context
7044 .compute_meter
7045 .mock_set_remaining(2 * bls12_381_g1_subtract_cost);
7046
7047 let result = SyscallCurveGroupOps::rust(
7048 &mut invoke_context,
7049 BLS12_381_G1_BE,
7050 SUB,
7051 p1_be_va,
7052 p2_be_va,
7053 result_be_va,
7054 );
7055
7056 assert_eq!(0, result.unwrap());
7057 assert_eq!(result_be_buf, expected_sub_be);
7058
7059 let result = SyscallCurveGroupOps::rust(
7060 &mut invoke_context,
7061 BLS12_381_G1_LE,
7062 SUB,
7063 p1_le_va,
7064 p2_le_va,
7065 result_le_va,
7066 );
7067
7068 assert_eq!(0, result.unwrap());
7069 assert_eq!(result_le_buf, expected_sub_le);
7070 }
7071
7072 #[test]
7073 fn test_syscall_bls12_381_g1_mul() {
7074 use {
7075 crate::bls12_381_curve_id::{BLS12_381_G1_BE, BLS12_381_G1_LE},
7076 solana_curve25519::curve_syscall_traits::MUL,
7077 };
7078
7079 let config = Config::default();
7080 let feature_set = SVMFeatureSet {
7081 enable_bls12_381_syscall: true,
7082 ..Default::default()
7083 };
7084 let feature_set = &feature_set;
7085 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
7086
7087 let mul_point_be: [u8; 96] = [
7088 20, 18, 233, 201, 110, 206, 56, 32, 8, 44, 140, 121, 37, 196, 157, 56, 180, 134, 164,
7089 33, 180, 130, 147, 7, 26, 239, 183, 163, 219, 85, 143, 197, 247, 243, 117, 252, 201,
7090 171, 156, 90, 210, 7, 43, 92, 89, 130, 165, 224, 5, 101, 24, 54, 189, 22, 73, 76, 145,
7091 136, 99, 59, 51, 255, 124, 43, 61, 8, 121, 30, 118, 90, 254, 12, 126, 92, 152, 78, 44,
7092 231, 126, 56, 220, 35, 54, 117, 2, 175, 190, 105, 138, 188, 202, 36, 171, 12, 231, 225,
7093 ];
7094 let mul_scalar_be: [u8; 32] = [
7095 29, 192, 111, 151, 187, 37, 109, 91, 129, 223, 188, 225, 117, 3, 120, 162, 107, 66,
7096 159, 255, 61, 128, 41, 32, 242, 95, 232, 202, 106, 188, 154, 147,
7097 ];
7098 let expected_mul_be: [u8; 96] = [
7099 22, 101, 72, 255, 3, 247, 39, 218, 234, 117, 208, 91, 158, 114, 126, 55, 166, 71, 227,
7100 205, 6, 124, 55, 255, 167, 66, 154, 237, 83, 143, 8, 179, 98, 185, 162, 164, 170, 62,
7101 141, 4, 1, 179, 41, 49, 95, 212, 139, 227, 18, 125, 245, 10, 169, 201, 171, 172, 152,
7102 1, 105, 81, 159, 160, 252, 184, 80, 59, 165, 170, 185, 114, 248, 208, 228, 111, 229,
7103 200, 221, 204, 9, 120, 153, 142, 88, 240, 228, 164, 157, 79, 72, 55, 119, 239, 56, 104,
7104 54, 58,
7105 ];
7106 let mul_point_le: [u8; 96] = [
7107 224, 165, 130, 89, 92, 43, 7, 210, 90, 156, 171, 201, 252, 117, 243, 247, 197, 143, 85,
7108 219, 163, 183, 239, 26, 7, 147, 130, 180, 33, 164, 134, 180, 56, 157, 196, 37, 121,
7109 140, 44, 8, 32, 56, 206, 110, 201, 233, 18, 20, 225, 231, 12, 171, 36, 202, 188, 138,
7110 105, 190, 175, 2, 117, 54, 35, 220, 56, 126, 231, 44, 78, 152, 92, 126, 12, 254, 90,
7111 118, 30, 121, 8, 61, 43, 124, 255, 51, 59, 99, 136, 145, 76, 73, 22, 189, 54, 24, 101,
7112 5,
7113 ];
7114 let mul_scalar_le: [u8; 32] = [
7115 147, 154, 188, 106, 202, 232, 95, 242, 32, 41, 128, 61, 255, 159, 66, 107, 162, 120, 3,
7116 117, 225, 188, 223, 129, 91, 109, 37, 187, 151, 111, 192, 29,
7117 ];
7118 let expected_mul_le: [u8; 96] = [
7119 227, 139, 212, 95, 49, 41, 179, 1, 4, 141, 62, 170, 164, 162, 185, 98, 179, 8, 143, 83,
7120 237, 154, 66, 167, 255, 55, 124, 6, 205, 227, 71, 166, 55, 126, 114, 158, 91, 208, 117,
7121 234, 218, 39, 247, 3, 255, 72, 101, 22, 58, 54, 104, 56, 239, 119, 55, 72, 79, 157,
7122 164, 228, 240, 88, 142, 153, 120, 9, 204, 221, 200, 229, 111, 228, 208, 248, 114, 185,
7123 170, 165, 59, 80, 184, 252, 160, 159, 81, 105, 1, 152, 172, 171, 201, 169, 10, 245,
7124 125, 18,
7125 ];
7126
7127 let scalar_be_va = 0x100000000;
7128 let point_be_va = 0x200000000;
7129 let scalar_le_va = 0x300000000;
7130 let point_le_va = 0x400000000;
7131 let result_be_va = 0x500000000;
7132 let result_le_va = 0x600000000;
7133
7134 let mut result_be_buf = [0u8; 96];
7135 let mut result_le_buf = [0u8; 96];
7136
7137 let memory_mapping = unsafe {
7138 MemoryMapping::new(
7139 vec![
7140 MemoryRegion::new(&raw const mul_scalar_be, scalar_be_va),
7141 MemoryRegion::new(&raw const mul_point_be, point_be_va),
7142 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7143 MemoryRegion::new(&raw const mul_scalar_le, scalar_le_va),
7144 MemoryRegion::new(&raw const mul_point_le, point_le_va),
7145 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7146 ],
7147 &config,
7148 SBPFVersion::V3,
7149 )
7150 .unwrap()
7151 };
7152 invoke_context
7153 .memory_contexts
7154 .mock_set_mapping_abi_v1(memory_mapping);
7155
7156 let bls12_381_g1_multiply_cost = invoke_context
7157 .get_execution_cost()
7158 .bls12_381_g1_multiply_cost;
7159 invoke_context
7160 .compute_meter
7161 .mock_set_remaining(2 * bls12_381_g1_multiply_cost);
7162
7163 let result = SyscallCurveGroupOps::rust(
7164 &mut invoke_context,
7165 BLS12_381_G1_BE,
7166 MUL,
7167 scalar_be_va,
7168 point_be_va,
7169 result_be_va,
7170 );
7171
7172 assert_eq!(0, result.unwrap());
7173 assert_eq!(result_be_buf, expected_mul_be);
7174
7175 let result = SyscallCurveGroupOps::rust(
7176 &mut invoke_context,
7177 BLS12_381_G1_LE,
7178 MUL,
7179 scalar_le_va,
7180 point_le_va,
7181 result_le_va,
7182 );
7183
7184 assert_eq!(0, result.unwrap());
7185 assert_eq!(result_le_buf, expected_mul_le);
7186 }
7187
7188 #[test]
7189 fn test_syscall_bls12_381_g2_add() {
7190 use {
7191 crate::bls12_381_curve_id::{BLS12_381_G2_BE, BLS12_381_G2_LE},
7192 solana_curve25519::curve_syscall_traits::ADD,
7193 };
7194
7195 let config = Config::default();
7196 let feature_set = SVMFeatureSet {
7197 enable_bls12_381_syscall: true,
7198 ..Default::default()
7199 };
7200 let feature_set = &feature_set;
7201
7202 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7203
7204 let p1_bytes_be: [u8; 192] = [
7205 11, 83, 21, 62, 4, 174, 123, 131, 163, 19, 62, 216, 192, 48, 25, 184, 57, 207, 80, 70,
7206 253, 51, 129, 169, 87, 182, 142, 1, 148, 102, 203, 99, 86, 111, 207, 55, 204, 117, 82,
7207 138, 199, 89, 131, 207, 158, 244, 204, 139, 18, 151, 214, 201, 158, 39, 101, 252, 189,
7208 53, 251, 236, 205, 27, 152, 163, 232, 101, 53, 197, 18, 238, 241, 70, 182, 113, 111,
7209 249, 99, 122, 42, 220, 55, 127, 55, 247, 172, 164, 183, 169, 146, 229, 218, 185, 144,
7210 176, 86, 174, 21, 132, 150, 29, 241, 241, 215, 77, 12, 75, 238, 103, 23, 90, 189, 191,
7211 85, 72, 181, 214, 85, 253, 183, 150, 158, 8, 250, 178, 220, 169, 215, 243, 146, 213,
7212 150, 12, 6, 40, 188, 197, 56, 210, 46, 125, 87, 5, 17, 7, 24, 27, 160, 22, 99, 114, 9,
7213 7, 244, 108, 179, 201, 38, 33, 153, 219, 10, 211, 2, 212, 74, 95, 151, 223, 200, 96,
7214 121, 166, 10, 186, 122, 40, 222, 87, 34, 227, 49, 166, 195, 139, 37, 221, 44, 227, 86,
7215 119, 190, 41,
7216 ];
7217 let p2_bytes_be: [u8; 192] = [
7218 14, 110, 180, 174, 46, 74, 145, 125, 94, 28, 39, 205, 107, 126, 53, 188, 36, 69, 162,
7219 98, 105, 79, 49, 148, 136, 229, 5, 128, 197, 187, 0, 234, 141, 201, 246, 223, 103, 75,
7220 177, 33, 2, 75, 90, 33, 139, 152, 156, 89, 25, 91, 158, 100, 20, 12, 135, 130, 191,
7221 181, 5, 41, 94, 195, 89, 36, 181, 111, 238, 24, 187, 178, 179, 143, 17, 181, 68, 203,
7222 184, 134, 185, 195, 176, 27, 90, 2, 29, 165, 209, 16, 143, 11, 224, 251, 63, 188, 218,
7223 41, 23, 71, 91, 90, 202, 108, 80, 160, 200, 194, 162, 109, 200, 96, 5, 102, 156, 245,
7224 43, 247, 221, 139, 148, 254, 253, 183, 161, 83, 253, 247, 22, 71, 133, 93, 36, 127,
7225 162, 248, 49, 64, 173, 201, 17, 210, 8, 214, 18, 65, 7, 222, 11, 4, 120, 17, 85, 49,
7226 205, 95, 132, 208, 152, 136, 92, 19, 195, 176, 136, 39, 90, 207, 17, 195, 14, 215, 33,
7227 191, 232, 59, 3, 86, 78, 78, 149, 165, 179, 145, 161, 190, 247, 67, 243, 252, 137, 1,
7228 39, 71,
7229 ];
7230 let expected_sum_be: [u8; 192] = [
7231 21, 157, 10, 251, 156, 56, 24, 174, 24, 91, 98, 201, 33, 37, 68, 76, 41, 161, 12, 166,
7232 16, 128, 161, 31, 108, 31, 92, 216, 56, 197, 198, 66, 210, 6, 64, 106, 154, 96, 135,
7233 57, 170, 119, 220, 210, 238, 73, 98, 83, 15, 146, 74, 122, 70, 40, 186, 123, 191, 139,
7234 11, 249, 221, 20, 12, 62, 81, 37, 191, 22, 248, 113, 78, 124, 29, 157, 228, 220, 187,
7235 6, 252, 15, 59, 236, 98, 198, 252, 205, 176, 190, 192, 199, 154, 213, 92, 126, 189, 55,
7236 2, 109, 8, 15, 128, 190, 31, 106, 180, 130, 96, 215, 125, 50, 11, 124, 71, 119, 83, 28,
7237 65, 209, 128, 47, 7, 46, 212, 157, 230, 199, 51, 98, 143, 220, 157, 254, 179, 203, 186,
7238 116, 41, 76, 35, 28, 123, 207, 54, 17, 5, 248, 36, 247, 193, 201, 116, 118, 202, 201,
7239 125, 201, 200, 13, 68, 244, 39, 207, 70, 206, 12, 117, 206, 192, 9, 232, 62, 33, 137,
7240 88, 73, 16, 121, 190, 139, 91, 158, 80, 147, 207, 125, 23, 177, 93, 227, 132, 103, 89,
7241 ];
7242 let p1_bytes_le: [u8; 192] = [
7243 174, 86, 176, 144, 185, 218, 229, 146, 169, 183, 164, 172, 247, 55, 127, 55, 220, 42,
7244 122, 99, 249, 111, 113, 182, 70, 241, 238, 18, 197, 53, 101, 232, 163, 152, 27, 205,
7245 236, 251, 53, 189, 252, 101, 39, 158, 201, 214, 151, 18, 139, 204, 244, 158, 207, 131,
7246 89, 199, 138, 82, 117, 204, 55, 207, 111, 86, 99, 203, 102, 148, 1, 142, 182, 87, 169,
7247 129, 51, 253, 70, 80, 207, 57, 184, 25, 48, 192, 216, 62, 19, 163, 131, 123, 174, 4,
7248 62, 21, 83, 11, 41, 190, 119, 86, 227, 44, 221, 37, 139, 195, 166, 49, 227, 34, 87,
7249 222, 40, 122, 186, 10, 166, 121, 96, 200, 223, 151, 95, 74, 212, 2, 211, 10, 219, 153,
7250 33, 38, 201, 179, 108, 244, 7, 9, 114, 99, 22, 160, 27, 24, 7, 17, 5, 87, 125, 46, 210,
7251 56, 197, 188, 40, 6, 12, 150, 213, 146, 243, 215, 169, 220, 178, 250, 8, 158, 150, 183,
7252 253, 85, 214, 181, 72, 85, 191, 189, 90, 23, 103, 238, 75, 12, 77, 215, 241, 241, 29,
7253 150, 132, 21,
7254 ];
7255 let p2_bytes_le: [u8; 192] = [
7256 41, 218, 188, 63, 251, 224, 11, 143, 16, 209, 165, 29, 2, 90, 27, 176, 195, 185, 134,
7257 184, 203, 68, 181, 17, 143, 179, 178, 187, 24, 238, 111, 181, 36, 89, 195, 94, 41, 5,
7258 181, 191, 130, 135, 12, 20, 100, 158, 91, 25, 89, 156, 152, 139, 33, 90, 75, 2, 33,
7259 177, 75, 103, 223, 246, 201, 141, 234, 0, 187, 197, 128, 5, 229, 136, 148, 49, 79, 105,
7260 98, 162, 69, 36, 188, 53, 126, 107, 205, 39, 28, 94, 125, 145, 74, 46, 174, 180, 110,
7261 14, 71, 39, 1, 137, 252, 243, 67, 247, 190, 161, 145, 179, 165, 149, 78, 78, 86, 3, 59,
7262 232, 191, 33, 215, 14, 195, 17, 207, 90, 39, 136, 176, 195, 19, 92, 136, 152, 208, 132,
7263 95, 205, 49, 85, 17, 120, 4, 11, 222, 7, 65, 18, 214, 8, 210, 17, 201, 173, 64, 49,
7264 248, 162, 127, 36, 93, 133, 71, 22, 247, 253, 83, 161, 183, 253, 254, 148, 139, 221,
7265 247, 43, 245, 156, 102, 5, 96, 200, 109, 162, 194, 200, 160, 80, 108, 202, 90, 91, 71,
7266 23,
7267 ];
7268 let expected_sum_le: [u8; 192] = [
7269 55, 189, 126, 92, 213, 154, 199, 192, 190, 176, 205, 252, 198, 98, 236, 59, 15, 252, 6,
7270 187, 220, 228, 157, 29, 124, 78, 113, 248, 22, 191, 37, 81, 62, 12, 20, 221, 249, 11,
7271 139, 191, 123, 186, 40, 70, 122, 74, 146, 15, 83, 98, 73, 238, 210, 220, 119, 170, 57,
7272 135, 96, 154, 106, 64, 6, 210, 66, 198, 197, 56, 216, 92, 31, 108, 31, 161, 128, 16,
7273 166, 12, 161, 41, 76, 68, 37, 33, 201, 98, 91, 24, 174, 24, 56, 156, 251, 10, 157, 21,
7274 89, 103, 132, 227, 93, 177, 23, 125, 207, 147, 80, 158, 91, 139, 190, 121, 16, 73, 88,
7275 137, 33, 62, 232, 9, 192, 206, 117, 12, 206, 70, 207, 39, 244, 68, 13, 200, 201, 125,
7276 201, 202, 118, 116, 201, 193, 247, 36, 248, 5, 17, 54, 207, 123, 28, 35, 76, 41, 116,
7277 186, 203, 179, 254, 157, 220, 143, 98, 51, 199, 230, 157, 212, 46, 7, 47, 128, 209, 65,
7278 28, 83, 119, 71, 124, 11, 50, 125, 215, 96, 130, 180, 106, 31, 190, 128, 15, 8, 109, 2,
7279 ];
7280
7281 let p1_be_va = 0x100000000;
7282 let p2_be_va = 0x200000000;
7283 let p1_le_va = 0x300000000;
7284 let p2_le_va = 0x400000000;
7285 let result_be_va = 0x500000000;
7286 let result_le_va = 0x600000000;
7287
7288 let mut result_be_buf = [0u8; 192];
7289 let mut result_le_buf = [0u8; 192];
7290
7291 let memory_mapping = unsafe {
7292 MemoryMapping::new(
7293 vec![
7294 MemoryRegion::new(&raw const p1_bytes_be, p1_be_va),
7295 MemoryRegion::new(&raw const p2_bytes_be, p2_be_va),
7296 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7297 MemoryRegion::new(&raw const p1_bytes_le, p1_le_va),
7298 MemoryRegion::new(&raw const p2_bytes_le, p2_le_va),
7299 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7300 ],
7301 &config,
7302 SBPFVersion::V3,
7303 )
7304 .unwrap()
7305 };
7306 invoke_context
7307 .memory_contexts
7308 .mock_set_mapping_abi_v1(memory_mapping);
7309
7310 let bls12_381_g2_add_cost = invoke_context.get_execution_cost().bls12_381_g2_add_cost;
7311 invoke_context
7312 .compute_meter
7313 .mock_set_remaining(2 * bls12_381_g2_add_cost);
7314
7315 let result = SyscallCurveGroupOps::rust(
7316 &mut invoke_context,
7317 BLS12_381_G2_BE,
7318 ADD,
7319 p1_be_va,
7320 p2_be_va,
7321 result_be_va,
7322 );
7323
7324 assert_eq!(0, result.unwrap());
7325 assert_eq!(result_be_buf, expected_sum_be);
7326
7327 let result = SyscallCurveGroupOps::rust(
7328 &mut invoke_context,
7329 BLS12_381_G2_LE,
7330 ADD,
7331 p1_le_va,
7332 p2_le_va,
7333 result_le_va,
7334 );
7335
7336 assert_eq!(0, result.unwrap());
7337 assert_eq!(result_le_buf, expected_sum_le);
7338 }
7339
7340 #[test]
7341 fn test_syscall_bls12_381_g2_sub() {
7342 use {
7343 crate::bls12_381_curve_id::{BLS12_381_G2_BE, BLS12_381_G2_LE},
7344 solana_curve25519::curve_syscall_traits::SUB,
7345 };
7346
7347 let config = Config::default();
7348 let feature_set = SVMFeatureSet {
7349 enable_bls12_381_syscall: true,
7350 ..Default::default()
7351 };
7352 let feature_set = &feature_set;
7353 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
7354
7355 let sub_p1_be: [u8; 192] = [
7356 1, 111, 113, 42, 165, 128, 194, 26, 130, 142, 58, 198, 61, 244, 113, 64, 25, 96, 196,
7357 12, 211, 55, 213, 85, 109, 210, 211, 177, 96, 48, 15, 122, 155, 173, 166, 16, 113, 95,
7358 253, 69, 196, 15, 187, 201, 207, 255, 81, 176, 15, 77, 24, 199, 78, 142, 23, 177, 55,
7359 118, 62, 248, 123, 41, 213, 72, 169, 177, 5, 176, 197, 158, 62, 1, 5, 219, 190, 92, 36,
7360 37, 117, 162, 202, 9, 231, 199, 13, 72, 102, 36, 246, 241, 52, 68, 185, 44, 238, 23,
7361 23, 1, 192, 28, 61, 103, 236, 74, 46, 28, 64, 67, 194, 243, 208, 186, 46, 201, 142, 7,
7362 166, 139, 114, 215, 101, 234, 108, 184, 93, 135, 61, 176, 154, 208, 28, 79, 210, 132,
7363 96, 21, 199, 11, 73, 210, 40, 241, 107, 215, 8, 203, 156, 2, 211, 33, 203, 196, 124,
7364 172, 148, 232, 121, 116, 109, 226, 15, 13, 147, 241, 20, 70, 28, 10, 17, 51, 143, 140,
7365 35, 127, 109, 7, 202, 220, 208, 97, 11, 167, 119, 94, 192, 92, 165, 215, 230, 160, 16,
7366 56,
7367 ];
7368 let sub_p2_be: [u8; 192] = [
7369 14, 73, 101, 89, 211, 85, 5, 115, 148, 81, 82, 216, 141, 148, 50, 174, 17, 86, 246,
7370 146, 42, 230, 181, 250, 40, 64, 248, 121, 6, 167, 117, 190, 219, 96, 57, 80, 127, 234,
7371 141, 179, 154, 109, 5, 82, 233, 254, 7, 48, 5, 108, 253, 196, 16, 144, 81, 140, 252,
7372 184, 236, 193, 97, 200, 129, 223, 132, 28, 135, 121, 129, 129, 60, 33, 77, 43, 181,
7373 180, 60, 224, 108, 127, 207, 112, 54, 66, 81, 185, 166, 120, 54, 169, 55, 238, 32, 219,
7374 172, 212, 24, 165, 106, 207, 20, 68, 130, 233, 190, 75, 177, 17, 157, 112, 174, 88,
7375 189, 182, 126, 219, 114, 136, 67, 15, 167, 133, 50, 172, 124, 94, 8, 149, 203, 232, 35,
7376 218, 144, 142, 74, 150, 94, 182, 33, 106, 111, 120, 203, 59, 10, 121, 79, 248, 118,
7377 165, 232, 57, 87, 60, 42, 223, 98, 104, 158, 238, 68, 152, 59, 19, 172, 89, 20, 238,
7378 63, 49, 204, 138, 108, 195, 10, 233, 81, 79, 215, 107, 43, 197, 190, 231, 15, 14, 251,
7379 203, 179, 205, 224, 195,
7380 ];
7381 let expected_sub_be: [u8; 192] = [
7382 15, 192, 220, 234, 246, 126, 141, 163, 107, 162, 43, 117, 171, 158, 195, 132, 196, 214,
7383 237, 133, 98, 133, 112, 248, 161, 148, 3, 163, 20, 26, 49, 136, 161, 244, 36, 179, 237,
7384 204, 58, 22, 51, 106, 0, 4, 239, 244, 242, 89, 5, 14, 149, 31, 78, 213, 70, 153, 147,
7385 43, 84, 19, 223, 100, 235, 61, 172, 66, 136, 201, 11, 81, 168, 136, 207, 46, 198, 208,
7386 171, 144, 187, 35, 77, 58, 186, 147, 191, 243, 9, 12, 224, 22, 230, 36, 112, 246, 114,
7387 19, 13, 116, 186, 62, 158, 176, 201, 150, 187, 13, 32, 135, 140, 108, 178, 174, 90,
7388 212, 50, 184, 238, 17, 229, 167, 195, 104, 179, 156, 166, 251, 99, 115, 133, 25, 144,
7389 101, 45, 70, 19, 86, 91, 247, 236, 93, 252, 14, 106, 212, 15, 42, 62, 104, 162, 216, 8,
7390 180, 156, 52, 254, 179, 29, 95, 94, 16, 245, 215, 165, 67, 115, 50, 186, 190, 227, 213,
7391 71, 126, 29, 81, 217, 43, 157, 12, 100, 105, 211, 172, 101, 212, 73, 140, 149, 109,
7392 252, 180, 98, 22,
7393 ];
7394 let sub_p1_le: [u8; 192] = [
7395 23, 238, 44, 185, 68, 52, 241, 246, 36, 102, 72, 13, 199, 231, 9, 202, 162, 117, 37,
7396 36, 92, 190, 219, 5, 1, 62, 158, 197, 176, 5, 177, 169, 72, 213, 41, 123, 248, 62, 118,
7397 55, 177, 23, 142, 78, 199, 24, 77, 15, 176, 81, 255, 207, 201, 187, 15, 196, 69, 253,
7398 95, 113, 16, 166, 173, 155, 122, 15, 48, 96, 177, 211, 210, 109, 85, 213, 55, 211, 12,
7399 196, 96, 25, 64, 113, 244, 61, 198, 58, 142, 130, 26, 194, 128, 165, 42, 113, 111, 1,
7400 56, 16, 160, 230, 215, 165, 92, 192, 94, 119, 167, 11, 97, 208, 220, 202, 7, 109, 127,
7401 35, 140, 143, 51, 17, 10, 28, 70, 20, 241, 147, 13, 15, 226, 109, 116, 121, 232, 148,
7402 172, 124, 196, 203, 33, 211, 2, 156, 203, 8, 215, 107, 241, 40, 210, 73, 11, 199, 21,
7403 96, 132, 210, 79, 28, 208, 154, 176, 61, 135, 93, 184, 108, 234, 101, 215, 114, 139,
7404 166, 7, 142, 201, 46, 186, 208, 243, 194, 67, 64, 28, 46, 74, 236, 103, 61, 28, 192, 1,
7405 23,
7406 ];
7407 let sub_p2_le: [u8; 192] = [
7408 212, 172, 219, 32, 238, 55, 169, 54, 120, 166, 185, 81, 66, 54, 112, 207, 127, 108,
7409 224, 60, 180, 181, 43, 77, 33, 60, 129, 129, 121, 135, 28, 132, 223, 129, 200, 97, 193,
7410 236, 184, 252, 140, 81, 144, 16, 196, 253, 108, 5, 48, 7, 254, 233, 82, 5, 109, 154,
7411 179, 141, 234, 127, 80, 57, 96, 219, 190, 117, 167, 6, 121, 248, 64, 40, 250, 181, 230,
7412 42, 146, 246, 86, 17, 174, 50, 148, 141, 216, 82, 81, 148, 115, 5, 85, 211, 89, 101,
7413 73, 14, 195, 224, 205, 179, 203, 251, 14, 15, 231, 190, 197, 43, 107, 215, 79, 81, 233,
7414 10, 195, 108, 138, 204, 49, 63, 238, 20, 89, 172, 19, 59, 152, 68, 238, 158, 104, 98,
7415 223, 42, 60, 87, 57, 232, 165, 118, 248, 79, 121, 10, 59, 203, 120, 111, 106, 33, 182,
7416 94, 150, 74, 142, 144, 218, 35, 232, 203, 149, 8, 94, 124, 172, 50, 133, 167, 15, 67,
7417 136, 114, 219, 126, 182, 189, 88, 174, 112, 157, 17, 177, 75, 190, 233, 130, 68, 20,
7418 207, 106, 165, 24,
7419 ];
7420 let expected_sub_le: [u8; 192] = [
7421 19, 114, 246, 112, 36, 230, 22, 224, 12, 9, 243, 191, 147, 186, 58, 77, 35, 187, 144,
7422 171, 208, 198, 46, 207, 136, 168, 81, 11, 201, 136, 66, 172, 61, 235, 100, 223, 19, 84,
7423 43, 147, 153, 70, 213, 78, 31, 149, 14, 5, 89, 242, 244, 239, 4, 0, 106, 51, 22, 58,
7424 204, 237, 179, 36, 244, 161, 136, 49, 26, 20, 163, 3, 148, 161, 248, 112, 133, 98, 133,
7425 237, 214, 196, 132, 195, 158, 171, 117, 43, 162, 107, 163, 141, 126, 246, 234, 220,
7426 192, 15, 22, 98, 180, 252, 109, 149, 140, 73, 212, 101, 172, 211, 105, 100, 12, 157,
7427 43, 217, 81, 29, 126, 71, 213, 227, 190, 186, 50, 115, 67, 165, 215, 245, 16, 94, 95,
7428 29, 179, 254, 52, 156, 180, 8, 216, 162, 104, 62, 42, 15, 212, 106, 14, 252, 93, 236,
7429 247, 91, 86, 19, 70, 45, 101, 144, 25, 133, 115, 99, 251, 166, 156, 179, 104, 195, 167,
7430 229, 17, 238, 184, 50, 212, 90, 174, 178, 108, 140, 135, 32, 13, 187, 150, 201, 176,
7431 158, 62, 186, 116, 13,
7432 ];
7433
7434 let p1_be_va = 0x100000000;
7435 let p2_be_va = 0x200000000;
7436 let p1_le_va = 0x300000000;
7437 let p2_le_va = 0x400000000;
7438 let result_be_va = 0x500000000;
7439 let result_le_va = 0x600000000;
7440
7441 let mut result_be_buf = [0u8; 192];
7442 let mut result_le_buf = [0u8; 192];
7443
7444 let memory_mapping = unsafe {
7445 MemoryMapping::new(
7446 vec![
7447 MemoryRegion::new(&raw const sub_p1_be, p1_be_va),
7448 MemoryRegion::new(&raw const sub_p2_be, p2_be_va),
7449 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7450 MemoryRegion::new(&raw const sub_p1_le, p1_le_va),
7451 MemoryRegion::new(&raw const sub_p2_le, p2_le_va),
7452 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7453 ],
7454 &config,
7455 SBPFVersion::V3,
7456 )
7457 .unwrap()
7458 };
7459 invoke_context
7460 .memory_contexts
7461 .mock_set_mapping_abi_v1(memory_mapping);
7462
7463 let bls12_381_g2_subtract_cost = invoke_context
7464 .get_execution_cost()
7465 .bls12_381_g2_subtract_cost;
7466 invoke_context
7467 .compute_meter
7468 .mock_set_remaining(2 * bls12_381_g2_subtract_cost);
7469
7470 let result = SyscallCurveGroupOps::rust(
7471 &mut invoke_context,
7472 BLS12_381_G2_BE,
7473 SUB,
7474 p1_be_va,
7475 p2_be_va,
7476 result_be_va,
7477 );
7478
7479 assert_eq!(0, result.unwrap());
7480 assert_eq!(result_be_buf, expected_sub_be);
7481
7482 let result = SyscallCurveGroupOps::rust(
7483 &mut invoke_context,
7484 BLS12_381_G2_LE,
7485 SUB,
7486 p1_le_va,
7487 p2_le_va,
7488 result_le_va,
7489 );
7490
7491 assert_eq!(0, result.unwrap());
7492 assert_eq!(result_le_buf, expected_sub_le);
7493 }
7494
7495 #[test]
7496 fn test_syscall_bls12_381_g2_mul() {
7497 use {
7498 crate::bls12_381_curve_id::{BLS12_381_G2_BE, BLS12_381_G2_LE},
7499 solana_curve25519::curve_syscall_traits::MUL,
7500 };
7501
7502 let config = Config::default();
7503 let feature_set = SVMFeatureSet {
7504 enable_bls12_381_syscall: true,
7505 ..Default::default()
7506 };
7507 let feature_set = &feature_set;
7508 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
7509
7510 let mul_point_be: [u8; 192] = [
7511 1, 95, 16, 90, 117, 185, 253, 76, 25, 68, 54, 111, 154, 161, 125, 203, 121, 4, 154, 67,
7512 205, 157, 76, 9, 128, 224, 37, 81, 214, 226, 71, 59, 224, 187, 152, 153, 199, 62, 58,
7513 74, 137, 245, 46, 101, 155, 17, 212, 64, 5, 134, 0, 185, 19, 132, 205, 101, 77, 204,
7514 118, 63, 71, 172, 208, 29, 210, 61, 51, 4, 190, 191, 211, 175, 105, 245, 204, 57, 56,
7515 84, 210, 184, 235, 169, 231, 161, 128, 83, 252, 234, 227, 255, 166, 219, 201, 176, 169,
7516 16, 20, 218, 203, 38, 181, 98, 213, 89, 152, 123, 230, 201, 4, 95, 42, 86, 29, 137, 67,
7517 233, 230, 161, 206, 231, 201, 176, 79, 12, 197, 56, 212, 36, 235, 216, 160, 27, 221,
7518 99, 124, 220, 133, 76, 123, 209, 200, 78, 122, 36, 16, 171, 18, 247, 111, 111, 132, 38,
7519 240, 183, 27, 76, 135, 211, 136, 202, 55, 93, 246, 235, 191, 146, 183, 161, 110, 129,
7520 4, 58, 238, 59, 77, 242, 56, 88, 96, 150, 146, 247, 137, 230, 137, 35, 9, 108, 95, 127,
7521 75, 78,
7522 ];
7523 let mul_scalar_be: [u8; 32] = [
7524 29, 192, 111, 151, 187, 37, 109, 91, 129, 223, 188, 225, 117, 3, 120, 162, 107, 66,
7525 159, 255, 61, 128, 41, 32, 242, 95, 232, 202, 106, 188, 154, 147,
7526 ];
7527 let expected_mul_be: [u8; 192] = [
7528 10, 92, 88, 192, 26, 200, 38, 128, 188, 148, 254, 16, 202, 39, 174, 252, 33, 111, 41,
7529 121, 211, 9, 209, 138, 43, 104, 122, 214, 4, 251, 34, 81, 36, 92, 143, 19, 151, 213,
7530 111, 240, 100, 15, 33, 74, 123, 143, 181, 153, 6, 107, 82, 96, 141, 147, 63, 200, 13,
7531 31, 66, 5, 184, 135, 24, 82, 189, 240, 58, 250, 48, 61, 132, 13, 23, 240, 31, 238, 252,
7532 33, 191, 241, 38, 90, 221, 201, 164, 137, 98, 92, 148, 246, 225, 22, 239, 99, 97, 179,
7533 20, 251, 39, 114, 14, 156, 165, 182, 58, 233, 100, 41, 34, 59, 119, 103, 40, 206, 50,
7534 175, 223, 126, 146, 17, 161, 14, 84, 43, 149, 58, 212, 197, 250, 15, 208, 122, 33, 4,
7535 87, 219, 82, 201, 12, 11, 44, 76, 59, 182, 18, 76, 38, 184, 175, 11, 211, 4, 64, 133,
7536 41, 104, 185, 153, 63, 246, 39, 145, 38, 113, 162, 183, 77, 2, 51, 134, 243, 196, 74,
7537 111, 183, 169, 222, 228, 191, 53, 129, 53, 186, 94, 97, 144, 31, 117, 218, 207, 214,
7538 189,
7539 ];
7540 let mul_point_le: [u8; 192] = [
7541 16, 169, 176, 201, 219, 166, 255, 227, 234, 252, 83, 128, 161, 231, 169, 235, 184, 210,
7542 84, 56, 57, 204, 245, 105, 175, 211, 191, 190, 4, 51, 61, 210, 29, 208, 172, 71, 63,
7543 118, 204, 77, 101, 205, 132, 19, 185, 0, 134, 5, 64, 212, 17, 155, 101, 46, 245, 137,
7544 74, 58, 62, 199, 153, 152, 187, 224, 59, 71, 226, 214, 81, 37, 224, 128, 9, 76, 157,
7545 205, 67, 154, 4, 121, 203, 125, 161, 154, 111, 54, 68, 25, 76, 253, 185, 117, 90, 16,
7546 95, 1, 78, 75, 127, 95, 108, 9, 35, 137, 230, 137, 247, 146, 150, 96, 88, 56, 242, 77,
7547 59, 238, 58, 4, 129, 110, 161, 183, 146, 191, 235, 246, 93, 55, 202, 136, 211, 135, 76,
7548 27, 183, 240, 38, 132, 111, 111, 247, 18, 171, 16, 36, 122, 78, 200, 209, 123, 76, 133,
7549 220, 124, 99, 221, 27, 160, 216, 235, 36, 212, 56, 197, 12, 79, 176, 201, 231, 206,
7550 161, 230, 233, 67, 137, 29, 86, 42, 95, 4, 201, 230, 123, 152, 89, 213, 98, 181, 38,
7551 203, 218, 20,
7552 ];
7553 let mul_scalar_le: [u8; 32] = [
7554 147, 154, 188, 106, 202, 232, 95, 242, 32, 41, 128, 61, 255, 159, 66, 107, 162, 120, 3,
7555 117, 225, 188, 223, 129, 91, 109, 37, 187, 151, 111, 192, 29,
7556 ];
7557 let expected_mul_le: [u8; 192] = [
7558 179, 97, 99, 239, 22, 225, 246, 148, 92, 98, 137, 164, 201, 221, 90, 38, 241, 191, 33,
7559 252, 238, 31, 240, 23, 13, 132, 61, 48, 250, 58, 240, 189, 82, 24, 135, 184, 5, 66, 31,
7560 13, 200, 63, 147, 141, 96, 82, 107, 6, 153, 181, 143, 123, 74, 33, 15, 100, 240, 111,
7561 213, 151, 19, 143, 92, 36, 81, 34, 251, 4, 214, 122, 104, 43, 138, 209, 9, 211, 121,
7562 41, 111, 33, 252, 174, 39, 202, 16, 254, 148, 188, 128, 38, 200, 26, 192, 88, 92, 10,
7563 189, 214, 207, 218, 117, 31, 144, 97, 94, 186, 53, 129, 53, 191, 228, 222, 169, 183,
7564 111, 74, 196, 243, 134, 51, 2, 77, 183, 162, 113, 38, 145, 39, 246, 63, 153, 185, 104,
7565 41, 133, 64, 4, 211, 11, 175, 184, 38, 76, 18, 182, 59, 76, 44, 11, 12, 201, 82, 219,
7566 87, 4, 33, 122, 208, 15, 250, 197, 212, 58, 149, 43, 84, 14, 161, 17, 146, 126, 223,
7567 175, 50, 206, 40, 103, 119, 59, 34, 41, 100, 233, 58, 182, 165, 156, 14, 114, 39, 251,
7568 20,
7569 ];
7570
7571 let scalar_be_va = 0x100000000;
7572 let point_be_va = 0x200000000;
7573 let scalar_le_va = 0x300000000;
7574 let point_le_va = 0x400000000;
7575 let result_be_va = 0x500000000;
7576 let result_le_va = 0x600000000;
7577
7578 let mut result_be_buf = [0u8; 192];
7579 let mut result_le_buf = [0u8; 192];
7580
7581 let memory_mapping = unsafe {
7582 MemoryMapping::new(
7583 vec![
7584 MemoryRegion::new(&raw const mul_scalar_be, scalar_be_va),
7585 MemoryRegion::new(&raw const mul_point_be, point_be_va),
7586 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7587 MemoryRegion::new(&raw const mul_scalar_le, scalar_le_va),
7588 MemoryRegion::new(&raw const mul_point_le, point_le_va),
7589 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7590 ],
7591 &config,
7592 SBPFVersion::V3,
7593 )
7594 .unwrap()
7595 };
7596 invoke_context
7597 .memory_contexts
7598 .mock_set_mapping_abi_v1(memory_mapping);
7599
7600 let bls12_381_g2_multiply_cost = invoke_context
7601 .get_execution_cost()
7602 .bls12_381_g2_multiply_cost;
7603 invoke_context
7604 .compute_meter
7605 .mock_set_remaining(2 * bls12_381_g2_multiply_cost);
7606
7607 let result = SyscallCurveGroupOps::rust(
7608 &mut invoke_context,
7609 BLS12_381_G2_BE,
7610 MUL,
7611 scalar_be_va,
7612 point_be_va,
7613 result_be_va,
7614 );
7615
7616 assert_eq!(0, result.unwrap());
7617 assert_eq!(result_be_buf, expected_mul_be);
7618
7619 let result = SyscallCurveGroupOps::rust(
7620 &mut invoke_context,
7621 BLS12_381_G2_LE,
7622 MUL,
7623 scalar_le_va,
7624 point_le_va,
7625 result_le_va,
7626 );
7627
7628 assert_eq!(0, result.unwrap());
7629 assert_eq!(result_le_buf, expected_mul_le);
7630 }
7631
7632 #[test]
7633 fn test_syscall_bls12_381_pairing_be() {
7634 use crate::bls12_381_curve_id::BLS12_381_BE;
7635
7636 let config = Config::default();
7637 let feature_set = SVMFeatureSet {
7638 enable_bls12_381_syscall: true,
7639 ..Default::default()
7640 };
7641 let feature_set = &feature_set;
7642
7643 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7644
7645 let g1_bytes: [u8; 96] = [
7646 3, 161, 104, 54, 242, 116, 16, 50, 15, 113, 42, 38, 108, 11, 127, 64, 43, 249, 50, 133,
7647 105, 8, 133, 238, 34, 6, 189, 119, 153, 36, 75, 65, 87, 249, 90, 109, 133, 200, 203,
7648 25, 127, 68, 251, 243, 14, 210, 204, 35, 18, 124, 149, 5, 68, 178, 57, 230, 253, 154,
7649 192, 163, 5, 146, 144, 100, 7, 102, 9, 76, 67, 251, 147, 45, 27, 111, 204, 213, 219,
7650 141, 58, 11, 235, 100, 6, 220, 77, 230, 232, 200, 210, 200, 3, 184, 10, 80, 23, 164,
7651 ];
7652 let g2_bytes: [u8; 192] = [
7653 8, 249, 218, 154, 232, 125, 250, 185, 153, 60, 132, 155, 188, 119, 50, 205, 32, 76,
7654 184, 181, 164, 158, 64, 12, 179, 181, 150, 95, 226, 9, 175, 51, 169, 185, 34, 178, 249,
7655 161, 27, 164, 210, 107, 171, 203, 246, 11, 158, 86, 14, 135, 197, 225, 7, 44, 94, 243,
7656 216, 200, 100, 199, 118, 14, 106, 181, 88, 202, 207, 156, 227, 101, 126, 236, 46, 189,
7657 238, 73, 220, 118, 151, 73, 255, 249, 103, 103, 255, 185, 91, 82, 212, 148, 110, 19,
7658 212, 111, 199, 197, 4, 144, 25, 145, 196, 142, 205, 252, 85, 85, 48, 243, 209, 62, 57,
7659 212, 44, 149, 81, 113, 171, 60, 193, 73, 40, 11, 36, 120, 19, 62, 2, 25, 22, 232, 227,
7660 50, 35, 75, 172, 205, 2, 37, 27, 65, 182, 6, 74, 43, 1, 239, 105, 129, 184, 98, 215,
7661 81, 15, 19, 171, 39, 252, 57, 176, 171, 181, 71, 124, 251, 53, 202, 213, 33, 58, 175,
7662 52, 41, 89, 230, 217, 177, 32, 24, 82, 166, 240, 232, 223, 24, 141, 70, 121, 25, 51,
7663 173, 30, 6,
7664 ];
7665 let expected_gt: [u8; 576] = [
7666 14, 57, 164, 128, 118, 229, 58, 194, 163, 179, 7, 155, 19, 27, 195, 184, 247, 246, 83,
7667 76, 63, 71, 120, 72, 143, 130, 2, 192, 35, 251, 36, 232, 229, 122, 68, 126, 54, 228,
7668 197, 249, 112, 234, 93, 130, 133, 246, 75, 41, 13, 31, 232, 225, 105, 219, 180, 105,
7669 225, 184, 43, 57, 184, 10, 228, 147, 245, 227, 40, 68, 215, 217, 15, 164, 14, 231, 119,
7670 134, 120, 33, 210, 52, 64, 47, 39, 42, 171, 221, 225, 58, 249, 247, 204, 161, 20, 16,
7671 103, 1, 0, 168, 109, 157, 223, 60, 147, 11, 76, 2, 95, 86, 174, 4, 100, 125, 124, 226,
7672 31, 159, 199, 160, 49, 98, 76, 124, 221, 101, 6, 213, 111, 44, 24, 172, 78, 42, 216,
7673 137, 91, 68, 211, 40, 210, 172, 242, 29, 115, 220, 11, 156, 249, 117, 118, 12, 59, 59,
7674 87, 137, 217, 190, 144, 62, 249, 103, 244, 247, 152, 112, 238, 31, 122, 136, 39, 9, 49,
7675 215, 22, 180, 164, 120, 166, 115, 62, 130, 4, 216, 57, 155, 8, 214, 116, 9, 222, 168,
7676 34, 242, 19, 47, 183, 124, 196, 222, 58, 135, 75, 97, 242, 231, 190, 238, 162, 50, 124,
7677 230, 229, 172, 156, 140, 196, 163, 213, 49, 153, 144, 167, 118, 122, 167, 70, 203, 145,
7678 120, 237, 46, 135, 130, 0, 204, 139, 61, 22, 10, 243, 232, 15, 38, 161, 146, 106, 138,
7679 86, 198, 8, 167, 229, 125, 95, 28, 120, 51, 23, 161, 250, 105, 125, 177, 169, 168, 97,
7680 5, 0, 231, 143, 141, 22, 92, 143, 148, 95, 66, 151, 154, 55, 169, 0, 91, 107, 5, 59,
7681 252, 8, 140, 0, 195, 64, 135, 197, 226, 235, 170, 127, 176, 217, 7, 180, 235, 222, 58,
7682 195, 221, 192, 130, 86, 143, 0, 199, 225, 53, 57, 181, 151, 152, 81, 183, 252, 251, 5,
7683 124, 61, 164, 133, 169, 14, 20, 206, 36, 56, 1, 197, 214, 23, 10, 32, 223, 128, 87,
7684 166, 33, 61, 29, 190, 90, 150, 82, 121, 109, 255, 211, 79, 46, 57, 48, 213, 125, 8, 93,
7685 10, 151, 162, 137, 133, 129, 237, 101, 77, 39, 85, 94, 234, 43, 85, 101, 240, 233, 93,
7686 57, 171, 13, 18, 38, 31, 29, 41, 169, 193, 49, 108, 119, 231, 130, 97, 45, 35, 252,
7687 149, 125, 116, 64, 163, 70, 40, 143, 160, 14, 15, 91, 168, 207, 77, 40, 74, 208, 114,
7688 50, 64, 119, 216, 182, 96, 218, 0, 185, 69, 105, 194, 103, 19, 129, 33, 204, 250, 237,
7689 191, 143, 122, 56, 234, 62, 8, 224, 1, 242, 110, 10, 194, 178, 198, 220, 151, 167, 234,
7690 235, 207, 148, 93, 249, 221, 153, 15, 86, 89, 76, 49, 29, 18, 74, 0, 246, 42, 143, 89,
7691 60, 48, 96, 23, 173, 209, 213, 156, 80, 154, 159, 161, 12, 178, 225, 226, 77, 99, 249,
7692 154, 246, 110, 96, 176, 79, 90, 2, 190, 63, 189, 123, 170, 206, 119, 142, 138, 15, 93,
7693 191, 230, 100, 159, 142, 50, 119, 204, 157, 201, 230, 93, 57, 3, 125, 96, 195, 247,
7694 195, 76, 24, 176, 99, 88, 206, 86, 63, 204, 37, 173, 182, 116, 51, 240, 15, 155, 199,
7695 199, 198, 183, 44, 241, 251, 236, 35, 178, 36, 8, 107, 82, 153, 144, 28, 29, 229, 150,
7696 157, 37, 216, 96, 116,
7697 ];
7698
7699 let g1_va = 0x100000000;
7700 let g2_va = 0x200000000;
7701 let result_va = 0x300000000;
7702
7703 let mut result_buf = [0u8; 576]; let memory_mapping = unsafe {
7706 MemoryMapping::new(
7707 vec![
7708 MemoryRegion::new(&raw const g1_bytes, g1_va),
7709 MemoryRegion::new(&raw const g2_bytes, g2_va),
7710 MemoryRegion::new(&raw mut result_buf, result_va),
7711 ],
7712 &config,
7713 SBPFVersion::V3,
7714 )
7715 .unwrap()
7716 };
7717 invoke_context
7718 .memory_contexts
7719 .mock_set_mapping_abi_v1(memory_mapping);
7720
7721 let bls12_381_one_pair_cost = invoke_context.get_execution_cost().bls12_381_one_pair_cost;
7722 invoke_context
7723 .compute_meter
7724 .mock_set_remaining(bls12_381_one_pair_cost);
7725
7726 let result = SyscallCurvePairingMap::rust(
7727 &mut invoke_context,
7728 BLS12_381_BE,
7729 1,
7730 g1_va,
7731 g2_va,
7732 result_va,
7733 );
7734
7735 assert_eq!(0, result.unwrap());
7736 assert_eq!(result_buf, expected_gt);
7737 }
7738
7739 #[test]
7740 fn test_syscall_bls12_381_pairing_le() {
7741 use crate::bls12_381_curve_id::BLS12_381_LE;
7742
7743 let config = Config::default();
7744 let feature_set = SVMFeatureSet {
7745 enable_bls12_381_syscall: true,
7746 ..Default::default()
7747 };
7748 let feature_set = &feature_set;
7749
7750 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7751
7752 let g1_bytes: [u8; 96] = [
7753 35, 204, 210, 14, 243, 251, 68, 127, 25, 203, 200, 133, 109, 90, 249, 87, 65, 75, 36,
7754 153, 119, 189, 6, 34, 238, 133, 8, 105, 133, 50, 249, 43, 64, 127, 11, 108, 38, 42,
7755 113, 15, 50, 16, 116, 242, 54, 104, 161, 3, 164, 23, 80, 10, 184, 3, 200, 210, 200,
7756 232, 230, 77, 220, 6, 100, 235, 11, 58, 141, 219, 213, 204, 111, 27, 45, 147, 251, 67,
7757 76, 9, 102, 7, 100, 144, 146, 5, 163, 192, 154, 253, 230, 57, 178, 68, 5, 149, 124, 18,
7758 ];
7759 let g2_bytes: [u8; 192] = [
7760 197, 199, 111, 212, 19, 110, 148, 212, 82, 91, 185, 255, 103, 103, 249, 255, 73, 151,
7761 118, 220, 73, 238, 189, 46, 236, 126, 101, 227, 156, 207, 202, 88, 181, 106, 14, 118,
7762 199, 100, 200, 216, 243, 94, 44, 7, 225, 197, 135, 14, 86, 158, 11, 246, 203, 171, 107,
7763 210, 164, 27, 161, 249, 178, 34, 185, 169, 51, 175, 9, 226, 95, 150, 181, 179, 12, 64,
7764 158, 164, 181, 184, 76, 32, 205, 50, 119, 188, 155, 132, 60, 153, 185, 250, 125, 232,
7765 154, 218, 249, 8, 6, 30, 173, 51, 25, 121, 70, 141, 24, 223, 232, 240, 166, 82, 24, 32,
7766 177, 217, 230, 89, 41, 52, 175, 58, 33, 213, 202, 53, 251, 124, 71, 181, 171, 176, 57,
7767 252, 39, 171, 19, 15, 81, 215, 98, 184, 129, 105, 239, 1, 43, 74, 6, 182, 65, 27, 37,
7768 2, 205, 172, 75, 35, 50, 227, 232, 22, 25, 2, 62, 19, 120, 36, 11, 40, 73, 193, 60,
7769 171, 113, 81, 149, 44, 212, 57, 62, 209, 243, 48, 85, 85, 252, 205, 142, 196, 145, 25,
7770 144, 4,
7771 ];
7772 let expected_gt: [u8; 576] = [
7773 116, 96, 216, 37, 157, 150, 229, 29, 28, 144, 153, 82, 107, 8, 36, 178, 35, 236, 251,
7774 241, 44, 183, 198, 199, 199, 155, 15, 240, 51, 116, 182, 173, 37, 204, 63, 86, 206, 88,
7775 99, 176, 24, 76, 195, 247, 195, 96, 125, 3, 57, 93, 230, 201, 157, 204, 119, 50, 142,
7776 159, 100, 230, 191, 93, 15, 138, 142, 119, 206, 170, 123, 189, 63, 190, 2, 90, 79, 176,
7777 96, 110, 246, 154, 249, 99, 77, 226, 225, 178, 12, 161, 159, 154, 80, 156, 213, 209,
7778 173, 23, 96, 48, 60, 89, 143, 42, 246, 0, 74, 18, 29, 49, 76, 89, 86, 15, 153, 221,
7779 249, 93, 148, 207, 235, 234, 167, 151, 220, 198, 178, 194, 10, 110, 242, 1, 224, 8, 62,
7780 234, 56, 122, 143, 191, 237, 250, 204, 33, 129, 19, 103, 194, 105, 69, 185, 0, 218, 96,
7781 182, 216, 119, 64, 50, 114, 208, 74, 40, 77, 207, 168, 91, 15, 14, 160, 143, 40, 70,
7782 163, 64, 116, 125, 149, 252, 35, 45, 97, 130, 231, 119, 108, 49, 193, 169, 41, 29, 31,
7783 38, 18, 13, 171, 57, 93, 233, 240, 101, 85, 43, 234, 94, 85, 39, 77, 101, 237, 129,
7784 133, 137, 162, 151, 10, 93, 8, 125, 213, 48, 57, 46, 79, 211, 255, 109, 121, 82, 150,
7785 90, 190, 29, 61, 33, 166, 87, 128, 223, 32, 10, 23, 214, 197, 1, 56, 36, 206, 20, 14,
7786 169, 133, 164, 61, 124, 5, 251, 252, 183, 81, 152, 151, 181, 57, 53, 225, 199, 0, 143,
7787 86, 130, 192, 221, 195, 58, 222, 235, 180, 7, 217, 176, 127, 170, 235, 226, 197, 135,
7788 64, 195, 0, 140, 8, 252, 59, 5, 107, 91, 0, 169, 55, 154, 151, 66, 95, 148, 143, 92,
7789 22, 141, 143, 231, 0, 5, 97, 168, 169, 177, 125, 105, 250, 161, 23, 51, 120, 28, 95,
7790 125, 229, 167, 8, 198, 86, 138, 106, 146, 161, 38, 15, 232, 243, 10, 22, 61, 139, 204,
7791 0, 130, 135, 46, 237, 120, 145, 203, 70, 167, 122, 118, 167, 144, 153, 49, 213, 163,
7792 196, 140, 156, 172, 229, 230, 124, 50, 162, 238, 190, 231, 242, 97, 75, 135, 58, 222,
7793 196, 124, 183, 47, 19, 242, 34, 168, 222, 9, 116, 214, 8, 155, 57, 216, 4, 130, 62,
7794 115, 166, 120, 164, 180, 22, 215, 49, 9, 39, 136, 122, 31, 238, 112, 152, 247, 244,
7795 103, 249, 62, 144, 190, 217, 137, 87, 59, 59, 12, 118, 117, 249, 156, 11, 220, 115, 29,
7796 242, 172, 210, 40, 211, 68, 91, 137, 216, 42, 78, 172, 24, 44, 111, 213, 6, 101, 221,
7797 124, 76, 98, 49, 160, 199, 159, 31, 226, 124, 125, 100, 4, 174, 86, 95, 2, 76, 11, 147,
7798 60, 223, 157, 109, 168, 0, 1, 103, 16, 20, 161, 204, 247, 249, 58, 225, 221, 171, 42,
7799 39, 47, 64, 52, 210, 33, 120, 134, 119, 231, 14, 164, 15, 217, 215, 68, 40, 227, 245,
7800 147, 228, 10, 184, 57, 43, 184, 225, 105, 180, 219, 105, 225, 232, 31, 13, 41, 75, 246,
7801 133, 130, 93, 234, 112, 249, 197, 228, 54, 126, 68, 122, 229, 232, 36, 251, 35, 192, 2,
7802 130, 143, 72, 120, 71, 63, 76, 83, 246, 247, 184, 195, 27, 19, 155, 7, 179, 163, 194,
7803 58, 229, 118, 128, 164, 57, 14,
7804 ];
7805
7806 let g1_va = 0x100000000;
7807 let g2_va = 0x200000000;
7808 let result_va = 0x300000000;
7809
7810 let mut result_buf = [0u8; 576]; let memory_mapping = unsafe {
7813 MemoryMapping::new(
7814 vec![
7815 MemoryRegion::new(&raw const g1_bytes, g1_va),
7816 MemoryRegion::new(&raw const g2_bytes, g2_va),
7817 MemoryRegion::new(&raw mut result_buf, result_va),
7818 ],
7819 &config,
7820 SBPFVersion::V3,
7821 )
7822 .unwrap()
7823 };
7824 invoke_context
7825 .memory_contexts
7826 .mock_set_mapping_abi_v1(memory_mapping);
7827
7828 let bls12_381_one_pair_cost = invoke_context.get_execution_cost().bls12_381_one_pair_cost;
7829 invoke_context
7830 .compute_meter
7831 .mock_set_remaining(bls12_381_one_pair_cost);
7832
7833 let result = SyscallCurvePairingMap::rust(
7834 &mut invoke_context,
7835 BLS12_381_LE,
7836 1,
7837 g1_va,
7838 g2_va,
7839 result_va,
7840 );
7841
7842 assert_eq!(0, result.unwrap());
7843 assert_eq!(result_buf, expected_gt);
7844 }
7845
7846 #[test]
7847 fn test_syscall_bls12_381_decompress_g1() {
7848 use crate::bls12_381_curve_id::{BLS12_381_G1_BE, BLS12_381_G1_LE};
7849
7850 let config = Config::default();
7851 let feature_set = SVMFeatureSet {
7852 enable_bls12_381_syscall: true,
7853 ..Default::default()
7854 };
7855 let feature_set = &feature_set;
7856
7857 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7858
7859 let compressed_be: [u8; 48] = [
7860 175, 159, 245, 68, 142, 96, 188, 154, 113, 143, 70, 58, 193, 2, 189, 111, 135, 114,
7861 230, 70, 12, 25, 7, 106, 108, 137, 213, 128, 110, 90, 142, 244, 75, 111, 59, 138, 240,
7862 158, 55, 164, 229, 100, 152, 122, 38, 185, 222, 218,
7863 ];
7864 let expected_affine_be: [u8; 96] = [
7865 15, 159, 245, 68, 142, 96, 188, 154, 113, 143, 70, 58, 193, 2, 189, 111, 135, 114, 230,
7866 70, 12, 25, 7, 106, 108, 137, 213, 128, 110, 90, 142, 244, 75, 111, 59, 138, 240, 158,
7867 55, 164, 229, 100, 152, 122, 38, 185, 222, 218, 18, 79, 1, 246, 62, 35, 162, 234, 146,
7868 109, 7, 85, 44, 104, 10, 250, 158, 31, 181, 244, 117, 193, 27, 53, 184, 79, 160, 237,
7869 168, 51, 41, 200, 58, 4, 107, 95, 246, 171, 241, 202, 120, 228, 135, 135, 100, 50, 123,
7870 58,
7871 ];
7872 let compressed_le: [u8; 48] = [
7873 218, 222, 185, 38, 122, 152, 100, 229, 164, 55, 158, 240, 138, 59, 111, 75, 244, 142,
7874 90, 110, 128, 213, 137, 108, 106, 7, 25, 12, 70, 230, 114, 135, 111, 189, 2, 193, 58,
7875 70, 143, 113, 154, 188, 96, 142, 68, 245, 159, 175,
7876 ];
7877 let expected_affine_le: [u8; 96] = [
7878 218, 222, 185, 38, 122, 152, 100, 229, 164, 55, 158, 240, 138, 59, 111, 75, 244, 142,
7879 90, 110, 128, 213, 137, 108, 106, 7, 25, 12, 70, 230, 114, 135, 111, 189, 2, 193, 58,
7880 70, 143, 113, 154, 188, 96, 142, 68, 245, 159, 15, 58, 123, 50, 100, 135, 135, 228,
7881 120, 202, 241, 171, 246, 95, 107, 4, 58, 200, 41, 51, 168, 237, 160, 79, 184, 53, 27,
7882 193, 117, 244, 181, 31, 158, 250, 10, 104, 44, 85, 7, 109, 146, 234, 162, 35, 62, 246,
7883 1, 79, 18,
7884 ];
7885
7886 let input_be_va = 0x100000000;
7887 let result_be_va = 0x200000000;
7888 let input_le_va = 0x300000000;
7889 let result_le_va = 0x400000000;
7890 let mut result_be_buf = [0u8; 96];
7891 let mut result_le_buf = [0u8; 96];
7892
7893 let memory_mapping = unsafe {
7894 MemoryMapping::new(
7895 vec![
7896 MemoryRegion::new(&raw const compressed_be, input_be_va),
7897 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7898 MemoryRegion::new(&raw const compressed_le, input_le_va),
7899 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7900 ],
7901 &config,
7902 SBPFVersion::V3,
7903 )
7904 .unwrap()
7905 };
7906 invoke_context
7907 .memory_contexts
7908 .mock_set_mapping_abi_v1(memory_mapping);
7909
7910 let bls12_381_g2_decompress_cost = invoke_context
7911 .get_execution_cost()
7912 .bls12_381_g2_decompress_cost;
7913 invoke_context
7914 .compute_meter
7915 .mock_set_remaining(2 * bls12_381_g2_decompress_cost);
7916
7917 let result = SyscallCurveDecompress::rust(
7918 &mut invoke_context,
7919 BLS12_381_G1_BE,
7920 input_be_va,
7921 result_be_va,
7922 0,
7923 0,
7924 );
7925
7926 assert_eq!(0, result.unwrap());
7927 assert_eq!(result_be_buf, expected_affine_be);
7928
7929 let result = SyscallCurveDecompress::rust(
7930 &mut invoke_context,
7931 BLS12_381_G1_LE,
7932 input_le_va,
7933 result_le_va,
7934 0,
7935 0,
7936 );
7937
7938 assert_eq!(0, result.unwrap());
7939 assert_eq!(result_le_buf, expected_affine_le);
7940 }
7941
7942 #[test]
7943 fn test_syscall_bls12_381_decompress_g2() {
7944 use crate::bls12_381_curve_id::{BLS12_381_G2_BE, BLS12_381_G2_LE};
7945
7946 let config = Config::default();
7947 let feature_set = SVMFeatureSet {
7948 enable_bls12_381_syscall: true,
7949 ..Default::default()
7950 };
7951 let feature_set = &feature_set;
7952
7953 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7954
7955 let compressed_be: [u8; 96] = [
7956 143, 106, 18, 220, 40, 152, 4, 228, 139, 35, 104, 146, 179, 74, 205, 172, 146, 137, 11,
7957 106, 74, 42, 135, 137, 53, 249, 64, 251, 173, 232, 48, 209, 125, 222, 13, 209, 121,
7958 238, 185, 179, 111, 105, 71, 223, 39, 48, 195, 104, 23, 24, 170, 59, 111, 106, 167, 51,
7959 231, 186, 224, 182, 172, 73, 15, 18, 211, 143, 59, 2, 115, 190, 196, 163, 111, 11, 36,
7960 133, 86, 96, 188, 135, 16, 37, 216, 175, 71, 182, 222, 31, 207, 155, 16, 255, 112, 78,
7961 242, 111,
7962 ];
7963 let expected_affine_be: [u8; 192] = [
7964 15, 106, 18, 220, 40, 152, 4, 228, 139, 35, 104, 146, 179, 74, 205, 172, 146, 137, 11,
7965 106, 74, 42, 135, 137, 53, 249, 64, 251, 173, 232, 48, 209, 125, 222, 13, 209, 121,
7966 238, 185, 179, 111, 105, 71, 223, 39, 48, 195, 104, 23, 24, 170, 59, 111, 106, 167, 51,
7967 231, 186, 224, 182, 172, 73, 15, 18, 211, 143, 59, 2, 115, 190, 196, 163, 111, 11, 36,
7968 133, 86, 96, 188, 135, 16, 37, 216, 175, 71, 182, 222, 31, 207, 155, 16, 255, 112, 78,
7969 242, 111, 11, 217, 244, 83, 201, 111, 182, 168, 171, 205, 183, 118, 199, 85, 130, 157,
7970 95, 69, 159, 126, 122, 27, 92, 84, 253, 147, 96, 176, 74, 57, 13, 228, 178, 111, 246,
7971 157, 74, 120, 174, 255, 146, 92, 32, 214, 164, 56, 206, 144, 13, 59, 111, 251, 170, 85,
7972 159, 219, 108, 187, 31, 15, 106, 176, 64, 191, 56, 77, 217, 87, 144, 196, 148, 21, 12,
7973 171, 99, 121, 128, 120, 187, 224, 192, 107, 104, 178, 75, 205, 118, 64, 234, 168, 214,
7974 11, 125, 153, 55, 5,
7975 ];
7976 let compressed_le: [u8; 96] = [
7977 111, 242, 78, 112, 255, 16, 155, 207, 31, 222, 182, 71, 175, 216, 37, 16, 135, 188, 96,
7978 86, 133, 36, 11, 111, 163, 196, 190, 115, 2, 59, 143, 211, 18, 15, 73, 172, 182, 224,
7979 186, 231, 51, 167, 106, 111, 59, 170, 24, 23, 104, 195, 48, 39, 223, 71, 105, 111, 179,
7980 185, 238, 121, 209, 13, 222, 125, 209, 48, 232, 173, 251, 64, 249, 53, 137, 135, 42,
7981 74, 106, 11, 137, 146, 172, 205, 74, 179, 146, 104, 35, 139, 228, 4, 152, 40, 220, 18,
7982 106, 143,
7983 ];
7984 let expected_affine_le: [u8; 192] = [
7985 111, 242, 78, 112, 255, 16, 155, 207, 31, 222, 182, 71, 175, 216, 37, 16, 135, 188, 96,
7986 86, 133, 36, 11, 111, 163, 196, 190, 115, 2, 59, 143, 211, 18, 15, 73, 172, 182, 224,
7987 186, 231, 51, 167, 106, 111, 59, 170, 24, 23, 104, 195, 48, 39, 223, 71, 105, 111, 179,
7988 185, 238, 121, 209, 13, 222, 125, 209, 48, 232, 173, 251, 64, 249, 53, 137, 135, 42,
7989 74, 106, 11, 137, 146, 172, 205, 74, 179, 146, 104, 35, 139, 228, 4, 152, 40, 220, 18,
7990 106, 15, 5, 55, 153, 125, 11, 214, 168, 234, 64, 118, 205, 75, 178, 104, 107, 192, 224,
7991 187, 120, 128, 121, 99, 171, 12, 21, 148, 196, 144, 87, 217, 77, 56, 191, 64, 176, 106,
7992 15, 31, 187, 108, 219, 159, 85, 170, 251, 111, 59, 13, 144, 206, 56, 164, 214, 32, 92,
7993 146, 255, 174, 120, 74, 157, 246, 111, 178, 228, 13, 57, 74, 176, 96, 147, 253, 84, 92,
7994 27, 122, 126, 159, 69, 95, 157, 130, 85, 199, 118, 183, 205, 171, 168, 182, 111, 201,
7995 83, 244, 217, 11,
7996 ];
7997
7998 let input_be_va = 0x100000000;
7999 let result_be_va = 0x200000000;
8000 let input_le_va = 0x300000000;
8001 let result_le_va = 0x400000000;
8002 let mut result_be_buf = [0u8; 192];
8003 let mut result_le_buf = [0u8; 192];
8004
8005 let memory_mapping = unsafe {
8006 MemoryMapping::new(
8007 vec![
8008 MemoryRegion::new(&raw const compressed_be, input_be_va),
8009 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
8010 MemoryRegion::new(&raw const compressed_le, input_le_va),
8011 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
8012 ],
8013 &config,
8014 SBPFVersion::V3,
8015 )
8016 .unwrap()
8017 };
8018 invoke_context
8019 .memory_contexts
8020 .mock_set_mapping_abi_v1(memory_mapping);
8021
8022 let bls12_381_g2_decompress_cost = invoke_context
8023 .get_execution_cost()
8024 .bls12_381_g2_decompress_cost;
8025 invoke_context
8026 .compute_meter
8027 .mock_set_remaining(2 * bls12_381_g2_decompress_cost);
8028
8029 let result = SyscallCurveDecompress::rust(
8030 &mut invoke_context,
8031 BLS12_381_G2_BE,
8032 input_be_va,
8033 result_be_va,
8034 0,
8035 0,
8036 );
8037
8038 assert_eq!(0, result.unwrap());
8039 assert_eq!(result_be_buf, expected_affine_be);
8040
8041 let result = SyscallCurveDecompress::rust(
8042 &mut invoke_context,
8043 BLS12_381_G2_LE,
8044 input_le_va,
8045 result_le_va,
8046 0,
8047 0,
8048 );
8049
8050 assert_eq!(0, result.unwrap());
8051 assert_eq!(result_le_buf, expected_affine_le);
8052 }
8053
8054 #[test]
8055 fn test_syscall_bls12_381_validate_g1() {
8056 use crate::bls12_381_curve_id::{BLS12_381_G1_BE, BLS12_381_G1_LE};
8057
8058 let config = Config::default();
8059 let feature_set = SVMFeatureSet {
8060 enable_bls12_381_syscall: true,
8061 ..Default::default()
8062 };
8063 let feature_set = &feature_set;
8064
8065 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
8066
8067 let point_bytes_be: [u8; 96] = [
8068 22, 163, 250, 67, 197, 168, 103, 201, 128, 33, 170, 96, 74, 40, 45, 90, 105, 181, 244,
8069 124, 128, 107, 27, 142, 158, 96, 0, 46, 144, 27, 61, 205, 65, 38, 141, 165, 55, 113,
8070 114, 23, 36, 105, 252, 115, 147, 16, 12, 39, 11, 19, 53, 215, 107, 128, 94, 68, 22, 46,
8071 74, 179, 236, 232, 220, 30, 48, 169, 85, 16, 70, 112, 26, 37, 73, 104, 203, 189, 42,
8072 96, 141, 90, 167, 41, 61, 82, 184, 80, 93, 112, 204, 140, 225, 245, 103, 130, 184, 194,
8073 ];
8074
8075 let point_bytes_le: [u8; 96] = [
8076 39, 12, 16, 147, 115, 252, 105, 36, 23, 114, 113, 55, 165, 141, 38, 65, 205, 61, 27,
8077 144, 46, 0, 96, 158, 142, 27, 107, 128, 124, 244, 181, 105, 90, 45, 40, 74, 96, 170,
8078 33, 128, 201, 103, 168, 197, 67, 250, 163, 22, 194, 184, 130, 103, 245, 225, 140, 204,
8079 112, 93, 80, 184, 82, 61, 41, 167, 90, 141, 96, 42, 189, 203, 104, 73, 37, 26, 112, 70,
8080 16, 85, 169, 48, 30, 220, 232, 236, 179, 74, 46, 22, 68, 94, 128, 107, 215, 53, 19, 11,
8081 ];
8082
8083 let point_be_va = 0x100000000;
8084 let point_le_va = 0x200000000;
8085
8086 let memory_mapping = unsafe {
8087 MemoryMapping::new(
8088 vec![
8089 MemoryRegion::new(&raw const point_bytes_be, point_be_va),
8090 MemoryRegion::new(&raw const point_bytes_le, point_le_va),
8091 ],
8092 &config,
8093 SBPFVersion::V3,
8094 )
8095 .unwrap()
8096 };
8097 invoke_context
8098 .memory_contexts
8099 .mock_set_mapping_abi_v1(memory_mapping);
8100
8101 let bls12_381_g1_validate_cost = invoke_context
8102 .get_execution_cost()
8103 .bls12_381_g1_validate_cost;
8104 invoke_context
8105 .compute_meter
8106 .mock_set_remaining(2 * bls12_381_g1_validate_cost);
8107
8108 let result = SyscallCurvePointValidation::rust(
8109 &mut invoke_context,
8110 BLS12_381_G1_BE,
8111 point_be_va,
8112 0,
8113 0,
8114 0,
8115 );
8116
8117 assert_eq!(0, result.unwrap());
8118
8119 let result = SyscallCurvePointValidation::rust(
8120 &mut invoke_context,
8121 BLS12_381_G1_LE,
8122 point_le_va,
8123 0,
8124 0,
8125 0,
8126 );
8127
8128 assert_eq!(0, result.unwrap());
8129 }
8130
8131 #[test]
8132 fn test_syscall_bls12_381_validate_g2() {
8133 use crate::bls12_381_curve_id::{BLS12_381_G2_BE, BLS12_381_G2_LE};
8134
8135 let config = Config::default();
8136 let feature_set = SVMFeatureSet {
8137 enable_bls12_381_syscall: true,
8138 ..Default::default()
8139 };
8140 let feature_set = &feature_set;
8141
8142 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
8143
8144 let point_bytes_be: [u8; 192] = [
8145 0, 79, 207, 115, 91, 72, 0, 80, 49, 59, 203, 189, 178, 240, 18, 141, 223, 147, 62, 79,
8146 98, 131, 147, 33, 103, 151, 137, 12, 160, 13, 78, 180, 13, 221, 89, 239, 178, 249, 141,
8147 8, 38, 137, 23, 71, 213, 2, 28, 13, 24, 168, 51, 6, 34, 184, 228, 22, 173, 11, 224,
8148 168, 14, 103, 154, 18, 166, 51, 255, 154, 45, 230, 253, 149, 145, 16, 251, 107, 248,
8149 55, 53, 150, 37, 131, 133, 138, 156, 195, 70, 202, 131, 144, 166, 164, 80, 251, 179,
8150 167, 8, 54, 188, 153, 10, 235, 83, 14, 211, 95, 212, 54, 120, 175, 148, 83, 253, 106,
8151 53, 178, 157, 118, 208, 110, 0, 187, 111, 14, 140, 246, 139, 200, 205, 178, 72, 36, 67,
8152 140, 39, 100, 163, 104, 140, 78, 91, 123, 130, 197, 12, 176, 70, 104, 65, 43, 104, 232,
8153 102, 238, 229, 115, 253, 62, 61, 207, 116, 223, 245, 206, 250, 163, 30, 200, 76, 101,
8154 93, 69, 216, 240, 189, 198, 253, 27, 199, 32, 215, 224, 12, 50, 78, 204, 106, 40, 117,
8155 68, 44, 113,
8156 ];
8157
8158 let point_bytes_le: [u8; 192] = [
8159 167, 179, 251, 80, 164, 166, 144, 131, 202, 70, 195, 156, 138, 133, 131, 37, 150, 53,
8160 55, 248, 107, 251, 16, 145, 149, 253, 230, 45, 154, 255, 51, 166, 18, 154, 103, 14,
8161 168, 224, 11, 173, 22, 228, 184, 34, 6, 51, 168, 24, 13, 28, 2, 213, 71, 23, 137, 38,
8162 8, 141, 249, 178, 239, 89, 221, 13, 180, 78, 13, 160, 12, 137, 151, 103, 33, 147, 131,
8163 98, 79, 62, 147, 223, 141, 18, 240, 178, 189, 203, 59, 49, 80, 0, 72, 91, 115, 207, 79,
8164 0, 113, 44, 68, 117, 40, 106, 204, 78, 50, 12, 224, 215, 32, 199, 27, 253, 198, 189,
8165 240, 216, 69, 93, 101, 76, 200, 30, 163, 250, 206, 245, 223, 116, 207, 61, 62, 253,
8166 115, 229, 238, 102, 232, 104, 43, 65, 104, 70, 176, 12, 197, 130, 123, 91, 78, 140,
8167 104, 163, 100, 39, 140, 67, 36, 72, 178, 205, 200, 139, 246, 140, 14, 111, 187, 0, 110,
8168 208, 118, 157, 178, 53, 106, 253, 83, 148, 175, 120, 54, 212, 95, 211, 14, 83, 235, 10,
8169 153, 188, 54, 8,
8170 ];
8171
8172 let point_be_va = 0x100000000;
8173 let point_le_va = 0x200000000;
8174
8175 let memory_mapping = unsafe {
8176 MemoryMapping::new(
8177 vec![
8178 MemoryRegion::new(&raw const point_bytes_be, point_be_va),
8179 MemoryRegion::new(&raw const point_bytes_le, point_le_va),
8180 ],
8181 &config,
8182 SBPFVersion::V3,
8183 )
8184 .unwrap()
8185 };
8186 invoke_context
8187 .memory_contexts
8188 .mock_set_mapping_abi_v1(memory_mapping);
8189
8190 let bls12_381_g2_validate_cost = invoke_context
8191 .get_execution_cost()
8192 .bls12_381_g2_validate_cost;
8193 invoke_context
8194 .compute_meter
8195 .mock_set_remaining(2 * bls12_381_g2_validate_cost);
8196
8197 let result = SyscallCurvePointValidation::rust(
8198 &mut invoke_context,
8199 BLS12_381_G2_BE,
8200 point_be_va,
8201 0,
8202 0,
8203 0,
8204 );
8205
8206 assert_eq!(0, result.unwrap());
8207
8208 let result = SyscallCurvePointValidation::rust(
8209 &mut invoke_context,
8210 BLS12_381_G2_LE,
8211 point_le_va,
8212 0,
8213 0,
8214 0,
8215 );
8216
8217 assert_eq!(0, result.unwrap());
8218 }
8219
8220 #[test]
8221 fn test_sol_alloc_free_registration() {
8222 let feature_set = SVMFeatureSet::all_enabled();
8223 let compute_budget = SVMTransactionExecutionBudget::default();
8224
8225 {
8227 let env = create_program_runtime_environment(
8228 &feature_set,
8229 &compute_budget,
8230 false,
8231 false,
8232 )
8233 .unwrap();
8234 assert!(
8235 env.get_function_registry()
8236 .lookup_by_name(b"sol_alloc_free_")
8237 .is_some()
8238 );
8239 }
8240
8241 {
8243 let env = create_program_runtime_environment(
8244 &feature_set,
8245 &compute_budget,
8246 true,
8247 false,
8248 )
8249 .unwrap();
8250 assert!(
8251 env.get_function_registry()
8252 .lookup_by_name(b"sol_alloc_free_")
8253 .is_none()
8254 );
8255 }
8256 }
8257
8258 #[test]
8259 fn test_sol_big_mod_exp_registration() {
8260 let compute_budget = SVMTransactionExecutionBudget::default();
8261
8262 let mut feature_set = SVMFeatureSet::all_enabled();
8263 feature_set.enable_big_mod_exp_syscall = true;
8264 let env = create_program_runtime_environment(
8265 &feature_set,
8266 &compute_budget,
8267 false,
8268 false,
8269 )
8270 .unwrap();
8271 assert!(
8272 env.get_function_registry()
8273 .lookup_by_name(b"sol_big_mod_exp")
8274 .is_some()
8275 );
8276
8277 feature_set.enable_big_mod_exp_syscall = false;
8278 let env = create_program_runtime_environment(
8279 &feature_set,
8280 &compute_budget,
8281 false,
8282 false,
8283 )
8284 .unwrap();
8285 assert!(
8286 env.get_function_registry()
8287 .lookup_by_name(b"sol_big_mod_exp")
8288 .is_none()
8289 );
8290 }
8291
8292 #[test]
8293 fn test_syscall_sha512() {
8294 let config = Config::default();
8295 prepare_mockup!(invoke_context, program_id, bpf_loader_deprecated::id());
8296
8297 let bytes1 = "Gaggablaghblagh!";
8298 let bytes2 = "flurbos";
8299
8300 let mock_slice1 = MockSlice {
8301 vm_addr: 0x300000000,
8302 len: bytes1.len(),
8303 };
8304 let mock_slice2 = MockSlice {
8305 vm_addr: 0x400000000,
8306 len: bytes2.len(),
8307 };
8308 let bytes_to_hash = [mock_slice1, mock_slice2];
8309 let mut hash_result = [0; solana_hash_512::HASH_BYTES];
8310 let ro_len = bytes_to_hash.len() as u64;
8311 let ro_va = 0x100000000;
8312 let rw_va = 0x200000000;
8313 let memory_mapping = unsafe {
8314 MemoryMapping::new(
8315 vec![
8316 MemoryRegion::new(bytes_of_slice(&bytes_to_hash), ro_va),
8317 MemoryRegion::new(bytes_of_slice_mut(&mut hash_result), rw_va),
8318 MemoryRegion::new(&raw const *bytes1.as_bytes(), bytes_to_hash[0].vm_addr),
8319 MemoryRegion::new(&raw const *bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
8320 ],
8321 &config,
8322 SBPFVersion::V3,
8323 )
8324 .unwrap()
8325 };
8326 invoke_context
8327 .memory_contexts
8328 .mock_set_mapping_abi_v1(memory_mapping);
8329 invoke_context.compute_meter.mock_set_remaining(
8330 (invoke_context.get_execution_cost().sha256_base_cost
8331 + invoke_context.get_execution_cost().mem_op_base_cost.max(
8332 invoke_context
8333 .get_execution_cost()
8334 .sha256_byte_cost
8335 .saturating_mul((bytes1.len() + bytes2.len()) as u64 / 2),
8336 ))
8337 * 4,
8338 );
8339
8340 let result =
8341 SyscallHash::<Sha512Hasher>::rust(&mut invoke_context, ro_va, ro_len, rw_va, 0, 0);
8342 result.unwrap();
8343
8344 let hash_local = sha512::hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes();
8345 assert_eq!(hash_result, hash_local);
8346 let result = SyscallHash::<Sha512Hasher>::rust(
8347 &mut invoke_context,
8348 ro_va - 1, ro_len,
8350 rw_va,
8351 0,
8352 0,
8353 );
8354 assert_access_violation!(result, ro_va - 1, 32);
8355 let result = SyscallHash::<Sha512Hasher>::rust(
8356 &mut invoke_context,
8357 ro_va,
8358 ro_len + 1, rw_va,
8360 0,
8361 0,
8362 );
8363 assert_access_violation!(result, ro_va, 48);
8364 let result = SyscallHash::<Sha512Hasher>::rust(
8365 &mut invoke_context,
8366 ro_va,
8367 ro_len,
8368 rw_va - 1, 0,
8370 0,
8371 );
8372 assert_access_violation!(result, rw_va - 1, solana_hash_512::HASH_BYTES as u64);
8373 let result =
8374 SyscallHash::<Sha512Hasher>::rust(&mut invoke_context, ro_va, ro_len, rw_va, 0, 0);
8375 assert_matches!(
8376 result,
8377 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
8378 );
8379 }
8380}