hopper_runtime/syscalls.rs
1//! Minimal syscall shims exposed through Hopper Runtime.
2//!
3//! Hopper-owned crates use this module instead of binding directly to backend
4//! SDK syscall paths. That keeps backend differences inside Hopper Runtime.
5
6/// Emit a `sol_log_data` event payload.
7///
8/// # Safety
9///
10/// `segments` must point to a valid array of slice descriptors for the active
11/// backend ABI, and `segments_len` must match the number of entries.
12#[inline(always)]
13pub unsafe fn sol_log_data(segments: *const u8, segments_len: u64) {
14 #[cfg(all(target_os = "solana", feature = "hopper-native-backend"))]
15 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
16 unsafe {
17 hopper_native::syscalls::sol_log_data(segments, segments_len);
18 }
19
20 #[cfg(all(target_os = "solana", feature = "legacy-pinocchio-compat"))]
21 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
22 unsafe {
23 pinocchio::syscalls::sol_log_data(segments, segments_len);
24 }
25
26 #[cfg(all(target_os = "solana", feature = "solana-program-backend"))]
27 {
28 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
29 let slices =
30 unsafe { core::slice::from_raw_parts(segments as *const &[u8], segments_len as usize) };
31 ::solana_program::log::sol_log_data(slices);
32 }
33
34 #[cfg(not(target_os = "solana"))]
35 {
36 let _ = (segments, segments_len);
37 }
38}
39
40/// Compute SHA-256 over a slice-of-slices payload.
41///
42/// # Safety
43///
44/// `vals` must point to a valid array of slice descriptors and `result` must
45/// point to writable storage for 32 output bytes.
46#[inline(always)]
47pub unsafe fn sol_sha256(vals: *const u8, vals_len: u64, result: *mut u8) {
48 #[cfg(all(target_os = "solana", feature = "hopper-native-backend"))]
49 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
50 unsafe {
51 hopper_native::syscalls::sol_sha256(vals, vals_len, result);
52 }
53
54 #[cfg(all(target_os = "solana", feature = "legacy-pinocchio-compat"))]
55 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
56 unsafe {
57 pinocchio::syscalls::sol_sha256(vals, vals_len, result);
58 }
59
60 #[cfg(all(target_os = "solana", feature = "solana-program-backend"))]
61 {
62 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
63 let slices =
64 unsafe { core::slice::from_raw_parts(vals as *const &[u8], vals_len as usize) };
65 let digest = ::solana_program::hash::hashv(slices).to_bytes();
66 // SAFETY: This block is part of Hopper's audited zero-copy/backend boundary; surrounding checks and caller contracts uphold the required raw-pointer, layout, and aliasing invariants.
67 unsafe {
68 core::ptr::copy_nonoverlapping(digest.as_ptr(), result, digest.len());
69 }
70 }
71
72 #[cfg(not(target_os = "solana"))]
73 {
74 let _ = (vals, vals_len, result);
75 }
76}