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}