-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
including following features: * CKB syscall bindings * File system and JavaScript module * Bytecode * Documents * Tests
- Loading branch information
0 parents
commit 98e5383
Showing
91 changed files
with
90,500 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: CI | ||
|
||
on: [push, pull_request] | ||
|
||
jobs: | ||
linux: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
submodules: recursive | ||
- name: Install llvm 16 | ||
run: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 && wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 16 | ||
- name: Build | ||
run: make all | ||
- name: Install tools | ||
run: make install | ||
- name: Tests | ||
run: make test | ||
|
||
macos: | ||
runs-on: macos-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
submodules: recursive | ||
- name: Install LLVM and Clang | ||
run: brew install llvm@16 | ||
- name: Build | ||
run: export PATH="/usr/local/opt/llvm/bin:$PATH" && make all |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Prerequisites | ||
*.d | ||
|
||
# Object files | ||
*.o | ||
*.ko | ||
*.obj | ||
*.elf | ||
|
||
# Linker output | ||
*.ilk | ||
*.map | ||
*.exp | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Libraries | ||
*.lib | ||
*.a | ||
*.la | ||
*.lo | ||
|
||
# Shared objects (inc. Windows DLLs) | ||
*.dll | ||
*.so | ||
*.so.* | ||
*.dylib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
*.i*86 | ||
*.x86_64 | ||
*.hex | ||
|
||
# Debug files | ||
*.dSYM/ | ||
*.su | ||
*.idb | ||
*.pdb | ||
|
||
# Kernel Module Compile Results | ||
*.mod* | ||
*.cmd | ||
.tmp_versions/ | ||
modules.order | ||
Module.symvers | ||
Mkfile.old | ||
dkms.conf | ||
|
||
.vscode | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
[submodule "deps/ckb-c-stdlib"] | ||
path = deps/ckb-c-stdlib | ||
url = https://github.com/nervosnetwork/ckb-c-stdlib.git | ||
[submodule "deps/compiler-rt-builtins-riscv"] | ||
path = deps/compiler-rt-builtins-riscv | ||
url = https://github.com/nervosnetwork/compiler-rt-builtins-riscv.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
|
||
CC := clang-16 | ||
LD := ld.lld-16 | ||
OBJCOPY := llvm-objcopy-16 | ||
AR := llvm-ar-16 | ||
RANLIB := llvm-ranlib-16 | ||
|
||
UNAME := $(shell uname) | ||
ifeq ($(UNAME), Darwin) | ||
LD := ld.lld | ||
OBJCOPY := llvm-objcopy | ||
RANLIB := llvm-ranlib | ||
endif | ||
|
||
CFLAGS := --target=riscv64 -march=rv64imc_zba_zbb_zbc_zbs | ||
CFLAGS += -g -Os \ | ||
-Wall -Werror -Wno-nonnull -Wno-unused-function \ | ||
-fno-builtin-printf -fno-builtin-memcmp \ | ||
-nostdinc -nostdlib\ | ||
-fdata-sections -ffunction-sections | ||
|
||
CFLAGS += -I deps/ckb-c-stdlib/libc -I deps/ckb-c-stdlib | ||
CFLAGS += -I include -I include/c-stdlib | ||
CFLAGS += -I deps/compiler-rt-builtins-riscv/compiler-rt/lib/builtins | ||
|
||
CFLAGS += -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wundef -Wuninitialized\ | ||
-Wunused -Wno-unused-parameter -Wchar-subscripts -funsigned-char -Wno-unused-function \ | ||
-DCONFIG_VERSION=\"2021-03-27-CKB\" | ||
CFLAGS += -Wno-incompatible-library-redeclaration -Wno-implicit-const-int-float-conversion -Wno-invalid-noreturn | ||
|
||
CFLAGS += -DCKB_DECLARATION_ONLY | ||
CFLAGS += -D__BYTE_ORDER=1234 -D__LITTLE_ENDIAN=1234 -D__ISO_C_VISIBLE=1999 -D__GNU_VISIBLE | ||
CFLAGS += -DCKB_MALLOC_DECLARATION_ONLY -DCKB_PRINTF_DECLARATION_ONLY -DCONFIG_BIGNUM | ||
|
||
LDFLAGS := -static --gc-sections | ||
LDFLAGS += -Ldeps/compiler-rt-builtins-riscv/build -lcompiler-rt | ||
|
||
OBJDIR=build | ||
|
||
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o \ | ||
$(OBJDIR)/cutils.o $(OBJDIR)/mocked.o $(OBJDIR)/std_module.o $(OBJDIR)/ckb_module.o $(OBJDIR)/ckb_cell_fs.o $(OBJDIR)/libbf.o | ||
|
||
STD_OBJS=$(OBJDIR)/string_impl.o $(OBJDIR)/malloc_impl.o $(OBJDIR)/math_impl.o \ | ||
$(OBJDIR)/math_log_impl.o $(OBJDIR)/math_pow_impl.o $(OBJDIR)/printf_impl.o $(OBJDIR)/stdio_impl.o \ | ||
$(OBJDIR)/locale_impl.o | ||
|
||
|
||
all: build/ckb-js-vm | ||
|
||
deps/compiler-rt-builtins-riscv/build/libcompiler-rt.a: | ||
cd deps/compiler-rt-builtins-riscv && make | ||
|
||
build/ckb-js-vm: $(STD_OBJS) $(QJS_OBJS) $(OBJDIR)/impl.o deps/compiler-rt-builtins-riscv/build/libcompiler-rt.a | ||
$(LD) $(LDFLAGS) -o $@ $^ | ||
cp $@ $@.debug | ||
$(OBJCOPY) --strip-debug --strip-all $@ | ||
ls -lh build/ckb-js-vm | ||
|
||
$(OBJDIR)/%.o: quickjs/%.c | ||
@echo build $< | ||
@$(CC) $(CFLAGS) -c -o $@ $< | ||
|
||
$(OBJDIR)/%.o: include/c-stdlib/src/%.c | ||
@echo build $< | ||
@$(CC) $(CFLAGS) -c -o $@ $< | ||
|
||
$(OBJDIR)/%.o: include/%.c | ||
@echo build $< | ||
@$(CC) $(CFLAGS) -c -o $@ $< | ||
|
||
$(OBJDIR)/impl.o: deps/ckb-c-stdlib/libc/src/impl.c | ||
@echo build $< | ||
@$(CC) $(filter-out -DCKB_DECLARATION_ONLY, $(CFLAGS)) -c -o $@ $< | ||
|
||
test: | ||
make -f tests/examples/Makefile | ||
make -f tests/basic/Makefile | ||
cd tests/ckb_js_tests && make all | ||
|
||
clean: | ||
rm -f build/*.o | ||
rm -f build/ckb-js-vm | ||
rm -f build/ckb-js-vm.debug | ||
cd tests/ckb_js_tests && make clean | ||
|
||
install: | ||
wget 'https://github.com/nervosnetwork/ckb-standalone-debugger/releases/download/v0.111.0/ckb-debugger-linux-x64.tar.gz' | ||
tar zxvf ckb-debugger-linux-x64.tar.gz | ||
mv ckb-debugger ~/.cargo/bin/ckb-debugger | ||
make -f tests/ckb_js_tests/Makefile install-lua | ||
|
||
.phony: all clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# ckb-js-vm | ||
The objective of this project is to develop scripts in JavaScript for CKB-VM, by | ||
adapting [quickjs](https://bellard.org/quickjs/). | ||
|
||
|
||
## Build | ||
The clang version 16 is required. | ||
|
||
```shell | ||
git submodule update --init | ||
make all | ||
``` | ||
|
||
## Documents | ||
* [Introduction](./docs/intro.md) | ||
* [CKB Syscall Bindings](./docs/syscalls.md) | ||
* [Simple File System and JavaScript Module](./docs/fs.md) | ||
|
||
|
||
## Examples | ||
|
||
* [Fibonacci Number](./tests/examples/fib.js) | ||
* [Calculate PI](./tests/examples/pi_bigint.js) | ||
|
||
More [tests and examples](./tests/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* |
Empty file.
Submodule ckb-c-stdlib
added at
bdc87e
Submodule compiler-rt-builtins-riscv
added at
8005bb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
# Simple File System and JavaScript Module | ||
|
||
In addition to executing individual JavaScript files, ckb-js-vm also supports | ||
JavaScript modules by Simple File System, files within the file system may be | ||
made available for Javascript to read, import, and execute, e.g. import modules | ||
by `import { * } from "./module.js";`. Each Simple File System contains at least | ||
one entry file named `main.js`, and ckb-js-vm will load this file system from | ||
any cell and execute `main.js` in it. | ||
|
||
A file system is represented as a binary file in the format described below. We | ||
may use the script [fs.lua](../tools/fs.lua) to create a file system from given | ||
files or unpack the file system into files. | ||
|
||
## How to create a Simple File System | ||
|
||
Consider the following two files: | ||
|
||
```js | ||
// File main.js | ||
import { fib } from "./fib_module.js"; | ||
console.log("fib(10)=", fib(10)); | ||
``` | ||
|
||
```js | ||
// File fib_module.js | ||
export function fib(n) { | ||
if (n <= 0) | ||
return 0; | ||
else if (n == 1) | ||
return 1; | ||
else | ||
return fib(n - 1) + fib(n - 2); | ||
} | ||
``` | ||
|
||
If we want ckb-js-vm to execute this code smoothly, we must package them into a | ||
file system first. To pack them within the current directory into `fib.fs`, you | ||
may run | ||
```shell | ||
find . -name *.js -type f | lua tools/fs.lua pack fib.fs | ||
``` | ||
|
||
``` | ||
// Output | ||
packing file ./fib_module.js to fib_module.js | ||
packing file ./main.js to main.js | ||
``` | ||
|
||
Note that all file paths piped into the `fs.lua` must be in the relative path | ||
format. The absolute path of a file in the current system is usually meaningless | ||
in the Simple File System. | ||
|
||
## How to deploy and use Simple File System | ||
|
||
In most cases, it is more resource-efficient to write all JavaScript code in one | ||
file. To enable file system support, we cannot directly use ckb-js-vm as a lock | ||
script, ckb-js-vm must be used as an exec Or the spawn target passes the "-f" | ||
parameter to it. | ||
|
||
We wrote an example that uses `spawn` syscall to call ckb-js-vm to demonstrate | ||
how to use the file system. | ||
|
||
```sh | ||
$ cd tests/ckb_js_tests | ||
$ make module | ||
``` | ||
|
||
The key is `spawn_caller`, in this example, `spawn_caller` is the real lock | ||
script, which then calls ckb-js-vm using `spawn` and passes it the `-f` | ||
parameter: ckb-js-vm will then run in file system mode. | ||
|
||
## Using JavaScript bytecode to improve performance | ||
|
||
When ckb-js-vm executes JavaScript codes, it will first compile them into | ||
bytecode, and then interpret and execute the bytecode. To improve the | ||
performance of ckb-js-vm, we can also choose to directly let ckb-js-vm execute | ||
bytecode. | ||
|
||
We define all JavaScript bytecode files to have a `.bc` extension. When | ||
ckb-js-vm obtains a file system, it will first look for the `main.js` file; if | ||
not, it continues to look for the `main.bc` file. When importing a module in | ||
JavaScript codes, e.g. `import { * } from "./module.js`, the steps are similar, | ||
ckb-js-vm will look for `./module.js` or `./module.bc`. | ||
|
||
In general, we only need to compile all JavaScript files into corresponding | ||
bytecode files, and then package the bytecode files just like packaging | ||
JavaScript files. | ||
|
||
## Unpack Simple File System to Files | ||
|
||
To unpack the files contained within a fs, you may run `lua tools/fs.lua unpack fib.fs .`. | ||
|
||
## Simple File System On-disk Representation | ||
|
||
The on-disk representation of a Simple File System consists of three parts, a | ||
number to represent the number of files contained in this file system, an array | ||
of metadata to store file metadata and an array of binary objects (also called | ||
blob) to store the actual file contents. | ||
|
||
A metadata is simply an offset from the start of the blob array and a datum | ||
length. Each file name and file content has a metadata. For each file stored in | ||
the fs, there is four `uint32_t` number in the metadata, i.e. the offset of the | ||
file name in the blob array, the length of the file name, the offset of the file | ||
content in the blob array, and the length of the file content. | ||
|
||
We represent the above structures using c struct-like syntax as follows. | ||
```c | ||
struct Blob { | ||
uint32_t offset; | ||
uint32_t length; | ||
} | ||
|
||
struct Metadata { | ||
struct Blob file_name; | ||
struct Blob file_content; | ||
} | ||
|
||
struct SimpleFileSystem { | ||
uint32_t file_count; | ||
struct Metadata metadata[..]; | ||
uint8_t payload[..]; | ||
} | ||
``` | ||
|
||
When serializing the file system into a file, all integers are encoded as a | ||
32-bit little-endian number. The file names are stored as null-terminated | ||
strings. | ||
|
||
Below is a binary dump of the file system created from a simple file called | ||
`main.js` with content `console.log('hello world!')`. | ||
|
||
```text | ||
00000000 01 00 00 00 00 00 00 00 08 00 00 00 08 00 00 00 |................| | ||
00000010 1c 00 00 00 6d 61 69 6e 2e 6a 73 00 63 6f 6e 73 |....main.js.cons| | ||
00000020 6f 6c 65 2e 6c 6f 67 28 27 68 65 6c 6c 6f 20 77 |ole.log('hello w| | ||
00000030 6f 72 6c 64 21 27 29 0a 00 |orld!')..| | ||
``` |
Oops, something went wrong.