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