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_bytes(
3068 solana_pubkey::new_rand(),
3069 b"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 = wincode::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 wincode::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 = wincode::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 = wincode::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 wincode::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 transaction_accounts = vec![(
4757 sysvar::stake_history::id(),
4758 create_account_shared_data_for_test(&src_history, STAKE_HISTORY_ACCOUNT_SIZE),
4759 )];
4760 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4761
4762 {
4763 let mut got_history_buf = vec![0; STAKE_HISTORY_ACCOUNT_SIZE];
4764 let got_history_buf_va = 0x100000000;
4765 let history_id_va = 0x200000000;
4766 let history_id = StakeHistory::id().to_bytes();
4767
4768 let memory_mapping = unsafe {
4769 MemoryMapping::new(
4770 vec![
4771 MemoryRegion::new(&raw mut got_history_buf[..], got_history_buf_va),
4772 MemoryRegion::new(&raw const history_id, history_id_va),
4773 ],
4774 &config,
4775 SBPFVersion::V3,
4776 )
4777 .unwrap()
4778 };
4779 invoke_context
4780 .memory_contexts
4781 .mock_set_mapping_abi_v1(memory_mapping);
4782
4783 let result = SyscallGetSysvar::rust(
4784 &mut invoke_context,
4785 history_id_va,
4786 got_history_buf_va,
4787 0,
4788 STAKE_HISTORY_ACCOUNT_SIZE as u64,
4789 0,
4790 );
4791 assert_eq!(result.unwrap(), 0);
4792
4793 let history_from_buf = wincode::deserialize::<StakeHistory>(&got_history_buf).unwrap();
4794 assert_eq!(history_from_buf, src_history);
4795 }
4796 }
4797
4798 #[test_case(false; "partial")]
4799 #[test_case(true; "full")]
4800 fn test_syscall_get_slot_hashes(filled: bool) {
4801 let config = Config::default();
4802
4803 let mut src_hashes = SlotHashes::default();
4804
4805 let slots = if filled {
4806 slot_hashes::MAX_ENTRIES + 1
4807 } else {
4808 slot_hashes::MAX_ENTRIES / 2
4809 } as u64;
4810
4811 for slot in 1..slots {
4812 src_hashes.add(slot, hashv(&[&slot.to_le_bytes()]));
4813 }
4814
4815 let src_hashes = src_hashes;
4816
4817 let mut src_hashes_buf = vec![0; solana_slot_hashes::SIZE];
4818 wincode::serialize_into(&mut src_hashes_buf, &src_hashes).unwrap();
4819
4820 let transaction_accounts = vec![(
4821 sysvar::slot_hashes::id(),
4822 create_account_shared_data_for_test(&src_hashes, solana_slot_hashes::SIZE),
4823 )];
4824 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
4825
4826 {
4827 let mut got_hashes_buf = vec![0; solana_slot_hashes::SIZE];
4828 let got_hashes_buf_va = 0x100000000;
4829 let hashes_id_va = 0x200000000;
4830 let hashes_id = SlotHashes::id().to_bytes();
4831
4832 let memory_mapping = unsafe {
4833 MemoryMapping::new(
4834 vec![
4835 MemoryRegion::new(&raw mut got_hashes_buf[..], got_hashes_buf_va),
4836 MemoryRegion::new(&raw const hashes_id, hashes_id_va),
4837 ],
4838 &config,
4839 SBPFVersion::V3,
4840 )
4841 .unwrap()
4842 };
4843 invoke_context
4844 .memory_contexts
4845 .mock_set_mapping_abi_v1(memory_mapping);
4846
4847 let result = SyscallGetSysvar::rust(
4848 &mut invoke_context,
4849 hashes_id_va,
4850 got_hashes_buf_va,
4851 0,
4852 solana_slot_hashes::SIZE as u64,
4853 0,
4854 );
4855 assert_eq!(result.unwrap(), 0);
4856
4857 let hashes_from_buf = wincode::deserialize::<SlotHashes>(&got_hashes_buf).unwrap();
4858 assert_eq!(hashes_from_buf, src_hashes);
4859 }
4860 }
4861
4862 #[test]
4863 fn test_syscall_get_sysvar_errors() {
4864 let config = Config::default();
4865
4866 let mut src_clock = create_filled_type::<Clock>(false);
4867 src_clock.slot = 1;
4868 src_clock.epoch_start_timestamp = 2;
4869 src_clock.epoch = 3;
4870 src_clock.leader_schedule_epoch = 4;
4871 src_clock.unix_timestamp = 5;
4872
4873 let clock_id_va = 0x300000000;
4874 let clock_id = Clock::id().to_bytes();
4875
4876 let mut got_clock_buf_rw = vec![0; solana_clock::SIZE];
4877 let got_clock_buf_rw_va = 0x300000100;
4878
4879 let got_clock_buf_ro = [0; solana_clock::SIZE];
4880 let got_clock_buf_ro_va = 0x300000200;
4881
4882 let access_violation_err =
4883 std::mem::discriminant(&EbpfError::AccessViolation(AccessType::Load, 0, 0, ""));
4884
4885 let got_clock_empty = vec![0; solana_clock::SIZE];
4886
4887 {
4888 with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
4890 let memory_mapping = unsafe {
4891 MemoryMapping::new(
4892 vec![
4893 MemoryRegion::new(&raw const clock_id, clock_id_va),
4894 MemoryRegion::new(&raw mut got_clock_buf_rw[..], got_clock_buf_rw_va),
4895 MemoryRegion::new(&raw const got_clock_buf_ro[..], got_clock_buf_ro_va),
4896 ],
4897 &config,
4898 SBPFVersion::V3,
4899 )
4900 .unwrap()
4901 };
4902 invoke_context
4903 .memory_contexts
4904 .mock_set_mapping_abi_v1(memory_mapping);
4905
4906 let e = SyscallGetSysvar::rust(
4908 &mut invoke_context,
4909 clock_id_va + 1,
4910 got_clock_buf_rw_va,
4911 0,
4912 solana_clock::SIZE as u64,
4913 0,
4914 )
4915 .unwrap_err();
4916
4917 assert_eq!(
4918 std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
4919 access_violation_err,
4920 );
4921 assert_eq!(got_clock_buf_rw, got_clock_empty);
4922
4923 let e = SyscallGetSysvar::rust(
4925 &mut invoke_context,
4926 clock_id_va,
4927 got_clock_buf_rw_va + 1,
4928 0,
4929 solana_clock::SIZE as u64,
4930 0,
4931 )
4932 .unwrap_err();
4933
4934 assert_eq!(
4935 std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
4936 access_violation_err,
4937 );
4938 assert_eq!(got_clock_buf_rw, got_clock_empty);
4939
4940 let e = SyscallGetSysvar::rust(
4941 &mut invoke_context,
4942 clock_id_va,
4943 got_clock_buf_ro_va,
4944 0,
4945 solana_clock::SIZE as u64,
4946 0,
4947 )
4948 .unwrap_err();
4949
4950 assert_eq!(
4951 std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
4952 access_violation_err,
4953 );
4954 assert_eq!(got_clock_buf_rw, got_clock_empty);
4955
4956 let e = SyscallGetSysvar::rust(
4958 &mut invoke_context,
4959 clock_id_va,
4960 got_clock_buf_rw_va,
4961 u64::MAX - solana_clock::SIZE as u64 / 2,
4962 solana_clock::SIZE as u64,
4963 0,
4964 )
4965 .unwrap_err();
4966
4967 assert_eq!(
4968 *e.downcast_ref::<InstructionError>().unwrap(),
4969 InstructionError::ArithmeticOverflow,
4970 );
4971 assert_eq!(got_clock_buf_rw, got_clock_empty);
4972
4973 let result = SyscallGetSysvar::rust(
4978 &mut invoke_context,
4979 clock_id_va,
4980 got_clock_buf_rw_va,
4981 0,
4982 solana_clock::SIZE as u64,
4983 0,
4984 )
4985 .unwrap();
4986
4987 assert_eq!(result, 2);
4988 assert_eq!(got_clock_buf_rw, got_clock_empty);
4989 }
4990
4991 {
4992 let transaction_accounts = vec![(
4993 sysvar::clock::id(),
4994 create_account_shared_data_for_test(&src_clock, solana_clock::SIZE),
4995 )];
4996 let memory_mapping = unsafe {
4997 MemoryMapping::new(
4998 vec![
4999 MemoryRegion::new(&raw const clock_id, clock_id_va),
5000 MemoryRegion::new(&raw mut got_clock_buf_rw[..], got_clock_buf_rw_va),
5001 MemoryRegion::new(&raw const got_clock_buf_ro[..], got_clock_buf_ro_va),
5002 ],
5003 &config,
5004 SBPFVersion::V3,
5005 )
5006 .unwrap()
5007 };
5008 with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
5009 invoke_context
5010 .memory_contexts
5011 .mock_set_mapping_abi_v1(memory_mapping);
5012
5013 let result = SyscallGetSysvar::rust(
5015 &mut invoke_context,
5016 clock_id_va,
5017 got_clock_buf_rw_va,
5018 1,
5019 solana_clock::SIZE as u64,
5020 0,
5021 )
5022 .unwrap();
5023
5024 assert_eq!(result, 1);
5025 assert_eq!(got_clock_buf_rw, got_clock_empty);
5026
5027 SyscallGetSysvar::rust(
5029 &mut invoke_context,
5030 clock_id_va,
5031 got_clock_buf_rw_va,
5032 0,
5033 solana_clock::SIZE as u64,
5034 0,
5035 )
5036 .unwrap();
5037
5038 let clock_from_buf = wincode::deserialize::<Clock>(&got_clock_buf_rw).unwrap();
5039
5040 assert_eq!(clock_from_buf, src_clock);
5041 }
5042 }
5043
5044 type BuiltinFunctionRustInterface<'a> = fn(
5045 &mut InvokeContext<'a, 'a>,
5046 u64,
5047 u64,
5048 u64,
5049 u64,
5050 u64,
5051 ) -> Result<u64, Box<dyn std::error::Error>>;
5052
5053 fn call_program_address_common<'a, 'b: 'a>(
5054 invoke_context: &'a mut InvokeContext<'b, 'b>,
5055 seeds: &[&[u8]],
5056 program_id: &Pubkey,
5057 overlap_outputs: bool,
5058 syscall: BuiltinFunctionRustInterface<'b>,
5059 ) -> Result<(Pubkey, u8), Error> {
5060 const SEEDS_VA: u64 = 0x100000000;
5061 const PROGRAM_ID_VA: u64 = 0x200000000;
5062 const ADDRESS_VA: u64 = 0x300000000;
5063 const BUMP_SEED_VA: u64 = 0x400000000;
5064 const SEED_VA: u64 = 0x500000000;
5065
5066 let config = Config::default();
5067 let mut address = Pubkey::default();
5068 let mut bump_seed = 0;
5069 let mut regions = vec![
5070 MemoryRegion::new(bytes_of(program_id), PROGRAM_ID_VA),
5071 MemoryRegion::new(bytes_of_mut(&mut address), ADDRESS_VA),
5072 MemoryRegion::new(bytes_of_mut(&mut bump_seed), BUMP_SEED_VA),
5073 ];
5074
5075 let mut mock_slices = Vec::with_capacity(seeds.len());
5076 for (i, seed) in seeds.iter().enumerate() {
5077 let vm_addr = SEED_VA.saturating_add((i as u64).saturating_mul(0x100000000));
5078 let mock_slice = MockSlice {
5079 vm_addr,
5080 len: seed.len(),
5081 };
5082 mock_slices.push(mock_slice);
5083 regions.push(MemoryRegion::new(bytes_of_slice(seed), vm_addr));
5084 }
5085 regions.push(MemoryRegion::new(bytes_of_slice(&mock_slices), SEEDS_VA));
5086 let memory_mapping =
5087 unsafe { MemoryMapping::new(regions, &config, SBPFVersion::V3).unwrap() };
5088 invoke_context
5089 .memory_contexts
5090 .mock_set_mapping_abi_v1(memory_mapping);
5091
5092 let result = syscall(
5093 invoke_context,
5094 SEEDS_VA,
5095 seeds.len() as u64,
5096 PROGRAM_ID_VA,
5097 ADDRESS_VA,
5098 if overlap_outputs {
5099 ADDRESS_VA
5100 } else {
5101 BUMP_SEED_VA
5102 },
5103 );
5104 result.map(|_| (address, bump_seed))
5105 }
5106
5107 fn create_program_address<'a>(
5108 invoke_context: &mut InvokeContext<'a, 'a>,
5109 seeds: &[&[u8]],
5110 address: &Pubkey,
5111 ) -> Result<Pubkey, Error> {
5112 let (address, _) = call_program_address_common(
5113 invoke_context,
5114 seeds,
5115 address,
5116 false,
5117 SyscallCreateProgramAddress::rust,
5118 )?;
5119 Ok(address)
5120 }
5121
5122 fn try_find_program_address<'a>(
5123 invoke_context: &mut InvokeContext<'a, 'a>,
5124 seeds: &[&[u8]],
5125 address: &Pubkey,
5126 ) -> Result<(Pubkey, u8), Error> {
5127 call_program_address_common(
5128 invoke_context,
5129 seeds,
5130 address,
5131 false,
5132 SyscallTryFindProgramAddress::rust,
5133 )
5134 }
5135
5136 #[test]
5137 fn test_set_and_get_return_data() {
5138 const SRC_VA: u64 = 0x100000000;
5139 const DST_VA: u64 = 0x200000000;
5140 const PROGRAM_ID_VA: u64 = 0x300000000;
5141 let data = [42; 24];
5142 let mut data_buffer = vec![0; 16];
5143 let mut id_buffer = vec![0; 32];
5144
5145 let config = Config::default();
5146 let memory_mapping = unsafe {
5147 MemoryMapping::new(
5148 vec![
5149 MemoryRegion::new(&raw const data, SRC_VA),
5150 MemoryRegion::new(&raw mut data_buffer[..], DST_VA),
5151 MemoryRegion::new(&raw mut id_buffer[..], PROGRAM_ID_VA),
5152 ],
5153 &config,
5154 SBPFVersion::V3,
5155 )
5156 .unwrap()
5157 };
5158
5159 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
5160 invoke_context
5161 .memory_contexts
5162 .mock_set_mapping_abi_v1(memory_mapping);
5163
5164 let result =
5165 SyscallSetReturnData::rust(&mut invoke_context, SRC_VA, data.len() as u64, 0, 0, 0);
5166 assert_eq!(result.unwrap(), 0);
5167
5168 let result = SyscallGetReturnData::rust(
5169 &mut invoke_context,
5170 DST_VA,
5171 data_buffer.len() as u64,
5172 PROGRAM_ID_VA,
5173 0,
5174 0,
5175 );
5176 assert_eq!(result.unwrap() as usize, data.len());
5177 assert_eq!(data.get(0..data_buffer.len()).unwrap(), data_buffer);
5178 assert_eq!(id_buffer, program_id.to_bytes());
5179
5180 let result = SyscallGetReturnData::rust(
5181 &mut invoke_context,
5182 PROGRAM_ID_VA,
5183 data_buffer.len() as u64,
5184 PROGRAM_ID_VA,
5185 0,
5186 0,
5187 );
5188 assert_matches!(
5189 result,
5190 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
5191 );
5192 }
5193
5194 #[test]
5195 fn test_syscall_sol_get_processed_sibling_instruction_top_level() {
5196 let transaction_accounts = (0..9)
5197 .map(|_| {
5198 (
5199 Pubkey::new_unique(),
5200 AccountSharedData::new(0, 0, &bpf_loader::id()),
5201 )
5202 })
5203 .collect::<Vec<_>>();
5204 with_mock_invoke_context!(invoke_context, transaction_context, 4, transaction_accounts);
5205
5206 let ixs = *b"ABCD";
5219 for (idx, ix) in ixs.iter().enumerate() {
5220 invoke_context
5221 .transaction_context
5222 .configure_top_level_instruction_for_tests(
5223 0,
5224 vec![InstructionAccount::new(idx as u16, false, false)],
5225 vec![*ix],
5226 )
5227 .unwrap();
5228 }
5229
5230 invoke_context.transaction_context.push(true).unwrap();
5238 invoke_context.transaction_context.pop().unwrap();
5239
5240 invoke_context.transaction_context.push(true).unwrap();
5242 invoke_context
5244 .transaction_context
5245 .configure_next_cpi_for_tests(
5246 1,
5247 vec![InstructionAccount::new(4, false, false)],
5248 vec![b'B', 1],
5249 )
5250 .unwrap();
5251 invoke_context.transaction_context.push(true).unwrap();
5252 invoke_context.transaction_context.pop().unwrap();
5253 invoke_context.transaction_context.pop().unwrap();
5254
5255 invoke_context.transaction_context.push(true).unwrap();
5257
5258 const VM_BASE_ADDRESS: u64 = 0x100000000;
5259 const META_OFFSET: usize = 0;
5260 const PROGRAM_ID_OFFSET: usize =
5261 META_OFFSET + std::mem::size_of::<ProcessedSiblingInstruction>();
5262 const DATA_OFFSET: usize = PROGRAM_ID_OFFSET + std::mem::size_of::<Pubkey>();
5263 const ACCOUNTS_OFFSET: usize = DATA_OFFSET + 0x100;
5264 const END_OFFSET: usize = ACCOUNTS_OFFSET + std::mem::size_of::<AccountInfo>() * 4;
5265 let mut memory = [0u8; END_OFFSET];
5266 let config = Config::default();
5267 let memory_mapping = unsafe {
5268 MemoryMapping::new(
5269 vec![MemoryRegion::new(&raw mut memory, VM_BASE_ADDRESS)],
5270 &config,
5271 SBPFVersion::V3,
5272 )
5273 .unwrap()
5274 };
5275 invoke_context
5276 .memory_contexts
5277 .mock_set_mapping_abi_v1(memory_mapping);
5278 let processed_sibling_instruction =
5279 unsafe { &mut *memory.as_mut_ptr().cast::<ProcessedSiblingInstruction>() };
5280 processed_sibling_instruction.data_len = 1;
5281 processed_sibling_instruction.accounts_len = 1;
5282
5283 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5284 invoke_context
5285 .compute_meter
5286 .mock_set_remaining(syscall_base_cost);
5287 let result = SyscallGetProcessedSiblingInstruction::rust(
5288 &mut invoke_context,
5289 0,
5290 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5291 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5292 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5293 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5294 );
5295 assert_eq!(result.unwrap(), 1);
5296 {
5297 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5298 let program_id = translate_type::<Pubkey>(
5299 memory_mapping,
5300 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5301 true,
5302 )
5303 .unwrap();
5304 let data = translate_slice::<u8>(
5305 memory_mapping,
5306 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5307 processed_sibling_instruction.data_len,
5308 true,
5309 )
5310 .unwrap();
5311 let accounts = translate_slice::<AccountMeta>(
5312 memory_mapping,
5313 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5314 processed_sibling_instruction.accounts_len,
5315 true,
5316 )
5317 .unwrap();
5318 let transaction_context = &invoke_context.transaction_context;
5319 assert_eq!(processed_sibling_instruction.data_len, 1);
5320 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5321 assert_eq!(
5322 program_id,
5323 transaction_context.get_key_of_account_at_index(0).unwrap(),
5324 );
5325 assert_eq!(data, b"B");
5326 assert_eq!(
5327 accounts,
5328 &[AccountMeta {
5329 pubkey: *transaction_context.get_key_of_account_at_index(1).unwrap(),
5330 is_signer: false,
5331 is_writable: false
5332 }]
5333 );
5334 }
5335
5336 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5337 invoke_context
5338 .compute_meter
5339 .mock_set_remaining(syscall_base_cost);
5340 let result = SyscallGetProcessedSiblingInstruction::rust(
5341 &mut invoke_context,
5342 1,
5343 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5344 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5345 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5346 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5347 );
5348
5349 assert_eq!(result.unwrap(), 1);
5350 {
5351 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5352 let program_id = translate_type::<Pubkey>(
5353 memory_mapping,
5354 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5355 true,
5356 )
5357 .unwrap();
5358 let data = translate_slice::<u8>(
5359 memory_mapping,
5360 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5361 processed_sibling_instruction.data_len,
5362 true,
5363 )
5364 .unwrap();
5365 let accounts = translate_slice::<AccountMeta>(
5366 memory_mapping,
5367 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5368 processed_sibling_instruction.accounts_len,
5369 true,
5370 )
5371 .unwrap();
5372 let transaction_context = &invoke_context.transaction_context;
5373 assert_eq!(processed_sibling_instruction.data_len, 1);
5374 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5375 assert_eq!(
5376 program_id,
5377 transaction_context.get_key_of_account_at_index(0).unwrap(),
5378 );
5379 assert_eq!(data, b"A");
5380 assert_eq!(
5381 accounts,
5382 &[AccountMeta {
5383 pubkey: *transaction_context.get_key_of_account_at_index(0).unwrap(),
5384 is_signer: false,
5385 is_writable: false
5386 }]
5387 );
5388 }
5389
5390 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5391 invoke_context
5392 .compute_meter
5393 .mock_set_remaining(syscall_base_cost);
5394 let result = SyscallGetProcessedSiblingInstruction::rust(
5395 &mut invoke_context,
5396 2,
5397 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5398 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5399 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5400 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5401 );
5402
5403 assert_eq!(result.unwrap(), 0);
5404
5405 invoke_context
5406 .compute_meter
5407 .mock_set_remaining(syscall_base_cost);
5408 let result = SyscallGetProcessedSiblingInstruction::rust(
5409 &mut invoke_context,
5410 0,
5411 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5412 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5413 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5414 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5415 );
5416 assert_matches!(
5417 result,
5418 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
5419 );
5420 }
5421
5422 #[test]
5423 fn test_syscall_sol_get_processed_sibling_instruction_cpi() {
5424 let transaction_accounts = (0..9)
5425 .map(|_| {
5426 (
5427 Pubkey::new_unique(),
5428 AccountSharedData::new(0, 0, &bpf_loader::id()),
5429 )
5430 })
5431 .collect::<Vec<_>>();
5432 with_mock_invoke_context!(invoke_context, transaction_context, 3, transaction_accounts);
5433
5434 const VM_BASE_ADDRESS: u64 = 0x100000000;
5435 const META_OFFSET: usize = 0;
5436 const PROGRAM_ID_OFFSET: usize =
5437 META_OFFSET + std::mem::size_of::<ProcessedSiblingInstruction>();
5438 const DATA_OFFSET: usize = PROGRAM_ID_OFFSET + std::mem::size_of::<Pubkey>();
5439 const ACCOUNTS_OFFSET: usize = DATA_OFFSET + 0x100;
5440 const END_OFFSET: usize = ACCOUNTS_OFFSET + std::mem::size_of::<AccountInfo>() * 4;
5441 let mut memory = [0u8; END_OFFSET];
5442 let config = Config::default();
5443 let memory_mapping = unsafe {
5444 MemoryMapping::new(
5445 vec![MemoryRegion::new(&raw mut memory, VM_BASE_ADDRESS)],
5446 &config,
5447 SBPFVersion::V3,
5448 )
5449 .unwrap()
5450 };
5451 invoke_context
5452 .memory_contexts
5453 .mock_set_mapping_abi_v1(memory_mapping);
5454 let processed_sibling_instruction =
5455 unsafe { &mut *memory.as_mut_ptr().cast::<ProcessedSiblingInstruction>() };
5456 processed_sibling_instruction.data_len = 2;
5457 processed_sibling_instruction.accounts_len = 1;
5458 let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
5459
5460 let top_level = *b"ABC";
5483 for (idx, ix) in top_level.iter().enumerate() {
5484 invoke_context
5485 .transaction_context
5486 .configure_top_level_instruction_for_tests(
5487 0,
5488 vec![InstructionAccount::new(idx as u16, false, false)],
5489 vec![*ix],
5490 )
5491 .unwrap();
5492 }
5493
5494 invoke_context.transaction_context.push(true).unwrap();
5502 invoke_context.transaction_context.pop().unwrap();
5503 invoke_context.transaction_context.push(true).unwrap();
5505 invoke_context
5507 .transaction_context
5508 .configure_next_cpi_for_tests(
5509 1,
5510 vec![InstructionAccount::new(1, false, false)],
5511 vec![b'B', 1],
5512 )
5513 .unwrap();
5514 invoke_context.transaction_context.push(true).unwrap();
5515 invoke_context
5517 .transaction_context
5518 .configure_next_cpi_for_tests(
5519 1,
5520 vec![InstructionAccount::new(2, false, false)],
5521 vec![b'B', 2],
5522 )
5523 .unwrap();
5524 invoke_context.transaction_context.push(true).unwrap();
5525 invoke_context.transaction_context.pop().unwrap();
5527 invoke_context.transaction_context.pop().unwrap();
5528 invoke_context
5530 .transaction_context
5531 .configure_next_cpi_for_tests(
5532 1,
5533 vec![InstructionAccount::new(3, false, false)],
5534 vec![b'B', 3],
5535 )
5536 .unwrap();
5537 invoke_context.transaction_context.push(true).unwrap();
5538 invoke_context.transaction_context.pop().unwrap();
5540 invoke_context
5542 .transaction_context
5543 .configure_next_cpi_for_tests(
5544 1,
5545 vec![InstructionAccount::new(4, false, false)],
5546 vec![b'B', 4],
5547 )
5548 .unwrap();
5549 invoke_context.transaction_context.push(true).unwrap();
5550 invoke_context
5552 .transaction_context
5553 .configure_next_cpi_for_tests(
5554 1,
5555 vec![InstructionAccount::new(5, false, false)],
5556 vec![b'B', 5],
5557 )
5558 .unwrap();
5559 invoke_context.transaction_context.push(true).unwrap();
5560
5561 invoke_context
5563 .compute_meter
5564 .mock_set_remaining(syscall_base_cost);
5565 let result = SyscallGetProcessedSiblingInstruction::rust(
5566 &mut invoke_context,
5567 0,
5568 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5569 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5570 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5571 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5572 );
5573 assert_eq!(result.unwrap(), 0);
5574
5575 invoke_context.transaction_context.pop().unwrap();
5577 invoke_context
5579 .transaction_context
5580 .configure_next_cpi_for_tests(
5581 2,
5582 vec![InstructionAccount::new(6, false, false)],
5583 vec![b'B', 6],
5584 )
5585 .unwrap();
5586 invoke_context.transaction_context.push(true).unwrap();
5587 invoke_context
5589 .transaction_context
5590 .configure_next_cpi_for_tests(
5591 1,
5592 vec![InstructionAccount::new(6, false, false)],
5593 vec![b'B', 7],
5594 )
5595 .unwrap();
5596 invoke_context.transaction_context.push(true).unwrap();
5597 invoke_context.transaction_context.pop().unwrap();
5599
5600 invoke_context
5602 .compute_meter
5603 .mock_set_remaining(syscall_base_cost);
5604 let result = SyscallGetProcessedSiblingInstruction::rust(
5605 &mut invoke_context,
5606 0,
5607 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5608 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5609 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5610 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5611 );
5612
5613 assert_eq!(result.unwrap(), 1);
5614 {
5615 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5616 let program_id = translate_type::<Pubkey>(
5617 memory_mapping,
5618 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5619 true,
5620 )
5621 .unwrap();
5622 let data = translate_slice::<u8>(
5623 memory_mapping,
5624 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5625 processed_sibling_instruction.data_len,
5626 true,
5627 )
5628 .unwrap();
5629 let accounts = translate_slice::<AccountMeta>(
5630 memory_mapping,
5631 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5632 processed_sibling_instruction.accounts_len,
5633 true,
5634 )
5635 .unwrap();
5636 let transaction_context = &invoke_context.transaction_context;
5637 assert_eq!(processed_sibling_instruction.data_len, 2);
5638 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5639 assert_eq!(
5640 program_id,
5641 transaction_context.get_key_of_account_at_index(1).unwrap(),
5642 );
5643 assert_eq!(data, &[b'B', 5]);
5644 assert_eq!(
5645 accounts,
5646 &[AccountMeta {
5647 pubkey: *transaction_context.get_key_of_account_at_index(5).unwrap(),
5648 is_signer: false,
5649 is_writable: false
5650 }]
5651 );
5652 }
5653
5654 invoke_context
5656 .compute_meter
5657 .mock_set_remaining(syscall_base_cost);
5658 let result = SyscallGetProcessedSiblingInstruction::rust(
5659 &mut invoke_context,
5660 1,
5661 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5662 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5663 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5664 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5665 );
5666 assert_eq!(result.unwrap(), 0);
5667
5668 invoke_context.transaction_context.pop().unwrap();
5670
5671 invoke_context
5673 .transaction_context
5674 .configure_next_cpi_for_tests(
5675 3,
5676 vec![InstructionAccount::new(8, false, false)],
5677 vec![b'B', 8],
5678 )
5679 .unwrap();
5680 invoke_context.transaction_context.push(true).unwrap();
5681
5682 invoke_context
5684 .compute_meter
5685 .mock_set_remaining(syscall_base_cost);
5686 let result = SyscallGetProcessedSiblingInstruction::rust(
5687 &mut invoke_context,
5688 0,
5689 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5690 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5691 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5692 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5693 );
5694
5695 assert_eq!(result.unwrap(), 1);
5696 {
5697 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5698 let program_id = translate_type::<Pubkey>(
5699 memory_mapping,
5700 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5701 true,
5702 )
5703 .unwrap();
5704 let data = translate_slice::<u8>(
5705 memory_mapping,
5706 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5707 processed_sibling_instruction.data_len,
5708 true,
5709 )
5710 .unwrap();
5711 let accounts = translate_slice::<AccountMeta>(
5712 memory_mapping,
5713 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5714 processed_sibling_instruction.accounts_len,
5715 true,
5716 )
5717 .unwrap();
5718 let transaction_context = &invoke_context.transaction_context;
5719 assert_eq!(processed_sibling_instruction.data_len, 2);
5720 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5721 assert_eq!(
5722 program_id,
5723 transaction_context.get_key_of_account_at_index(2).unwrap(),
5724 );
5725 assert_eq!(data, &[b'B', 6]);
5726 assert_eq!(
5727 accounts,
5728 &[AccountMeta {
5729 pubkey: *transaction_context.get_key_of_account_at_index(6).unwrap(),
5730 is_signer: false,
5731 is_writable: false
5732 }]
5733 );
5734 }
5735
5736 invoke_context
5738 .compute_meter
5739 .mock_set_remaining(syscall_base_cost);
5740 let result = SyscallGetProcessedSiblingInstruction::rust(
5741 &mut invoke_context,
5742 1,
5743 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5744 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5745 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5746 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5747 );
5748
5749 assert_eq!(result.unwrap(), 1);
5750 {
5751 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5752 let program_id = translate_type::<Pubkey>(
5753 memory_mapping,
5754 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5755 true,
5756 )
5757 .unwrap();
5758 let data = translate_slice::<u8>(
5759 memory_mapping,
5760 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5761 processed_sibling_instruction.data_len,
5762 true,
5763 )
5764 .unwrap();
5765 let accounts = translate_slice::<AccountMeta>(
5766 memory_mapping,
5767 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5768 processed_sibling_instruction.accounts_len,
5769 true,
5770 )
5771 .unwrap();
5772 let transaction_context = &invoke_context.transaction_context;
5773 assert_eq!(processed_sibling_instruction.data_len, 2);
5774 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5775 assert_eq!(
5776 program_id,
5777 transaction_context.get_key_of_account_at_index(1).unwrap(),
5778 );
5779 assert_eq!(data, &[b'B', 5]);
5780 assert_eq!(
5781 accounts,
5782 &[AccountMeta {
5783 pubkey: *transaction_context.get_key_of_account_at_index(5).unwrap(),
5784 is_signer: false,
5785 is_writable: false
5786 }]
5787 );
5788 }
5789
5790 invoke_context
5792 .compute_meter
5793 .mock_set_remaining(syscall_base_cost);
5794 let result = SyscallGetProcessedSiblingInstruction::rust(
5795 &mut invoke_context,
5796 2,
5797 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5798 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5799 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5800 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5801 );
5802 assert_eq!(result.unwrap(), 0);
5803
5804 invoke_context.transaction_context.pop().unwrap();
5806 invoke_context.transaction_context.pop().unwrap();
5808 invoke_context.transaction_context.pop().unwrap();
5810
5811 invoke_context.transaction_context.push(true).unwrap();
5813
5814 invoke_context
5816 .compute_meter
5817 .mock_set_remaining(syscall_base_cost);
5818 processed_sibling_instruction.data_len = 1;
5819 let result = SyscallGetProcessedSiblingInstruction::rust(
5820 &mut invoke_context,
5821 0,
5822 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5823 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5824 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5825 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5826 );
5827
5828 assert_eq!(result.unwrap(), 1);
5829 {
5830 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5831 let program_id = translate_type::<Pubkey>(
5832 memory_mapping,
5833 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5834 true,
5835 )
5836 .unwrap();
5837 let data = translate_slice::<u8>(
5838 memory_mapping,
5839 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5840 processed_sibling_instruction.data_len,
5841 true,
5842 )
5843 .unwrap();
5844 let accounts = translate_slice::<AccountMeta>(
5845 memory_mapping,
5846 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5847 processed_sibling_instruction.accounts_len,
5848 true,
5849 )
5850 .unwrap();
5851 let transaction_context = &invoke_context.transaction_context;
5852 assert_eq!(processed_sibling_instruction.data_len, 1);
5853 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5854 assert_eq!(
5855 program_id,
5856 transaction_context.get_key_of_account_at_index(0).unwrap(),
5857 );
5858 assert_eq!(data, b"B");
5859 assert_eq!(
5860 accounts,
5861 &[AccountMeta {
5862 pubkey: *transaction_context.get_key_of_account_at_index(1).unwrap(),
5863 is_signer: false,
5864 is_writable: false
5865 }]
5866 );
5867 }
5868
5869 invoke_context
5871 .transaction_context
5872 .configure_next_cpi_for_tests(
5873 2,
5874 vec![InstructionAccount::new(7, false, false)],
5875 vec![b'C', 1],
5876 )
5877 .unwrap();
5878 invoke_context.transaction_context.push(true).unwrap();
5879
5880 invoke_context
5882 .compute_meter
5883 .mock_set_remaining(syscall_base_cost);
5884 let result = SyscallGetProcessedSiblingInstruction::rust(
5885 &mut invoke_context,
5886 0,
5887 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5888 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5889 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5890 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5891 );
5892 assert_eq!(result.unwrap(), 0);
5893
5894 invoke_context.transaction_context.pop().unwrap();
5896 invoke_context
5898 .transaction_context
5899 .configure_next_cpi_for_tests(
5900 2,
5901 vec![InstructionAccount::new(7, false, false)],
5902 vec![b'C', 2],
5903 )
5904 .unwrap();
5905 invoke_context.transaction_context.push(true).unwrap();
5906
5907 invoke_context
5909 .compute_meter
5910 .mock_set_remaining(syscall_base_cost);
5911 processed_sibling_instruction.data_len = 2;
5912 let result = SyscallGetProcessedSiblingInstruction::rust(
5913 &mut invoke_context,
5914 0,
5915 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5916 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5917 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5918 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5919 );
5920
5921 assert_eq!(result.unwrap(), 1);
5922 {
5923 let memory_mapping = invoke_context.memory_contexts.memory_mapping().unwrap();
5924 let program_id = translate_type::<Pubkey>(
5925 memory_mapping,
5926 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5927 true,
5928 )
5929 .unwrap();
5930 let data = translate_slice::<u8>(
5931 memory_mapping,
5932 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5933 processed_sibling_instruction.data_len,
5934 true,
5935 )
5936 .unwrap();
5937 let accounts = translate_slice::<AccountMeta>(
5938 memory_mapping,
5939 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5940 processed_sibling_instruction.accounts_len,
5941 true,
5942 )
5943 .unwrap();
5944 let transaction_context = &invoke_context.transaction_context;
5945 assert_eq!(processed_sibling_instruction.data_len, 2);
5946 assert_eq!(processed_sibling_instruction.accounts_len, 1);
5947 assert_eq!(
5948 program_id,
5949 transaction_context.get_key_of_account_at_index(2).unwrap(),
5950 );
5951 assert_eq!(data, &[b'C', 1]);
5952 assert_eq!(
5953 accounts,
5954 &[AccountMeta {
5955 pubkey: *transaction_context.get_key_of_account_at_index(7).unwrap(),
5956 is_signer: false,
5957 is_writable: false
5958 }]
5959 );
5960 }
5961
5962 invoke_context
5964 .compute_meter
5965 .mock_set_remaining(syscall_base_cost);
5966 let result = SyscallGetProcessedSiblingInstruction::rust(
5967 &mut invoke_context,
5968 1,
5969 VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
5970 VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
5971 VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
5972 VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
5973 );
5974 assert_eq!(result.unwrap(), 0);
5975 }
5976
5977 #[test]
5978 fn test_create_program_address() {
5979 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
5982 let address = bpf_loader_upgradeable::id();
5983
5984 let exceeded_seed = &[127; MAX_SEED_LEN + 1];
5985 assert_matches!(
5986 create_program_address(&mut invoke_context, &[exceeded_seed], &address),
5987 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
5988 );
5989 assert_matches!(
5990 create_program_address(
5991 &mut invoke_context,
5992 &[b"short_seed", exceeded_seed],
5993 &address,
5994 ),
5995 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
5996 );
5997 let max_seed = &[0; MAX_SEED_LEN];
5998 assert!(create_program_address(&mut invoke_context, &[max_seed], &address).is_ok());
5999 let exceeded_seeds: &[&[u8]] = &[
6000 &[1],
6001 &[2],
6002 &[3],
6003 &[4],
6004 &[5],
6005 &[6],
6006 &[7],
6007 &[8],
6008 &[9],
6009 &[10],
6010 &[11],
6011 &[12],
6012 &[13],
6013 &[14],
6014 &[15],
6015 &[16],
6016 ];
6017 assert!(create_program_address(&mut invoke_context, exceeded_seeds, &address).is_ok());
6018 let max_seeds: &[&[u8]] = &[
6019 &[1],
6020 &[2],
6021 &[3],
6022 &[4],
6023 &[5],
6024 &[6],
6025 &[7],
6026 &[8],
6027 &[9],
6028 &[10],
6029 &[11],
6030 &[12],
6031 &[13],
6032 &[14],
6033 &[15],
6034 &[16],
6035 &[17],
6036 ];
6037 assert_matches!(
6038 create_program_address(&mut invoke_context, max_seeds, &address),
6039 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6040 );
6041 assert_eq!(
6042 create_program_address(&mut invoke_context, &[b"", &[1]], &address).unwrap(),
6043 "BwqrghZA2htAcqq8dzP1WDAhTXYTYWj7CHxF5j7TDBAe"
6044 .parse()
6045 .unwrap(),
6046 );
6047 assert_eq!(
6048 create_program_address(&mut invoke_context, &["☉".as_ref(), &[0]], &address).unwrap(),
6049 "13yWmRpaTR4r5nAktwLqMpRNr28tnVUZw26rTvPSSB19"
6050 .parse()
6051 .unwrap(),
6052 );
6053 assert_eq!(
6054 create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
6055 .unwrap(),
6056 "2fnQrngrQT4SeLcdToJAD96phoEjNL2man2kfRLCASVk"
6057 .parse()
6058 .unwrap(),
6059 );
6060 let public_key = Pubkey::from_str("SeedPubey1111111111111111111111111111111111").unwrap();
6061 assert_eq!(
6062 create_program_address(&mut invoke_context, &[public_key.as_ref(), &[1]], &address)
6063 .unwrap(),
6064 "976ymqVnfE32QFe6NfGDctSvVa36LWnvYxhU6G2232YL"
6065 .parse()
6066 .unwrap(),
6067 );
6068 assert_ne!(
6069 create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
6070 .unwrap(),
6071 create_program_address(&mut invoke_context, &[b"Talking"], &address).unwrap(),
6072 );
6073 invoke_context.compute_meter.mock_set_remaining(0);
6074 assert_matches!(
6075 create_program_address(&mut invoke_context, &[b"", &[1]], &address),
6076 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
6077 );
6078 }
6079
6080 #[test]
6081 fn test_find_program_address() {
6082 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6083 let cost = invoke_context
6084 .get_execution_cost()
6085 .create_program_address_units;
6086 let address = bpf_loader_upgradeable::id();
6087 let max_tries = 256; for _ in 0..1_000 {
6090 let address = Pubkey::new_unique();
6091 invoke_context
6092 .compute_meter
6093 .mock_set_remaining(cost * max_tries);
6094 let (found_address, bump_seed) =
6095 try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address)
6096 .unwrap();
6097 assert_eq!(
6098 found_address,
6099 create_program_address(
6100 &mut invoke_context,
6101 &[b"Lil'", b"Bits", &[bump_seed]],
6102 &address,
6103 )
6104 .unwrap()
6105 );
6106 }
6107
6108 let seeds: &[&[u8]] = &[b""];
6109 invoke_context
6110 .compute_meter
6111 .mock_set_remaining(cost * max_tries);
6112 let (_, bump_seed) =
6113 try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
6114 invoke_context
6115 .compute_meter
6116 .mock_set_remaining(cost * (max_tries - bump_seed as u64));
6117 try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
6118 invoke_context
6119 .compute_meter
6120 .mock_set_remaining(cost * (max_tries - bump_seed as u64 - 1));
6121 assert_matches!(
6122 try_find_program_address(&mut invoke_context, seeds, &address),
6123 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
6124 );
6125
6126 let exceeded_seed = &[127; MAX_SEED_LEN + 1];
6127 invoke_context
6128 .compute_meter
6129 .mock_set_remaining(cost * (max_tries - 1));
6130 assert_matches!(
6131 try_find_program_address(&mut invoke_context, &[exceeded_seed], &address),
6132 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6133 );
6134 let exceeded_seeds: &[&[u8]] = &[
6135 &[1],
6136 &[2],
6137 &[3],
6138 &[4],
6139 &[5],
6140 &[6],
6141 &[7],
6142 &[8],
6143 &[9],
6144 &[10],
6145 &[11],
6146 &[12],
6147 &[13],
6148 &[14],
6149 &[15],
6150 &[16],
6151 &[17],
6152 ];
6153 invoke_context
6154 .compute_meter
6155 .mock_set_remaining(cost * (max_tries - 1));
6156 assert_matches!(
6157 try_find_program_address(&mut invoke_context, exceeded_seeds, &address),
6158 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
6159 );
6160
6161 assert_matches!(
6162 call_program_address_common(
6163 &mut invoke_context,
6164 seeds,
6165 &address,
6166 true,
6167 SyscallTryFindProgramAddress::rust,
6168 ),
6169 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
6170 );
6171 }
6172
6173 #[test]
6174 fn test_syscall_big_mod_exp() {
6175 let config = Config::default();
6176 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6177
6178 const VADDR_PARAMS: u64 = 0x100000000;
6179 const VADDR_BASE: u64 = 0x200000000;
6180 const VADDR_EXPONENT: u64 = 0x300000000;
6181 const VADDR_MODULUS: u64 = 0x400000000;
6182 const VADDR_OUT: u64 = 0x500000000;
6183
6184 let base = [0x03];
6185 let exponent = [
6186 0x2e, 0xfc, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6187 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6188 0xff, 0xff, 0xff, 0xff,
6189 ];
6190 let modulus = [
6191 0x2f, 0xfc, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6192 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6193 0xff, 0xff, 0xff, 0xff,
6194 ];
6195 let mut data_out = [0u8; 32];
6196 let mut expected = [0u8; 32];
6197 expected[0] = 1;
6198 assert_eq!(
6199 big_mod_exp(&base, &exponent, &modulus),
6200 Some(expected.to_vec())
6201 );
6202 let params = BigModExpParams {
6203 base: VADDR_BASE,
6204 base_len: base.len() as u64,
6205 exponent: VADDR_EXPONENT,
6206 exponent_len: exponent.len() as u64,
6207 modulus: VADDR_MODULUS,
6208 modulus_len: modulus.len() as u64,
6209 };
6210
6211 let memory_mapping = unsafe {
6212 MemoryMapping::new(
6213 vec![
6214 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6215 MemoryRegion::new(bytes_of_slice(&base), VADDR_BASE),
6216 MemoryRegion::new(bytes_of_slice(&exponent), VADDR_EXPONENT),
6217 MemoryRegion::new(bytes_of_slice(&modulus), VADDR_MODULUS),
6218 MemoryRegion::new(bytes_of_slice_mut(&mut data_out), VADDR_OUT),
6219 ],
6220 &config,
6221 SBPFVersion::V3,
6222 )
6223 .unwrap()
6224 };
6225 invoke_context
6226 .memory_contexts
6227 .mock_set_mapping_abi_v1(memory_mapping);
6228 let budget = invoke_context.get_execution_cost();
6229 let cost = budget.big_modular_exponentiation_base_cost
6230 + big_mod_exp_operation_cost(
6231 budget.big_modular_exponentiation_cost_divisor,
6232 ¶ms,
6233 &exponent,
6234 )
6235 .unwrap();
6236 invoke_context.compute_meter.mock_set_remaining(cost);
6237
6238 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_OUT, 0, 0, 0);
6239
6240 assert_eq!(result.unwrap(), SUCCESS);
6241 assert_eq!(data_out, expected);
6242 }
6243
6244 #[test]
6245 fn test_syscall_big_mod_exp_invalid_modulus() {
6246 let config = Config::default();
6247 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6248
6249 const VADDR_PARAMS: u64 = 0x100000000;
6250 const VADDR_BASE: u64 = 0x200000000;
6251 const VADDR_EXPONENT: u64 = 0x300000000;
6252 const VADDR_MODULUS: u64 = 0x400000000;
6253 const VADDR_OUT: u64 = 0x500000000;
6254
6255 let base = [0x05];
6256 let exponent = [0x02];
6257 let modulus = [0x02];
6258 let mut data_out = [0u8; 1];
6259 let params = BigModExpParams {
6260 base: VADDR_BASE,
6261 base_len: base.len() as u64,
6262 exponent: VADDR_EXPONENT,
6263 exponent_len: exponent.len() as u64,
6264 modulus: VADDR_MODULUS,
6265 modulus_len: modulus.len() as u64,
6266 };
6267
6268 let memory_mapping = unsafe {
6269 MemoryMapping::new(
6270 vec![
6271 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6272 MemoryRegion::new(bytes_of_slice(&base), VADDR_BASE),
6273 MemoryRegion::new(bytes_of_slice(&exponent), VADDR_EXPONENT),
6274 MemoryRegion::new(bytes_of_slice(&modulus), VADDR_MODULUS),
6275 MemoryRegion::new(bytes_of_slice_mut(&mut data_out), VADDR_OUT),
6276 ],
6277 &config,
6278 SBPFVersion::V3,
6279 )
6280 .unwrap()
6281 };
6282 invoke_context
6283 .memory_contexts
6284 .mock_set_mapping_abi_v1(memory_mapping);
6285 let budget = invoke_context.get_execution_cost();
6286 let cost = budget.big_modular_exponentiation_base_cost
6287 + big_mod_exp_operation_cost(
6288 budget.big_modular_exponentiation_cost_divisor,
6289 ¶ms,
6290 &exponent,
6291 )
6292 .unwrap();
6293 invoke_context.compute_meter.mock_set_remaining(cost);
6294
6295 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_OUT, 0, 0, 0);
6296
6297 assert_matches!(
6298 result,
6299 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::InvalidAttribute
6300 );
6301 assert_eq!(data_out, [0x00]);
6302 }
6303
6304 #[test]
6305 fn test_syscall_big_mod_exp_overlapping_result() {
6306 let config = Config::default();
6307 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6308
6309 const VADDR_PARAMS: u64 = 0x100000000;
6310 const VADDR_BASE: u64 = 0x200000000;
6311 const VADDR_EXPONENT: u64 = 0x300000000;
6312 const VADDR_MODULUS: u64 = 0x400000000;
6313 let mut base = [0x05];
6314 let exponent = [0x02];
6315 let modulus = [0x07];
6316 assert_eq!(big_mod_exp(&[0x05], &[0x02], &[0x07]), Some(vec![0x04]));
6317 let params = BigModExpParams {
6318 base: VADDR_BASE,
6319 base_len: 1,
6320 exponent: VADDR_EXPONENT,
6321 exponent_len: 1,
6322 modulus: VADDR_MODULUS,
6323 modulus_len: 1,
6324 };
6325
6326 let memory_mapping = unsafe {
6327 MemoryMapping::new(
6328 vec![
6329 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6330 MemoryRegion::new(bytes_of_slice_mut(&mut base), VADDR_BASE),
6331 MemoryRegion::new(bytes_of_slice(&exponent), VADDR_EXPONENT),
6332 MemoryRegion::new(bytes_of_slice(&modulus), VADDR_MODULUS),
6333 ],
6334 &config,
6335 SBPFVersion::V3,
6336 )
6337 .unwrap()
6338 };
6339 invoke_context
6340 .memory_contexts
6341 .mock_set_mapping_abi_v1(memory_mapping);
6342 let budget = invoke_context.get_execution_cost();
6343 let cost = budget.big_modular_exponentiation_base_cost
6344 + big_mod_exp_operation_cost(
6345 budget.big_modular_exponentiation_cost_divisor,
6346 ¶ms,
6347 &exponent,
6348 )
6349 .unwrap();
6350 invoke_context.compute_meter.mock_set_remaining(cost);
6351
6352 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_BASE, 0, 0, 0);
6353
6354 assert_eq!(result.unwrap(), SUCCESS);
6355 assert_eq!(base, [0x04]);
6356 }
6357
6358 #[test]
6359 fn test_syscall_big_mod_exp_abort_conditions() {
6360 let config = Config::default();
6361 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6362
6363 const VADDR_PARAMS: u64 = 0x100000000;
6364 const VADDR_DATA: u64 = 0x200000000;
6365 const VADDR_OUT: u64 = 0x300000000;
6366 let data = [0u8; 1];
6367 let mut data_out = [0u8; 1];
6368 let params = BigModExpParams {
6369 base: VADDR_DATA,
6370 base_len: BIG_MOD_EXP_MAX_BYTES + 1,
6371 exponent: VADDR_DATA,
6372 exponent_len: 0,
6373 modulus: VADDR_DATA,
6374 modulus_len: 1,
6375 };
6376
6377 let memory_mapping = unsafe {
6378 MemoryMapping::new(
6379 vec![
6380 MemoryRegion::new(bytes_of(¶ms), VADDR_PARAMS),
6381 MemoryRegion::new(bytes_of_slice(&data), VADDR_DATA),
6382 MemoryRegion::new(bytes_of_slice_mut(&mut data_out), VADDR_OUT),
6383 ],
6384 &config,
6385 SBPFVersion::V3,
6386 )
6387 .unwrap()
6388 };
6389 invoke_context
6390 .memory_contexts
6391 .mock_set_mapping_abi_v1(memory_mapping);
6392
6393 let result = SyscallBigModExp::rust(&mut invoke_context, VADDR_PARAMS, VADDR_OUT, 0, 0, 0);
6394 assert_matches!(
6395 result,
6396 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::InvalidLength
6397 );
6398 }
6399
6400 #[test]
6401 fn test_syscall_get_epoch_stake_total_stake() {
6402 let config = Config::default();
6403 let compute_cost = SVMTransactionExecutionCost::default();
6404 let mut compute_budget = SVMTransactionExecutionBudget::default();
6405 let sysvar_cache = Arc::<SysvarCache>::default();
6406
6407 const EXPECTED_TOTAL_STAKE: u64 = 200_000_000_000_000;
6408
6409 struct MockCallback {}
6410 impl InvokeContextCallback for MockCallback {
6411 fn get_epoch_stake(&self) -> u64 {
6412 EXPECTED_TOTAL_STAKE
6413 }
6414 }
6416
6417 let expected_cus = compute_cost.syscall_base_cost;
6420
6421 compute_budget.compute_unit_limit = expected_cus;
6424
6425 with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
6426 let feature_set = SVMFeatureSet::default();
6427 let program_runtime_environments = ProgramRuntimeEnvironments::mock();
6428 invoke_context.environment_config = EnvironmentConfig::new(
6429 Hash::default(),
6430 0,
6431 false,
6432 &MockCallback {},
6433 &feature_set,
6434 &program_runtime_environments,
6435 &sysvar_cache,
6436 );
6437 invoke_context
6438 .compute_meter
6439 .mock_set_remaining(compute_budget.compute_unit_limit);
6440
6441 let null_pointer_var = std::ptr::null::<Pubkey>() as u64;
6442
6443 let memory_mapping =
6444 unsafe { MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap() };
6445 invoke_context
6446 .memory_contexts
6447 .mock_set_mapping_abi_v1(memory_mapping);
6448
6449 let result =
6450 SyscallGetEpochStake::rust(&mut invoke_context, null_pointer_var, 0, 0, 0, 0).unwrap();
6451
6452 assert_eq!(result, EXPECTED_TOTAL_STAKE);
6453 }
6454
6455 #[test]
6456 fn test_syscall_get_epoch_stake_vote_account_stake() {
6457 let config = Config::default();
6458 let mut compute_budget = SVMTransactionExecutionBudget::default();
6459 let compute_cost = SVMTransactionExecutionCost::default();
6460 let sysvar_cache = Arc::<SysvarCache>::default();
6461
6462 const TARGET_VOTE_ADDRESS: Pubkey = Pubkey::new_from_array([2; 32]);
6463 const EXPECTED_EPOCH_STAKE: u64 = 55_000_000_000;
6464
6465 struct MockCallback {}
6466 impl InvokeContextCallback for MockCallback {
6467 fn get_epoch_stake_for_vote_account(&self, vote_address: &Pubkey) -> u64 {
6469 if *vote_address == TARGET_VOTE_ADDRESS {
6470 EXPECTED_EPOCH_STAKE
6471 } else {
6472 0
6473 }
6474 }
6475 }
6476
6477 let expected_cus = compute_cost.syscall_base_cost
6482 + (PUBKEY_BYTES as u64) / compute_cost.cpi_bytes_per_unit
6483 + compute_cost.mem_op_base_cost;
6484
6485 compute_budget.compute_unit_limit = expected_cus;
6488
6489 with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
6490 let feature_set = SVMFeatureSet::default();
6491 let program_runtime_environments = ProgramRuntimeEnvironments::mock();
6492 invoke_context.environment_config = EnvironmentConfig::new(
6493 Hash::default(),
6494 0,
6495 false,
6496 &MockCallback {},
6497 &feature_set,
6498 &program_runtime_environments,
6499 &sysvar_cache,
6500 );
6501
6502 {
6503 let vote_address_var = 0x100000000;
6506 let memory = [2; 31];
6507
6508 let memory_mapping = unsafe {
6509 MemoryMapping::new(
6510 vec![
6511 MemoryRegion::new(&raw const memory, vote_address_var),
6513 ],
6514 &config,
6515 SBPFVersion::V3,
6516 )
6517 .unwrap()
6518 };
6519 invoke_context
6520 .memory_contexts
6521 .mock_set_mapping_abi_v1(memory_mapping);
6522
6523 let result =
6524 SyscallGetEpochStake::rust(&mut invoke_context, vote_address_var, 0, 0, 0, 0);
6525
6526 assert_access_violation!(result, vote_address_var, 32);
6527 }
6528
6529 invoke_context
6530 .compute_meter
6531 .mock_set_remaining(compute_budget.compute_unit_limit);
6532 {
6533 let vote_address_var = 0x100000000;
6537
6538 let memory_mapping = unsafe {
6539 MemoryMapping::new(
6540 vec![MemoryRegion::new(
6541 bytes_of(&TARGET_VOTE_ADDRESS),
6542 vote_address_var,
6543 )],
6544 &config,
6545 SBPFVersion::V3,
6546 )
6547 .unwrap()
6548 };
6549 invoke_context
6550 .memory_contexts
6551 .mock_set_mapping_abi_v1(memory_mapping);
6552
6553 let result =
6554 SyscallGetEpochStake::rust(&mut invoke_context, vote_address_var, 0, 0, 0, 0)
6555 .unwrap();
6556
6557 assert_eq!(result, EXPECTED_EPOCH_STAKE);
6558 }
6559
6560 invoke_context
6561 .compute_meter
6562 .mock_set_remaining(compute_budget.compute_unit_limit);
6563 {
6564 let vote_address_var = 0x100000000;
6568 let not_a_vote_address = Pubkey::new_unique(); let memory_mapping = unsafe {
6571 MemoryMapping::new(
6572 vec![MemoryRegion::new(
6573 bytes_of(¬_a_vote_address),
6574 vote_address_var,
6575 )],
6576 &config,
6577 SBPFVersion::V3,
6578 )
6579 .unwrap()
6580 };
6581 invoke_context
6582 .memory_contexts
6583 .mock_set_mapping_abi_v1(memory_mapping);
6584
6585 let result =
6586 SyscallGetEpochStake::rust(&mut invoke_context, vote_address_var, 0, 0, 0, 0)
6587 .unwrap();
6588
6589 assert_eq!(result, 0); }
6591 }
6592
6593 #[test]
6594 fn test_check_type_assumptions() {
6595 check_type_assumptions();
6596 }
6597
6598 fn bytes_of<T>(val: &T) -> *const [u8] {
6599 let size = mem::size_of::<T>();
6600 core::ptr::slice_from_raw_parts(std::slice::from_ref(val).as_ptr().cast(), size)
6601 }
6602
6603 fn bytes_of_mut<T>(val: &mut T) -> *mut [u8] {
6604 let size = mem::size_of::<T>();
6605 core::ptr::slice_from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size)
6606 }
6607
6608 fn bytes_of_slice<T>(val: &[T]) -> *const [u8] {
6609 let size = val.len().wrapping_mul(mem::size_of::<T>());
6610 core::ptr::slice_from_raw_parts(val.as_ptr().cast(), size)
6611 }
6612
6613 fn bytes_of_slice_mut<T>(val: &mut [T]) -> *mut [u8] {
6614 let size = val.len().wrapping_mul(mem::size_of::<T>());
6615 core::ptr::slice_from_raw_parts_mut(val.as_mut_ptr().cast(), size)
6616 }
6617
6618 #[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]) {
6625 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6626 let mem = (0..12).collect::<Vec<u8>>();
6627 let mut result_mem = vec![0; 4];
6628 let config = Config::default();
6629 let memory_mapping = unsafe {
6630 MemoryMapping::new(
6631 vec![
6632 MemoryRegion::new(&raw const mem[..], 0x100000000),
6633 MemoryRegion::new(&raw const mem[..], 0x200000000),
6634 MemoryRegion::new(&raw mut result_mem[..], 0x300000000),
6635 ],
6636 &config,
6637 SBPFVersion::V3,
6638 )
6639 .unwrap()
6640 };
6641 invoke_context
6642 .memory_contexts
6643 .mock_set_mapping_abi_v1(memory_mapping);
6644
6645 let result = SyscallMemcmp::rust(&mut invoke_context, src_a, src_b, 4, 0x300000000, 0);
6646 result.unwrap();
6647 assert_eq!(result_mem, expected_result);
6648 }
6649
6650 #[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) {
6659 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6660 let mut mem = (0..24).collect::<Vec<u8>>();
6661 let config = Config::default();
6662 let memory_mapping = unsafe {
6663 MemoryMapping::new(
6664 vec![
6665 MemoryRegion::new(&raw mut mem[..12], 0x100000000),
6666 MemoryRegion::new(&raw mut mem[12..], 0x200000000),
6667 ],
6668 &config,
6669 SBPFVersion::V3,
6670 )
6671 .unwrap()
6672 };
6673 invoke_context
6674 .memory_contexts
6675 .mock_set_mapping_abi_v1(memory_mapping);
6676
6677 let result = SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0);
6678 result.unwrap();
6679 let mut hasher = DefaultHasher::new();
6680 mem.hash(&mut hasher);
6681 assert_eq!(hasher.finish(), expected_hash);
6682 }
6683
6684 #[test_case(0x100000002, 0x00, 6070675560359421890)]
6685 #[test_case(0x100000002, 0xFF, 3413209638111181029)]
6686 fn test_memset_success(dst: u64, value: u64, expected_hash: u64) {
6687 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6688 let mut mem = (0..12).collect::<Vec<u8>>();
6689 let config = Config::default();
6690 let memory_mapping = unsafe {
6691 MemoryMapping::new(
6692 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6693 &config,
6694 SBPFVersion::V3,
6695 )
6696 .unwrap()
6697 };
6698 invoke_context
6699 .memory_contexts
6700 .mock_set_mapping_abi_v1(memory_mapping);
6701
6702 let result = SyscallMemset::rust(&mut invoke_context, dst, value, 4, 0, 0);
6703 result.unwrap();
6704 let mut hasher = DefaultHasher::new();
6705 mem.hash(&mut hasher);
6706 assert_eq!(hasher.finish(), expected_hash);
6707 }
6708
6709 #[test_case(0x100000002, 0x100000004)] #[test_case(0x100000004, 0x100000002)] fn test_memcpy_overlapping(dst: u64, src: u64) {
6712 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6713 let mut mem = (0..12).collect::<Vec<u8>>();
6714 let config = Config::default();
6715 let memory_mapping = unsafe {
6716 MemoryMapping::new(
6717 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6718 &config,
6719 SBPFVersion::V3,
6720 )
6721 .unwrap()
6722 };
6723 invoke_context
6724 .memory_contexts
6725 .mock_set_mapping_abi_v1(memory_mapping);
6726
6727 let result = SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0);
6728 assert_matches!(
6729 result,
6730 Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
6731 );
6732 }
6733
6734 #[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) {
6739 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6740 let mut mem = (0..12).collect::<Vec<u8>>();
6741 let config = Config::default();
6742 let memory_mapping = unsafe {
6743 MemoryMapping::new(
6744 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6745 &config,
6746 SBPFVersion::V3,
6747 )
6748 .unwrap()
6749 };
6750 invoke_context
6751 .memory_contexts
6752 .mock_set_mapping_abi_v1(memory_mapping);
6753
6754 let result = SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0);
6755 assert_access_violation!(result, fault_address, 4);
6756 let result = SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0);
6757 assert_access_violation!(result, fault_address, 4);
6758 let result = SyscallMemcmp::rust(&mut invoke_context, dst, src, 4, 0, 0);
6759 assert_access_violation!(result, fault_address, 4);
6760 }
6761
6762 #[test_case(0xFFFFFFFFF)] #[test_case(0x100000010)] fn test_memset_access_violation(dst: u64) {
6765 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6766 let mut mem = (0..12).collect::<Vec<u8>>();
6767 let config = Config::default();
6768 let memory_mapping = unsafe {
6769 MemoryMapping::new(
6770 vec![MemoryRegion::new(&raw mut mem[..], 0x100000000)],
6771 &config,
6772 SBPFVersion::V3,
6773 )
6774 .unwrap()
6775 };
6776 invoke_context
6777 .memory_contexts
6778 .mock_set_mapping_abi_v1(memory_mapping);
6779
6780 let result = SyscallMemset::rust(&mut invoke_context, dst, 0, 4, 0, 0);
6781 assert_access_violation!(result, dst, 4);
6782 }
6783
6784 #[test]
6785 fn test_memcmp_result_access_violation() {
6786 prepare_mockup!(invoke_context, program_id, bpf_loader::id());
6787 let mem = (0..12).collect::<Vec<u8>>();
6788 let config = Config::default();
6789 let memory_mapping = unsafe {
6790 MemoryMapping::new(
6791 vec![MemoryRegion::new(&raw const mem[..], 0x100000000)],
6792 &config,
6793 SBPFVersion::V3,
6794 )
6795 .unwrap()
6796 };
6797 invoke_context
6798 .memory_contexts
6799 .mock_set_mapping_abi_v1(memory_mapping);
6800
6801 let result = SyscallMemcmp::rust(
6802 &mut invoke_context,
6803 0x100000000,
6804 0x100000000,
6805 4,
6806 0x100000000,
6807 0,
6808 );
6809 assert_access_violation!(result, 0x100000000, 4);
6810 }
6811
6812 #[test]
6813 fn test_syscall_bls12_381_g1_add() {
6814 use {
6815 solana_curve25519::curve_syscall_traits::ADD,
6816 solana_define_syscall::curve_constants::{BLS12_381_G1_BE, BLS12_381_G1_LE},
6817 };
6818
6819 let config = Config::default();
6820 let feature_set = SVMFeatureSet {
6821 enable_bls12_381_syscall: true,
6822 ..Default::default()
6823 };
6824 let feature_set = &feature_set;
6825 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
6826
6827 let p1_bytes_be: [u8; 96] = [
6828 9, 86, 169, 212, 236, 245, 17, 101, 127, 183, 56, 13, 99, 100, 183, 133, 57, 107, 96,
6829 220, 198, 197, 2, 215, 225, 175, 212, 57, 168, 143, 104, 127, 117, 242, 180, 200, 162,
6830 135, 72, 155, 88, 154, 58, 90, 58, 46, 248, 176, 10, 206, 25, 112, 240, 1, 57, 89, 10,
6831 30, 165, 94, 164, 252, 219, 225, 133, 214, 161, 4, 118, 177, 123, 53, 57, 53, 233, 255,
6832 112, 117, 241, 247, 185, 195, 232, 36, 123, 31, 221, 6, 57, 176, 251, 163, 195, 39, 35,
6833 175,
6834 ];
6835 let p2_bytes_be: [u8; 96] = [
6836 13, 32, 61, 215, 83, 124, 186, 189, 82, 0, 79, 244, 67, 167, 21, 50, 48, 229, 8, 107,
6837 51, 15, 19, 47, 75, 77, 246, 185, 63, 66, 143, 109, 237, 211, 153, 146, 163, 175, 74,
6838 69, 50, 198, 235, 218, 9, 170, 225, 46, 22, 211, 116, 84, 32, 115, 130, 224, 106, 250,
6839 205, 143, 238, 115, 74, 207, 238, 193, 232, 16, 59, 140, 20, 252, 7, 34, 144, 47, 137,
6840 56, 190, 170, 235, 189, 238, 45, 97, 58, 199, 202, 45, 164, 139, 200, 190, 215, 9, 59,
6841 ];
6842 let expected_sum_be: [u8; 96] = [
6843 23, 62, 255, 137, 157, 188, 98, 86, 192, 102, 136, 171, 187, 49, 155, 83, 204, 133,
6844 217, 144, 137, 103, 15, 4, 116, 75, 127, 65, 29, 89, 223, 147, 32, 161, 91, 104, 96,
6845 211, 239, 102, 233, 95, 48, 130, 207, 154, 19, 189, 18, 112, 102, 145, 36, 73, 17, 27,
6846 47, 96, 116, 45, 56, 25, 16, 191, 56, 21, 86, 216, 133, 245, 207, 71, 158, 31, 29, 51,
6847 84, 185, 134, 138, 64, 68, 55, 161, 55, 153, 214, 155, 250, 21, 233, 4, 3, 117, 41,
6848 239,
6849 ];
6850 let p1_bytes_le: [u8; 96] = [
6851 176, 248, 46, 58, 90, 58, 154, 88, 155, 72, 135, 162, 200, 180, 242, 117, 127, 104,
6852 143, 168, 57, 212, 175, 225, 215, 2, 197, 198, 220, 96, 107, 57, 133, 183, 100, 99, 13,
6853 56, 183, 127, 101, 17, 245, 236, 212, 169, 86, 9, 175, 35, 39, 195, 163, 251, 176, 57,
6854 6, 221, 31, 123, 36, 232, 195, 185, 247, 241, 117, 112, 255, 233, 53, 57, 53, 123, 177,
6855 118, 4, 161, 214, 133, 225, 219, 252, 164, 94, 165, 30, 10, 89, 57, 1, 240, 112, 25,
6856 206, 10,
6857 ];
6858 let p2_bytes_le: [u8; 96] = [
6859 46, 225, 170, 9, 218, 235, 198, 50, 69, 74, 175, 163, 146, 153, 211, 237, 109, 143, 66,
6860 63, 185, 246, 77, 75, 47, 19, 15, 51, 107, 8, 229, 48, 50, 21, 167, 67, 244, 79, 0, 82,
6861 189, 186, 124, 83, 215, 61, 32, 13, 59, 9, 215, 190, 200, 139, 164, 45, 202, 199, 58,
6862 97, 45, 238, 189, 235, 170, 190, 56, 137, 47, 144, 34, 7, 252, 20, 140, 59, 16, 232,
6863 193, 238, 207, 74, 115, 238, 143, 205, 250, 106, 224, 130, 115, 32, 84, 116, 211, 22,
6864 ];
6865 let expected_sum_le: [u8; 96] = [
6866 189, 19, 154, 207, 130, 48, 95, 233, 102, 239, 211, 96, 104, 91, 161, 32, 147, 223, 89,
6867 29, 65, 127, 75, 116, 4, 15, 103, 137, 144, 217, 133, 204, 83, 155, 49, 187, 171, 136,
6868 102, 192, 86, 98, 188, 157, 137, 255, 62, 23, 239, 41, 117, 3, 4, 233, 21, 250, 155,
6869 214, 153, 55, 161, 55, 68, 64, 138, 134, 185, 84, 51, 29, 31, 158, 71, 207, 245, 133,
6870 216, 86, 21, 56, 191, 16, 25, 56, 45, 116, 96, 47, 27, 17, 73, 36, 145, 102, 112, 18,
6871 ];
6872
6873 let p1_be_va = 0x100000000;
6874 let p2_be_va = 0x200000000;
6875 let p1_le_va = 0x300000000;
6876 let p2_le_va = 0x400000000;
6877 let result_be_va = 0x500000000;
6878 let result_le_va = 0x600000000;
6879
6880 let mut result_be_buf = [0u8; 96];
6881 let mut result_le_buf = [0u8; 96];
6882
6883 let memory_mapping = unsafe {
6884 MemoryMapping::new(
6885 vec![
6886 MemoryRegion::new(&raw const p1_bytes_be, p1_be_va),
6887 MemoryRegion::new(&raw const p2_bytes_be, p2_be_va),
6888 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
6889 MemoryRegion::new(&raw const p1_bytes_le, p1_le_va),
6890 MemoryRegion::new(&raw const p2_bytes_le, p2_le_va),
6891 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
6892 ],
6893 &config,
6894 SBPFVersion::V3,
6895 )
6896 .unwrap()
6897 };
6898 invoke_context
6899 .memory_contexts
6900 .mock_set_mapping_abi_v1(memory_mapping);
6901
6902 let bls12_381_g1_add_cost = invoke_context.get_execution_cost().bls12_381_g1_add_cost;
6903 invoke_context
6904 .compute_meter
6905 .mock_set_remaining(2 * bls12_381_g1_add_cost);
6906
6907 let result = SyscallCurveGroupOps::rust(
6908 &mut invoke_context,
6909 BLS12_381_G1_BE,
6910 ADD,
6911 p1_be_va,
6912 p2_be_va,
6913 result_be_va,
6914 );
6915
6916 assert_eq!(0, result.unwrap());
6917 assert_eq!(result_be_buf, expected_sum_be);
6918
6919 let result = SyscallCurveGroupOps::rust(
6920 &mut invoke_context,
6921 BLS12_381_G1_LE,
6922 ADD,
6923 p1_le_va,
6924 p2_le_va,
6925 result_le_va,
6926 );
6927
6928 assert_eq!(0, result.unwrap());
6929 assert_eq!(result_le_buf, expected_sum_le);
6930 }
6931
6932 #[test]
6933 fn test_syscall_bls12_381_g1_sub() {
6934 use {
6935 solana_curve25519::curve_syscall_traits::SUB,
6936 solana_define_syscall::curve_constants::{BLS12_381_G1_BE, BLS12_381_G1_LE},
6937 };
6938
6939 let config = Config::default();
6940 let feature_set = SVMFeatureSet {
6941 enable_bls12_381_syscall: true,
6942 ..Default::default()
6943 };
6944 let feature_set = &feature_set;
6945 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
6946
6947 let sub_p1_be: [u8; 96] = [
6948 6, 126, 67, 177, 221, 168, 219, 147, 17, 32, 109, 112, 204, 95, 207, 179, 227, 202, 32,
6949 250, 118, 43, 195, 105, 176, 47, 188, 43, 181, 226, 123, 119, 132, 240, 97, 172, 225,
6950 247, 180, 76, 58, 229, 188, 121, 247, 28, 245, 198, 17, 128, 94, 239, 206, 10, 10, 20,
6951 148, 186, 226, 202, 12, 196, 71, 72, 167, 44, 87, 64, 24, 214, 238, 218, 6, 166, 113,
6952 165, 178, 8, 221, 0, 21, 154, 72, 160, 158, 70, 46, 244, 127, 4, 250, 158, 31, 2, 130,
6953 152,
6954 ];
6955 let sub_p2_be: [u8; 96] = [
6956 12, 173, 131, 106, 17, 172, 169, 46, 205, 228, 83, 25, 204, 216, 118, 223, 16, 102, 52,
6957 235, 202, 255, 183, 91, 99, 78, 141, 169, 14, 244, 161, 28, 240, 32, 214, 46, 0, 93,
6958 106, 73, 41, 176, 220, 160, 251, 37, 18, 110, 15, 86, 67, 210, 137, 114, 71, 220, 167,
6959 121, 177, 224, 142, 151, 152, 29, 206, 12, 35, 6, 46, 60, 53, 127, 84, 78, 231, 88, 49,
6960 95, 219, 36, 224, 182, 0, 253, 136, 115, 59, 15, 80, 229, 136, 103, 27, 211, 120, 90,
6961 ];
6962 let expected_sub_be: [u8; 96] = [
6963 13, 144, 131, 116, 67, 229, 136, 165, 135, 146, 181, 191, 197, 215, 68, 126, 103, 158,
6964 231, 50, 49, 105, 8, 243, 53, 209, 99, 16, 39, 177, 211, 99, 128, 164, 37, 101, 139,
6965 186, 14, 225, 84, 210, 120, 16, 203, 115, 160, 49, 10, 243, 68, 241, 87, 193, 186, 179,
6966 87, 214, 88, 39, 123, 126, 136, 31, 178, 134, 203, 222, 127, 206, 218, 240, 135, 183,
6967 93, 145, 136, 148, 174, 238, 159, 0, 117, 212, 171, 247, 148, 197, 206, 7, 225, 81,
6968 114, 74, 63, 201,
6969 ];
6970 let sub_p1_le: [u8; 96] = [
6971 198, 245, 28, 247, 121, 188, 229, 58, 76, 180, 247, 225, 172, 97, 240, 132, 119, 123,
6972 226, 181, 43, 188, 47, 176, 105, 195, 43, 118, 250, 32, 202, 227, 179, 207, 95, 204,
6973 112, 109, 32, 17, 147, 219, 168, 221, 177, 67, 126, 6, 152, 130, 2, 31, 158, 250, 4,
6974 127, 244, 46, 70, 158, 160, 72, 154, 21, 0, 221, 8, 178, 165, 113, 166, 6, 218, 238,
6975 214, 24, 64, 87, 44, 167, 72, 71, 196, 12, 202, 226, 186, 148, 20, 10, 10, 206, 239,
6976 94, 128, 17,
6977 ];
6978 let sub_p2_le: [u8; 96] = [
6979 110, 18, 37, 251, 160, 220, 176, 41, 73, 106, 93, 0, 46, 214, 32, 240, 28, 161, 244,
6980 14, 169, 141, 78, 99, 91, 183, 255, 202, 235, 52, 102, 16, 223, 118, 216, 204, 25, 83,
6981 228, 205, 46, 169, 172, 17, 106, 131, 173, 12, 90, 120, 211, 27, 103, 136, 229, 80, 15,
6982 59, 115, 136, 253, 0, 182, 224, 36, 219, 95, 49, 88, 231, 78, 84, 127, 53, 60, 46, 6,
6983 35, 12, 206, 29, 152, 151, 142, 224, 177, 121, 167, 220, 71, 114, 137, 210, 67, 86, 15,
6984 ];
6985 let expected_sub_le: [u8; 96] = [
6986 49, 160, 115, 203, 16, 120, 210, 84, 225, 14, 186, 139, 101, 37, 164, 128, 99, 211,
6987 177, 39, 16, 99, 209, 53, 243, 8, 105, 49, 50, 231, 158, 103, 126, 68, 215, 197, 191,
6988 181, 146, 135, 165, 136, 229, 67, 116, 131, 144, 13, 201, 63, 74, 114, 81, 225, 7, 206,
6989 197, 148, 247, 171, 212, 117, 0, 159, 238, 174, 148, 136, 145, 93, 183, 135, 240, 218,
6990 206, 127, 222, 203, 134, 178, 31, 136, 126, 123, 39, 88, 214, 87, 179, 186, 193, 87,
6991 241, 68, 243, 10,
6992 ];
6993
6994 let p1_be_va = 0x100000000;
6995 let p2_be_va = 0x200000000;
6996 let p1_le_va = 0x300000000;
6997 let p2_le_va = 0x400000000;
6998 let result_be_va = 0x500000000;
6999 let result_le_va = 0x600000000;
7000
7001 let mut result_be_buf = [0u8; 96];
7002 let mut result_le_buf = [0u8; 96];
7003
7004 let memory_mapping = unsafe {
7005 MemoryMapping::new(
7006 vec![
7007 MemoryRegion::new(&raw const sub_p1_be, p1_be_va),
7008 MemoryRegion::new(&raw const sub_p2_be, p2_be_va),
7009 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7010 MemoryRegion::new(&raw const sub_p1_le, p1_le_va),
7011 MemoryRegion::new(&raw const sub_p2_le, p2_le_va),
7012 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7013 ],
7014 &config,
7015 SBPFVersion::V3,
7016 )
7017 .unwrap()
7018 };
7019 invoke_context
7020 .memory_contexts
7021 .mock_set_mapping_abi_v1(memory_mapping);
7022
7023 let bls12_381_g1_subtract_cost = invoke_context
7024 .get_execution_cost()
7025 .bls12_381_g1_subtract_cost;
7026 invoke_context
7027 .compute_meter
7028 .mock_set_remaining(2 * bls12_381_g1_subtract_cost);
7029
7030 let result = SyscallCurveGroupOps::rust(
7031 &mut invoke_context,
7032 BLS12_381_G1_BE,
7033 SUB,
7034 p1_be_va,
7035 p2_be_va,
7036 result_be_va,
7037 );
7038
7039 assert_eq!(0, result.unwrap());
7040 assert_eq!(result_be_buf, expected_sub_be);
7041
7042 let result = SyscallCurveGroupOps::rust(
7043 &mut invoke_context,
7044 BLS12_381_G1_LE,
7045 SUB,
7046 p1_le_va,
7047 p2_le_va,
7048 result_le_va,
7049 );
7050
7051 assert_eq!(0, result.unwrap());
7052 assert_eq!(result_le_buf, expected_sub_le);
7053 }
7054
7055 #[test]
7056 fn test_syscall_bls12_381_g1_mul() {
7057 use {
7058 solana_curve25519::curve_syscall_traits::MUL,
7059 solana_define_syscall::curve_constants::{BLS12_381_G1_BE, BLS12_381_G1_LE},
7060 };
7061
7062 let config = Config::default();
7063 let feature_set = SVMFeatureSet {
7064 enable_bls12_381_syscall: true,
7065 ..Default::default()
7066 };
7067 let feature_set = &feature_set;
7068 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
7069
7070 let mul_point_be: [u8; 96] = [
7071 20, 18, 233, 201, 110, 206, 56, 32, 8, 44, 140, 121, 37, 196, 157, 56, 180, 134, 164,
7072 33, 180, 130, 147, 7, 26, 239, 183, 163, 219, 85, 143, 197, 247, 243, 117, 252, 201,
7073 171, 156, 90, 210, 7, 43, 92, 89, 130, 165, 224, 5, 101, 24, 54, 189, 22, 73, 76, 145,
7074 136, 99, 59, 51, 255, 124, 43, 61, 8, 121, 30, 118, 90, 254, 12, 126, 92, 152, 78, 44,
7075 231, 126, 56, 220, 35, 54, 117, 2, 175, 190, 105, 138, 188, 202, 36, 171, 12, 231, 225,
7076 ];
7077 let mul_scalar_be: [u8; 32] = [
7078 29, 192, 111, 151, 187, 37, 109, 91, 129, 223, 188, 225, 117, 3, 120, 162, 107, 66,
7079 159, 255, 61, 128, 41, 32, 242, 95, 232, 202, 106, 188, 154, 147,
7080 ];
7081 let expected_mul_be: [u8; 96] = [
7082 22, 101, 72, 255, 3, 247, 39, 218, 234, 117, 208, 91, 158, 114, 126, 55, 166, 71, 227,
7083 205, 6, 124, 55, 255, 167, 66, 154, 237, 83, 143, 8, 179, 98, 185, 162, 164, 170, 62,
7084 141, 4, 1, 179, 41, 49, 95, 212, 139, 227, 18, 125, 245, 10, 169, 201, 171, 172, 152,
7085 1, 105, 81, 159, 160, 252, 184, 80, 59, 165, 170, 185, 114, 248, 208, 228, 111, 229,
7086 200, 221, 204, 9, 120, 153, 142, 88, 240, 228, 164, 157, 79, 72, 55, 119, 239, 56, 104,
7087 54, 58,
7088 ];
7089 let mul_point_le: [u8; 96] = [
7090 224, 165, 130, 89, 92, 43, 7, 210, 90, 156, 171, 201, 252, 117, 243, 247, 197, 143, 85,
7091 219, 163, 183, 239, 26, 7, 147, 130, 180, 33, 164, 134, 180, 56, 157, 196, 37, 121,
7092 140, 44, 8, 32, 56, 206, 110, 201, 233, 18, 20, 225, 231, 12, 171, 36, 202, 188, 138,
7093 105, 190, 175, 2, 117, 54, 35, 220, 56, 126, 231, 44, 78, 152, 92, 126, 12, 254, 90,
7094 118, 30, 121, 8, 61, 43, 124, 255, 51, 59, 99, 136, 145, 76, 73, 22, 189, 54, 24, 101,
7095 5,
7096 ];
7097 let mul_scalar_le: [u8; 32] = [
7098 147, 154, 188, 106, 202, 232, 95, 242, 32, 41, 128, 61, 255, 159, 66, 107, 162, 120, 3,
7099 117, 225, 188, 223, 129, 91, 109, 37, 187, 151, 111, 192, 29,
7100 ];
7101 let expected_mul_le: [u8; 96] = [
7102 227, 139, 212, 95, 49, 41, 179, 1, 4, 141, 62, 170, 164, 162, 185, 98, 179, 8, 143, 83,
7103 237, 154, 66, 167, 255, 55, 124, 6, 205, 227, 71, 166, 55, 126, 114, 158, 91, 208, 117,
7104 234, 218, 39, 247, 3, 255, 72, 101, 22, 58, 54, 104, 56, 239, 119, 55, 72, 79, 157,
7105 164, 228, 240, 88, 142, 153, 120, 9, 204, 221, 200, 229, 111, 228, 208, 248, 114, 185,
7106 170, 165, 59, 80, 184, 252, 160, 159, 81, 105, 1, 152, 172, 171, 201, 169, 10, 245,
7107 125, 18,
7108 ];
7109
7110 let scalar_be_va = 0x100000000;
7111 let point_be_va = 0x200000000;
7112 let scalar_le_va = 0x300000000;
7113 let point_le_va = 0x400000000;
7114 let result_be_va = 0x500000000;
7115 let result_le_va = 0x600000000;
7116
7117 let mut result_be_buf = [0u8; 96];
7118 let mut result_le_buf = [0u8; 96];
7119
7120 let memory_mapping = unsafe {
7121 MemoryMapping::new(
7122 vec![
7123 MemoryRegion::new(&raw const mul_scalar_be, scalar_be_va),
7124 MemoryRegion::new(&raw const mul_point_be, point_be_va),
7125 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7126 MemoryRegion::new(&raw const mul_scalar_le, scalar_le_va),
7127 MemoryRegion::new(&raw const mul_point_le, point_le_va),
7128 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7129 ],
7130 &config,
7131 SBPFVersion::V3,
7132 )
7133 .unwrap()
7134 };
7135 invoke_context
7136 .memory_contexts
7137 .mock_set_mapping_abi_v1(memory_mapping);
7138
7139 let bls12_381_g1_multiply_cost = invoke_context
7140 .get_execution_cost()
7141 .bls12_381_g1_multiply_cost;
7142 invoke_context
7143 .compute_meter
7144 .mock_set_remaining(2 * bls12_381_g1_multiply_cost);
7145
7146 let result = SyscallCurveGroupOps::rust(
7147 &mut invoke_context,
7148 BLS12_381_G1_BE,
7149 MUL,
7150 scalar_be_va,
7151 point_be_va,
7152 result_be_va,
7153 );
7154
7155 assert_eq!(0, result.unwrap());
7156 assert_eq!(result_be_buf, expected_mul_be);
7157
7158 let result = SyscallCurveGroupOps::rust(
7159 &mut invoke_context,
7160 BLS12_381_G1_LE,
7161 MUL,
7162 scalar_le_va,
7163 point_le_va,
7164 result_le_va,
7165 );
7166
7167 assert_eq!(0, result.unwrap());
7168 assert_eq!(result_le_buf, expected_mul_le);
7169 }
7170
7171 #[test]
7172 fn test_syscall_bls12_381_g2_add() {
7173 use {
7174 solana_curve25519::curve_syscall_traits::ADD,
7175 solana_define_syscall::curve_constants::{BLS12_381_G2_BE, BLS12_381_G2_LE},
7176 };
7177
7178 let config = Config::default();
7179 let feature_set = SVMFeatureSet {
7180 enable_bls12_381_syscall: true,
7181 ..Default::default()
7182 };
7183 let feature_set = &feature_set;
7184
7185 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7186
7187 let p1_bytes_be: [u8; 192] = [
7188 11, 83, 21, 62, 4, 174, 123, 131, 163, 19, 62, 216, 192, 48, 25, 184, 57, 207, 80, 70,
7189 253, 51, 129, 169, 87, 182, 142, 1, 148, 102, 203, 99, 86, 111, 207, 55, 204, 117, 82,
7190 138, 199, 89, 131, 207, 158, 244, 204, 139, 18, 151, 214, 201, 158, 39, 101, 252, 189,
7191 53, 251, 236, 205, 27, 152, 163, 232, 101, 53, 197, 18, 238, 241, 70, 182, 113, 111,
7192 249, 99, 122, 42, 220, 55, 127, 55, 247, 172, 164, 183, 169, 146, 229, 218, 185, 144,
7193 176, 86, 174, 21, 132, 150, 29, 241, 241, 215, 77, 12, 75, 238, 103, 23, 90, 189, 191,
7194 85, 72, 181, 214, 85, 253, 183, 150, 158, 8, 250, 178, 220, 169, 215, 243, 146, 213,
7195 150, 12, 6, 40, 188, 197, 56, 210, 46, 125, 87, 5, 17, 7, 24, 27, 160, 22, 99, 114, 9,
7196 7, 244, 108, 179, 201, 38, 33, 153, 219, 10, 211, 2, 212, 74, 95, 151, 223, 200, 96,
7197 121, 166, 10, 186, 122, 40, 222, 87, 34, 227, 49, 166, 195, 139, 37, 221, 44, 227, 86,
7198 119, 190, 41,
7199 ];
7200 let p2_bytes_be: [u8; 192] = [
7201 14, 110, 180, 174, 46, 74, 145, 125, 94, 28, 39, 205, 107, 126, 53, 188, 36, 69, 162,
7202 98, 105, 79, 49, 148, 136, 229, 5, 128, 197, 187, 0, 234, 141, 201, 246, 223, 103, 75,
7203 177, 33, 2, 75, 90, 33, 139, 152, 156, 89, 25, 91, 158, 100, 20, 12, 135, 130, 191,
7204 181, 5, 41, 94, 195, 89, 36, 181, 111, 238, 24, 187, 178, 179, 143, 17, 181, 68, 203,
7205 184, 134, 185, 195, 176, 27, 90, 2, 29, 165, 209, 16, 143, 11, 224, 251, 63, 188, 218,
7206 41, 23, 71, 91, 90, 202, 108, 80, 160, 200, 194, 162, 109, 200, 96, 5, 102, 156, 245,
7207 43, 247, 221, 139, 148, 254, 253, 183, 161, 83, 253, 247, 22, 71, 133, 93, 36, 127,
7208 162, 248, 49, 64, 173, 201, 17, 210, 8, 214, 18, 65, 7, 222, 11, 4, 120, 17, 85, 49,
7209 205, 95, 132, 208, 152, 136, 92, 19, 195, 176, 136, 39, 90, 207, 17, 195, 14, 215, 33,
7210 191, 232, 59, 3, 86, 78, 78, 149, 165, 179, 145, 161, 190, 247, 67, 243, 252, 137, 1,
7211 39, 71,
7212 ];
7213 let expected_sum_be: [u8; 192] = [
7214 21, 157, 10, 251, 156, 56, 24, 174, 24, 91, 98, 201, 33, 37, 68, 76, 41, 161, 12, 166,
7215 16, 128, 161, 31, 108, 31, 92, 216, 56, 197, 198, 66, 210, 6, 64, 106, 154, 96, 135,
7216 57, 170, 119, 220, 210, 238, 73, 98, 83, 15, 146, 74, 122, 70, 40, 186, 123, 191, 139,
7217 11, 249, 221, 20, 12, 62, 81, 37, 191, 22, 248, 113, 78, 124, 29, 157, 228, 220, 187,
7218 6, 252, 15, 59, 236, 98, 198, 252, 205, 176, 190, 192, 199, 154, 213, 92, 126, 189, 55,
7219 2, 109, 8, 15, 128, 190, 31, 106, 180, 130, 96, 215, 125, 50, 11, 124, 71, 119, 83, 28,
7220 65, 209, 128, 47, 7, 46, 212, 157, 230, 199, 51, 98, 143, 220, 157, 254, 179, 203, 186,
7221 116, 41, 76, 35, 28, 123, 207, 54, 17, 5, 248, 36, 247, 193, 201, 116, 118, 202, 201,
7222 125, 201, 200, 13, 68, 244, 39, 207, 70, 206, 12, 117, 206, 192, 9, 232, 62, 33, 137,
7223 88, 73, 16, 121, 190, 139, 91, 158, 80, 147, 207, 125, 23, 177, 93, 227, 132, 103, 89,
7224 ];
7225 let p1_bytes_le: [u8; 192] = [
7226 174, 86, 176, 144, 185, 218, 229, 146, 169, 183, 164, 172, 247, 55, 127, 55, 220, 42,
7227 122, 99, 249, 111, 113, 182, 70, 241, 238, 18, 197, 53, 101, 232, 163, 152, 27, 205,
7228 236, 251, 53, 189, 252, 101, 39, 158, 201, 214, 151, 18, 139, 204, 244, 158, 207, 131,
7229 89, 199, 138, 82, 117, 204, 55, 207, 111, 86, 99, 203, 102, 148, 1, 142, 182, 87, 169,
7230 129, 51, 253, 70, 80, 207, 57, 184, 25, 48, 192, 216, 62, 19, 163, 131, 123, 174, 4,
7231 62, 21, 83, 11, 41, 190, 119, 86, 227, 44, 221, 37, 139, 195, 166, 49, 227, 34, 87,
7232 222, 40, 122, 186, 10, 166, 121, 96, 200, 223, 151, 95, 74, 212, 2, 211, 10, 219, 153,
7233 33, 38, 201, 179, 108, 244, 7, 9, 114, 99, 22, 160, 27, 24, 7, 17, 5, 87, 125, 46, 210,
7234 56, 197, 188, 40, 6, 12, 150, 213, 146, 243, 215, 169, 220, 178, 250, 8, 158, 150, 183,
7235 253, 85, 214, 181, 72, 85, 191, 189, 90, 23, 103, 238, 75, 12, 77, 215, 241, 241, 29,
7236 150, 132, 21,
7237 ];
7238 let p2_bytes_le: [u8; 192] = [
7239 41, 218, 188, 63, 251, 224, 11, 143, 16, 209, 165, 29, 2, 90, 27, 176, 195, 185, 134,
7240 184, 203, 68, 181, 17, 143, 179, 178, 187, 24, 238, 111, 181, 36, 89, 195, 94, 41, 5,
7241 181, 191, 130, 135, 12, 20, 100, 158, 91, 25, 89, 156, 152, 139, 33, 90, 75, 2, 33,
7242 177, 75, 103, 223, 246, 201, 141, 234, 0, 187, 197, 128, 5, 229, 136, 148, 49, 79, 105,
7243 98, 162, 69, 36, 188, 53, 126, 107, 205, 39, 28, 94, 125, 145, 74, 46, 174, 180, 110,
7244 14, 71, 39, 1, 137, 252, 243, 67, 247, 190, 161, 145, 179, 165, 149, 78, 78, 86, 3, 59,
7245 232, 191, 33, 215, 14, 195, 17, 207, 90, 39, 136, 176, 195, 19, 92, 136, 152, 208, 132,
7246 95, 205, 49, 85, 17, 120, 4, 11, 222, 7, 65, 18, 214, 8, 210, 17, 201, 173, 64, 49,
7247 248, 162, 127, 36, 93, 133, 71, 22, 247, 253, 83, 161, 183, 253, 254, 148, 139, 221,
7248 247, 43, 245, 156, 102, 5, 96, 200, 109, 162, 194, 200, 160, 80, 108, 202, 90, 91, 71,
7249 23,
7250 ];
7251 let expected_sum_le: [u8; 192] = [
7252 55, 189, 126, 92, 213, 154, 199, 192, 190, 176, 205, 252, 198, 98, 236, 59, 15, 252, 6,
7253 187, 220, 228, 157, 29, 124, 78, 113, 248, 22, 191, 37, 81, 62, 12, 20, 221, 249, 11,
7254 139, 191, 123, 186, 40, 70, 122, 74, 146, 15, 83, 98, 73, 238, 210, 220, 119, 170, 57,
7255 135, 96, 154, 106, 64, 6, 210, 66, 198, 197, 56, 216, 92, 31, 108, 31, 161, 128, 16,
7256 166, 12, 161, 41, 76, 68, 37, 33, 201, 98, 91, 24, 174, 24, 56, 156, 251, 10, 157, 21,
7257 89, 103, 132, 227, 93, 177, 23, 125, 207, 147, 80, 158, 91, 139, 190, 121, 16, 73, 88,
7258 137, 33, 62, 232, 9, 192, 206, 117, 12, 206, 70, 207, 39, 244, 68, 13, 200, 201, 125,
7259 201, 202, 118, 116, 201, 193, 247, 36, 248, 5, 17, 54, 207, 123, 28, 35, 76, 41, 116,
7260 186, 203, 179, 254, 157, 220, 143, 98, 51, 199, 230, 157, 212, 46, 7, 47, 128, 209, 65,
7261 28, 83, 119, 71, 124, 11, 50, 125, 215, 96, 130, 180, 106, 31, 190, 128, 15, 8, 109, 2,
7262 ];
7263
7264 let p1_be_va = 0x100000000;
7265 let p2_be_va = 0x200000000;
7266 let p1_le_va = 0x300000000;
7267 let p2_le_va = 0x400000000;
7268 let result_be_va = 0x500000000;
7269 let result_le_va = 0x600000000;
7270
7271 let mut result_be_buf = [0u8; 192];
7272 let mut result_le_buf = [0u8; 192];
7273
7274 let memory_mapping = unsafe {
7275 MemoryMapping::new(
7276 vec![
7277 MemoryRegion::new(&raw const p1_bytes_be, p1_be_va),
7278 MemoryRegion::new(&raw const p2_bytes_be, p2_be_va),
7279 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7280 MemoryRegion::new(&raw const p1_bytes_le, p1_le_va),
7281 MemoryRegion::new(&raw const p2_bytes_le, p2_le_va),
7282 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7283 ],
7284 &config,
7285 SBPFVersion::V3,
7286 )
7287 .unwrap()
7288 };
7289 invoke_context
7290 .memory_contexts
7291 .mock_set_mapping_abi_v1(memory_mapping);
7292
7293 let bls12_381_g2_add_cost = invoke_context.get_execution_cost().bls12_381_g2_add_cost;
7294 invoke_context
7295 .compute_meter
7296 .mock_set_remaining(2 * bls12_381_g2_add_cost);
7297
7298 let result = SyscallCurveGroupOps::rust(
7299 &mut invoke_context,
7300 BLS12_381_G2_BE,
7301 ADD,
7302 p1_be_va,
7303 p2_be_va,
7304 result_be_va,
7305 );
7306
7307 assert_eq!(0, result.unwrap());
7308 assert_eq!(result_be_buf, expected_sum_be);
7309
7310 let result = SyscallCurveGroupOps::rust(
7311 &mut invoke_context,
7312 BLS12_381_G2_LE,
7313 ADD,
7314 p1_le_va,
7315 p2_le_va,
7316 result_le_va,
7317 );
7318
7319 assert_eq!(0, result.unwrap());
7320 assert_eq!(result_le_buf, expected_sum_le);
7321 }
7322
7323 #[test]
7324 fn test_syscall_bls12_381_g2_sub() {
7325 use {
7326 solana_curve25519::curve_syscall_traits::SUB,
7327 solana_define_syscall::curve_constants::{BLS12_381_G2_BE, BLS12_381_G2_LE},
7328 };
7329
7330 let config = Config::default();
7331 let feature_set = SVMFeatureSet {
7332 enable_bls12_381_syscall: true,
7333 ..Default::default()
7334 };
7335 let feature_set = &feature_set;
7336 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
7337
7338 let sub_p1_be: [u8; 192] = [
7339 1, 111, 113, 42, 165, 128, 194, 26, 130, 142, 58, 198, 61, 244, 113, 64, 25, 96, 196,
7340 12, 211, 55, 213, 85, 109, 210, 211, 177, 96, 48, 15, 122, 155, 173, 166, 16, 113, 95,
7341 253, 69, 196, 15, 187, 201, 207, 255, 81, 176, 15, 77, 24, 199, 78, 142, 23, 177, 55,
7342 118, 62, 248, 123, 41, 213, 72, 169, 177, 5, 176, 197, 158, 62, 1, 5, 219, 190, 92, 36,
7343 37, 117, 162, 202, 9, 231, 199, 13, 72, 102, 36, 246, 241, 52, 68, 185, 44, 238, 23,
7344 23, 1, 192, 28, 61, 103, 236, 74, 46, 28, 64, 67, 194, 243, 208, 186, 46, 201, 142, 7,
7345 166, 139, 114, 215, 101, 234, 108, 184, 93, 135, 61, 176, 154, 208, 28, 79, 210, 132,
7346 96, 21, 199, 11, 73, 210, 40, 241, 107, 215, 8, 203, 156, 2, 211, 33, 203, 196, 124,
7347 172, 148, 232, 121, 116, 109, 226, 15, 13, 147, 241, 20, 70, 28, 10, 17, 51, 143, 140,
7348 35, 127, 109, 7, 202, 220, 208, 97, 11, 167, 119, 94, 192, 92, 165, 215, 230, 160, 16,
7349 56,
7350 ];
7351 let sub_p2_be: [u8; 192] = [
7352 14, 73, 101, 89, 211, 85, 5, 115, 148, 81, 82, 216, 141, 148, 50, 174, 17, 86, 246,
7353 146, 42, 230, 181, 250, 40, 64, 248, 121, 6, 167, 117, 190, 219, 96, 57, 80, 127, 234,
7354 141, 179, 154, 109, 5, 82, 233, 254, 7, 48, 5, 108, 253, 196, 16, 144, 81, 140, 252,
7355 184, 236, 193, 97, 200, 129, 223, 132, 28, 135, 121, 129, 129, 60, 33, 77, 43, 181,
7356 180, 60, 224, 108, 127, 207, 112, 54, 66, 81, 185, 166, 120, 54, 169, 55, 238, 32, 219,
7357 172, 212, 24, 165, 106, 207, 20, 68, 130, 233, 190, 75, 177, 17, 157, 112, 174, 88,
7358 189, 182, 126, 219, 114, 136, 67, 15, 167, 133, 50, 172, 124, 94, 8, 149, 203, 232, 35,
7359 218, 144, 142, 74, 150, 94, 182, 33, 106, 111, 120, 203, 59, 10, 121, 79, 248, 118,
7360 165, 232, 57, 87, 60, 42, 223, 98, 104, 158, 238, 68, 152, 59, 19, 172, 89, 20, 238,
7361 63, 49, 204, 138, 108, 195, 10, 233, 81, 79, 215, 107, 43, 197, 190, 231, 15, 14, 251,
7362 203, 179, 205, 224, 195,
7363 ];
7364 let expected_sub_be: [u8; 192] = [
7365 15, 192, 220, 234, 246, 126, 141, 163, 107, 162, 43, 117, 171, 158, 195, 132, 196, 214,
7366 237, 133, 98, 133, 112, 248, 161, 148, 3, 163, 20, 26, 49, 136, 161, 244, 36, 179, 237,
7367 204, 58, 22, 51, 106, 0, 4, 239, 244, 242, 89, 5, 14, 149, 31, 78, 213, 70, 153, 147,
7368 43, 84, 19, 223, 100, 235, 61, 172, 66, 136, 201, 11, 81, 168, 136, 207, 46, 198, 208,
7369 171, 144, 187, 35, 77, 58, 186, 147, 191, 243, 9, 12, 224, 22, 230, 36, 112, 246, 114,
7370 19, 13, 116, 186, 62, 158, 176, 201, 150, 187, 13, 32, 135, 140, 108, 178, 174, 90,
7371 212, 50, 184, 238, 17, 229, 167, 195, 104, 179, 156, 166, 251, 99, 115, 133, 25, 144,
7372 101, 45, 70, 19, 86, 91, 247, 236, 93, 252, 14, 106, 212, 15, 42, 62, 104, 162, 216, 8,
7373 180, 156, 52, 254, 179, 29, 95, 94, 16, 245, 215, 165, 67, 115, 50, 186, 190, 227, 213,
7374 71, 126, 29, 81, 217, 43, 157, 12, 100, 105, 211, 172, 101, 212, 73, 140, 149, 109,
7375 252, 180, 98, 22,
7376 ];
7377 let sub_p1_le: [u8; 192] = [
7378 23, 238, 44, 185, 68, 52, 241, 246, 36, 102, 72, 13, 199, 231, 9, 202, 162, 117, 37,
7379 36, 92, 190, 219, 5, 1, 62, 158, 197, 176, 5, 177, 169, 72, 213, 41, 123, 248, 62, 118,
7380 55, 177, 23, 142, 78, 199, 24, 77, 15, 176, 81, 255, 207, 201, 187, 15, 196, 69, 253,
7381 95, 113, 16, 166, 173, 155, 122, 15, 48, 96, 177, 211, 210, 109, 85, 213, 55, 211, 12,
7382 196, 96, 25, 64, 113, 244, 61, 198, 58, 142, 130, 26, 194, 128, 165, 42, 113, 111, 1,
7383 56, 16, 160, 230, 215, 165, 92, 192, 94, 119, 167, 11, 97, 208, 220, 202, 7, 109, 127,
7384 35, 140, 143, 51, 17, 10, 28, 70, 20, 241, 147, 13, 15, 226, 109, 116, 121, 232, 148,
7385 172, 124, 196, 203, 33, 211, 2, 156, 203, 8, 215, 107, 241, 40, 210, 73, 11, 199, 21,
7386 96, 132, 210, 79, 28, 208, 154, 176, 61, 135, 93, 184, 108, 234, 101, 215, 114, 139,
7387 166, 7, 142, 201, 46, 186, 208, 243, 194, 67, 64, 28, 46, 74, 236, 103, 61, 28, 192, 1,
7388 23,
7389 ];
7390 let sub_p2_le: [u8; 192] = [
7391 212, 172, 219, 32, 238, 55, 169, 54, 120, 166, 185, 81, 66, 54, 112, 207, 127, 108,
7392 224, 60, 180, 181, 43, 77, 33, 60, 129, 129, 121, 135, 28, 132, 223, 129, 200, 97, 193,
7393 236, 184, 252, 140, 81, 144, 16, 196, 253, 108, 5, 48, 7, 254, 233, 82, 5, 109, 154,
7394 179, 141, 234, 127, 80, 57, 96, 219, 190, 117, 167, 6, 121, 248, 64, 40, 250, 181, 230,
7395 42, 146, 246, 86, 17, 174, 50, 148, 141, 216, 82, 81, 148, 115, 5, 85, 211, 89, 101,
7396 73, 14, 195, 224, 205, 179, 203, 251, 14, 15, 231, 190, 197, 43, 107, 215, 79, 81, 233,
7397 10, 195, 108, 138, 204, 49, 63, 238, 20, 89, 172, 19, 59, 152, 68, 238, 158, 104, 98,
7398 223, 42, 60, 87, 57, 232, 165, 118, 248, 79, 121, 10, 59, 203, 120, 111, 106, 33, 182,
7399 94, 150, 74, 142, 144, 218, 35, 232, 203, 149, 8, 94, 124, 172, 50, 133, 167, 15, 67,
7400 136, 114, 219, 126, 182, 189, 88, 174, 112, 157, 17, 177, 75, 190, 233, 130, 68, 20,
7401 207, 106, 165, 24,
7402 ];
7403 let expected_sub_le: [u8; 192] = [
7404 19, 114, 246, 112, 36, 230, 22, 224, 12, 9, 243, 191, 147, 186, 58, 77, 35, 187, 144,
7405 171, 208, 198, 46, 207, 136, 168, 81, 11, 201, 136, 66, 172, 61, 235, 100, 223, 19, 84,
7406 43, 147, 153, 70, 213, 78, 31, 149, 14, 5, 89, 242, 244, 239, 4, 0, 106, 51, 22, 58,
7407 204, 237, 179, 36, 244, 161, 136, 49, 26, 20, 163, 3, 148, 161, 248, 112, 133, 98, 133,
7408 237, 214, 196, 132, 195, 158, 171, 117, 43, 162, 107, 163, 141, 126, 246, 234, 220,
7409 192, 15, 22, 98, 180, 252, 109, 149, 140, 73, 212, 101, 172, 211, 105, 100, 12, 157,
7410 43, 217, 81, 29, 126, 71, 213, 227, 190, 186, 50, 115, 67, 165, 215, 245, 16, 94, 95,
7411 29, 179, 254, 52, 156, 180, 8, 216, 162, 104, 62, 42, 15, 212, 106, 14, 252, 93, 236,
7412 247, 91, 86, 19, 70, 45, 101, 144, 25, 133, 115, 99, 251, 166, 156, 179, 104, 195, 167,
7413 229, 17, 238, 184, 50, 212, 90, 174, 178, 108, 140, 135, 32, 13, 187, 150, 201, 176,
7414 158, 62, 186, 116, 13,
7415 ];
7416
7417 let p1_be_va = 0x100000000;
7418 let p2_be_va = 0x200000000;
7419 let p1_le_va = 0x300000000;
7420 let p2_le_va = 0x400000000;
7421 let result_be_va = 0x500000000;
7422 let result_le_va = 0x600000000;
7423
7424 let mut result_be_buf = [0u8; 192];
7425 let mut result_le_buf = [0u8; 192];
7426
7427 let memory_mapping = unsafe {
7428 MemoryMapping::new(
7429 vec![
7430 MemoryRegion::new(&raw const sub_p1_be, p1_be_va),
7431 MemoryRegion::new(&raw const sub_p2_be, p2_be_va),
7432 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7433 MemoryRegion::new(&raw const sub_p1_le, p1_le_va),
7434 MemoryRegion::new(&raw const sub_p2_le, p2_le_va),
7435 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7436 ],
7437 &config,
7438 SBPFVersion::V3,
7439 )
7440 .unwrap()
7441 };
7442 invoke_context
7443 .memory_contexts
7444 .mock_set_mapping_abi_v1(memory_mapping);
7445
7446 let bls12_381_g2_subtract_cost = invoke_context
7447 .get_execution_cost()
7448 .bls12_381_g2_subtract_cost;
7449 invoke_context
7450 .compute_meter
7451 .mock_set_remaining(2 * bls12_381_g2_subtract_cost);
7452
7453 let result = SyscallCurveGroupOps::rust(
7454 &mut invoke_context,
7455 BLS12_381_G2_BE,
7456 SUB,
7457 p1_be_va,
7458 p2_be_va,
7459 result_be_va,
7460 );
7461
7462 assert_eq!(0, result.unwrap());
7463 assert_eq!(result_be_buf, expected_sub_be);
7464
7465 let result = SyscallCurveGroupOps::rust(
7466 &mut invoke_context,
7467 BLS12_381_G2_LE,
7468 SUB,
7469 p1_le_va,
7470 p2_le_va,
7471 result_le_va,
7472 );
7473
7474 assert_eq!(0, result.unwrap());
7475 assert_eq!(result_le_buf, expected_sub_le);
7476 }
7477
7478 #[test]
7479 fn test_syscall_bls12_381_g2_mul() {
7480 use {
7481 solana_curve25519::curve_syscall_traits::MUL,
7482 solana_define_syscall::curve_constants::{BLS12_381_G2_BE, BLS12_381_G2_LE},
7483 };
7484
7485 let config = Config::default();
7486 let feature_set = SVMFeatureSet {
7487 enable_bls12_381_syscall: true,
7488 ..Default::default()
7489 };
7490 let feature_set = &feature_set;
7491 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set);
7492
7493 let mul_point_be: [u8; 192] = [
7494 1, 95, 16, 90, 117, 185, 253, 76, 25, 68, 54, 111, 154, 161, 125, 203, 121, 4, 154, 67,
7495 205, 157, 76, 9, 128, 224, 37, 81, 214, 226, 71, 59, 224, 187, 152, 153, 199, 62, 58,
7496 74, 137, 245, 46, 101, 155, 17, 212, 64, 5, 134, 0, 185, 19, 132, 205, 101, 77, 204,
7497 118, 63, 71, 172, 208, 29, 210, 61, 51, 4, 190, 191, 211, 175, 105, 245, 204, 57, 56,
7498 84, 210, 184, 235, 169, 231, 161, 128, 83, 252, 234, 227, 255, 166, 219, 201, 176, 169,
7499 16, 20, 218, 203, 38, 181, 98, 213, 89, 152, 123, 230, 201, 4, 95, 42, 86, 29, 137, 67,
7500 233, 230, 161, 206, 231, 201, 176, 79, 12, 197, 56, 212, 36, 235, 216, 160, 27, 221,
7501 99, 124, 220, 133, 76, 123, 209, 200, 78, 122, 36, 16, 171, 18, 247, 111, 111, 132, 38,
7502 240, 183, 27, 76, 135, 211, 136, 202, 55, 93, 246, 235, 191, 146, 183, 161, 110, 129,
7503 4, 58, 238, 59, 77, 242, 56, 88, 96, 150, 146, 247, 137, 230, 137, 35, 9, 108, 95, 127,
7504 75, 78,
7505 ];
7506 let mul_scalar_be: [u8; 32] = [
7507 29, 192, 111, 151, 187, 37, 109, 91, 129, 223, 188, 225, 117, 3, 120, 162, 107, 66,
7508 159, 255, 61, 128, 41, 32, 242, 95, 232, 202, 106, 188, 154, 147,
7509 ];
7510 let expected_mul_be: [u8; 192] = [
7511 10, 92, 88, 192, 26, 200, 38, 128, 188, 148, 254, 16, 202, 39, 174, 252, 33, 111, 41,
7512 121, 211, 9, 209, 138, 43, 104, 122, 214, 4, 251, 34, 81, 36, 92, 143, 19, 151, 213,
7513 111, 240, 100, 15, 33, 74, 123, 143, 181, 153, 6, 107, 82, 96, 141, 147, 63, 200, 13,
7514 31, 66, 5, 184, 135, 24, 82, 189, 240, 58, 250, 48, 61, 132, 13, 23, 240, 31, 238, 252,
7515 33, 191, 241, 38, 90, 221, 201, 164, 137, 98, 92, 148, 246, 225, 22, 239, 99, 97, 179,
7516 20, 251, 39, 114, 14, 156, 165, 182, 58, 233, 100, 41, 34, 59, 119, 103, 40, 206, 50,
7517 175, 223, 126, 146, 17, 161, 14, 84, 43, 149, 58, 212, 197, 250, 15, 208, 122, 33, 4,
7518 87, 219, 82, 201, 12, 11, 44, 76, 59, 182, 18, 76, 38, 184, 175, 11, 211, 4, 64, 133,
7519 41, 104, 185, 153, 63, 246, 39, 145, 38, 113, 162, 183, 77, 2, 51, 134, 243, 196, 74,
7520 111, 183, 169, 222, 228, 191, 53, 129, 53, 186, 94, 97, 144, 31, 117, 218, 207, 214,
7521 189,
7522 ];
7523 let mul_point_le: [u8; 192] = [
7524 16, 169, 176, 201, 219, 166, 255, 227, 234, 252, 83, 128, 161, 231, 169, 235, 184, 210,
7525 84, 56, 57, 204, 245, 105, 175, 211, 191, 190, 4, 51, 61, 210, 29, 208, 172, 71, 63,
7526 118, 204, 77, 101, 205, 132, 19, 185, 0, 134, 5, 64, 212, 17, 155, 101, 46, 245, 137,
7527 74, 58, 62, 199, 153, 152, 187, 224, 59, 71, 226, 214, 81, 37, 224, 128, 9, 76, 157,
7528 205, 67, 154, 4, 121, 203, 125, 161, 154, 111, 54, 68, 25, 76, 253, 185, 117, 90, 16,
7529 95, 1, 78, 75, 127, 95, 108, 9, 35, 137, 230, 137, 247, 146, 150, 96, 88, 56, 242, 77,
7530 59, 238, 58, 4, 129, 110, 161, 183, 146, 191, 235, 246, 93, 55, 202, 136, 211, 135, 76,
7531 27, 183, 240, 38, 132, 111, 111, 247, 18, 171, 16, 36, 122, 78, 200, 209, 123, 76, 133,
7532 220, 124, 99, 221, 27, 160, 216, 235, 36, 212, 56, 197, 12, 79, 176, 201, 231, 206,
7533 161, 230, 233, 67, 137, 29, 86, 42, 95, 4, 201, 230, 123, 152, 89, 213, 98, 181, 38,
7534 203, 218, 20,
7535 ];
7536 let mul_scalar_le: [u8; 32] = [
7537 147, 154, 188, 106, 202, 232, 95, 242, 32, 41, 128, 61, 255, 159, 66, 107, 162, 120, 3,
7538 117, 225, 188, 223, 129, 91, 109, 37, 187, 151, 111, 192, 29,
7539 ];
7540 let expected_mul_le: [u8; 192] = [
7541 179, 97, 99, 239, 22, 225, 246, 148, 92, 98, 137, 164, 201, 221, 90, 38, 241, 191, 33,
7542 252, 238, 31, 240, 23, 13, 132, 61, 48, 250, 58, 240, 189, 82, 24, 135, 184, 5, 66, 31,
7543 13, 200, 63, 147, 141, 96, 82, 107, 6, 153, 181, 143, 123, 74, 33, 15, 100, 240, 111,
7544 213, 151, 19, 143, 92, 36, 81, 34, 251, 4, 214, 122, 104, 43, 138, 209, 9, 211, 121,
7545 41, 111, 33, 252, 174, 39, 202, 16, 254, 148, 188, 128, 38, 200, 26, 192, 88, 92, 10,
7546 189, 214, 207, 218, 117, 31, 144, 97, 94, 186, 53, 129, 53, 191, 228, 222, 169, 183,
7547 111, 74, 196, 243, 134, 51, 2, 77, 183, 162, 113, 38, 145, 39, 246, 63, 153, 185, 104,
7548 41, 133, 64, 4, 211, 11, 175, 184, 38, 76, 18, 182, 59, 76, 44, 11, 12, 201, 82, 219,
7549 87, 4, 33, 122, 208, 15, 250, 197, 212, 58, 149, 43, 84, 14, 161, 17, 146, 126, 223,
7550 175, 50, 206, 40, 103, 119, 59, 34, 41, 100, 233, 58, 182, 165, 156, 14, 114, 39, 251,
7551 20,
7552 ];
7553
7554 let scalar_be_va = 0x100000000;
7555 let point_be_va = 0x200000000;
7556 let scalar_le_va = 0x300000000;
7557 let point_le_va = 0x400000000;
7558 let result_be_va = 0x500000000;
7559 let result_le_va = 0x600000000;
7560
7561 let mut result_be_buf = [0u8; 192];
7562 let mut result_le_buf = [0u8; 192];
7563
7564 let memory_mapping = unsafe {
7565 MemoryMapping::new(
7566 vec![
7567 MemoryRegion::new(&raw const mul_scalar_be, scalar_be_va),
7568 MemoryRegion::new(&raw const mul_point_be, point_be_va),
7569 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7570 MemoryRegion::new(&raw const mul_scalar_le, scalar_le_va),
7571 MemoryRegion::new(&raw const mul_point_le, point_le_va),
7572 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7573 ],
7574 &config,
7575 SBPFVersion::V3,
7576 )
7577 .unwrap()
7578 };
7579 invoke_context
7580 .memory_contexts
7581 .mock_set_mapping_abi_v1(memory_mapping);
7582
7583 let bls12_381_g2_multiply_cost = invoke_context
7584 .get_execution_cost()
7585 .bls12_381_g2_multiply_cost;
7586 invoke_context
7587 .compute_meter
7588 .mock_set_remaining(2 * bls12_381_g2_multiply_cost);
7589
7590 let result = SyscallCurveGroupOps::rust(
7591 &mut invoke_context,
7592 BLS12_381_G2_BE,
7593 MUL,
7594 scalar_be_va,
7595 point_be_va,
7596 result_be_va,
7597 );
7598
7599 assert_eq!(0, result.unwrap());
7600 assert_eq!(result_be_buf, expected_mul_be);
7601
7602 let result = SyscallCurveGroupOps::rust(
7603 &mut invoke_context,
7604 BLS12_381_G2_LE,
7605 MUL,
7606 scalar_le_va,
7607 point_le_va,
7608 result_le_va,
7609 );
7610
7611 assert_eq!(0, result.unwrap());
7612 assert_eq!(result_le_buf, expected_mul_le);
7613 }
7614
7615 #[test]
7616 fn test_syscall_bls12_381_pairing_be() {
7617 use solana_define_syscall::curve_constants::BLS12_381_BE;
7618
7619 let config = Config::default();
7620 let feature_set = SVMFeatureSet {
7621 enable_bls12_381_syscall: true,
7622 ..Default::default()
7623 };
7624 let feature_set = &feature_set;
7625
7626 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7627
7628 let g1_bytes: [u8; 96] = [
7629 3, 161, 104, 54, 242, 116, 16, 50, 15, 113, 42, 38, 108, 11, 127, 64, 43, 249, 50, 133,
7630 105, 8, 133, 238, 34, 6, 189, 119, 153, 36, 75, 65, 87, 249, 90, 109, 133, 200, 203,
7631 25, 127, 68, 251, 243, 14, 210, 204, 35, 18, 124, 149, 5, 68, 178, 57, 230, 253, 154,
7632 192, 163, 5, 146, 144, 100, 7, 102, 9, 76, 67, 251, 147, 45, 27, 111, 204, 213, 219,
7633 141, 58, 11, 235, 100, 6, 220, 77, 230, 232, 200, 210, 200, 3, 184, 10, 80, 23, 164,
7634 ];
7635 let g2_bytes: [u8; 192] = [
7636 8, 249, 218, 154, 232, 125, 250, 185, 153, 60, 132, 155, 188, 119, 50, 205, 32, 76,
7637 184, 181, 164, 158, 64, 12, 179, 181, 150, 95, 226, 9, 175, 51, 169, 185, 34, 178, 249,
7638 161, 27, 164, 210, 107, 171, 203, 246, 11, 158, 86, 14, 135, 197, 225, 7, 44, 94, 243,
7639 216, 200, 100, 199, 118, 14, 106, 181, 88, 202, 207, 156, 227, 101, 126, 236, 46, 189,
7640 238, 73, 220, 118, 151, 73, 255, 249, 103, 103, 255, 185, 91, 82, 212, 148, 110, 19,
7641 212, 111, 199, 197, 4, 144, 25, 145, 196, 142, 205, 252, 85, 85, 48, 243, 209, 62, 57,
7642 212, 44, 149, 81, 113, 171, 60, 193, 73, 40, 11, 36, 120, 19, 62, 2, 25, 22, 232, 227,
7643 50, 35, 75, 172, 205, 2, 37, 27, 65, 182, 6, 74, 43, 1, 239, 105, 129, 184, 98, 215,
7644 81, 15, 19, 171, 39, 252, 57, 176, 171, 181, 71, 124, 251, 53, 202, 213, 33, 58, 175,
7645 52, 41, 89, 230, 217, 177, 32, 24, 82, 166, 240, 232, 223, 24, 141, 70, 121, 25, 51,
7646 173, 30, 6,
7647 ];
7648 let expected_gt: [u8; 576] = [
7649 14, 57, 164, 128, 118, 229, 58, 194, 163, 179, 7, 155, 19, 27, 195, 184, 247, 246, 83,
7650 76, 63, 71, 120, 72, 143, 130, 2, 192, 35, 251, 36, 232, 229, 122, 68, 126, 54, 228,
7651 197, 249, 112, 234, 93, 130, 133, 246, 75, 41, 13, 31, 232, 225, 105, 219, 180, 105,
7652 225, 184, 43, 57, 184, 10, 228, 147, 245, 227, 40, 68, 215, 217, 15, 164, 14, 231, 119,
7653 134, 120, 33, 210, 52, 64, 47, 39, 42, 171, 221, 225, 58, 249, 247, 204, 161, 20, 16,
7654 103, 1, 0, 168, 109, 157, 223, 60, 147, 11, 76, 2, 95, 86, 174, 4, 100, 125, 124, 226,
7655 31, 159, 199, 160, 49, 98, 76, 124, 221, 101, 6, 213, 111, 44, 24, 172, 78, 42, 216,
7656 137, 91, 68, 211, 40, 210, 172, 242, 29, 115, 220, 11, 156, 249, 117, 118, 12, 59, 59,
7657 87, 137, 217, 190, 144, 62, 249, 103, 244, 247, 152, 112, 238, 31, 122, 136, 39, 9, 49,
7658 215, 22, 180, 164, 120, 166, 115, 62, 130, 4, 216, 57, 155, 8, 214, 116, 9, 222, 168,
7659 34, 242, 19, 47, 183, 124, 196, 222, 58, 135, 75, 97, 242, 231, 190, 238, 162, 50, 124,
7660 230, 229, 172, 156, 140, 196, 163, 213, 49, 153, 144, 167, 118, 122, 167, 70, 203, 145,
7661 120, 237, 46, 135, 130, 0, 204, 139, 61, 22, 10, 243, 232, 15, 38, 161, 146, 106, 138,
7662 86, 198, 8, 167, 229, 125, 95, 28, 120, 51, 23, 161, 250, 105, 125, 177, 169, 168, 97,
7663 5, 0, 231, 143, 141, 22, 92, 143, 148, 95, 66, 151, 154, 55, 169, 0, 91, 107, 5, 59,
7664 252, 8, 140, 0, 195, 64, 135, 197, 226, 235, 170, 127, 176, 217, 7, 180, 235, 222, 58,
7665 195, 221, 192, 130, 86, 143, 0, 199, 225, 53, 57, 181, 151, 152, 81, 183, 252, 251, 5,
7666 124, 61, 164, 133, 169, 14, 20, 206, 36, 56, 1, 197, 214, 23, 10, 32, 223, 128, 87,
7667 166, 33, 61, 29, 190, 90, 150, 82, 121, 109, 255, 211, 79, 46, 57, 48, 213, 125, 8, 93,
7668 10, 151, 162, 137, 133, 129, 237, 101, 77, 39, 85, 94, 234, 43, 85, 101, 240, 233, 93,
7669 57, 171, 13, 18, 38, 31, 29, 41, 169, 193, 49, 108, 119, 231, 130, 97, 45, 35, 252,
7670 149, 125, 116, 64, 163, 70, 40, 143, 160, 14, 15, 91, 168, 207, 77, 40, 74, 208, 114,
7671 50, 64, 119, 216, 182, 96, 218, 0, 185, 69, 105, 194, 103, 19, 129, 33, 204, 250, 237,
7672 191, 143, 122, 56, 234, 62, 8, 224, 1, 242, 110, 10, 194, 178, 198, 220, 151, 167, 234,
7673 235, 207, 148, 93, 249, 221, 153, 15, 86, 89, 76, 49, 29, 18, 74, 0, 246, 42, 143, 89,
7674 60, 48, 96, 23, 173, 209, 213, 156, 80, 154, 159, 161, 12, 178, 225, 226, 77, 99, 249,
7675 154, 246, 110, 96, 176, 79, 90, 2, 190, 63, 189, 123, 170, 206, 119, 142, 138, 15, 93,
7676 191, 230, 100, 159, 142, 50, 119, 204, 157, 201, 230, 93, 57, 3, 125, 96, 195, 247,
7677 195, 76, 24, 176, 99, 88, 206, 86, 63, 204, 37, 173, 182, 116, 51, 240, 15, 155, 199,
7678 199, 198, 183, 44, 241, 251, 236, 35, 178, 36, 8, 107, 82, 153, 144, 28, 29, 229, 150,
7679 157, 37, 216, 96, 116,
7680 ];
7681
7682 let g1_va = 0x100000000;
7683 let g2_va = 0x200000000;
7684 let result_va = 0x300000000;
7685
7686 let mut result_buf = [0u8; 576]; let memory_mapping = unsafe {
7689 MemoryMapping::new(
7690 vec![
7691 MemoryRegion::new(&raw const g1_bytes, g1_va),
7692 MemoryRegion::new(&raw const g2_bytes, g2_va),
7693 MemoryRegion::new(&raw mut result_buf, result_va),
7694 ],
7695 &config,
7696 SBPFVersion::V3,
7697 )
7698 .unwrap()
7699 };
7700 invoke_context
7701 .memory_contexts
7702 .mock_set_mapping_abi_v1(memory_mapping);
7703
7704 let bls12_381_one_pair_cost = invoke_context.get_execution_cost().bls12_381_one_pair_cost;
7705 invoke_context
7706 .compute_meter
7707 .mock_set_remaining(bls12_381_one_pair_cost);
7708
7709 let result = SyscallCurvePairingMap::rust(
7710 &mut invoke_context,
7711 BLS12_381_BE,
7712 1,
7713 g1_va,
7714 g2_va,
7715 result_va,
7716 );
7717
7718 assert_eq!(0, result.unwrap());
7719 assert_eq!(result_buf, expected_gt);
7720 }
7721
7722 #[test]
7723 fn test_syscall_bls12_381_pairing_le() {
7724 use solana_define_syscall::curve_constants::BLS12_381_LE;
7725
7726 let config = Config::default();
7727 let feature_set = SVMFeatureSet {
7728 enable_bls12_381_syscall: true,
7729 ..Default::default()
7730 };
7731 let feature_set = &feature_set;
7732
7733 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7734
7735 let g1_bytes: [u8; 96] = [
7736 35, 204, 210, 14, 243, 251, 68, 127, 25, 203, 200, 133, 109, 90, 249, 87, 65, 75, 36,
7737 153, 119, 189, 6, 34, 238, 133, 8, 105, 133, 50, 249, 43, 64, 127, 11, 108, 38, 42,
7738 113, 15, 50, 16, 116, 242, 54, 104, 161, 3, 164, 23, 80, 10, 184, 3, 200, 210, 200,
7739 232, 230, 77, 220, 6, 100, 235, 11, 58, 141, 219, 213, 204, 111, 27, 45, 147, 251, 67,
7740 76, 9, 102, 7, 100, 144, 146, 5, 163, 192, 154, 253, 230, 57, 178, 68, 5, 149, 124, 18,
7741 ];
7742 let g2_bytes: [u8; 192] = [
7743 197, 199, 111, 212, 19, 110, 148, 212, 82, 91, 185, 255, 103, 103, 249, 255, 73, 151,
7744 118, 220, 73, 238, 189, 46, 236, 126, 101, 227, 156, 207, 202, 88, 181, 106, 14, 118,
7745 199, 100, 200, 216, 243, 94, 44, 7, 225, 197, 135, 14, 86, 158, 11, 246, 203, 171, 107,
7746 210, 164, 27, 161, 249, 178, 34, 185, 169, 51, 175, 9, 226, 95, 150, 181, 179, 12, 64,
7747 158, 164, 181, 184, 76, 32, 205, 50, 119, 188, 155, 132, 60, 153, 185, 250, 125, 232,
7748 154, 218, 249, 8, 6, 30, 173, 51, 25, 121, 70, 141, 24, 223, 232, 240, 166, 82, 24, 32,
7749 177, 217, 230, 89, 41, 52, 175, 58, 33, 213, 202, 53, 251, 124, 71, 181, 171, 176, 57,
7750 252, 39, 171, 19, 15, 81, 215, 98, 184, 129, 105, 239, 1, 43, 74, 6, 182, 65, 27, 37,
7751 2, 205, 172, 75, 35, 50, 227, 232, 22, 25, 2, 62, 19, 120, 36, 11, 40, 73, 193, 60,
7752 171, 113, 81, 149, 44, 212, 57, 62, 209, 243, 48, 85, 85, 252, 205, 142, 196, 145, 25,
7753 144, 4,
7754 ];
7755 let expected_gt: [u8; 576] = [
7756 116, 96, 216, 37, 157, 150, 229, 29, 28, 144, 153, 82, 107, 8, 36, 178, 35, 236, 251,
7757 241, 44, 183, 198, 199, 199, 155, 15, 240, 51, 116, 182, 173, 37, 204, 63, 86, 206, 88,
7758 99, 176, 24, 76, 195, 247, 195, 96, 125, 3, 57, 93, 230, 201, 157, 204, 119, 50, 142,
7759 159, 100, 230, 191, 93, 15, 138, 142, 119, 206, 170, 123, 189, 63, 190, 2, 90, 79, 176,
7760 96, 110, 246, 154, 249, 99, 77, 226, 225, 178, 12, 161, 159, 154, 80, 156, 213, 209,
7761 173, 23, 96, 48, 60, 89, 143, 42, 246, 0, 74, 18, 29, 49, 76, 89, 86, 15, 153, 221,
7762 249, 93, 148, 207, 235, 234, 167, 151, 220, 198, 178, 194, 10, 110, 242, 1, 224, 8, 62,
7763 234, 56, 122, 143, 191, 237, 250, 204, 33, 129, 19, 103, 194, 105, 69, 185, 0, 218, 96,
7764 182, 216, 119, 64, 50, 114, 208, 74, 40, 77, 207, 168, 91, 15, 14, 160, 143, 40, 70,
7765 163, 64, 116, 125, 149, 252, 35, 45, 97, 130, 231, 119, 108, 49, 193, 169, 41, 29, 31,
7766 38, 18, 13, 171, 57, 93, 233, 240, 101, 85, 43, 234, 94, 85, 39, 77, 101, 237, 129,
7767 133, 137, 162, 151, 10, 93, 8, 125, 213, 48, 57, 46, 79, 211, 255, 109, 121, 82, 150,
7768 90, 190, 29, 61, 33, 166, 87, 128, 223, 32, 10, 23, 214, 197, 1, 56, 36, 206, 20, 14,
7769 169, 133, 164, 61, 124, 5, 251, 252, 183, 81, 152, 151, 181, 57, 53, 225, 199, 0, 143,
7770 86, 130, 192, 221, 195, 58, 222, 235, 180, 7, 217, 176, 127, 170, 235, 226, 197, 135,
7771 64, 195, 0, 140, 8, 252, 59, 5, 107, 91, 0, 169, 55, 154, 151, 66, 95, 148, 143, 92,
7772 22, 141, 143, 231, 0, 5, 97, 168, 169, 177, 125, 105, 250, 161, 23, 51, 120, 28, 95,
7773 125, 229, 167, 8, 198, 86, 138, 106, 146, 161, 38, 15, 232, 243, 10, 22, 61, 139, 204,
7774 0, 130, 135, 46, 237, 120, 145, 203, 70, 167, 122, 118, 167, 144, 153, 49, 213, 163,
7775 196, 140, 156, 172, 229, 230, 124, 50, 162, 238, 190, 231, 242, 97, 75, 135, 58, 222,
7776 196, 124, 183, 47, 19, 242, 34, 168, 222, 9, 116, 214, 8, 155, 57, 216, 4, 130, 62,
7777 115, 166, 120, 164, 180, 22, 215, 49, 9, 39, 136, 122, 31, 238, 112, 152, 247, 244,
7778 103, 249, 62, 144, 190, 217, 137, 87, 59, 59, 12, 118, 117, 249, 156, 11, 220, 115, 29,
7779 242, 172, 210, 40, 211, 68, 91, 137, 216, 42, 78, 172, 24, 44, 111, 213, 6, 101, 221,
7780 124, 76, 98, 49, 160, 199, 159, 31, 226, 124, 125, 100, 4, 174, 86, 95, 2, 76, 11, 147,
7781 60, 223, 157, 109, 168, 0, 1, 103, 16, 20, 161, 204, 247, 249, 58, 225, 221, 171, 42,
7782 39, 47, 64, 52, 210, 33, 120, 134, 119, 231, 14, 164, 15, 217, 215, 68, 40, 227, 245,
7783 147, 228, 10, 184, 57, 43, 184, 225, 105, 180, 219, 105, 225, 232, 31, 13, 41, 75, 246,
7784 133, 130, 93, 234, 112, 249, 197, 228, 54, 126, 68, 122, 229, 232, 36, 251, 35, 192, 2,
7785 130, 143, 72, 120, 71, 63, 76, 83, 246, 247, 184, 195, 27, 19, 155, 7, 179, 163, 194,
7786 58, 229, 118, 128, 164, 57, 14,
7787 ];
7788
7789 let g1_va = 0x100000000;
7790 let g2_va = 0x200000000;
7791 let result_va = 0x300000000;
7792
7793 let mut result_buf = [0u8; 576]; let memory_mapping = unsafe {
7796 MemoryMapping::new(
7797 vec![
7798 MemoryRegion::new(&raw const g1_bytes, g1_va),
7799 MemoryRegion::new(&raw const g2_bytes, g2_va),
7800 MemoryRegion::new(&raw mut result_buf, result_va),
7801 ],
7802 &config,
7803 SBPFVersion::V3,
7804 )
7805 .unwrap()
7806 };
7807 invoke_context
7808 .memory_contexts
7809 .mock_set_mapping_abi_v1(memory_mapping);
7810
7811 let bls12_381_one_pair_cost = invoke_context.get_execution_cost().bls12_381_one_pair_cost;
7812 invoke_context
7813 .compute_meter
7814 .mock_set_remaining(bls12_381_one_pair_cost);
7815
7816 let result = SyscallCurvePairingMap::rust(
7817 &mut invoke_context,
7818 BLS12_381_LE,
7819 1,
7820 g1_va,
7821 g2_va,
7822 result_va,
7823 );
7824
7825 assert_eq!(0, result.unwrap());
7826 assert_eq!(result_buf, expected_gt);
7827 }
7828
7829 #[test]
7830 fn test_syscall_bls12_381_decompress_g1() {
7831 use solana_define_syscall::curve_constants::{BLS12_381_G1_BE, BLS12_381_G1_LE};
7832
7833 let config = Config::default();
7834 let feature_set = SVMFeatureSet {
7835 enable_bls12_381_syscall: true,
7836 ..Default::default()
7837 };
7838 let feature_set = &feature_set;
7839
7840 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7841
7842 let compressed_be: [u8; 48] = [
7843 175, 159, 245, 68, 142, 96, 188, 154, 113, 143, 70, 58, 193, 2, 189, 111, 135, 114,
7844 230, 70, 12, 25, 7, 106, 108, 137, 213, 128, 110, 90, 142, 244, 75, 111, 59, 138, 240,
7845 158, 55, 164, 229, 100, 152, 122, 38, 185, 222, 218,
7846 ];
7847 let expected_affine_be: [u8; 96] = [
7848 15, 159, 245, 68, 142, 96, 188, 154, 113, 143, 70, 58, 193, 2, 189, 111, 135, 114, 230,
7849 70, 12, 25, 7, 106, 108, 137, 213, 128, 110, 90, 142, 244, 75, 111, 59, 138, 240, 158,
7850 55, 164, 229, 100, 152, 122, 38, 185, 222, 218, 18, 79, 1, 246, 62, 35, 162, 234, 146,
7851 109, 7, 85, 44, 104, 10, 250, 158, 31, 181, 244, 117, 193, 27, 53, 184, 79, 160, 237,
7852 168, 51, 41, 200, 58, 4, 107, 95, 246, 171, 241, 202, 120, 228, 135, 135, 100, 50, 123,
7853 58,
7854 ];
7855 let compressed_le: [u8; 48] = [
7856 218, 222, 185, 38, 122, 152, 100, 229, 164, 55, 158, 240, 138, 59, 111, 75, 244, 142,
7857 90, 110, 128, 213, 137, 108, 106, 7, 25, 12, 70, 230, 114, 135, 111, 189, 2, 193, 58,
7858 70, 143, 113, 154, 188, 96, 142, 68, 245, 159, 175,
7859 ];
7860 let expected_affine_le: [u8; 96] = [
7861 218, 222, 185, 38, 122, 152, 100, 229, 164, 55, 158, 240, 138, 59, 111, 75, 244, 142,
7862 90, 110, 128, 213, 137, 108, 106, 7, 25, 12, 70, 230, 114, 135, 111, 189, 2, 193, 58,
7863 70, 143, 113, 154, 188, 96, 142, 68, 245, 159, 15, 58, 123, 50, 100, 135, 135, 228,
7864 120, 202, 241, 171, 246, 95, 107, 4, 58, 200, 41, 51, 168, 237, 160, 79, 184, 53, 27,
7865 193, 117, 244, 181, 31, 158, 250, 10, 104, 44, 85, 7, 109, 146, 234, 162, 35, 62, 246,
7866 1, 79, 18,
7867 ];
7868
7869 let input_be_va = 0x100000000;
7870 let result_be_va = 0x200000000;
7871 let input_le_va = 0x300000000;
7872 let result_le_va = 0x400000000;
7873 let mut result_be_buf = [0u8; 96];
7874 let mut result_le_buf = [0u8; 96];
7875
7876 let memory_mapping = unsafe {
7877 MemoryMapping::new(
7878 vec![
7879 MemoryRegion::new(&raw const compressed_be, input_be_va),
7880 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7881 MemoryRegion::new(&raw const compressed_le, input_le_va),
7882 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7883 ],
7884 &config,
7885 SBPFVersion::V3,
7886 )
7887 .unwrap()
7888 };
7889 invoke_context
7890 .memory_contexts
7891 .mock_set_mapping_abi_v1(memory_mapping);
7892
7893 let bls12_381_g2_decompress_cost = invoke_context
7894 .get_execution_cost()
7895 .bls12_381_g2_decompress_cost;
7896 invoke_context
7897 .compute_meter
7898 .mock_set_remaining(2 * bls12_381_g2_decompress_cost);
7899
7900 let result = SyscallCurveDecompress::rust(
7901 &mut invoke_context,
7902 BLS12_381_G1_BE,
7903 input_be_va,
7904 result_be_va,
7905 0,
7906 0,
7907 );
7908
7909 assert_eq!(0, result.unwrap());
7910 assert_eq!(result_be_buf, expected_affine_be);
7911
7912 let result = SyscallCurveDecompress::rust(
7913 &mut invoke_context,
7914 BLS12_381_G1_LE,
7915 input_le_va,
7916 result_le_va,
7917 0,
7918 0,
7919 );
7920
7921 assert_eq!(0, result.unwrap());
7922 assert_eq!(result_le_buf, expected_affine_le);
7923 }
7924
7925 #[test]
7926 fn test_syscall_bls12_381_decompress_g2() {
7927 use solana_define_syscall::curve_constants::{BLS12_381_G2_BE, BLS12_381_G2_LE};
7928
7929 let config = Config::default();
7930 let feature_set = SVMFeatureSet {
7931 enable_bls12_381_syscall: true,
7932 ..Default::default()
7933 };
7934 let feature_set = &feature_set;
7935
7936 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
7937
7938 let compressed_be: [u8; 96] = [
7939 143, 106, 18, 220, 40, 152, 4, 228, 139, 35, 104, 146, 179, 74, 205, 172, 146, 137, 11,
7940 106, 74, 42, 135, 137, 53, 249, 64, 251, 173, 232, 48, 209, 125, 222, 13, 209, 121,
7941 238, 185, 179, 111, 105, 71, 223, 39, 48, 195, 104, 23, 24, 170, 59, 111, 106, 167, 51,
7942 231, 186, 224, 182, 172, 73, 15, 18, 211, 143, 59, 2, 115, 190, 196, 163, 111, 11, 36,
7943 133, 86, 96, 188, 135, 16, 37, 216, 175, 71, 182, 222, 31, 207, 155, 16, 255, 112, 78,
7944 242, 111,
7945 ];
7946 let expected_affine_be: [u8; 192] = [
7947 15, 106, 18, 220, 40, 152, 4, 228, 139, 35, 104, 146, 179, 74, 205, 172, 146, 137, 11,
7948 106, 74, 42, 135, 137, 53, 249, 64, 251, 173, 232, 48, 209, 125, 222, 13, 209, 121,
7949 238, 185, 179, 111, 105, 71, 223, 39, 48, 195, 104, 23, 24, 170, 59, 111, 106, 167, 51,
7950 231, 186, 224, 182, 172, 73, 15, 18, 211, 143, 59, 2, 115, 190, 196, 163, 111, 11, 36,
7951 133, 86, 96, 188, 135, 16, 37, 216, 175, 71, 182, 222, 31, 207, 155, 16, 255, 112, 78,
7952 242, 111, 11, 217, 244, 83, 201, 111, 182, 168, 171, 205, 183, 118, 199, 85, 130, 157,
7953 95, 69, 159, 126, 122, 27, 92, 84, 253, 147, 96, 176, 74, 57, 13, 228, 178, 111, 246,
7954 157, 74, 120, 174, 255, 146, 92, 32, 214, 164, 56, 206, 144, 13, 59, 111, 251, 170, 85,
7955 159, 219, 108, 187, 31, 15, 106, 176, 64, 191, 56, 77, 217, 87, 144, 196, 148, 21, 12,
7956 171, 99, 121, 128, 120, 187, 224, 192, 107, 104, 178, 75, 205, 118, 64, 234, 168, 214,
7957 11, 125, 153, 55, 5,
7958 ];
7959 let compressed_le: [u8; 96] = [
7960 111, 242, 78, 112, 255, 16, 155, 207, 31, 222, 182, 71, 175, 216, 37, 16, 135, 188, 96,
7961 86, 133, 36, 11, 111, 163, 196, 190, 115, 2, 59, 143, 211, 18, 15, 73, 172, 182, 224,
7962 186, 231, 51, 167, 106, 111, 59, 170, 24, 23, 104, 195, 48, 39, 223, 71, 105, 111, 179,
7963 185, 238, 121, 209, 13, 222, 125, 209, 48, 232, 173, 251, 64, 249, 53, 137, 135, 42,
7964 74, 106, 11, 137, 146, 172, 205, 74, 179, 146, 104, 35, 139, 228, 4, 152, 40, 220, 18,
7965 106, 143,
7966 ];
7967 let expected_affine_le: [u8; 192] = [
7968 111, 242, 78, 112, 255, 16, 155, 207, 31, 222, 182, 71, 175, 216, 37, 16, 135, 188, 96,
7969 86, 133, 36, 11, 111, 163, 196, 190, 115, 2, 59, 143, 211, 18, 15, 73, 172, 182, 224,
7970 186, 231, 51, 167, 106, 111, 59, 170, 24, 23, 104, 195, 48, 39, 223, 71, 105, 111, 179,
7971 185, 238, 121, 209, 13, 222, 125, 209, 48, 232, 173, 251, 64, 249, 53, 137, 135, 42,
7972 74, 106, 11, 137, 146, 172, 205, 74, 179, 146, 104, 35, 139, 228, 4, 152, 40, 220, 18,
7973 106, 15, 5, 55, 153, 125, 11, 214, 168, 234, 64, 118, 205, 75, 178, 104, 107, 192, 224,
7974 187, 120, 128, 121, 99, 171, 12, 21, 148, 196, 144, 87, 217, 77, 56, 191, 64, 176, 106,
7975 15, 31, 187, 108, 219, 159, 85, 170, 251, 111, 59, 13, 144, 206, 56, 164, 214, 32, 92,
7976 146, 255, 174, 120, 74, 157, 246, 111, 178, 228, 13, 57, 74, 176, 96, 147, 253, 84, 92,
7977 27, 122, 126, 159, 69, 95, 157, 130, 85, 199, 118, 183, 205, 171, 168, 182, 111, 201,
7978 83, 244, 217, 11,
7979 ];
7980
7981 let input_be_va = 0x100000000;
7982 let result_be_va = 0x200000000;
7983 let input_le_va = 0x300000000;
7984 let result_le_va = 0x400000000;
7985 let mut result_be_buf = [0u8; 192];
7986 let mut result_le_buf = [0u8; 192];
7987
7988 let memory_mapping = unsafe {
7989 MemoryMapping::new(
7990 vec![
7991 MemoryRegion::new(&raw const compressed_be, input_be_va),
7992 MemoryRegion::new(&raw mut result_be_buf, result_be_va),
7993 MemoryRegion::new(&raw const compressed_le, input_le_va),
7994 MemoryRegion::new(&raw mut result_le_buf, result_le_va),
7995 ],
7996 &config,
7997 SBPFVersion::V3,
7998 )
7999 .unwrap()
8000 };
8001 invoke_context
8002 .memory_contexts
8003 .mock_set_mapping_abi_v1(memory_mapping);
8004
8005 let bls12_381_g2_decompress_cost = invoke_context
8006 .get_execution_cost()
8007 .bls12_381_g2_decompress_cost;
8008 invoke_context
8009 .compute_meter
8010 .mock_set_remaining(2 * bls12_381_g2_decompress_cost);
8011
8012 let result = SyscallCurveDecompress::rust(
8013 &mut invoke_context,
8014 BLS12_381_G2_BE,
8015 input_be_va,
8016 result_be_va,
8017 0,
8018 0,
8019 );
8020
8021 assert_eq!(0, result.unwrap());
8022 assert_eq!(result_be_buf, expected_affine_be);
8023
8024 let result = SyscallCurveDecompress::rust(
8025 &mut invoke_context,
8026 BLS12_381_G2_LE,
8027 input_le_va,
8028 result_le_va,
8029 0,
8030 0,
8031 );
8032
8033 assert_eq!(0, result.unwrap());
8034 assert_eq!(result_le_buf, expected_affine_le);
8035 }
8036
8037 #[test]
8038 fn test_syscall_bls12_381_validate_g1() {
8039 use solana_define_syscall::curve_constants::{BLS12_381_G1_BE, BLS12_381_G1_LE};
8040
8041 let config = Config::default();
8042 let feature_set = SVMFeatureSet {
8043 enable_bls12_381_syscall: true,
8044 ..Default::default()
8045 };
8046 let feature_set = &feature_set;
8047
8048 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
8049
8050 let point_bytes_be: [u8; 96] = [
8051 22, 163, 250, 67, 197, 168, 103, 201, 128, 33, 170, 96, 74, 40, 45, 90, 105, 181, 244,
8052 124, 128, 107, 27, 142, 158, 96, 0, 46, 144, 27, 61, 205, 65, 38, 141, 165, 55, 113,
8053 114, 23, 36, 105, 252, 115, 147, 16, 12, 39, 11, 19, 53, 215, 107, 128, 94, 68, 22, 46,
8054 74, 179, 236, 232, 220, 30, 48, 169, 85, 16, 70, 112, 26, 37, 73, 104, 203, 189, 42,
8055 96, 141, 90, 167, 41, 61, 82, 184, 80, 93, 112, 204, 140, 225, 245, 103, 130, 184, 194,
8056 ];
8057
8058 let point_bytes_le: [u8; 96] = [
8059 39, 12, 16, 147, 115, 252, 105, 36, 23, 114, 113, 55, 165, 141, 38, 65, 205, 61, 27,
8060 144, 46, 0, 96, 158, 142, 27, 107, 128, 124, 244, 181, 105, 90, 45, 40, 74, 96, 170,
8061 33, 128, 201, 103, 168, 197, 67, 250, 163, 22, 194, 184, 130, 103, 245, 225, 140, 204,
8062 112, 93, 80, 184, 82, 61, 41, 167, 90, 141, 96, 42, 189, 203, 104, 73, 37, 26, 112, 70,
8063 16, 85, 169, 48, 30, 220, 232, 236, 179, 74, 46, 22, 68, 94, 128, 107, 215, 53, 19, 11,
8064 ];
8065
8066 let point_be_va = 0x100000000;
8067 let point_le_va = 0x200000000;
8068
8069 let memory_mapping = unsafe {
8070 MemoryMapping::new(
8071 vec![
8072 MemoryRegion::new(&raw const point_bytes_be, point_be_va),
8073 MemoryRegion::new(&raw const point_bytes_le, point_le_va),
8074 ],
8075 &config,
8076 SBPFVersion::V3,
8077 )
8078 .unwrap()
8079 };
8080 invoke_context
8081 .memory_contexts
8082 .mock_set_mapping_abi_v1(memory_mapping);
8083
8084 let bls12_381_g1_validate_cost = invoke_context
8085 .get_execution_cost()
8086 .bls12_381_g1_validate_cost;
8087 invoke_context
8088 .compute_meter
8089 .mock_set_remaining(2 * bls12_381_g1_validate_cost);
8090
8091 let result = SyscallCurvePointValidation::rust(
8092 &mut invoke_context,
8093 BLS12_381_G1_BE,
8094 point_be_va,
8095 0,
8096 0,
8097 0,
8098 );
8099
8100 assert_eq!(0, result.unwrap());
8101
8102 let result = SyscallCurvePointValidation::rust(
8103 &mut invoke_context,
8104 BLS12_381_G1_LE,
8105 point_le_va,
8106 0,
8107 0,
8108 0,
8109 );
8110
8111 assert_eq!(0, result.unwrap());
8112 }
8113
8114 #[test]
8115 fn test_syscall_bls12_381_validate_g2() {
8116 use solana_define_syscall::curve_constants::{BLS12_381_G2_BE, BLS12_381_G2_LE};
8117
8118 let config = Config::default();
8119 let feature_set = SVMFeatureSet {
8120 enable_bls12_381_syscall: true,
8121 ..Default::default()
8122 };
8123 let feature_set = &feature_set;
8124
8125 prepare_mock_with_feature_set!(invoke_context, program_id, bpf_loader::id(), feature_set,);
8126
8127 let point_bytes_be: [u8; 192] = [
8128 0, 79, 207, 115, 91, 72, 0, 80, 49, 59, 203, 189, 178, 240, 18, 141, 223, 147, 62, 79,
8129 98, 131, 147, 33, 103, 151, 137, 12, 160, 13, 78, 180, 13, 221, 89, 239, 178, 249, 141,
8130 8, 38, 137, 23, 71, 213, 2, 28, 13, 24, 168, 51, 6, 34, 184, 228, 22, 173, 11, 224,
8131 168, 14, 103, 154, 18, 166, 51, 255, 154, 45, 230, 253, 149, 145, 16, 251, 107, 248,
8132 55, 53, 150, 37, 131, 133, 138, 156, 195, 70, 202, 131, 144, 166, 164, 80, 251, 179,
8133 167, 8, 54, 188, 153, 10, 235, 83, 14, 211, 95, 212, 54, 120, 175, 148, 83, 253, 106,
8134 53, 178, 157, 118, 208, 110, 0, 187, 111, 14, 140, 246, 139, 200, 205, 178, 72, 36, 67,
8135 140, 39, 100, 163, 104, 140, 78, 91, 123, 130, 197, 12, 176, 70, 104, 65, 43, 104, 232,
8136 102, 238, 229, 115, 253, 62, 61, 207, 116, 223, 245, 206, 250, 163, 30, 200, 76, 101,
8137 93, 69, 216, 240, 189, 198, 253, 27, 199, 32, 215, 224, 12, 50, 78, 204, 106, 40, 117,
8138 68, 44, 113,
8139 ];
8140
8141 let point_bytes_le: [u8; 192] = [
8142 167, 179, 251, 80, 164, 166, 144, 131, 202, 70, 195, 156, 138, 133, 131, 37, 150, 53,
8143 55, 248, 107, 251, 16, 145, 149, 253, 230, 45, 154, 255, 51, 166, 18, 154, 103, 14,
8144 168, 224, 11, 173, 22, 228, 184, 34, 6, 51, 168, 24, 13, 28, 2, 213, 71, 23, 137, 38,
8145 8, 141, 249, 178, 239, 89, 221, 13, 180, 78, 13, 160, 12, 137, 151, 103, 33, 147, 131,
8146 98, 79, 62, 147, 223, 141, 18, 240, 178, 189, 203, 59, 49, 80, 0, 72, 91, 115, 207, 79,
8147 0, 113, 44, 68, 117, 40, 106, 204, 78, 50, 12, 224, 215, 32, 199, 27, 253, 198, 189,
8148 240, 216, 69, 93, 101, 76, 200, 30, 163, 250, 206, 245, 223, 116, 207, 61, 62, 253,
8149 115, 229, 238, 102, 232, 104, 43, 65, 104, 70, 176, 12, 197, 130, 123, 91, 78, 140,
8150 104, 163, 100, 39, 140, 67, 36, 72, 178, 205, 200, 139, 246, 140, 14, 111, 187, 0, 110,
8151 208, 118, 157, 178, 53, 106, 253, 83, 148, 175, 120, 54, 212, 95, 211, 14, 83, 235, 10,
8152 153, 188, 54, 8,
8153 ];
8154
8155 let point_be_va = 0x100000000;
8156 let point_le_va = 0x200000000;
8157
8158 let memory_mapping = unsafe {
8159 MemoryMapping::new(
8160 vec![
8161 MemoryRegion::new(&raw const point_bytes_be, point_be_va),
8162 MemoryRegion::new(&raw const point_bytes_le, point_le_va),
8163 ],
8164 &config,
8165 SBPFVersion::V3,
8166 )
8167 .unwrap()
8168 };
8169 invoke_context
8170 .memory_contexts
8171 .mock_set_mapping_abi_v1(memory_mapping);
8172
8173 let bls12_381_g2_validate_cost = invoke_context
8174 .get_execution_cost()
8175 .bls12_381_g2_validate_cost;
8176 invoke_context
8177 .compute_meter
8178 .mock_set_remaining(2 * bls12_381_g2_validate_cost);
8179
8180 let result = SyscallCurvePointValidation::rust(
8181 &mut invoke_context,
8182 BLS12_381_G2_BE,
8183 point_be_va,
8184 0,
8185 0,
8186 0,
8187 );
8188
8189 assert_eq!(0, result.unwrap());
8190
8191 let result = SyscallCurvePointValidation::rust(
8192 &mut invoke_context,
8193 BLS12_381_G2_LE,
8194 point_le_va,
8195 0,
8196 0,
8197 0,
8198 );
8199
8200 assert_eq!(0, result.unwrap());
8201 }
8202
8203 #[test]
8204 fn test_sol_alloc_free_registration() {
8205 let feature_set = SVMFeatureSet::all_enabled();
8206 let compute_budget = SVMTransactionExecutionBudget::default();
8207
8208 {
8210 let env = create_program_runtime_environment(
8211 &feature_set,
8212 &compute_budget,
8213 false,
8214 false,
8215 )
8216 .unwrap();
8217 assert!(
8218 env.get_function_registry()
8219 .lookup_by_name(b"sol_alloc_free_")
8220 .is_some()
8221 );
8222 }
8223
8224 {
8226 let env = create_program_runtime_environment(
8227 &feature_set,
8228 &compute_budget,
8229 true,
8230 false,
8231 )
8232 .unwrap();
8233 assert!(
8234 env.get_function_registry()
8235 .lookup_by_name(b"sol_alloc_free_")
8236 .is_none()
8237 );
8238 }
8239 }
8240
8241 #[test]
8242 fn test_sol_big_mod_exp_registration() {
8243 let compute_budget = SVMTransactionExecutionBudget::default();
8244
8245 let mut feature_set = SVMFeatureSet::all_enabled();
8246 feature_set.enable_big_mod_exp_syscall = true;
8247 let env = create_program_runtime_environment(
8248 &feature_set,
8249 &compute_budget,
8250 false,
8251 false,
8252 )
8253 .unwrap();
8254 assert!(
8255 env.get_function_registry()
8256 .lookup_by_name(b"sol_big_mod_exp")
8257 .is_some()
8258 );
8259
8260 feature_set.enable_big_mod_exp_syscall = false;
8261 let env = create_program_runtime_environment(
8262 &feature_set,
8263 &compute_budget,
8264 false,
8265 false,
8266 )
8267 .unwrap();
8268 assert!(
8269 env.get_function_registry()
8270 .lookup_by_name(b"sol_big_mod_exp")
8271 .is_none()
8272 );
8273 }
8274
8275 #[test]
8276 fn test_syscall_sha512() {
8277 let config = Config::default();
8278 prepare_mockup!(invoke_context, program_id, bpf_loader_deprecated::id());
8279
8280 let bytes1 = "Gaggablaghblagh!";
8281 let bytes2 = "flurbos";
8282
8283 let mock_slice1 = MockSlice {
8284 vm_addr: 0x300000000,
8285 len: bytes1.len(),
8286 };
8287 let mock_slice2 = MockSlice {
8288 vm_addr: 0x400000000,
8289 len: bytes2.len(),
8290 };
8291 let bytes_to_hash = [mock_slice1, mock_slice2];
8292 let mut hash_result = [0; solana_hash_512::HASH_BYTES];
8293 let ro_len = bytes_to_hash.len() as u64;
8294 let ro_va = 0x100000000;
8295 let rw_va = 0x200000000;
8296 let memory_mapping = unsafe {
8297 MemoryMapping::new(
8298 vec![
8299 MemoryRegion::new(bytes_of_slice(&bytes_to_hash), ro_va),
8300 MemoryRegion::new(bytes_of_slice_mut(&mut hash_result), rw_va),
8301 MemoryRegion::new(&raw const *bytes1.as_bytes(), bytes_to_hash[0].vm_addr),
8302 MemoryRegion::new(&raw const *bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
8303 ],
8304 &config,
8305 SBPFVersion::V3,
8306 )
8307 .unwrap()
8308 };
8309 invoke_context
8310 .memory_contexts
8311 .mock_set_mapping_abi_v1(memory_mapping);
8312 invoke_context.compute_meter.mock_set_remaining(
8313 (invoke_context.get_execution_cost().sha256_base_cost
8314 + invoke_context.get_execution_cost().mem_op_base_cost.max(
8315 invoke_context
8316 .get_execution_cost()
8317 .sha256_byte_cost
8318 .saturating_mul((bytes1.len() + bytes2.len()) as u64 / 2),
8319 ))
8320 * 4,
8321 );
8322
8323 let result =
8324 SyscallHash::<Sha512Hasher>::rust(&mut invoke_context, ro_va, ro_len, rw_va, 0, 0);
8325 result.unwrap();
8326
8327 let hash_local = sha512::hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes();
8328 assert_eq!(hash_result, hash_local);
8329 let result = SyscallHash::<Sha512Hasher>::rust(
8330 &mut invoke_context,
8331 ro_va - 1, ro_len,
8333 rw_va,
8334 0,
8335 0,
8336 );
8337 assert_access_violation!(result, ro_va - 1, 32);
8338 let result = SyscallHash::<Sha512Hasher>::rust(
8339 &mut invoke_context,
8340 ro_va,
8341 ro_len + 1, rw_va,
8343 0,
8344 0,
8345 );
8346 assert_access_violation!(result, ro_va, 48);
8347 let result = SyscallHash::<Sha512Hasher>::rust(
8348 &mut invoke_context,
8349 ro_va,
8350 ro_len,
8351 rw_va - 1, 0,
8353 0,
8354 );
8355 assert_access_violation!(result, rw_va - 1, solana_hash_512::HASH_BYTES as u64);
8356 let result =
8357 SyscallHash::<Sha512Hasher>::rust(&mut invoke_context, ro_va, ro_len, rw_va, 0, 0);
8358 assert_matches!(
8359 result,
8360 Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
8361 );
8362 }
8363}