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