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

Support wasmtime in the sandbox of europa #2

Merged
merged 2 commits into from
Jan 21, 2021
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
3 changes: 2 additions & 1 deletion src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Yep, a blog, fine, no more introduce, technical records here.

## Table of Contents

1. [Enable WASM Backtrace](/enable-wasm-backtrace.md)
1. [Enable WASM Backtrace](https://patractlabs.github.io/blog/enable-wasm-backtrace.html)
2. [Support wasmtime in sandbox](https://patractlabs.github.io/blog/support-wasmtime-in-sandbox.html)


## LICENSE
Expand Down
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
---

- [Enable WASM Backtrace](./enable-wasm-backtrace.md)
- [Support wasmtime in sandbox](./support-wasmtime-in-sandbox.md)
2 changes: 1 addition & 1 deletion src/enable-wasm-backtrace.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ to the WASM contracts at [paritytech/wasm-utils/gas/mod.rs#L467][wasm-utils/gas]
function indecies in name section that we can not get the correct backtraces.


## 3. Impelment WASM backtrace to WASMI
## 3. Impelment WASM backtrace for WASMI

* Source: [patractlabs/wasmi](https://github.com/patractlabs/wasmi)

Expand Down
104 changes: 104 additions & 0 deletions src/support-wasmtime-in-sandbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Support wasmtime in sandbox

Just supported [wasmtime][wasmtime] in the sandbox of [europa][europa] these days, we
can execute ink! contracts using JIT and trace the panicking line numbers of the rust
code with DWARF for now.


## 1. The arch of sandbox

The `sandbox` we are talking here is `primitives/sandbox` which executes ink! contract
in `pallet-contracts`, it abstracts a WASM layer that can adapt different wasm executors.

```rust
/// Sandbox liner memory
struct Memory { ... }

/// WASM imports
struct EnvironmentDefinitionBuilder<T> { ... }

/// WASM module instance
struct Instance { ... }
```

### 1.1 Memory

The host functions defined in `pallet-contracts` use `(ptr: u32, len: u32,)` as arguments
since WASM only can accept integer.

The process is like:

+ (pallet-contract): Alloc memory from the liner memory of WASM
+ (pallet-contract): Passing pointers into wasm interface
+ (wasm-executor): Get porinters and executue functions
+ (wasm-executor): Return result to pallet-contract
+ (pallet-contract): Read result from liner memory through pointers


### 1.2 Environment

The environment in sandbox includes `Host Functions` and `Memory`, both memory and functions
could be externed outside WASM module. It sets up the interaction between native machine and
wasm module.


### 1.3 Instance

WASM module with human friendly interfaces comes to instance, it used for invoking functions
in the sandbox.


## 2. Wasmtime

There are not a lot of trouble adapting wasmtime into the sandbox, passing generic types to
the host function may be the one could be mentioned.


```rust
pub fn wrap_fn<T>(store: &Store, state: usize, f: usize, sig: FunctionType) -> Func {
let func = move |_: Caller<'_>, args: &[Val], results: &mut [Val]| {
let mut inner_args = vec![];
for arg in args {
if let Some(arg) = from_val(arg.clone()) {
inner_args.push(arg);
} else {
return Err(Trap::new("Could not wrap host function"));
}
}

// HACK the LIFETIME
//
// # Safety
//
// Runtime only run for one call.
let state: &mut T = unsafe { mem::transmute(state) };
let func: HostFuncType<T> = unsafe { mem::transmute(f) };
match func(state, &inner_args) {
Ok(ret) => {
if let Some(ret) = from_ret_val(ret) {
results[0] = ret;
}
Ok(())
}
Err(_) => Err(Trap::new("Could not wrap host function")),
}
};
Func::new(store, wasmtime_sig(sig), func)
}
```

Likewise, we pass pointers to the `Func` struct of wasmtime with `unsafe` code that we can define
our host functions.


## 3. DWARF

The support of DWARF in wasm is still in an early stage for now, which hasn't been written into the
SPEC, but an document [DWARF for WebAssembly][dwarf] has introduced it.

As a result, we use the `DWARF` implementation in wasmtime directly now, it could be enable with
envrionment `WASM_BACKTRACE_DETAILS=1` as how it works in wasmtime.

[europa]: https://github.com/patractlabs/europa
[wasmtime]: https://github.com/bytecodealliance/wasmtime
[dwarf]: https://yurydelendik.github.io/webassembly-dwarf/