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