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