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