wasmerio / wasmer

🚀 The leading Wasm Runtime supporting WASIX and WASI
https://wasmer.io
MIT License
18.93k stars 811 forks source link

Determenistic WASI #4252

Open Noc0r opened 1 year ago

Noc0r commented 1 year ago

Summary

Can i somehow override syscalls from wasmer-wasix crate? I want to achieve next behavior:

console.log(Math.random());
console.log(new Date());

should return predefined values instead of real random value and real date. As i understood on logs it calls clock_time_get:

2023-10-11T14:35:33.827764Z TRACE clock_time_get{clock_id=Snapshot0Clockid::Realtime precision=1000}: wasmer_wasix::syscalls::wasi::clock_time_get: return=Errno::success
2023-10-11T14:35:33.828647Z TRACE fd_fdstat_get{fd=5}: wasmer_wasix::syscalls::wasi::fd_fdstat_get: return=Errno::success
2023-10-11T14:35:33.829050Z DEBUG path_open{dirfd=5 follow_symlinks=true path="contract/onchain.js" ret_fd=6}: wasmer_wasix::syscalls::wasi::path_open: return=Errno::success
2023-10-11T14:35:33.829307Z TRACE fd_seek:fd_seek{fd=6 offset=0 whence=Whence::End}: wasmer_wasix::syscalls::wasi::fd_seek: new_offset=52
2023-10-11T14:35:33.829347Z TRACE fd_seek:fd_seek{fd=6 offset=0 whence=Whence::End}: wasmer_wasix::syscalls::wasi::fd_seek: return=Ok(Errno::success)
2023-10-11T14:35:33.829402Z DEBUG fd_seek: wasmer_wasix::syscalls::legacy::snapshot0: return=Ok(Errno::success)
2023-10-11T14:35:33.829488Z TRACE fd_seek:fd_seek{fd=6 offset=0 whence=Whence::Cur}: wasmer_wasix::syscalls::wasi::fd_seek: new_offset=52
2023-10-11T14:35:33.829519Z TRACE fd_seek:fd_seek{fd=6 offset=0 whence=Whence::Cur}: wasmer_wasix::syscalls::wasi::fd_seek: return=Ok(Errno::success)
2023-10-11T14:35:33.829558Z DEBUG fd_seek: wasmer_wasix::syscalls::legacy::snapshot0: return=Ok(Errno::success)
2023-10-11T14:35:33.829629Z TRACE fd_seek:fd_seek{fd=6 offset=0 whence=Whence::Set}: wasmer_wasix::syscalls::wasi::fd_seek: new_offset=0
2023-10-11T14:35:33.829659Z TRACE fd_seek:fd_seek{fd=6 offset=0 whence=Whence::Set}: wasmer_wasix::syscalls::wasi::fd_seek: return=Ok(Errno::success)
2023-10-11T14:35:33.829702Z DEBUG fd_seek: wasmer_wasix::syscalls::legacy::snapshot0: return=Ok(Errno::success)
2023-10-11T14:35:33.829847Z TRACE fd_read{fd=6 nread=52}: wasmer_wasix::syscalls::wasi::fd_read: return=Errno::success
2023-10-11T14:35:33.829961Z TRACE fd_close{pid=1 fd=6}: wasmer_wasix::fs: weakening file descriptor fd=6 inode=8 ref_cnt=2
2023-10-11T14:35:33.830000Z DEBUG fd_close{pid=1 fd=6}: wasmer_wasix::syscalls::wasi::fd_close: return=Errno::success
2023-10-11T14:35:33.830240Z TRACE fd_fdstat_get{fd=1}: wasmer_wasix::syscalls::wasi::fd_fdstat_get: return=Errno::success
2023-10-11T14:35:33.830401Z TRACE fd_write{fd=1 nwritten=21}: wasmer_wasix::syscalls::wasi::fd_write: return=Errno::success
2023-10-11T14:35:33.830494Z TRACE clock_time_get{clock_id=Snapshot0Clockid::Realtime precision=1000}: wasmer_wasix::syscalls::wasi::clock_time_get: return=Errno::success
2023-10-11T14:35:33.830620Z TRACE fd_write{fd=1 nwritten=34}: wasmer_wasix::syscalls::wasi::fd_write: return=Errno::success
Michael-F-Bryan commented 1 year ago

@Noc0r WASIX has a wasmer_wasix::Runtime trait which acts as an abstraction of the "Operating System", and WASIX syscalls are implemented in terms of that abstraction.

To make syscalls deterministic, we would need to add methods for getting the time and populating a buffer with random bytes and make sure syscalls go through that rather than directly calling the equivalent functions on the host.

It should be quite possible to do, however the core Wasmer team probably won't have spare capacity to make those changes in the foreseeable time. We are happy to guide PRs to implement this feature, though.

Noc0r commented 1 year ago

@Michael-F-Bryan I implemented logic for deterministic, can i somehow create PR for this?

Noc0r commented 1 year ago

@Michael-F-Bryan May be you know what can be the issue: I'm using this quickjs engine: https://wasmer.io/saghul/quickjs And when i'm trying to get new Date(), then it works fine. But Math.random() still returns random data. I checked code of quickjs and looks like it uses syscall to gettimeofday host function.

static void js_random_init(JSContext *ctx)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
    /* the state must be non zero */
    if (ctx->random_state == 0)
        ctx->random_state = 1;
}