ckb_ssri_std/utils/syscalls/native.rs
1#[cfg(target_arch = "riscv64")]
2use core::arch::asm;
3
4use ckb_std::{ckb_constants::SYS_VM_VERSION, error::SysError};
5
6/// System call number for finding an OutPoint by type script
7pub const SYS_FIND_OUT_POINT_BY_TYPE: u64 = 2277;
8/// System call number for finding a cell by OutPoint
9pub const SYS_FIND_CELL_BY_OUT_POINT: u64 = 2287;
10/// System call number for finding cell data by OutPoint
11pub const SYS_FIND_CELL_DATA_BY_OUT_POINT: u64 = 2297;
12
13#[cfg(target_arch = "riscv64")]
14#[allow(clippy::too_many_arguments)]
15pub unsafe fn syscall(
16 mut a0: u64,
17 a1: u64,
18 a2: u64,
19 a3: u64,
20 a4: u64,
21 a5: u64,
22 a6: u64,
23 a7: u64,
24) -> u64 {
25 asm!(
26 "ecall",
27 inout("a0") a0,
28 in("a1") a1,
29 in("a2") a2,
30 in("a3") a3,
31 in("a4") a4,
32 in("a5") a5,
33 in("a6") a6,
34 in("a7") a7
35 );
36 a0
37}
38
39#[cfg(not(target_arch = "riscv64"))]
40#[allow(clippy::too_many_arguments)]
41pub unsafe fn syscall(
42 _a0: u64,
43 _a1: u64,
44 _a2: u64,
45 _a3: u64,
46 _a4: u64,
47 _a5: u64,
48 _a6: u64,
49 _a7: u64,
50) -> u64 {
51 u64::MAX
52}
53
54pub fn vm_version() -> u64 {
55 unsafe { syscall(0, 0, 0, 0, 0, 0, 0, SYS_VM_VERSION) }
56}
57
58
59
60/// Load data
61/// Return data length or syscall error
62fn syscall_load(
63 buf_ptr: *mut u8,
64 len: usize,
65 a2: usize,
66 a3: u64,
67 a4: u64,
68 a5: u64,
69 a6: u64,
70 syscall_num: u64,
71) -> Result<usize, SysError> {
72 let mut actual_data_len = len;
73 let len_ptr: *mut usize = &mut actual_data_len;
74 let ret = unsafe {
75 syscall(
76 buf_ptr as u64,
77 len_ptr as u64,
78 a2 as u64,
79 a3,
80 a4,
81 a5,
82 a6,
83 syscall_num,
84 )
85 };
86 build_syscall_result(ret, len, actual_data_len)
87}
88
89fn build_syscall_result(
90 errno: u64,
91 load_len: usize,
92 actual_data_len: usize,
93) -> Result<usize, SysError> {
94 use SysError::*;
95
96 match errno {
97 0 => {
98 if actual_data_len > load_len {
99 return Err(LengthNotEnough(actual_data_len));
100 }
101 Ok(actual_data_len)
102 }
103 1 => Err(IndexOutOfBound),
104 2 => Err(ItemMissing),
105 _ => Err(Unknown(errno)),
106 }
107}
108
109
110/// Find an OutPoint by searching for a specific type script
111///
112/// Searches for a cell with the given type script and returns its OutPoint.
113/// The OutPoint data is written to the provided buffer.
114///
115/// # Arguments
116///
117/// * `buf` - A mutable buffer to receive the OutPoint data
118/// * `type_script` - The serialized type script to search for
119///
120/// # Returns
121///
122/// * `Ok(usize)` - The actual length of the OutPoint data written to the buffer
123/// * `Err(SysError)` - A system error if the operation fails
124///
125/// # Errors
126///
127/// Returns `SysError::LengthNotEnough` if the buffer is too small to hold the data
128/// Returns `SysError::IndexOutOfBound` if the type script is invalid
129/// Returns `SysError::ItemMissing` if no matching cell is found
130pub fn find_out_point_by_type(
131 buf: &mut [u8],
132 type_script: &[u8],
133) -> Result<usize, SysError> {
134 syscall_load(
135 buf.as_mut_ptr(),
136 buf.len(),
137 type_script.as_ptr() as usize,
138 type_script.len() as u64,
139 0,
140 0,
141 0,
142 SYS_FIND_OUT_POINT_BY_TYPE,
143 )
144}
145
146/// Find a cell by its OutPoint
147///
148/// Retrieves cell information using the specified OutPoint.
149/// The cell data is written to the provided buffer.
150///
151/// # Arguments
152///
153/// * `buf` - A mutable buffer to receive the cell data
154/// * `out_point` - The serialized OutPoint identifying the cell to find
155///
156/// # Returns
157///
158/// * `Ok(usize)` - The actual length of the cell data written to the buffer
159/// * `Err(SysError)` - A system error if the operation fails
160///
161/// # Errors
162///
163/// Returns `SysError::LengthNotEnough` if the buffer is too small to hold the data
164/// Returns `SysError::IndexOutOfBound` if the OutPoint is invalid
165/// Returns `SysError::ItemMissing` if the cell cannot be found
166pub fn find_cell_by_out_point(
167 buf: &mut [u8],
168 out_point: &[u8],
169) -> Result<usize, SysError> {
170 syscall_load(
171 buf.as_mut_ptr(),
172 buf.len(),
173 out_point.as_ptr() as usize,
174 0,
175 0,
176 0,
177 0,
178 SYS_FIND_CELL_BY_OUT_POINT,
179 )
180}
181
182/// Find cell data by OutPoint
183///
184/// Retrieves the data contained in a cell identified by the specified OutPoint.
185/// The cell's data is written to the provided buffer.
186///
187/// # Arguments
188///
189/// * `buf` - A mutable buffer to receive the cell's data
190/// * `out_point` - The serialized OutPoint identifying the cell whose data to retrieve
191///
192/// # Returns
193///
194/// * `Ok(usize)` - The actual length of the cell data written to the buffer
195/// * `Err(SysError)` - A system error if the operation fails
196///
197/// # Errors
198///
199/// Returns `SysError::LengthNotEnough` if the buffer is too small to hold the data
200/// Returns `SysError::IndexOutOfBound` if the OutPoint is invalid
201/// Returns `SysError::ItemMissing` if the cell cannot be found
202pub fn find_cell_data_by_out_point(
203 buf: &mut [u8],
204 out_point: &[u8],
205) -> Result<usize, SysError> {
206 syscall_load(
207 buf.as_mut_ptr(),
208 buf.len(),
209 out_point.as_ptr() as usize,
210 0,
211 0,
212 0,
213 0,
214 SYS_FIND_CELL_DATA_BY_OUT_POINT,
215 )
216}
217