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