From d3d06ca46fd5bdf32998dfe672933a73bc778c2a Mon Sep 17 00:00:00 2001 From: Mohanson Date: Thu, 12 Oct 2023 13:26:34 +0800 Subject: [PATCH] Support mount (#1) --- docs/syscalls.md | 19 ++++- quickjs/ckb_module.c | 18 +++++ quickjs/qjs.c | 29 +++++++ tests/ckb_js_tests/Makefile | 4 + tests/ckb_js_tests/src/bin/module_mount.rs | 9 +++ .../templates/fs_module_mount.json | 75 +++++++++++++++++++ .../test_data/fs_module_mount/fib_module.js | 10 +++ .../test_data/fs_module_mount/main.js | 11 +++ 8 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 tests/ckb_js_tests/src/bin/module_mount.rs create mode 100644 tests/ckb_js_tests/templates/fs_module_mount.json create mode 100644 tests/ckb_js_tests/test_data/fs_module_mount/fib_module.js create mode 100644 tests/ckb_js_tests/test_data/fs_module_mount/main.js diff --git a/docs/syscalls.md b/docs/syscalls.md index a21de1b..588611d 100644 --- a/docs/syscalls.md +++ b/docs/syscalls.md @@ -312,7 +312,7 @@ See also: [`ckb_vm_version` syscall](https://github.com/nervosnetwork/rfcs/blob/ #### ckb.exec_cell Description: runs an executable file from specified cell data in the context of -an already existing machine, replacing the previous executable. +an already existing machine, replacing the previous executable. Example: ```js @@ -329,7 +329,7 @@ See also: [`ckb_exec` syscall](https://github.com/nervosnetwork/rfcs/blob/master #### ckb.spawn_cell Description: runs an executable file from specified cell data in a new -context, without changing previous executable. +context, without changing previous executable. Example: ```js @@ -344,7 +344,7 @@ let content = value.content; let exit_code = value.exit_code; ``` -Arguments: +Arguments: - code_hash/hash_type(denote a cell to load JS code) - spawn_args, extra spawn arguments * content_length, optional, specify content length, default to 0 @@ -404,10 +404,21 @@ Return value(s): memory size in bytes See also: [`ckb_current_memory` syscall](https://github.com/nervosnetwork/rfcs/pull/418/files) +#### ckb.mount +Description: Load the file system in the cell. + +Example: +```js +ckb.mount(2, ckb.SOURCE_CELL_DEP) +``` + +Arguments: index (the index of the cell), source (the source of the cell) + +Return value(s): none ## Exported Constants -Most constants here are directly taken from [ckb_consts.h](https://github.com/nervosnetwork/ckb-system-scripts/blob/master/c/ckb_consts.h): +Most constants here are directly taken from [ckb_consts.h](https://github.com/nervosnetwork/ckb-system-scripts/blob/master/c/ckb_consts.h): ``` ckb.SOURCE_INPUT diff --git a/quickjs/ckb_module.c b/quickjs/ckb_module.c index a05aa9d..1feab1a 100644 --- a/quickjs/ckb_module.c +++ b/quickjs/ckb_module.c @@ -5,6 +5,7 @@ #include "ckb_syscalls.h" #include "molecule/blockchain.h" #include "molecule/molecule_reader.h" +#include "ckb_cell_fs.h" // For syscalls supporting partial loading, the arguments are described as: // argument 1: index @@ -460,6 +461,21 @@ static JSValue syscall_current_memory(JSContext *ctx, JSValueConst this_value, i return JS_NewUint32(ctx, (uint32_t)size); } +static JSValue mount(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { + JSValue buf = syscall_load_cell_data(ctx, this_value, argc, argv); + if (JS_IsException(buf)) { + return JS_EXCEPTION; + } + size_t psize = 0; + uint8_t *addr = JS_GetArrayBuffer(ctx, &psize, buf); + int err = ckb_load_fs(addr, psize); + if (err != 0) { + return JS_EXCEPTION; + } else { + return JS_UNDEFINED; + } +} + /* TODO: // who allocated the memory indicated by aligned_addr? @@ -501,6 +517,8 @@ int js_init_module_ckb(JSContext *ctx) { JS_NewCFunction(ctx, syscall_get_memory_limit, "get_memory_limit", 0)); JS_SetPropertyStr(ctx, ckb, "current_memory", JS_NewCFunction(ctx, syscall_current_memory, "current_memory", 0)); + 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)); JS_SetPropertyStr(ctx, ckb, "SOURCE_CELL_DEP", JS_NewInt64(ctx, CKB_SOURCE_CELL_DEP)); diff --git a/quickjs/qjs.c b/quickjs/qjs.c index 65bcd6b..2760ce1 100644 --- a/quickjs/qjs.c +++ b/quickjs/qjs.c @@ -123,6 +123,20 @@ void js_std_dump_error(JSContext *ctx) { JS_FreeValue(ctx, exception_val); } +void js_std_loop(JSContext *ctx) { + JSContext *ctx1; + int err; + for(;;) { + err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + if (err <= 0) { + if (err < 0) { + js_std_dump_error(ctx1); + } + break; + } + } +} + int compile_from_file(JSContext *ctx) { enable_local_access(1); char buf[1024 * 512]; @@ -304,18 +318,33 @@ int main(int argc, const char **argv) { switch (type) { case RunJsWithCode: err = eval_buf(ctx, argv[1], strlen(argv[1]), "", 0); + if (err == 0) { + js_std_loop(ctx); + } break; case RunJsWithFile: err = run_from_cell_data(ctx, false); + if (err == 0) { + js_std_loop(ctx); + } break; case RunJsWithFileSystem: err = run_from_cell_data(ctx, true); + if (err == 0) { + js_std_loop(ctx); + } break; case RunJsWithDbgFile: err = run_from_local_file(ctx, false); + if (err == 0) { + js_std_loop(ctx); + } break; case RunJsWithDbgFileSystem: err = run_from_local_file(ctx, true); + if (err == 0) { + js_std_loop(ctx); + } break; case CompileWithFile: JS_SetModuleLoaderFunc(rt, NULL, js_module_dummy_loader, NULL); diff --git a/tests/ckb_js_tests/Makefile b/tests/ckb_js_tests/Makefile index 26f605e..09927c9 100644 --- a/tests/ckb_js_tests/Makefile +++ b/tests/ckb_js_tests/Makefile @@ -36,6 +36,10 @@ file_system: build/testdata_fs_modules.bin syscall: cargo run --bin syscall | $(CKB_DEBUGGER) --tx-file=- -s lock +fs_mount: + cd test_data/fs_module_mount && lua ../../../../tools/fs.lua pack ../../../../build/fib_module.bin fib_module.js + cargo run --bin module_mount | ${CKB_DEBUGGER} --tx-file=- -s lock + install-lua: sudo apt install lua5.4 diff --git a/tests/ckb_js_tests/src/bin/module_mount.rs b/tests/ckb_js_tests/src/bin/module_mount.rs new file mode 100644 index 0000000..c76844b --- /dev/null +++ b/tests/ckb_js_tests/src/bin/module_mount.rs @@ -0,0 +1,9 @@ +use ckb_js_tests::read_tx_template; + +pub fn main() -> Result<(), Box> { + let tx = read_tx_template("templates/fs_module_mount.json")?; + + let json = serde_json::to_string_pretty(&tx).unwrap(); + println!("{}", json); + Ok(()) +} diff --git a/tests/ckb_js_tests/templates/fs_module_mount.json b/tests/ckb_js_tests/templates/fs_module_mount.json new file mode 100644 index 0000000..28d015e --- /dev/null +++ b/tests/ckb_js_tests/templates/fs_module_mount.json @@ -0,0 +1,75 @@ +{ + "mock_info": { + "inputs": [ + { + "output": { + "capacity": "0x10000000", + "lock": { + "args": "0x0000{{ ref_type js-code-file }}01", + "code_hash": "0x{{ ref_type ckb-js-vm }}", + "hash_type": "type" + }, + "type": null + }, + "data": "0x" + } + ], + "cell_deps": [ + { + "output": { + "capacity": "0x10000000", + "lock": { + "args": "0x00AE9DF3447C404A645BC48BEA4B7643B95AC5C3AE", + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data1" + }, + "type": "{{ def_type ckb-js-vm }}" + }, + "data": "0x{{ data ../../../build/ckb-js-vm }}" + }, + { + "output": { + "capacity": "0x10000000", + "lock": { + "args": "0x00AE9DF3447C404A645BC48BEA4B7643B95AC5C3AE", + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data1" + }, + "type": "{{ def_type js-code-file }}" + }, + "data": "0x{{ data ../test_data/fs_module_mount/main.js }}" + }, + { + "output": { + "capacity": "0x10000000", + "lock": { + "args": "0x00AE9DF3447C404A645BC48BEA4B7643B95AC5C3AE", + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data1" + }, + "type": "{{ def_type fib_module }}" + }, + "data": "0x{{ data ../../../build/fib_module.bin }}" + } + ], + "header_deps": [] + }, + "tx": { + "outputs": [ + { + "capacity": "0x0", + "lock": { + "args": "0x00AE9DF3447C404A645BC48BEA4B7643B95AC5C3AE", + "code_hash": "0x{{ ref_type ckb-js-vm }}", + "hash_type": "type" + } + } + ], + "witnesses": [ + "0x55000000100000005500000055000000410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ], + "outputs_data": [ + "0x" + ] + } + } diff --git a/tests/ckb_js_tests/test_data/fs_module_mount/fib_module.js b/tests/ckb_js_tests/test_data/fs_module_mount/fib_module.js new file mode 100644 index 0000000..6a81071 --- /dev/null +++ b/tests/ckb_js_tests/test_data/fs_module_mount/fib_module.js @@ -0,0 +1,10 @@ +/* fib module */ +export function fib(n) +{ + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib(n - 1) + fib(n - 2); +} diff --git a/tests/ckb_js_tests/test_data/fs_module_mount/main.js b/tests/ckb_js_tests/test_data/fs_module_mount/main.js new file mode 100644 index 0000000..4292b50 --- /dev/null +++ b/tests/ckb_js_tests/test_data/fs_module_mount/main.js @@ -0,0 +1,11 @@ +/* example of JS module */ + +ckb.mount(2, ckb.SOURCE_CELL_DEP) + +import('./fib_module.js') + .then((module) => { + console.log("fib(10)=", module.fib(10)) + }) + .catch((err) => { + console.log(err) + });