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