Wasm VM Specification

Abstract

Quai Network should utilize a Wasm VM in in order to conform to a public standard of computing. Wasm has generally been adopted and maintained by the larger software community. Wasm also aligns with our general goals of security, portability, and toolchain compatibility.

Copyright

This QIP licensed under the BSD 2-clause license.

Definitions

  • Quai environment interface (QEI): a set of methods available to wasm contracts
  • metering: the act of measuring execution cost in a deterministic way
  • metering injector: a transformation tool inserting metering code to an wasm contract

Motivations

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

Objectives of WebAssembly include:

Efficient and fast

The Wasm stack machine is designed to be encoded in a size- and load-time-efficient binary format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.

Safe

WebAssembly describes a memory-safe, sandboxed execution environment that may even be implemented inside existing JavaScript virtual machines. When embedded in the web, WebAssembly will enforce the same-origin and permissions security policies of the browser.

Open and debuggable

WebAssembly is designed to be pretty-printed in a textual format for debugging, testing, experimenting, optimizing, learning, teaching, and writing programs by hand. The textual format will be used when viewing the source of Wasm modules on the web.

Part of the open web platform

WebAssembly is designed to maintain the versionless, feature-tested, and backwards-compatible nature of the web. WebAssembly modules will be able to call into and out of the JavaScript context and access browser functionality through the same Web APIs accessible from JavaScript. WebAssembly also supports non-web embeddings.

Specification

  • To provide a specification of the Quai node interface and subsequent host function capabilities
  • To provide an solidity transcompiler
  • To provide a VM implementation for executing Wasm contracts
  • To provide a metering injector if needed
  • To provide a library and instructions for writing contracts in Rust/C/Go/AssemblyScript

An initial draft PR utilizing the wazero Wasm engine has been created here:

This would of course need to be discussed alongside options like RISC0 and RISC-V

I have a few questions that I’ll just drop here. I’m sure I’ll have more questions as I think about this more, but for now:

  1. how does metering get deterministically injected? How do contract devs know the hash of the metered contract before deployment, without relying on the dev to inject the metering?
  2. will a wazero implementation be interoperable with other engines? e.g. if someone writes a Quai client in rust and uses a different wasm VM written in rust? How do other VMs handle metering, and what would it take to get another VM to interoperate with wazero metering?
  3. if we’re considering new VMs, is there any interest in choosing one that is ZK verifiable?
  1. Great question that will require some discovery.
  2. The WASM engine itself is portable. If we write a client in Rust then the only non-deterministic behavior would be the host function calls. Example: Does getBlockByNumber return data the same way in Go vs Rust. That is why standardizing the QEI is so important.
  3. Another great question. Given we rely so heavily on Golang right now, RISC0 doesn’t seem like an option due to lack of Go bindings. Unless we of course decided to write our own Go bindings and add additional complexity.

I completely agree. I guess the question I was really trying to ask is: Is the host interface defined for wazero (i.e. your QEI proposal) the only development effort if someone built a rust/c++ client?

We cannot tolerate differences in behavior between two VMs. A contract should execute identically (including same gas metering) in any different VM. Since wazero’s gas metering is bespoke, how do we guarantee interoperability between other wasm VMs and their implementations of gas metering?

Example wasmer-go implementation. Would need to define the gasCost using this metering middleware:

wasmer-go has not had a release that brings in the monitoring changes :confused:

Reopened the WIP PR against go-quai for wazero: `WIP` WasmVM implemented with wazero by alanorwick · Pull Request #1178 · dominant-strategies/go-quai · GitHub

Adding initial Wasm VM specification with QEI interface methods: https://github.com/dominant-strategies/quai-specs/pull/35