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