Comparing Michelson and WebAssembly

This is the first article about exploring a custom WebAssembly runtime environment for Tezos. Let’s start with comparing Michelson and WebAssembly.

Michelson

Michelson is a stack-based smart contract language with high level data types and primitives for Tezos. As the language is used to program money that’s stored on a distributed ledger, some unique characteristics apply:

  • it’s important that a contract can be verified to do exactly what it says it does. And to do this on any machine that it runs on.
  • storing a contract on the ledger can be done by anyone, and it’s not clear if a contract comes from an attacker or not. Therefore the space that’s used is important, and every byte on the ledger costs money.
  • executing the instructions of the smart contract takes time, and can be misused, therefore instructions cost money as well.

These last two points are also known as gas costs.

Next to these unique characteristics, there are also several other characteristics worth mentioning:

  • Contracts are written in plain text. Therefore it first needs to parsed before it can be checked and evaluated.
  • No exception handling.
  • Immutable variables.
  • Strict type system, which includes Tezos specific types.
  • The language can evolve through amendment.

For more info see: http://tezos.gitlab.io/whitedoc/michelson.html

WebAssembly

WebAssembly is a stack-based binary instruction format with low level data types and primitives, that’s used as a compilation target for a growing list of programming languages. An important characteristic of WebAssembly is that it’s memory-safe and sandboxed. To achieve this a strict type system is used together with implicit access to the system stack. The implicit access to the system stack also makes it quite different from more traditional compilation targets.

Beyond this, for WebAssembly - the MVP specification - some other important characteristics apply:

  • There are four value types: i32, i64, f32, f64. The sign bit of the floats is non-deterministic as described here: https://github.com/WebAssembly/design/blob/master/Nondeterminism.md. Functions are typed as well.
  • It can be printed to s-expressions.
  • There is no nested function support.
  • WebAssembly MVP has access to a single block of bounds checked linear memory. There is no form of automatic memory management.
  • Indirect calls can be made and are checked at runtime.

For more info see: https://webassembly.github.io/spec/

Although the WebAssembly MVP specification is finished and implemented many times, new features are being added to WebAssembly through extensions.

For this post I want to mention the reference types specification (https://github.com/WebAssembly/reference-types), which adds the anyref value type. This allows host references to be directly used from WebAssembly. The only downside with the current iteration is that all anyrefs are equal. There are however ideas to make reference types unique - https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md#type-importexport.

Summarizing

Most of the instructions used by Michelson can be transferred to WebAssembly. A challenge will be having the same kind of type safety that Michelson has, and might require help with reference types standardization work. Tezos specific instructions will need to be supported by the host environment.

Not all functionality that WebAssembly has is supported by Michelson. Floats, linear memory, and indirect calls are not supported by Michelson.

WebAssembly by default has no support for gas cost calculation, but this can be solved in the runtime.


Now that we have a basic understanding of the differences between Michelson and WebAssembly, what are your thoughts? Did I miss something essential here?

As we are not the first ones to explore WebAssembly for a smart contract platform, let’s take a look at prior art in the next article about exploring a custom WebAssembly runtime environment for Tezos.

8 Likes

Thanks for the write up. Can you point out the advantages of WebAssembly vs Michelson? According to google: it has better performance & easier compilation on the web (browser). I don’t see how that is relevant to blockchains, given the code is ultimately run on the node and has nothing to do with the browser?

@mootjes Thanks for the questions.

Although it’s called WebAssembly, a better name would probably be “UniversalBytecode” as it reach is well beyond the web and it’s too high level to call it actual assembly. This is also why multiple programming languages are interesting in supporting WebAssembly as a compilation target.

As multiple languages target and contribute to WebAssembly, this also makes it interesting to support WebAssembly as a smart contract runtime. The more people who can write smart contracts, the better. I expect that WebAssembly is more likely to get people outside of the Tezos community onboard, compared to Michelson.

However, I believe a good amount of skepticism is important and just implementing WebAssembly as-is in Tezos would be a bad idea. Running a classic application is definitely something different than running a “smart contract” application. Other blockchains have implemented WebAssembly as-is though, and I’m not a fan - as there is very little type safety due to the limited amount of supported types by default in WebAssembly. This is why I mentioned Reference Types in the post above. Also, I’m not sure if every feature should be supported from the start. Why would you want to manage a piece of memory for example if Michelson completely lacks this? A more conservative approach would have my preference. Unfortunately this approach has some downsides for supporting multiple languages, as those will probably expect certain features to be there.

If the Tezos community would decide to support WebAssembly, it would need to be at least be as good as Michelson. These posts are about exploring the idea of a WebAssembly runtime for Tezos, and I will try to make the best case for this.