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.
www.w3.org/community/webassembly
(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)))))))
(i64.const 42)
(i32.const 0xffffffff)
(i64.const -644)
(i64.load (i64.const 4))
(i64.store (get_local $a) (i64.const 4))
(call_import $useGas (i64.const 33))
0061736d0b00000004747970651003400101004005020202020
10040000006696d706f727412010008657468657265756d0675
73654761730866756e6374696f6e03020102066d656d6f72790
3010101066578706f7274070101046d61696e04636f64655f02
01005b01020110601500107f15010201011401107f4d0310000
40a0f080000000000000f1006180100140010a0ff0153030a0f
11001100110011e000140016050014001020401500110011001
10011001400160500140010204015000f0f
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
e^WASM
Metering is decoupled from the VM
st=>start: raw wasm
e=>end: run
op=>operation: Validate
op2=>operation: Injection Metering
cond=>condition: Yes or No?
st->op->op2->e
Glueing all this together
Defines the Ethereum blockchain methods for contracts:
A total of 29 methods.
(call_import $storageLoad (i32.const 0) (i32.const 32))
;; ^ key offset in memory
;; ^ result offset in memory
Simples.
Defines the format of contracts:
Drumroll:
(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))
)
)
Sentinel
evm2wasm!
EVM1 precompiled contracts
Only 3 new rules for a client:
Check contract code for eWASM signature
Use evm2wasm to transcompile if needed
Use sentinel contract during contract creation
ewasm-kernel
Hera
clang & ewasm-libc
#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);
}
Input:
contract A {
function a() {
throw;
}
function b() payable returns (uint64) {
uint64 x = 42;
return x;
}
}
Output:
;; 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))
)
)
)
Gas cost is based on the cycle count of the instructions.
The gas cost table is stored in a contract.
SHA256 performance (of 8kb data):
See more awesome details at https://github.com/ewasm
Error: Out-Of-Gas!