From f664e2f8a6db01d3b71279c24a282fc2b3a82407 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 10 Sep 2024 14:09:15 +0800 Subject: [PATCH] Full implemention --- quickjs/ckb_module.c | 202 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 179 insertions(+), 23 deletions(-) diff --git a/quickjs/ckb_module.c b/quickjs/ckb_module.c index 3a4690d..05636e7 100644 --- a/quickjs/ckb_module.c +++ b/quickjs/ckb_module.c @@ -365,6 +365,18 @@ static int get_property(JSContext *ctx, JSValueConst *obj, const char *prop, int return err; } +int ckb_spawn_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, + uint32_t length, spawn_args_t* spawn_args) { + size_t index = SIZE_MAX; + int ret = ckb_look_for_dep_with_hash2(code_hash, hash_type, &index); + if (ret != CKB_SUCCESS) { + return ret; + } + size_t bounds = ((size_t)offset << 32) | length; + return syscall(SYS_ckb_spawn, index, CKB_SOURCE_CELL_DEP, 0, bounds, + spawn_args, 0); +} + static JSValue syscall_spawn_cell(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { int err = 0; size_t code_hash_len = 0; @@ -374,8 +386,8 @@ static JSValue syscall_spawn_cell(JSContext *ctx, JSValueConst this_value, int a uint32_t length = 0; uint32_t spgs_argc = 0; const char* spgs_argv[32] = {}; - // uint64_t spgs_process_id = 0; - // uint64_t* spgs_inherited_fds = {}; + uint64_t spgs_pid = 0; + uint64_t spgs_fds[32] = {0}; JSValue buffer = JS_GetTypedArrayBuffer(ctx, argv[0], NULL, NULL, NULL); CHECK2(!JS_IsException(buffer), SyscallErrorArgument); @@ -412,19 +424,129 @@ static JSValue syscall_spawn_cell(JSContext *ctx, JSValueConst this_value, int a } JS_FreeValue(ctx, val); - // err = get_property(ctx, &argv[2], "memory_limit", &memory_limit); - // CHECK(err); - // err = get_property(ctx, &argv[2], "offset", &offset); - // CHECK(err); - // err = get_property(ctx, &argv[2], "length", &length); - // CHECK(err); - - // spawn_args_t spgs = { - // .argc = 2, - // .argv = argv, - // .process_id = &pid, - // .inherited_fds = inherited_fds, - // }; + val = JS_GetPropertyStr(ctx, argv[4], "inherited_fds"); + CHECK2(!JS_IsException(val), SyscallErrorArgument); + if (!JS_IsUndefined(val)) { + JSValue buffer = JS_GetTypedArrayBuffer(ctx, val, NULL, NULL, NULL); + CHECK2(!JS_IsException(buffer), SyscallErrorArgument); + uint32_t temp; + for (int i = 0; i < 32; i++) { + const JSValue elem = JS_GetPropertyUint32(ctx, buffer, i); + err = JS_ToUint32(ctx, &temp, elem); + CHECK(err); + spgs_fds[i] = temp; + if (temp == 0) { + break; + } + } + } + JS_FreeValue(ctx, val); + + spawn_args_t spgs = { + .argc = spgs_argc, + .argv = spgs_argv, + .process_id = &spgs_pid, + .inherited_fds = &spgs_fds[0], + }; + + err = ckb_spawn_cell(code_hash, hash_type, offset, length, &spgs); + CHECK(err); +exit: + if (err != 0) { + return JS_EXCEPTION; + } else { + return JS_NewInt64(ctx, spgs_pid); + } +} + +static JSValue syscall_pipe(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + int err = 0; + uint64_t fds[2]; + err = ckb_pipe(fds); + CHECK(err); + JSValue obj = JS_NewArray(ctx); + CHECK2(!JS_IsException(obj), SyscallErrorArgument); + JS_SetPropertyUint32(ctx, obj, 0, JS_NewUint32(ctx, fds[0])); + JS_SetPropertyUint32(ctx, obj, 1, JS_NewUint32(ctx, fds[1])); +exit: + if (err != 0) { + return JS_EXCEPTION; + } else { + return obj; + } +} + +static JSValue syscall_inherited_file_descriptors(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + int err = 0; + uint64_t fds[2]; + uint64_t length; + err = ckb_inherited_file_descriptors(fds, &length); + CHECK(err); + JSValue obj = JS_NewArray(ctx); + CHECK2(!JS_IsException(obj), SyscallErrorArgument); + for (int i = 0; i < length; i++) { + JS_SetPropertyUint32(ctx, obj, i, JS_NewUint32(ctx, (uint32_t)fds[i])); + } +exit: + if (err != 0) { + return JS_EXCEPTION; + } else { + return obj; + } +} + +static JSValue syscall_read(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + int err = 0; + uint64_t fd = 0; + void* buffer = {}; + size_t length = 0; + uint32_t u32 = 0; + err = JS_ToUint32(ctx, &u32, argv[0]); + CHECK(err); + fd = u32; + err = JS_ToUint32(ctx, &u32, argv[1]); + CHECK(err); + length = u32; + CHECK2(length <= 1024, SyscallErrorArgument); + err = ckb_read(fd, buffer, &length); + CHECK(err); +exit: + if (err != 0) { + return JS_EXCEPTION; + } else { + return JS_NewArrayBuffer(ctx, buffer, length, my_free, buffer, false); + } +} + +static JSValue syscall_write(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + int err = 0; + uint64_t fd = 0; + uint32_t u32 = 0; + err = JS_ToUint32(ctx, &u32, argv[0]); + CHECK(err); + fd = (uint64_t)u32; + size_t length = 0; + JSValue buffer = JS_GetTypedArrayBuffer(ctx, argv[1], NULL, NULL, NULL); + CHECK2(!JS_IsException(buffer), SyscallErrorArgument); + uint8_t *content = JS_GetArrayBuffer(ctx, &length, buffer); + CHECK2(content != NULL, SyscallErrorUnknown); + err = ckb_write(fd, content, &length); + CHECK(err); +exit: + if (err != 0) { + return JS_EXCEPTION; + } else { + return JS_UNDEFINED; + } +} + +static JSValue syscall_close(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + int err = 0; + uint32_t fd = 0; + err = JS_ToUint32(ctx, &fd, argv[0]); + CHECK(err); + err = ckb_close((uint64_t)fd); + CHECK(err); exit: if (err != 0) { return JS_EXCEPTION; @@ -433,14 +555,39 @@ static JSValue syscall_spawn_cell(JSContext *ctx, JSValueConst this_value, int a } } -// - [Pipe] -// - [Inherited File Descriptors] -// - [Read] -// - [Write] -// - [Close] -// - [Wait] -// - [Process ID] -// - [Load Block Extension] +static JSValue syscall_wait(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + int err = 0; + uint32_t fd = 0; + int8_t exit = 0; + err = JS_ToUint32(ctx, &fd, argv[0]); + CHECK(err); + err = ckb_wait((uint64_t)fd, &exit); + CHECK(err); +exit: + if (err != 0) { + return JS_EXCEPTION; + } else { + return JS_NewInt32(ctx, exit); + } +} + +static JSValue syscall_process_id(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + uint64_t pid = ckb_process_id(); + return JS_NewUint32(ctx, (uint32_t)pid); +} + +static int _load_block_extension(void *addr, uint64_t *len, LoadData *data) { + return ckb_load_block_extension(addr, len, data->offset, data->index, data->source); +} + +static JSValue syscall_load_block_extension(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { + LoadData data = {0}; + JSValue ret = parse_args(ctx, &data, false, argc, argv, _load_block_extension); + if (JS_IsException(ret)) { + return ret; + } + return syscall_load(ctx, &data); +} static JSValue mount(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { JSValue buf = syscall_load_cell_data(ctx, this_value, argc, argv); @@ -493,6 +640,15 @@ int js_init_module_ckb(JSContext *ctx) { JS_SetPropertyStr(ctx, ckb, "vm_version", JS_NewCFunction(ctx, syscall_vm_version, "vm_version", 0)); JS_SetPropertyStr(ctx, ckb, "current_cycles", JS_NewCFunction(ctx, syscall_current_cycles, "current_cycles", 0)); JS_SetPropertyStr(ctx, ckb, "exec_cell", JS_NewCFunction(ctx, syscall_exec_cell, "exec_cell", 4)); + JS_SetPropertyStr(ctx, ckb, "spawn_cell", JS_NewCFunction(ctx, syscall_spawn_cell, "spawn_cell", 5)); + JS_SetPropertyStr(ctx, ckb, "pipe", JS_NewCFunction(ctx, syscall_pipe, "pipe", 0)); + JS_SetPropertyStr(ctx, ckb, "inherited_file_descriptors", JS_NewCFunction(ctx, syscall_inherited_file_descriptors, "inherited_file_descriptors", 0)); + JS_SetPropertyStr(ctx, ckb, "read", JS_NewCFunction(ctx, syscall_read, "read", 2)); + JS_SetPropertyStr(ctx, ckb, "write", JS_NewCFunction(ctx, syscall_write, "write", 2)); + JS_SetPropertyStr(ctx, ckb, "close", JS_NewCFunction(ctx, syscall_close, "close", 1)); + JS_SetPropertyStr(ctx, ckb, "wait", JS_NewCFunction(ctx, syscall_wait, "wait", 1)); + JS_SetPropertyStr(ctx, ckb, "process_id", JS_NewCFunction(ctx, syscall_process_id, "process_id", 0)); + JS_SetPropertyStr(ctx, ckb, "load_block_extension", JS_NewCFunction(ctx, syscall_load_block_extension, "load_block_extension", 3)); JS_SetPropertyStr(ctx, ckb, "mount", JS_NewCFunction(ctx, mount, "mount", 2)); JS_SetPropertyStr(ctx, ckb, "SOURCE_INPUT", JS_NewInt64(ctx, CKB_SOURCE_INPUT)); JS_SetPropertyStr(ctx, ckb, "SOURCE_OUTPUT", JS_NewInt64(ctx, CKB_SOURCE_OUTPUT));