ckb-script 1.1.0

CKB component to run the type/lock scripts
Documentation
/*  Script Description:
 *  - Args:
 *    - A little endian unsigned integer: `number`.
 *    - The `code_hash`(`data_hash`) of a shared library which contains the method `is_even`.
 *  - Returns `CKB_SUCCESS` if and only if any follow conditions satisfied:
 *    - `number` is zero.
 *    - `number` is not even.
 */
#include <stdlib.h>
#include "blockchain.h"
#include "ckb_dlfcn.h"
#include "ckb_syscalls.h"

#ifdef DEBUG
#include <stdio.h>
#else
#define ckb_debug(...)
#define sprintf(...)
#endif

#define SCRIPT_SIZE 32768

void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); }

uint64_t read_u64_le(const uint8_t *src) { return *(const uint64_t *)src; }

int main(int argc, char *argv[]) {
    int ret;
    uint64_t len = SCRIPT_SIZE;
    uint8_t script[SCRIPT_SIZE];
#ifdef DEBUG
    char message[2048];
#endif

    ret = ckb_load_script(script, &len, 0);
    if (ret != CKB_SUCCESS) {
        return -1;
    }
    if (len > SCRIPT_SIZE) {
        return -2;
    }

    mol_seg_t script_seg;
    mol_seg_t args_seg;
    mol_seg_t bytes_seg;
    script_seg.ptr = (uint8_t *)script;
    script_seg.size = len;
    if (MolReader_Script_verify(&script_seg, false) != MOL_OK) {
        return -3;
    }
    args_seg = MolReader_Script_get_args(&script_seg);
    bytes_seg = MolReader_Bytes_raw_bytes(&args_seg);

    if (bytes_seg.size != 8 + 32) {
        return -4;
    }

    volatile uint64_t number = read_u64_le(bytes_seg.ptr);
    sprintf(message, "number = %ld", number);
    ckb_debug(message);

    if (number == 0) {
        return CKB_SUCCESS;
    }

    bool is_even = false;
    {
        void *handle = NULL;
        uint64_t consumed_size = 0;

        uint64_t code_buffer_size = 100 * 1024;
        uint8_t code_buffer[code_buffer_size] __attribute__((aligned(RISCV_PGSIZE)));
        uint8_t hash_type = 0;
        ret = ckb_dlopen2(bytes_seg.ptr + 8, hash_type, code_buffer, code_buffer_size, &handle, &consumed_size);
        if (ret != CKB_SUCCESS) {
            return ret;
        }
        bool (*func)(int);
        *(void **)(&func) = ckb_dlsym(handle, "is_even");
        if (func == NULL) {
            return -6;
        }
        try_pause();
        is_even = func(number);
    }

    sprintf(message, "is_even(%ld) = %d", number, is_even);
    ckb_debug(message);

    if (is_even) {
        return -8;
    }

    return CKB_SUCCESS;
}