4 Commits

Author SHA1 Message Date
vms
90b08c0780 update readme 2019-08-14 22:16:32 +03:00
vms
80bb40d11c activate json1 module 2019-08-14 21:35:55 +03:00
vms
24978af696 better multimodules support for Rust backend 2019-08-14 17:58:50 +03:00
vms
dddce7bf93 move to wasi 6 2019-08-14 01:20:56 +03:00
4 changed files with 98 additions and 7 deletions

View File

@ -4,9 +4,10 @@ RUN apt-get update \
&& apt-get install -y ca-certificates \
curl \
git \
make
make \
libtinfo5
RUN curl -L https://github.com/CraneStation/wasi-sdk/releases/download/wasi-sdk-5/wasi-sdk-5.0-linux.tar.gz | tar xz --strip-components=1 -C /
RUN curl -L https://github.com/CraneStation/wasi-sdk/releases/download/wasi-sdk-6/wasi-sdk-6.0-linux.tar.gz | tar xz --strip-components=1 -C /
VOLUME /code
WORKDIR /code

View File

@ -1,13 +1,13 @@
TARGET = sqlite3
CC = /opt/wasi-sdk/bin/clang
SYSROOT = /opt/wasi-sdk/share/sysroot
SYSROOT = /opt/wasi-sdk/share/wasi-sysroot
TARGET_TRIPLE = wasm32-unknown-wasi
CFLAGS = -nostartfiles -fvisibility=hidden
LDFLAGS = -Wl,--no-entry,--demangle,--allow-undefined
EXPORT_FUNCS = --export=allocate,--export=deallocate,--export=invoke,--export=load,--export=store
EXPORT_FUNCS = --export=allocate,--export=deallocate,--export=invoke,--export=load,--export=store,--export=sqlite_allocate,--export=sqlite_deallocate,--export=sqlite_invoke,--export=sqlite_load,--export=sqlite_store
SQLITE_SRC = src/alter.c src/analyze.c src/attach.c src/auth.c src/backup.c src/bitvec.c src/btmutex.c src/btree.c src/build.c src/callback.c src/complete.c src/ctime.c src/date.c src/dbpage.c src/dbstat.c src/delete.c src/expr.c src/fault.c src/fkey.c src/fts3.c src/fts3_write.c src/fts3_aux.c src/fts3_expr.c src/fts3_hash.c src/fts3_icu.c src/fts3_porter.c src/fts3_snippet.c src/fts3_tokenize_vtab.c src/fts3_tokenizer.c src/fts3_tokenizer1.c src/fts3_unicode.c src/fts3_unicode2.c src/fts5.c src/func.c src/global.c src/hash.c src/insert.c src/json1.c src/legacy.c src/loadext.c src/main.c src/malloc.c src/memdb.c src/mem0.c src/mem1.c src/mem2.c src/memjournal.c src/notify.c src/opcodes.c src/os.c src/pager.c src/parse.c src/pcache.c src/pcache1.c src/pragma.c src/prepare.c src/printf.c src/random.c src/resolve.c src/rowset.c src/rtree.c src/select.c src/sqlite3session.c src/status.c src/stmt.c src/table.c src/tokenize.c src/treeview.c src/trigger.c src/update.c src/upsert.c src/userauth.c src/utf.c src/util.c src/vacuum.c src/vdbe.c src/vdbeapi.c src/vdbeaux.c src/vdbeblob.c src/vdbemem.c src/vdbesort.c src/vdbetrace.c src/vtab.c src/wal.c src/walker.c src/where.c src/wherecode.c src/whereexpr.c src/window.c
WRAPPER_SRC = src/wrapper.c
SQLITE_FLAGS = -DSQLITE_CORE -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite -DNDEBUG -DSQLITE_THREADSAFE=0 -DHAVE_READLINE=0 -DHAVE_EDITLINE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_ENABLE_DESERIALIZE -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_OMIT_POPEN
SQLITE_FLAGS = -DSQLITE_CORE -D_HAVE_SQLITE_CONFIG_H -DSQLITE_ENABLE_JSON1 -DBUILD_sqlite -DNDEBUG -DSQLITE_THREADSAFE=0 -DHAVE_READLINE=0 -DHAVE_EDITLINE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_ENABLE_DESERIALIZE -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_OMIT_POPEN
SDK = sdk/logger.c
.PHONY: default all clean
@ -16,7 +16,7 @@ default: $(TARGET)
all: default
$(TARGET): $(SDK) $(SQLITE_SRC) $(WRAPPER_SRC)
$(CC) --sysroot=$(SYSROOT) --target=$(TARGET_TRIPLE) -O2 $(SQLITE_FLAGS) $(CFLAGS) $(LDFLAGS) -Wl,$(EXPORT_FUNCS) $^ -o $@.wasm
$(CC) -O3 --sysroot=$(SYSROOT) --target=$(TARGET_TRIPLE) $(SQLITE_FLAGS) $(CFLAGS) $(LDFLAGS) -Wl,$(EXPORT_FUNCS) $^ -o $@.wasm
.PRECIOUS: $(TARGET)

View File

@ -1,6 +1,6 @@
# SQLite
Sqlite fork ported to WebAssembly.
Sqlite fork ported to WebAssembly and adapted for the Fluence network. Could be launched and played on the Fluence [dashboard](http://dash.fluence.network/deploy/sqlite).
# How to build
@ -14,3 +14,72 @@ or by Makefile with [wasi-sdk](https://github.com/CraneStation/wasi-sdk) install
```bash
make
```
# How to use
At now, this fork exports five API functions:
```cpp
/**
* Executes given SQL request and returns result in as a pointer to the following structure: | result size (4 bytes, le)| result (size bytes) |.
*
* @param sql a pointer to the supplied sql request
* @param length a size of the supplied sql request
* @return a pointer to the struct contains result_size and result
*/
char *invoke(const char *sql, size_t length);
/**
* Allocates a memory region of a given size. Could be used by Wasm execution environments for byte array passing.
*
* @param size a size of allocated memory region
* @return a pointer to the allocated memory region
*/
void *allocate(size_t size);
/**
* Frees a memory region. Could be used by Wasm execution environments for freeing previous memory allocated by `allocate` function.
*
* @param ptr a pointer to the previously allocated memory region
* @param size a size of the previously allocated memory region
*/
void deallocate(void *ptr, size_t size);
/**
* Stores one byte by a given address in the module memory.
*
* @param ptr a address where byte should be stored
* @param value a byte to be stored
*/
void store(void *ptr, char value);
/**
* Returns one byte by a given address in the module memory.
*
* @param ptr a address at which the needed byte is located
* @return the byte at the given address
*/
char load(void *ptr);
```
Given char string `sql` as the request, the general scheme to use it is following:
1. `void *ptr = allocate(strlen(sql))` that returns a pointer to the memory region enough for the string
2. `void *res = invoke(ptr, strlen(sql))` to execute the request
3. read a result from the `res` by reading 4 bytes as little-endian `result_size` and the read `result_size` bytes as the final result.
4. `deallocate(res, strlen(sql))` to clean memory.
Depends on your Wasm execution environment, `load`/`store` could be used for reading and writing a module memory.
## More insights
At Fluence, we use WebAssembly (Wasm) to run applications in a trustless network of independent nodes. This trustless environment mandates that every piece of the code executed by any network node must be verified by another node to check whether the execution was performed correctly. In order to be verifiable, every computation must be made deterministic, which means that to run WebAssembly code in a trustless network, we need to make its execution deterministic.
There are three primary sources of nondeterminism in WebAssembly: external functions invocation, NaN payloads, and VM resource exhaustion. The first one is the most problematic; currently, we deal with it by simply prohibiting any interactions with the host environment from Wasm programs. This means that submitted WebAssembly code should not contain any external imports.
The main purpose of this fork is to compile to Wasm without any imports. SQlite is famous for it embeddability and allows to configure itself by variety of macros. E.g. multithreading that produces a lot of imports of host functions could be completely disabled by setting SQLITE_THREADSAFE to 0. Also this fork has been patched to use only memory database without any interaction with a hard disk. So, now it is Wasm in-memory database.
More information about ways of porting C/C++ code to Wasm could be found in our [article](https://medium.com/fluence-network/porting-redis-to-webassembly-with-clang-wasi-af99b264ca8) about porting of Redis.
## Future plans
We are working on supporting of subset of WASI syscalls to allow interaction with hard disk in a deterministic way.

View File

@ -19,18 +19,34 @@ void store(char *ptr, unsigned char byte) {
*ptr = byte;
}
void sqlite_store(char *ptr, unsigned char byte) {
store(ptr, byte);
}
unsigned char load(const unsigned char *ptr) {
return *ptr;
}
unsigned char sqlite_load(const unsigned char *ptr) {
return load(ptr);
}
void* allocate(size_t size) {
return malloc(size + 1);
}
void* sqlite_allocate(size_t size) {
return allocate(size);
}
void deallocate(void *ptr, int size) {
free(ptr);
}
void sqlite_deallocate(void *ptr, int size) {
deallocate(ptr, size);
}
char *write_response(char *response, int response_size) {
char *result_response = allocate(response_size + 4);
@ -147,7 +163,12 @@ const char *invoke(char *request, int request_size) {
}
}
deallocate(request, request_size + 1);
freeText(&str);
return response;
}
const char *sqlite_invoke(char *request, int request_size) {
return invoke(request, request_size);
}