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()))
}