ckb_ssri_std/utils/high_level.rs
1use crate::utils::syscalls;
2use alloc::vec;
3use alloc::vec::Vec;
4use ckb_std::{
5 ckb_types::{
6 packed::{CellOutput, CellOutputReader, OutPoint, OutPointReader, Script},
7 prelude::*,
8 },
9 error::SysError,
10 high_level::BUF_SIZE,
11};
12
13/// Common method to fully load data from syscall
14fn load_data<F: Fn(&mut [u8], usize) -> Result<usize, SysError>>(
15 syscall: F,
16) -> Result<Vec<u8>, SysError> {
17 let mut buf = [0u8; BUF_SIZE];
18 match syscall(&mut buf, 0) {
19 Ok(len) => Ok(buf[..len].to_vec()),
20 Err(SysError::LengthNotEnough(actual_size)) => {
21 let mut data = vec![0; actual_size];
22 let loaded_len = buf.len();
23 data[..loaded_len].copy_from_slice(&buf);
24 let len = syscall(&mut data[loaded_len..], loaded_len)?;
25 debug_assert_eq!(len + loaded_len, actual_size);
26 Ok(data)
27 }
28 Err(err) => Err(err),
29 }
30}
31
32/// Find an OutPoint by searching for a cell with a specific type script
33///
34/// Searches the transaction for a cell that matches the given type script
35/// and returns its OutPoint if found.
36///
37/// # Arguments
38///
39/// * `type_script` - The Script to search for as a cell's type script
40///
41/// # Returns
42///
43/// * `Ok(OutPoint)` - The OutPoint of the first matching cell
44/// * `Err(SysError)` - A system error if the operation fails
45///
46/// # Example
47///
48/// ```
49/// let out_point = find_out_point_by_type(type_script).unwrap();
50/// ```
51///
52/// # Errors
53///
54/// * Returns `SysError::ItemMissing` if no cell with matching type script is found
55/// * Returns `SysError::Encoding` if the OutPoint data is malformed
56///
57/// # Panics
58///
59/// This function can panic if the underlying data is too large,
60/// potentially causing an out-of-memory error.
61pub fn find_out_point_by_type(type_script: Script) -> Result<OutPoint, SysError> {
62 let mut data = [0u8; OutPoint::TOTAL_SIZE];
63 syscalls::find_out_point_by_type(&mut data, &type_script.as_slice())?;
64 match OutPointReader::verify(&data, false) {
65 Ok(()) => Ok(OutPoint::new_unchecked(data.to_vec().into())),
66 Err(_err) => Err(SysError::Encoding),
67 }
68}
69
70/// Find a cell by its OutPoint
71///
72/// Retrieves the CellOutput of a cell identified by the given OutPoint.
73///
74/// # Arguments
75///
76/// * `out_point` - The OutPoint identifying the cell to find
77///
78/// # Returns
79///
80/// * `Ok(CellOutput)` - The cell's output data if found
81/// * `Err(SysError)` - A system error if the operation fails
82///
83/// # Example
84///
85/// ```
86/// let out_point = OutPoint::new(...);
87/// let cell_output = find_cell_by_out_point(out_point).unwrap();
88/// ```
89///
90/// # Errors
91///
92/// * Returns `SysError::ItemMissing` if the cell cannot be found
93/// * Returns `SysError::Encoding` if the CellOutput data is malformed
94///
95/// # Panics
96///
97/// This function can panic if the underlying data is too large,
98/// potentially causing an out-of-memory error.
99pub fn find_cell_by_out_point(out_point: OutPoint) -> Result<CellOutput, SysError> {
100 let data =
101 load_data(|buf, _offset| syscalls::find_cell_by_out_point(buf, out_point.as_slice()))?;
102
103 match CellOutputReader::verify(&data, false) {
104 Ok(()) => Ok(CellOutput::new_unchecked(data.into())),
105 Err(_err) => Err(SysError::Encoding),
106 }
107}
108
109/// Find cell data by OutPoint
110///
111/// Retrieves the data contained in a cell identified by the given OutPoint.
112///
113/// # Arguments
114///
115/// * `out_point` - The OutPoint identifying the cell whose data to retrieve
116///
117/// # Returns
118///
119/// * `Ok(Vec<u8>)` - The cell's data as a byte vector if found
120/// * `Err(SysError)` - A system error if the operation fails
121///
122/// # Example
123///
124/// ```
125/// let out_point = OutPoint::new(...);
126/// let data = find_cell_data_by_out_point(out_point).unwrap();
127/// ```
128///
129/// # Errors
130///
131/// * Returns `SysError::ItemMissing` if the cell cannot be found
132/// * Returns `SysError::LengthNotEnough` if the data buffer is too small
133///
134/// # Panics
135///
136/// This function can panic if the underlying data is too large,
137/// potentially causing an out-of-memory error.
138pub fn find_cell_data_by_out_point(out_point: OutPoint) -> Result<Vec<u8>, SysError> {
139 load_data(|buf, _offset| syscalls::find_cell_data_by_out_point(buf, out_point.as_slice()))
140}