Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update readme to reflect recent changes #72

Merged
merged 8 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ jsvm:
cd jsvm && ./build.sh && cd ..
cp jsvm/jsvm.wasm res/jsvm.wasm

jsvm-nightly:
echo "Building jsvm.wasm..."
cd jsvm && NEAR_NIGHTLY=1 ./build.sh && cd ..
cp jsvm/jsvm_nightly.wasm res/jsvm_nightly.wasm

qjsc:
echo "Building qjsc bytecode compiler"
cd quickjs && ./build.sh && cd ..
Expand Down
735 changes: 375 additions & 360 deletions README.md

Large diffs are not rendered by default.

139 changes: 0 additions & 139 deletions jsvm/jsvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,17 @@ extern void panic(void);
extern void panic_utf8(uint64_t len, uint64_t ptr);
extern void log_utf8(uint64_t len, uint64_t ptr);
extern void log_utf16(uint64_t len, uint64_t ptr);
// Name confliction with WASI. Can be re-exported with a different name on NEAR side with a protocol upgrade
// Or, this is actually not a primitive, can be implement with log and panic host functions in C side or JS side.
// extern void abort(uint32_t msg_ptr, uint32_t filename_ptr, uint32_t u32, uint32_t col);
// ################
// # Promises API #
// ################
extern uint64_t promise_create(uint64_t account_id_len, uint64_t account_id_ptr, uint64_t method_name_len, uint64_t method_name_ptr, uint64_t arguments_len, uint64_t arguments_ptr, uint64_t amount_ptr, uint64_t gas);
extern uint64_t promise_then(uint64_t promise_index, uint64_t account_id_len, uint64_t account_id_ptr, uint64_t method_name_len, uint64_t method_name_ptr, uint64_t arguments_len, uint64_t arguments_ptr, uint64_t amount_ptr, uint64_t gas);
extern uint64_t promise_and(uint64_t promise_idx_ptr, uint64_t promise_idx_count);
extern uint64_t promise_batch_create(uint64_t account_id_len, uint64_t account_id_ptr);
extern uint64_t promise_batch_then(uint64_t promise_index, uint64_t account_id_len, uint64_t account_id_ptr);
// #######################
// # Promise API actions #
// #######################
extern void promise_batch_action_transfer(uint64_t promise_index, uint64_t amount_ptr);
// #######################
// # Promise API results #
// #######################
extern uint64_t promise_results_count(void);
extern uint64_t promise_result(uint64_t result_idx, uint64_t register_id);
extern void promise_return(uint64_t promise_idx);
// ###############
// # Storage API #
Expand Down Expand Up @@ -460,128 +451,6 @@ static JSValue near_log_utf16(JSContext *ctx, JSValueConst this_val, int argc, J
return JS_UNDEFINED;
}

static JSValue near_promise_create(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
const char *account_id_ptr, *method_name_ptr, *arguments_ptr;
size_t account_id_len, method_name_len, arguments_len;
uint64_t amount_ptr[2]; // amount is u128
uint64_t gas, ret;

account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[0]);
method_name_ptr = JS_ToCStringLen(ctx, &method_name_len, argv[1]);
arguments_ptr = JS_ToCStringLenRaw(ctx, &arguments_len, argv[2]);
if (quickjs_to_u128(ctx, argv[3], amount_ptr) != 0) {
return JS_ThrowTypeError(ctx, "Expect Uint128 for amount");
}
if (JS_ToUint64Ext(ctx, &gas, argv[4]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for gas");
}

ret = promise_create(account_id_len, (uint64_t)account_id_ptr, method_name_len, (uint64_t)method_name_ptr, arguments_len, (uint64_t)arguments_ptr, (uint64_t)amount_ptr, gas);

return JS_NewBigUint64(ctx, ret);
}

static JSValue near_promise_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
uint64_t promise_index;
const char *account_id_ptr, *method_name_ptr, *arguments_ptr;
size_t account_id_len, method_name_len, arguments_len;
uint64_t amount_ptr[2]; // amount is u128
uint64_t gas, ret;

if (JS_ToUint64Ext(ctx, &promise_index, argv[0]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_index");
}
account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[1]);
method_name_ptr = JS_ToCStringLen(ctx, &method_name_len, argv[2]);
arguments_ptr = JS_ToCStringLenRaw(ctx, &arguments_len, argv[3]);
if (quickjs_to_u128(ctx, argv[4], amount_ptr) != 0) {
return JS_ThrowTypeError(ctx, "Expect Uint128 for amount");
}
if (JS_ToUint64Ext(ctx, &gas, argv[5]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for gas");
}

ret = promise_then(promise_index, account_id_len, (uint64_t)account_id_ptr, method_name_len, (uint64_t)method_name_ptr, arguments_len, (uint64_t)arguments_ptr, (uint64_t)amount_ptr, gas);

return JS_NewBigUint64(ctx, ret);
}

static JSValue near_promise_and(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
uint64_t promise_idx_ptr[argc], ret;

for(int i = 0; i < argc; i++) {
if (JS_ToUint64Ext(ctx, &promise_idx_ptr[i], argv[i]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_id");
}
}
ret = promise_and((uint64_t)promise_idx_ptr, argc);
return JS_NewBigUint64(ctx, ret);
}

static JSValue near_promise_batch_create(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
const char *account_id_ptr;
size_t account_id_len;
uint64_t ret;

account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[0]);
ret = promise_batch_create(account_id_len, (uint64_t)account_id_ptr);
return JS_NewBigUint64(ctx, ret);
}

static JSValue near_promise_batch_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
uint64_t promise_index;
const char *account_id_ptr;
size_t account_id_len;
uint64_t ret;

if (JS_ToUint64Ext(ctx, &promise_index, argv[0]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_index");
}
account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[1]);
ret = promise_batch_then(promise_index, account_id_len, (uint64_t)account_id_ptr);
return JS_NewBigUint64(ctx, ret);
}

static JSValue near_promise_results_count(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
uint64_t value;

value = promise_results_count();
return JS_NewBigUint64(ctx, value);
}

static JSValue near_promise_result(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
uint64_t result_idx, register_id;
uint64_t ret;

if (JS_ToUint64Ext(ctx, &result_idx, argv[0]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for result_idx");
}
if (JS_ToUint64Ext(ctx, &register_id, argv[1]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for register_id");
}
ret = promise_result(result_idx, register_id);

return JS_NewBigUint64(ctx, ret);
}

static JSValue near_promise_return(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
uint64_t promise_idx;
if (JS_ToUint64Ext(ctx, &promise_idx, argv[0]) < 0) {
return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_idx");
}
promise_return(promise_idx);

return JS_UNDEFINED;
}

const uint64_t STORAGE_PRICE_PER_BYTE_U64 = 10000000000000000000ul;
const char *STORAGE_PRICE_PER_BYTE = "10000000000000000000";

Expand Down Expand Up @@ -1151,14 +1020,6 @@ static void js_add_near_host_functions(JSContext* ctx) {
JS_SetPropertyStr(ctx, env, "log", JS_NewCFunction(ctx, near_log, "log", 1));
JS_SetPropertyStr(ctx, env, "log_utf8", JS_NewCFunction(ctx, near_log_utf8, "log_utf8", 1));
JS_SetPropertyStr(ctx, env, "log_utf16", JS_NewCFunction(ctx, near_log_utf16, "log_utf16", 1));
JS_SetPropertyStr(ctx, env, "promise_create", JS_NewCFunction(ctx, near_promise_create, "promise_create", 5));
JS_SetPropertyStr(ctx, env, "promise_then", JS_NewCFunction(ctx, near_promise_then, "promise_then", 6));
JS_SetPropertyStr(ctx, env, "promise_and", JS_NewCFunction(ctx, near_promise_and, "promise_and", 1));
JS_SetPropertyStr(ctx, env, "promise_batch_create", JS_NewCFunction(ctx, near_promise_batch_create, "promise_batch_create", 1));
JS_SetPropertyStr(ctx, env, "promise_batch_then", JS_NewCFunction(ctx, near_promise_batch_then, "promise_batch_then", 2));
JS_SetPropertyStr(ctx, env, "promise_results_count", JS_NewCFunction(ctx, near_promise_results_count, "promise_results_count", 0));
JS_SetPropertyStr(ctx, env, "promise_result", JS_NewCFunction(ctx, near_promise_result, "promise_result", 2));
JS_SetPropertyStr(ctx, env, "promise_return", JS_NewCFunction(ctx, near_promise_return, "promise_return", 1));
JS_SetPropertyStr(ctx, env, "storage_read", JS_NewCFunction(ctx, near_storage_read, "storage_read", 2));
JS_SetPropertyStr(ctx, env, "storage_has_key", JS_NewCFunction(ctx, near_storage_has_key, "storage_has_key", 1));
JS_SetPropertyStr(ctx, env, "validator_stake", JS_NewCFunction(ctx, near_validator_stake, "validator_stake", 2));
Expand Down
Binary file modified res/jsvm.wasm
Binary file not shown.
Binary file added res/jsvm_nightly.wasm
Binary file not shown.
82 changes: 79 additions & 3 deletions src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,30 @@ export function predecessorAccountId() {
return env.read_register(0)
}

export function blockIndex() {
return env.block_index()
}

export function blockTimestamp() {
return env.block_timestamp()
}

export function epochHeight() {
return env.epoch_height()
}

export function attachedDeposit() {
return env.attached_deposit()
}

export function prepaidGas() {
return env.prepaid_gas()
}

export function usedGas() {
return env.used_gas()
}

export function randomSeed() {
env.random_seed(0)
return env.read_register(0)
Expand Down Expand Up @@ -49,7 +73,21 @@ export function ecrecover(hash, sign, v, malleabilityFlag) {
return env.read_register(0)
}

// TODO: env.promise_result returns need additioonal handling
export function panic(msg) {
env.panic(msg)
}

export function panicUtf8(msg) {
env.panic_utf8(msg)
}

export function logUtf8(msg) {
env.log_utf8(msg)
}

export function logUtf16(msg) {
env.log_utf16(msg)
}

export function storageRead(key) {
let ret = env.storage_read(key, 0)
Expand All @@ -60,6 +98,23 @@ export function storageRead(key) {
}
}

export function storageHasKey(key) {
let ret = env.storage_has_key(key)
if (ret === 1n) {
return true
} else {
return false
}
}

export function validatorStake(accountId) {
return env.validator_stake(accountId)
}

export function validatorTotalStake() {
return env.validator_total_stake()
}

export function altBn128G1Multiexp(value) {
env.alt_bn128_g1_multiexp(value, 0)
return env.read_register(0)
Expand All @@ -70,6 +125,15 @@ export function altBn128G1Sum(value) {
return env.read_register(0)
}

export function altBn128PairingCheck(value) {
let ret = env.alt_bn128_pairing_check(value)
if (ret === 1n) {
return true
} else {
return false
}
}

export function jsvmAccountId() {
env.jsvm_account_id(0)
return env.read_register(0)
Expand Down Expand Up @@ -122,11 +186,23 @@ export function jsvmStorageHasKey(key) {
return false
}

export function jsvmCall(contractName, method, args) {
export function jsvmCallRaw(contractName, method, args) {
env.jsvm_call(contractName, method, JSON.stringify(args), 0)
return JSON.parse(env.read_register(0) || 'null')
return env.read_register(0)
}

export function jsvmCall(contractName, method, args) {
let ret = jsvmCallRaw(contractName, method, args)
if (ret === null) {
return ret
}
return JSON.parse(ret)
}

export function storageGetEvicted() {
return env.read_register(EVICTED_REGISTER)
}

export function jsvmValueReturn(value) {
env.jsvm_value_return(value)
}
4 changes: 4 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ export function stringToU8Array(string) {
ret[i] = string.charCodeAt(i)
}
return ret
}

export function encodeCall(contract, method, args) {
return Buffer.concat([Buffer.from(contract), Buffer.from([0]), Buffer.from(method), Buffer.from([0]), Buffer.from(JSON.stringify(args))])
}