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