# ZK WASM Hacking notes ## Links - [Tech setup](https://hackmd.io/xlfXSX0qQGe2npk4S0Kf3A?view) - Test files https://github.com/akashin/zkwasm/tree/main/data - Generated ZK ASM: https://github.com/near/wasmtime/tree/zkasm-hackaton/cranelift/data ## Investigations - https://github.com/near/nearcore/issues/9531 ## Refactoring/Features - https://github.com/near/nearcore/issues/9529 ### Example module WASM Module ```wasm (module (import "env" "assert_eq" (func $assert_eq (param i32) (param i32))) (func $main (local $counter i32) (local.set $counter (i32.const 0)) (block (loop (local.set $counter (i32.add (local.get $counter) (i32.const 1))) (br_if 1 (i32.eq (local.get $counter) (i32.const 10) ) ) (br 0) ) ) (local.get $counter) (i32.const 10) call $assert_eq) (start $main)) ``` Corresponding Cranelift IR ``` ; Selected as wasm start function function u0:1(i32 vmctx) fast { sig0 = (i32, i32, i32 vmctx) fast fn0 = u0:0 sig0 block0(v0: i32): @0034 v2 = iconst.i32 0 @003a jump block3(v2) ; v2 = 0 block3(v3: i32): @003e v4 = iconst.i32 1 @0040 v5 = iadd v3, v4 ; v4 = 1 @0045 v6 = iconst.i32 10 @0047 v7 = icmp eq v5, v6 ; v6 = 10 @0047 v8 = uextend.i32 v7 @0048 brif v8, block2, block5 block5: v13 = iconst.i32 1 v14 = iadd.i32 v3, v13 ; v13 = 1 @004a jump block3(v14) block2: v10 = iconst.i32 1 v11 = iadd.i32 v3, v10 ; v10 = 1 v12 = iconst.i32 10 @0052 call fn0(v11, v12, v0) ; v12 = 10 @0054 jump block1 block1: @0054 return } ``` Cranelift ZK ASM output ``` start: zkPC + 2 => RR :JMP(function_1) :JMP(finalizeExecution) function_1: SP + 1 => SP RR :MSTORE(SP) 0 + 0 => A :JMP(L1_1) L1_1: 0 + 1 => B $ => A :ADD 0 + 10 => B $ => B :EQ B :JMPNZ(L1_3) :JMP(L1_1) L1_3: 0 + 10 => B B :ASSERT $ => RR :MLOAD(SP) SP - 1 => SP :JMP(RR) finalizeExecution: ${beforeLast()} :JMPN(finalizeExecution) :JMP(start) ``` WASM transpiler ZK ASM output ``` start: :JMP(function_1) function_1: 2 :MSTORE(SP++) 3 :MSTORE(SP++) SP - 1 => SP $ => A: MLOAD(SP) SP - 1 => SP $ => B: MLOAD(SP) $ => A :ADD A :MSTORE(SP++) 5 :MSTORE(SP++) SP - 1 => SP $ => A: MLOAD(SP) SP - 1 => SP $ => B: MLOAD(SP) B :ASSERT finalizeExecution: ${beforeLast()} :JMPN(finalizeExecution) :JMP(start) ``` --- ### Authoring backend https://github.com/bytecodealliance/wasmtime/issues/4126 - Implement `ZK::isa_builder` - Implement `ZKBackend` and wrap it - Implement `compile::compile<ZKBackend>` - Implement `create_reg_env` This is relatively simple. - Implement `MachInstEmit` Also looks relatively simple - Implement `AArch64MachineDeps` This looks like ABI that ISA provides, so a translation for some common ops 10-20 methods, all nicely documented, so shouldn't be a big problem - Implement `Inst` pretty-printer 2. Find an interpreter - Compile it to WASM/Cranelift - Produce small/efficient ZK ASM out of it ## Done - [x] Fix warnings - [x] Make sure that CTX register is not clobbered - [x] Why do we use `C` as intermediate in `2 + 3 => C, C => A` be? - [x] Add function calls - [x] Add global label numbering - [x] Fix CMP implementation - [x] Fix useless `C => E` call, clobber? - [x] Decrease number of registers needed for counters.wat - [x] Fix negative number offsets - [x] Fix stack shifting size - [x] Add indentation for anything but labels - [x] Fix stack growth direction - [x] Fix +SMTH numbers - [x] Rewrite STORE similar to LOAD - [x] Run `cargo fmt` - [x] Fix register naming - [x] Add zkasm preamble - [x] Understand why we need stack pushing - [x] CALL: Only handle ASSERT - [x] Understand why we use stack allocations - [x] Do we need a frame pointer? - [x] LOAD instruction integer formatting - [x] Rename Addi instruction - [x] Fix storing values to stack - [x] Fix loading values from stack - [x] Adjust stack size - [x] Implement Mov - [x] Simonas: Int32 - [x] Andrei: Sink put_data - [X] Leo: Complete TODOs with println - [x] Copy RiscV backend as a blueprint - [x] TODO(akashin): Look into ZK ASM code generation - Seems a bit complicated https://gist.github.com/akashin/d6f1dcafeb496029b456bed5700ea9f4 - https://github.com/0xPolygonHermez/zkasmcom/blob/main/src/compiler.js - [X] Give access to zkwasm repo https://github.com/akashin/zkwasm - [X] Fork wasmtime https://github.com/near/wasmtime - [X] Update wasmtime to latest