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