# Ethereum
# ❤️
# WebAssembly
Martin Becze github.com/wanderer
Alex Beregszaszi github.com/axic
[comment]: # (this talk will give an overview of ewasm)
---
## The core of the system is the VM
![](https://i.imgur.com/aLMhvso.gif)
---
## EVM, growing pains
- 256 bit words<!-- .element: class="fragment" data-fragment-index="1" -->
- It has instuctions that shoudn't be instuctions (GASLIMIT, BALANCE, SHA3, etc)<!-- .element: class="fragment" data-fragment-index="2" -->
- Missing instuctions like shift and rotate<!-- .element: class="fragment" data-fragment-index="3" -->
- No system call equivalent <!-- .element: class="fragment" data-fragment-index="4" -->
- Its a hard compilation target for many HLL <!-- .element: class="fragment" data-fragment-index="5" -->
- Largely incompatible with the ecosystems outside of Ethereum <!-- .element: class="fragment" data-fragment-index="6" -->
---
## Can there be a better way?
---
## What is WebAssembly?
> WebAssembly or wasm is a new, portable, size- and load-time-efficient binary format that aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.
---
## What is WebAssembly?
- Fast & Efficient <!-- .element: class="fragment" data-fragment-index="1" -->
- Secure Sandbox <!-- .element: class="fragment" data-fragment-index="2" -->
- Toolchain Compatibility <!-- .element: class="fragment" data-fragment-index="3" -->
- Extensible <!-- .element: class="fragment" data-fragment-index="4" -->
- The Combined Powers of the Web!<!-- .element: class="fragment" data-fragment-index="5" --><br>![](https://i.imgur.com/Av9JHNY.gif)<!-- .element: class="fragment" data-fragment-index="5" -->
----
### W3C Working Group
www.w3.org/community/webassembly
- Participants (660) <!-- .element: class="fragment" data-fragment-index="1" -->
- Mozilla <!-- .element: class="fragment" data-fragment-index="2" -->
- Google <!-- .element: class="fragment" data-fragment-index="3" -->
- Microsoft <!-- .element: class="fragment" data-fragment-index="4" -->
- Apple <!-- .element: class="fragment" data-fragment-index="5" -->
----
### Instruction Set and AST
- RISC like <!-- .element: class="fragment" data-fragment-index="1" -->
- Integer and float operations <!-- .element: class="fragment" data-fragment-index="2" -->
- Defined as an AST <!-- .element: class="fragment" data-fragment-index="3" -->
- can be easily processed
- can be easily transformed
- can be interpreted with a Stack Machine
- or JITed
----
### S-Expressions
```clojure=
(module
(import $useGas "ethereum" "useGas"
(param i32))
(memory 1)
(export "memory" memory)
(export "main" $main)
(func $main
(local $sp i32)
(local $jump_dest i32)
(set_local $sp
(i32.const -32))
(set_local $jump_dest
(i32.const -1))
(loop $done $loop
(block $1
(block $0
(br_table $0
(if
(i32.eq
(get_local $jump_dest)
(i32.const -1))
(then
(i32.const 0))
(else
(unreachable)))))
(call_import $useGas
(i32.const 6))
(if
(i32.gt_s
(get_local $sp)
(i32.const 32672))
(then
(unreachable)))
(call $PUSH
(i64.const 0)
(i64.const 0)
(i64.const 0)
(i64.const 96)
(get_local $sp))
(set_local $sp
(i32.add
(get_local $sp)
(i32.const 32)))
(call $PUSH
(i64.const 0)
(i64.const 0)
(i64.const 0)
(i64.const 0)
(get_local $sp))
(set_local $sp
(i32.add
(get_local $sp)
(i32.const 32)))))))
```
----
### Semantics
* `(i64.const 42)`<!-- .element: class="fragment" data-fragment-index="1" -->
* Types<!-- .element: class="fragment" data-fragment-index="2" -->
* i32 `(i32.const 0xffffffff)`
* i64 `(i64.const -644)`
* <!-- .element: class="fragment" data-fragment-index="3" -->`(local $a)`
* Memory Access <!-- .element: class="fragment" data-fragment-index="4" -->
* `(i64.load (i64.const 4))`
* `(i64.store (get_local $a) (i64.const 4))`
* Arithmetic<!-- .element: class="fragment" data-fragment-index="5" -->
* Conditionals <!-- .element: class="fragment" data-fragment-index="6" -->
* <!-- .element: class="fragment" data-fragment-index="7" -->Calls
* `(call_import $useGas (i64.const 33))`
----
### Binary Dump
```
0061736d0b00000004747970651003400101004005020202020
10040000006696d706f727412010008657468657265756d0675
73654761730866756e6374696f6e03020102066d656d6f72790
3010101066578706f7274070101046d61696e04636f64655f02
01005b01020110601500107f15010201011401107f4d0310000
40a0f080000000000000f1006180100140010a0ff0153030a0f
11001100110011e000140016050014001020401500110011001
10011001400160500140010204015000f0f
```
----
### Binary Disected
```python=
0000000: 0061 736d ; WASM_BINARY_MAGIC
0000004: 0b00 0000 ; WASM_BINARY_VERSION
; section "type"
0000008: 04 ; string length
0000009: 7479 7065 ; section id: "type"
000000d: 00 ; section size (guess)
000000e: 01 ; num types
; type 0
000000f: 40 ; function form
0000010: 02 ; num params
0000011: 01 ; param type
0000012: 01 ; param type
0000013: 01 ; num results
0000014: 01 ; result_type
; section "function"
0000015: 08 ; string length
0000016: 6675 6e63 7469 6f6e ; section id: "function"
000001e: 00 ; section size (guess)
000001f: 01 ; num functions
0000020: 00 ; function 0 signature index
000001e: 02 ; FIXUP section size
; section "export"
0000021: 06 ; string length
0000022: 6578 706f 7274 ; section id: "export"
0000028: 00 ; section size (guess)
0000029: 01 ; num exports
000002a: 00 ; export func index
000002b: 06 ; string length
000002c: 6164 6454 776f ; export name
; section "code"
0000032: 04 ; string length
0000033: 636f 6465 ; section id: "code"
0000037: 00 ; section size (guess)
0000038: 01 ; num functions
; function body 0
0000039: 00 ; func body size (guess)
000003a: 00 ; local decl count
000003b: 14 ; OPCODE_GET_LOCAL
```
----
### Binary Encoding
- Fast decoding <!-- .element: class="fragment" data-fragment-index="1" -->
- Single pass validation <!-- .element: class="fragment" data-fragment-index="2" -->
- Extensible <!-- .element: class="fragment" data-fragment-index="3" -->
----
### Availability of VMs
- <!-- .element: class="fragment" data-fragment-index="1" -->Chrome (chrome://flags - enable-webassembly)
- <!-- .element: class="fragment" data-fragment-index="2" -->Firefox Nightly (about:config and set `javascript.options.wasm` to true)
- <!-- .element: class="fragment" data-fragment-index="3" -->Microsoft Edge
- <!-- .element: class="fragment" data-fragment-index="4" -->node.js 7.0-pre (--enable-wasm)
- <!-- .element: class="fragment" data-fragment-index="5" -->wasm-jit-prototype (github.com/WebAssembly/wasm-jit-prototype)
- <!-- .element: class="fragment" data-fragment-index="6" -->Ocaml "the spec" (github.com/WebAssembly/spec)
- interpreters<!-- .element: class="fragment" data-fragment-index="7" -->
- sexpr-wasm-prototypen (github.com/WebAssembly/sexpr-wasm-prototype)
- binaryen (github.com/WebAssembly/binaryen)
---
## Ethereum flavored WebAssembly `e^WASM`
- A proposed replacement for EVM<!-- .element: class="fragment" data-fragment-index="1" -->
- A restricted subset of WebAssembly<!-- .element: class="fragment" data-fragment-index="2" -->
- No floating point operations
- Defines Backwards Compatibility<!-- .element: class="fragment" data-fragment-index="3" -->
- Defines Metering<!-- .element: class="fragment" data-fragment-index="4" -->
- Defines an interface for interacting with the Ethereum Blockchain<!-- .element: class="fragment" data-fragment-index="5" -->
----
### EVM2WASM
- Transcompiles EVM code to WebAssembly<!-- .element: class="fragment" data-fragment-index="1" -->
- Can be run as a contract<!-- .element: class="fragment" data-fragment-index="2" -->
- Compliant with the offical EVM tests<!-- .element: class="fragment" data-fragment-index="3" -->
- Produces very fast EVM code<!-- .element: class="fragment" data-fragment-index="4" -->
- ~5000 line of wasm<!-- .element: class="fragment" data-fragment-index="5" -->
- ~400 line of js<!-- .element: class="fragment" data-fragment-index="6" -->
----
### EVM2WASM
<iframe width="100%" height="500" style='background:white' src="https://ewasm.github.io/evm2wasm-frontend/dist/" frameborder="0"></iframe>
----
### Metering Injection
Metering is decoupled from the VM
```flow
st=>start: raw wasm
e=>end: run
op=>operation: Validate
op2=>operation: Injection Metering
cond=>condition: Yes or No?
st->op->op2->e
```
----
### Metering By Branch
![](https://i.imgur.com/axIXk25.jpg)
----
### Metering By Branch
![](https://i.imgur.com/dngglBx.jpg)
---
## Interfaces
<!-- Transition: by now you all are experts in WebAssembly and S-expressions. Let's glue all of this together. -->
*Glueing all this together*
---
### eWASM Ethereum Interface (EEI)
Defines the Ethereum blockchain methods for contracts:
- getCallDataSize ~ CALLDATASIZE
- callDataCopy ~ CALLDATACOPY
- storageLoad ~ SLOAD
- storageStore ~ SSTORE
- call ~ CALL
- delegateCall ~ DELEGATECALL
- return ~ RETURN
- ...
A total of 29 methods.
---
### Example: storageLoad
```clojure
(call_import $storageLoad (i32.const 0) (i32.const 32))
;; ^ key offset in memory
;; ^ result offset in memory
```
Simples.
---
<!-- Transition: now it is time to wrap all these calls into an actual contract. -->
### eWASM Contract Interface (ECI)
Defines the format of contracts:
- WebAssembly binary encoding version 0xb
- Single entry point: *main*
- Sets other limitations.
---
### Example contract
Drumroll:
```clojure
(module
(memory 1
(segment 0 "Hello World!")
)
(import $return "ethereum" "return" (param i32 i32))
(export "main" $main)
(func $main
(call_import $return (i32.const 0) (i32.const 12))
)
)
```
---
<!-- Transition: if we can write contract, we can also write system contracts -->
### System Contracts
1) Sentinel
- ECI validation
- metering injection
- wrap into deployer
2) evm2wasm! <!-- .element: class="fragment" data-fragment-index="3" -->
3) EVM1 precompiled contracts <!-- .element: class="fragment" data-fragment-index="4" -->
---
<!-- Transition: having system contracts simplifies the client implementation a lot -->
## VM Semantics
Only 3 new rules for a client:
1) Check contract code for eWASM signature <!-- .element: class="fragment" data-fragment-index="1" -->
2) Use evm2wasm to transcompile if needed <!-- .element: class="fragment" data-fragment-index="2" -->
3) Use sentinel contract during contract creation <!-- .element: class="fragment" data-fragment-index="3" -->
<!-- Note: transcompiled code is not stored in the state. -->
---
## ewasm-kernel and Hera
1) ewasm-kernel
- Javascript
- runs in browsers and node.js
- < 1000 lines for the interface and VM core
2) Hera
- C++
- *EVM-C compatible*
- works with cpp-ethereum (eth --vm hera)
- and pyethereum \o/
- ... and hopefully go-ethereum + parity in the future
---
## The test network
<!-- ZCASH -->
---
<!-- Transition: don't be afraid, no need to write S-expressions. Contracts can be written in C and C++. -->
## Programming in C and the precompiles
*clang & ewasm-libc*
---
## Example: sha256
```c
#include "ethereum.h"
#define BASE_FEE 60
#define WORD_FEE 12
void main() {
size_t datasize = ethereum_calldatasize();
unsigned char data[datasize];
unsigned char ret[32] = { 0 };
ethereum_calldatacopy(data, 0, datasize);
ethereum_usegas(BASE_FEE + (((datasize + 31) / 32) * WORD_FEE));
mbedtls_sha256(data, datasize, ret, 0);
ethereum_return(ret, 32);
}
```
---
<!-- Transition: afraid of C? Solidity! -->
## Solidity for eWASM
Input:
```js
contract A {
function a() {
throw;
}
function b() payable returns (uint64) {
uint64 x = 42;
return x;
}
}
```
---
## Solidity for eWASM
Output:
```clojure
;; Contract: A
(module
(import $callDataCopy "ethereum" "callDataCopy" (param i32 i32 i32))
(import $getCallValue "ethereum" "getCallValue" (param i32))
(import $return "ethereum" "return" (param i32))
(memory 1 1)
(export "memory" memory)
(export "main" $main)
(func $main
(call_import $callDataCopy (i32.const 0) (i32.const 0) (i32.const 4))
(call $dispatcher (i32.load (i32.const 0)))
(unreachable)
)
(func $ensureNotPayable
(call_import $getCallValue (i32.const 0))
(if (i64.ne (i64.const 0) (i64.load (i32.const 0)) (unreachable))
(if (i64.ne (i64.const 0) (i64.load (i32.const 8)) (unreachable))
)
(func $dispatcher
(param $sig i32)
(if (i32.eq (get_local $sig) (i32.const 0x0dbe671f)) (then (call $__0dbe671f)))
(if (i32.eq (get_local $sig) (i32.const 0x4df7e3d0)) (then (call $__4df7e3d0)))
(unreachable)
)
;; function: a()
(func $__0dbe671f
(call $ensureNotPayable)
(block
(unreachable)
)
)
;; function: b() payable
(func $__4df7e3d0
(block
(local $x (param i64))
(set_local $x (i64.const 42))
(i64.store (i32.const 0) (i64.const 0))
(i64.store (i32.const 8) (i64.const 0))
(i64.store (i32.const 16) (i64.const 0))
(i64.store (i32.const 24) (get_local $x))
(call_import $return (i32.const 0) (i32.const 32))
)
)
)
```
---
## Bonus: Gas Cost Calculation
1) Gas cost is based on the cycle count of the instructions.<!-- .element: class="fragment" data-fragment-index="1" -->
2) The gas cost table is stored in a contract.<!-- .element: class="fragment" data-fragment-index="2" -->
3) SHA256 performance (of 8kb data):<!-- .element: class="fragment" data-fragment-index="3" -->
- precompile cost: ~3 100<!-- .element: class="fragment" data-fragment-index="3" -->
- eWASM cost: ~6 500<!-- .element: class="fragment" data-fragment-index="3" -->
- EVM (Solidity) cost: ~32 000 000<!-- .element: class="fragment" data-fragment-index="3" -->
- EVM (Solidity) cost (with shifts): ~1 000 000<!-- .element: class="fragment" data-fragment-index="3" -->
---
## (call_import $ethereumReturn)
See more awesome details at https://github.com/ewasm
>:::danger
>:fire: Error: Out-Of-Gas! :fire:
>:::
<!-- .element: class="fragment" data-fragment-index="2" -->
{"metaMigratedAt":"2023-06-14T11:52:28.497Z","metaMigratedFrom":"Content","title":"Ethereum","breaks":true,"contributors":"[]"}