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