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
#![no_std]

#[cfg(not(feature = "lock_binary"))]
extern crate alloc;

#[cfg(any(feature = "lock_binary", feature = "test_tool"))]
extern crate std;

pub mod locks;
#[cfg(feature = "test_tool")]
pub mod test_tool;

#[derive(Debug)]
pub enum Error {
    DynamicLoading(ckb_std::dynamic_loading::Error),
    ValidationFunctionNotFound,
    ValidateFailure(i32),
}

use ckb_std::dynamic_loading::{CKBDLContext, Symbol};

type Validate = unsafe extern "C" fn(args: *const u8, len: u64) -> i32;
const VALIDATE: &[u8; 8] = b"validate";

pub struct DynLock {
    validate: Symbol<Validate>,
}

impl DynLock {
    pub fn load<T>(context: &mut CKBDLContext<T>, code_hash: &[u8]) -> Result<Self, Error> {
        let lock = context.load(code_hash).map_err(Error::DynamicLoading)?;

        let validate: Symbol<Validate> = unsafe {
            lock.get(VALIDATE)
                .ok_or_else(|| Error::ValidationFunctionNotFound)?
        };

        Ok(DynLock { validate })
    }

    pub fn validate(&self, args: &[u8]) -> Result<(), Error> {
        let f = &self.validate;
        let error_code = unsafe { f(args.as_ptr(), args.len() as u64) };

        if error_code != 0 {
            return Err(Error::ValidateFailure(error_code));
        }
        Ok(())
    }
}