From 65613b42ae2134a5ce164a7676c3b6e83fb05821 Mon Sep 17 00:00:00 2001 From: laisolizq Date: Thu, 16 Mar 2023 19:07:54 +0100 Subject: [PATCH 1/3] update tests zkasm --- .github/workflows/main.yaml | 3 + package.json | 1 + test/bitwise.zkasm | 73 --------------- test/comp.zkasm | 71 --------------- test/opcalldatacopy.zkasm | 146 ++---------------------------- test/rotate.zkasm | 167 +++++++++++------------------------ test/tests-executor.js | 83 +++++++++++++++++ test/touched-assert.zkasm | 27 +++--- test/utils-expAD.zkasm | 4 +- test/utils-getLenBytes.zkasm | 6 +- 10 files changed, 163 insertions(+), 418 deletions(-) delete mode 100644 test/bitwise.zkasm delete mode 100644 test/comp.zkasm create mode 100644 test/tests-executor.js diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 82f24a60..6cdb3199 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -27,6 +27,9 @@ jobs: - name: run counters tests run: | npm run test:counters + - name: run zkasm tests + run: | + npm run test:zkasm - name: Generate tests run: | npm run test:gen diff --git a/package.json b/package.json index 0ee8483a..50ccbbc1 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "test:counters": "node counters/counters-executor.js", "test:calldatacopy": "mkdir -p build && npx zkasm test/opcalldatacopy.zkasm -o build/opcalldatacopy.test.json", "test:mstorex": "mkdir -p build && npx zkasm test/mstorex.zkasm -o build/mstorex.test.json", + "test:zkasm": "node test/tests-executor.js", "eslint": "npx eslint tools/**.js", "eslint:fix": "npx eslint tools/**.js --fix", "test:gen": "node tools/gen-parallel-tests.js", diff --git a/test/bitwise.zkasm b/test/bitwise.zkasm deleted file mode 100644 index bb9cf106..00000000 --- a/test/bitwise.zkasm +++ /dev/null @@ -1,73 +0,0 @@ -start: - - 1 => B - 1 => C - 1 => A - ${bitwise_and(B, C)} :ASSERT - - ${loadScalar(115792089237316195423570985008687907853269984665640564039457584007913129639935)} => B - ${loadScalar(255)} => A - ${bitwise_and(B, 255)} :ASSERT - - 2**32 + 5 => B - 2**8 - 1 => C - 5 => A - ${bitwise_and(B, C)} :ASSERT - - 2**32 + 5 => B - 2**8 - 1 => C - 5 => A - ${bitwise_and(B, C)} :ASSERT - - 10 => B - 5 => C - 15 => A - ${bitwise_or(B, C)} :ASSERT - - 2**16 => B - 2**8 => C - 2**16 + 2**8 => A - ${bitwise_or(B, C)} :ASSERT - - ${loadScalar(57896044618658097711785492504343953926634992332820282019728792003956564819968)} => B - ${loadScalar(1)} => C - ${loadScalar(57896044618658097711785492504343953926634992332820282019728792003956564819969)} => A - ${bitwise_or(B, C)} :ASSERT - - 0 => B - 7 => C - 7 => A - ${bitwise_xor(B, C)} :ASSERT - - 2**32 - 1 => B - 2**32 - 1 => C - 0 => A - ${bitwise_xor(B, C)} :ASSERT - - 2**32 - 1 => B - 2**32 - 1 => C - 0 => A - ${bitwise_xor(B, C)} :ASSERT - - 10 => B - 5 => C - 15 => A - ${bitwise_xor(B, C)} :ASSERT - - 0 => B - ${loadScalar(115792089237316195423570985008687907853269984665640564039457584007913129639935)} => A - ${bitwise_not(B)} :ASSERT - - ${loadScalar(115792089237316195423570985008687907853269984665640564039457584007913129639935)} => B - 0 => A - ${bitwise_not(B)} :ASSERT - - ${loadScalar(115792089237316195423570985008687907853269984665640564039457584007913129639929)} => B - 0x06 => A - ${bitwise_not(B)} :ASSERT - - - 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 - :JMP(finalWait) - -INCLUDE "../main/end.zkasm" \ No newline at end of file diff --git a/test/comp.zkasm b/test/comp.zkasm deleted file mode 100644 index f09b6eeb..00000000 --- a/test/comp.zkasm +++ /dev/null @@ -1,71 +0,0 @@ -start: - - 6 => B - 2 => C - 1 => A - ${comp_gt(B, C)} :ASSERT - - 2**250 => B - 2**249 => C - 1 => A - ${comp_gt(B, C)} :ASSERT - - 0 => B - 0 => C - 0 => A - ${comp_gt(B, C)} :ASSERT - - 2**52 => B - 2**52 => C - 0 => A - ${comp_gt(B, C)} :ASSERT - - 1 => B - 2 => C - 1 => A - ${comp_lt(B, C)} :ASSERT - - 2 => B - 1 => C - 0 => A - ${comp_lt(B, C)} :ASSERT - - 2**255 - 1 => B - 2**255 => C - 1 => A - ${comp_lt(B, C)} :ASSERT - - 2**255 => B - 2**255 => C - 0 => A - ${comp_lt(B, C)} :ASSERT - - 2**255 => B - 2**255 - 1 => C - 0 => A - ${comp_lt(B, C)} :ASSERT - - 0 => B - 0 => C - 1 => A - ${comp_eq(B, C)} :ASSERT - - 2**256 - 1 => B - 2**256 - 1 => C - 1 => A - ${comp_eq(B, C)} :ASSERT - - 2**256 - 1 => B - 2**256 - 2 => C - 0 => A - ${comp_eq(B, C)} :ASSERT - - 1 => B - 2 => C - 0 => A - ${comp_eq(B, C)} :ASSERT - - 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 - :JMP(finalWait) - -INCLUDE "../main/end.zkasm" \ No newline at end of file diff --git a/test/opcalldatacopy.zkasm b/test/opcalldatacopy.zkasm index 1986935e..f65300f1 100644 --- a/test/opcalldatacopy.zkasm +++ b/test/opcalldatacopy.zkasm @@ -13,6 +13,7 @@ start: 20 :MSTORE(SP++) ;size 0 :MSTORE(SP++) ;offset 32 :MSTORE(SP) ;destOffset + 100000000 => GAS :CALL(fillCalldataPattern) :CALL(fillMemPattern0) @@ -310,10 +311,6 @@ fillMemPattern: INCLUDE "../main/main.zkasm" -VAR GLOBAL auxDestOffset2 -VAR GLOBAL calldataOffset2 -VAR GLOBAL auxOffset2 -VAR GLOBAL numLastBytes2 VAR GLOBAL tmpSHXZkPCtest /** * @link [https://www.evm.codes/#37?fork=berlin] @@ -325,143 +322,10 @@ VAR GLOBAL tmpSHXZkPCtest * - stack output: [] */ opCALLDATACOPY2: - RR :MSTORE(tmpSHXZkPCtest) - ; checks zk-counters - ;%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - ;%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - ;%MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 2 :JMPN(outOfCountersMemalign) - ; check stack underflow - SP - 3 => SP :JMPN(stackUnderflow) - $ => E :MLOAD(SP+2); [destOffset => E] - $ => B :MLOAD(SP+1); [offset => B] - B :MSTORE(auxOffset2) - $ => C :MLOAD(SP); [size => C] - C :MSTORE(numLastBytes2) - ; store lastMemOffset for memory expansion gas cost - E :MSTORE(lastMemOffset) - ; store lastMemLength for memory expansion gas cost - C :MSTORE(lastMemLength);, CALL(saveMem); in: [lastMemOffset, lastMemLength] - ; check out-of-gas - ;GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas) - ;${3*((C+31)/32)} - ;(C+31)/32 => A - C+31 => A - :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - ;GAS - 3*E => GAS :JMPN(outOfGas) - ; save current stack pointer - SP :MSTORE(SPw) - ; Recover destOffset at E - $ => E :MLOAD(lastMemOffset) - ; Recover size at C - $ => C :MLOAD(lastMemLength) - B => A - $ => B :MLOAD(txCalldataLen); less than 2**32 bytes (calldata). Enforced by memory expansion gas cost & smart contract batchL2DataHash - ; if offset is not lower than calldata length, return 0 - $ :LT,JMPNC(opCALLDATACOPY02) - B => A - $ => B :MLOAD(auxOffset2) - B + C => B - ; if txCalldataLen < (offset + size) --> opCALLDATACOPYX0 - $ :LT,JMPC(opCALLDATACOPYX02) - $ => B :MLOAD(auxOffset2),JMP(opCALLDATACOPYloop2) - -opCALLDATACOPYX02: - $ => C :MLOAD(txCalldataLen) - $ => B :MLOAD(auxOffset2) - C - B => C :MSTORE(numLastBytes2) - -opCALLDATACOPYloop2: - ; checks zk-counters - ;%MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep) - ; finish loop - C :JMPZ(opCALLDATACOPYcheckLen2) - ; copy last bytes - C - 32 :JMPN(opCALLDATACOPYfinal2) - B => A :MSTORE(calldataOffset2) - E => B - :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - ; add %CALLDATA_OFFSET to offset to reach calldata in memory - ; set stack pointer to first byte to read - %CALLDATA_OFFSET + E => SP - B => E - $ => A :MLOAD(SP++) - $ => B :MLOAD(SP) - $ => A :MEM_ALIGN_RD, MSTORE(bytesToStore) - E => A - ; Store 32 bytes from calldata to memory - :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - E :MSTORE(auxDestOffset2) - $ => A :MLOAD(MEM:E) - $ => B :MLOAD(MEM:E+1) - ${memAlignWR_W0(A,mem.bytesToStore,C)} => D ; no trust calculate W0 - ${memAlignWR_W1(B,mem.bytesToStore,C)} => E ; no trust calculate W1 - $ :MEM_ALIGN_WR,MLOAD(bytesToStore) - E => A - $ => E :MLOAD(auxDestOffset2) - D :MSTORE(MEM:E) ; write W0 - A :MSTORE(MEM:E+1) ; write W1 - ; recover stack pointer - $ => C :MLOAD(numLastBytes2) - C - 32 => C :MSTORE(numLastBytes2) - $ => E :MLOAD(lastMemOffset) - E + 32 => E :MSTORE(lastMemOffset) - $ => B :MLOAD(calldataOffset2) - B + 32 => B :JMP(opCALLDATACOPYloop2) - -opCALLDATACOPYfinal2: - ; copy last bytes - C :MSTORE(numLastBytes2) - B => A - E => D - :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - ; add %CALLDATA_OFFSET to offset to reach calldata in memory - ; set SP to calldata - %CALLDATA_OFFSET + E => SP - D => E - C => D - $ => A :MLOAD(SP++), CALL(SHLarith); [calldata => A]; in: [A: value, D: #bytes to left shift] out: [A: shifted result] - ; Recover init SP to recover input size - $ => C :MLOAD(numLastBytes2); [size => C] - ; point to next memory slot - C - 32 + D => D :JMPN(opCALLDATACOPYxor2) - D :JMPZ(opCALLDATACOPYxor2) - A => B - $ => A :MLOAD(SP); [calldata => C] - 32 - D => D :CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] - 32 - C => D :CALL(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] - B + A => A - ; set bytesToStore with value to use in MSTORE - A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset] - :JMP(opCALLDATACOPYcheckLen2) - -opCALLDATACOPY02: - C :JMPZ(opCALLDATACOPYend2) - 32 - C :JMPN(opCALLDATACOPY3202) - ; set bytesToStore with value to use in MSTORE - 0 :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset] - :JMP(opCALLDATACOPYend2) - -opCALLDATACOPY3202: - ; set bytesToStore with value to use in MSTORE - 0 :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] - C - 32 => C :JMP(opCALLDATACOPY02) - - -opCALLDATACOPYxor2: - 32 - C => D :CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] - :CALL(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] - ; set bytesToStore with value to use in MSTORE - A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset] - -opCALLDATACOPYcheckLen2: - ; fill missing values with 0 (size > calldata) - $ => C :MLOAD(lastMemLength) - $ => A :MLOAD(txCalldataLen) - $ => B :MLOAD(auxOffset2) - C - A + B => C :JMPN(opCALLDATACOPYend2, opCALLDATACOPY02) - - -opCALLDATACOPYend2: + RR :MSTORE(tmpSHXZkPCtest) + :CALL(opCALLDATACOPY) + +opCALLDATACOPYend: ; retrieve SP $ => SP :MLOAD(SPw) $ => RR :MLOAD(tmpSHXZkPCtest) diff --git a/test/rotate.zkasm b/test/rotate.zkasm index 9ec7ca49..f14f3af9 100644 --- a/test/rotate.zkasm +++ b/test/rotate.zkasm @@ -1,120 +1,61 @@ VAR GLOBAL test ; test valid for op-arith-final_0.json input start: - 0x270b206cd7f7637a125ddc55aef59e54ef3ea0898dbc9b9094e5665fcd937bedn => A - 399n => PC - 8 => D ; read 20 bytes - ${getBytecode(A,PC,D)} => B - - -VAR GLOBAL leftBytes -VAR GLOBAL numBlock -; Params ==> bytes to read (readBytes) (PUSHX) -; compute ==> num_blocks --> readBytes / 4 -; compute ==> contador de 4 en 4 -; dos contadores: 0,1,2,3 0,1,2,3 0,1,2,3 0, 1 -----> insideBlock -; ------- ------- ------- ------ -; 0 1 2 -----> nums de ROTL_C -; alreadyReadBytes = numBlock * 4 + insideBlock; -readPush: - D => A 0 => E - PC + D - 1 => PC - ${A >> 2} => B - ${A & 0x03} => D - B * 4 + D :ASSERT - D => A - 0x04 => B - $ :LT,JMPNC(failAssert) - D :MSTORE(leftBytes) - B :MSTORE(numBlock) - 0 => B - :JMP(readPushBlock) - -readPushBlock: - $ => A :MLOAD(numBlock) - $ :EQ, JMPC(endPushInit) - - 0x270b206cd7f7637a125ddc55aef59e54ef3ea0898dbc9b9094e5665fcd937bedn => A ; load address - - ${getBytecode(A,PC,1)} => C - PC - 1 => PC - - ${getBytecode(A,PC,1)} => D - PC - 1 => PC - D*256 + C => C - ${getBytecode(A,PC,1)} => D - PC - 1 => PC - D*65536 + C => C - ${getBytecode(A,PC,1)} => D - PC - 1 => PC - D*16777216 + C => C - :JMP(doRotate) - -doRotate: - B - 1 => A - - :JMP(doRotateLoop) - -doRotateLoop: - A :JMPN(endRotate) - ROTL_C => C - A - 1 => A - :JMP(doRotateLoop) - -endRotate: - C + E => E - B + 1 => B - :JMP(readPushBlock) - -doRotate2: - B - 1 => A - :JMP(doRotateLoop2) - -doRotateLoop2: - A :JMPN(endRotate2) - ROTL_C => C - A - 1 => A - :JMP(doRotateLoop2) - -endRotate2: - C + E => E - :JMP(finalPush) - -endPushInit: - $ => A :MLOAD(leftBytes) - A - 1 :JMPN(finalPush) - 0 => C - 0 => B - :JMP(endPushLoop) - -endPushLoop: - $ => A :MLOAD(leftBytes) - $ :EQ, JMPC(endPushFinal) - 0x270b206cd7f7637a125ddc55aef59e54ef3ea0898dbc9b9094e5665fcd937bedn => A ; load address - ${getBytecode(A,PC,1)} => D - PC - 1 => PC - B - 1 => A - :JMP(computeFactorLoop) - -computeFactorLoop: - A :JMPN(computeFactorEnd) - 256*D => D - A - 1 => A - :JMP(computeFactorLoop) - -computeFactorEnd: - B + 1 => B - D + C => C - :JMP(endPushLoop) - -endPushFinal: - $ => B :MLOAD(numBlock) - :JMP(doRotate2) - -finalPush: + 0x270b206cd7f7637a125ddc55aef59e54ef3ea0898dbc9b9094e5665fcd937bedn => A + ; "0x270b206cd7f7637a125ddc55aef59e54ef3ea0898dbc9b9094e5665fcd937bed": + ;"0x608060405234801561001057600080fd5b50600436106100885760003560e01c + ; 806364fbb77c1161005b57806364fbb77c146100c75780636664f730146100d1 + ; 578063bfb371c2146100ed578063c68f6d1a146100f757610088565b80630e4d + ; 2d021461008d5780631592781914610097578063242e46d2146100a157806339 + ; 31a6b3146100bd575b600080fd5b610095610101565b005b61009f61010d565b + ; 005b6100bb60048036038101906100b69190610180565b610119565b005b6100 + ; c561012f565b005b6100cf61013b565b005b6100eb60048036038101906100e6 + ; 9190610180565b61013d565b005b6100f5610153565b005b6100ff61015f565b + ; 005b6002600a048060005550565b60026001018060005550565b808261012591 + ; 90610216565b6000819055505050565b60046003028060005550565b005b8082 + ; 61014991906101c0565b6000819055505050565b6002600a058060005550565b + ; 60056006038060005550565b60008135905061017a816102b4565b9291505056 + ; 5b60008060408385031215610197576101966102af565b5b60006101a5858286 + ; 0161016b565b92505060206101b68582860161016b565b915050925092905056 + ; 5b60006101cb82610247565b91506101d683610247565b9250827fffffffffff + ; ffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561 + ; 020b5761020a610251565b5b828201905092915050565b600061022182610247 + ; 565b915061022c83610247565b92508261023c5761023b610280565b5b828204 + ; 905092915050565b6000819050919050565b7f4e487b71000000000000000000 + ; 00000000000000000000000000000000000000600052601160045260246000fd + ; 5b7f4e487b710000000000000000000000000000000000000000000000000000 + ; 0000600052601260045260246000fd5b600080fd5b6102bd81610247565b8114 + ; 6102c857600080fd5b5056fea264697066735822122046eacdba7371636f1207 + ; 79f19da9f157d18a1c0bb321f5f890873de82d15f6ca64736f6c634300080700 + ; 33", + + ; load contract bytecode + A :HASHPDIGEST(E) + + 1 => D + 0 :MSTORE(contractHashId) + 1 => PC + 0x80 :MSTORE(test) + :CALL(readPush); in: [D: bytes to read] out: [E: value read] + E :MLOAD(test) + + 31 => PC + 0x1c :MSTORE(test) + :CALL(readPush); in: [D: bytes to read] out: [E: value read] + E :MLOAD(test) + + 480 => PC + 0xff :MSTORE(test) + :CALL(readPush); in: [D: bytes to read] out: [E: value read] + E :MLOAD(test) + + 768 => PC + 0x33 :MSTORE(test) + :CALL(readPush); in: [D: bytes to read] out: [E: value read] + E :MLOAD(test) 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 - :JMP(finalWait) + :JMP(finalizeExecution) -INCLUDE "../main/end.zkasm" +INCLUDE "../main/main.zkasm" diff --git a/test/tests-executor.js b/test/tests-executor.js new file mode 100644 index 00000000..6cdc0e6b --- /dev/null +++ b/test/tests-executor.js @@ -0,0 +1,83 @@ +const path = require('path'); +const fs = require('fs'); +const smMain = require('@0xpolygonhermez/zkevm-proverjs/src/sm/sm_main/sm_main'); +const fileCachePil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json'); +const no_empty_input = require('@0xpolygonhermez/zkevm-testvectors/inputs-executor/calldata/op-arith-final_0.json') +const empty_input = require('@0xpolygonhermez/zkevm-proverjs/test/inputs/empty_input.json') +const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon; +const pathMainPil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/pil/main.pil'); +const { newCommitPolsArray } = require('pilcom'); +const { compile } = require('pilcom'); +const zkasm = require("@0xpolygonhermez/zkasmcom"); +const testFilesDir = __dirname; +const { argv } = require('yargs'); + +async function main() { + + // Compile pil + const cmPols = await compilePil(); + + // Get all zkasm files + const files = getTestFiles(); + + // Run all zkasm files + for (let file of files) { + await runTest(file, cmPols) + } +} + +async function runTest(testName, cmPols) { + const zkasmFile = `${testFilesDir}/${testName}`; + // Compile rom + const configZkasm = { + defines: [], + allowUndefinedLabels: true, + allowOverwriteLabels: true, + }; + + const rom = await zkasm.compile(zkasmFile, null, configZkasm); + const config = { + debug: true, + stepsN: 8388608, + } + const input = zkasmFile.includes("rotate.zkasm") ? no_empty_input : empty_input; + console.log(`Running ${testName}`) + // Execute test + try { + await smMain.execute(cmPols.Main, input, rom, config); + } catch(e) { + if(zkasmFile.includes("rotate.zkasm") && e.toString().includes("Assert Error: newStateRoot does not match")) { + console.log("Assert outputs run succesfully") + } else { + throw new Error(e); + } + } +} + +// Get all zkasm counter test files +function getTestFiles() { + if(argv.test){ + return [`${argv.test}.zkasm`]; + } + const files = fs.readdirSync(testFilesDir).filter(name => name.endsWith('.zkasm')) + return files; +} + +async function compilePil() { + if (!fs.existsSync(fileCachePil)) { + const poseidon = await buildPoseidon(); + const { F } = poseidon; + const pilConfig = { + defines: { N: 4096 }, + namespaces: ['Main', 'Global'], + disableUnusedError: true + }; + const p = await compile(F, pathMainPil, null, pilConfig); + fs.writeFileSync(fileCachePil, `${JSON.stringify(p, null, 1)}\n`, 'utf8'); + } + + const pil = JSON.parse(fs.readFileSync(fileCachePil)); + return newCommitPolsArray(pil); +} + +main() \ No newline at end of file diff --git a/test/touched-assert.zkasm b/test/touched-assert.zkasm index bcfe29ce..de628243 100644 --- a/test/touched-assert.zkasm +++ b/test/touched-assert.zkasm @@ -1,6 +1,3 @@ -INCLUDE "../main/constants.zkasm" -INCLUDE "../main/vars.zkasm" - start: ; set root state & init root touched 0xABCDEFn => SR @@ -12,51 +9,51 @@ start: ; set address 0x0123456789012345678901234567890123456789n => A - ; cold address and mark it as warm - :CALL(isWarmedAddress) + ; if the address is cold [0 if warm, 1 if cold] + ; cold address + :CALL(isColdAddress) D => A 1 :ASSERT ; warm address 0x0123456789012345678901234567890123456789n => A - :CALL(isWarmedAddress) + :CALL(isColdAddress) D => A 0 :ASSERT ; set address & storage position 0x0123456789012345678901234567890123456789n => A 0xAn => C + ; if the storage slot is cold [0 if warm, 1 if cold] ; cold slot and mark it as warm - :CALL(isWarmedSlot) + :CALL(isColdSlot) 1 :ASSERT ; warm slot 0x0123456789012345678901234567890123456789n => A 0xAn => C - :CALL(isWarmedSlot) + :CALL(isColdSlot) 0 :ASSERT ; warm precompiled 0x3n => A - :CALL(isWarmedAddress) + :CALL(isColdAddress) D => A 0 :ASSERT ; cold zero address 0x0n => A - :CALL(isWarmedAddress) + :CALL(isColdAddress) D => A 1 :ASSERT ; warm zero address 0x0n => A - :CALL(isWarmedAddress) + :CALL(isColdAddress) D => A 0 :ASSERT 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 - finalizeExecution: - :JMP(finalWait) + :JMP(finalizeExecution) -INCLUDE "../main/end.zkasm" -INCLUDE "../main/touched.zkasm" \ No newline at end of file +INCLUDE "../main/main.zkasm" \ No newline at end of file diff --git a/test/utils-expAD.zkasm b/test/utils-expAD.zkasm index e0cf9052..c2b3bd8c 100644 --- a/test/utils-expAD.zkasm +++ b/test/utils-expAD.zkasm @@ -42,7 +42,7 @@ start: 0xf2eda75a1e9624437a4f18c1316372866f14b6bf3f7ff7441996f65b747a0001n => A $ :MLOAD(test),ASSERT -0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 - :JMP(finalWait) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 + :JMP(finalizeExecution) INCLUDE "../main/main.zkasm" \ No newline at end of file diff --git a/test/utils-getLenBytes.zkasm b/test/utils-getLenBytes.zkasm index 8d8089f6..9ec9023a 100644 --- a/test/utils-getLenBytes.zkasm +++ b/test/utils-getLenBytes.zkasm @@ -24,13 +24,13 @@ start: 4 => A $ :MLOAD(test),ASSERT - 0x666666666666 => B + 0x666666666666n => B :CALL(getLenBytes) A :MSTORE(test) 6 => A $ :MLOAD(test),ASSERT -0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 - :JMP(finalWait) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 + :JMP(finalizeExecution) INCLUDE "../main/main.zkasm" \ No newline at end of file From 7638903f41f77b227772e57841da1065a8a307a6 Mon Sep 17 00:00:00 2001 From: krlosMata Date: Mon, 3 Apr 2023 17:00:34 +0200 Subject: [PATCH 2/3] WIP run tests zkasm --- package.json | 2 +- test/tests-executor.js => tools/run-tests-zkasm.js | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/tests-executor.js => tools/run-tests-zkasm.js (100%) diff --git a/package.json b/package.json index 50ccbbc1..a592ea13 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "test:counters": "node counters/counters-executor.js", "test:calldatacopy": "mkdir -p build && npx zkasm test/opcalldatacopy.zkasm -o build/opcalldatacopy.test.json", "test:mstorex": "mkdir -p build && npx zkasm test/mstorex.zkasm -o build/mstorex.test.json", - "test:zkasm": "node test/tests-executor.js", + "test:zkasm": "node test/helpers/tests-executor.js", "eslint": "npx eslint tools/**.js", "eslint:fix": "npx eslint tools/**.js --fix", "test:gen": "node tools/gen-parallel-tests.js", diff --git a/test/tests-executor.js b/tools/run-tests-zkasm.js similarity index 100% rename from test/tests-executor.js rename to tools/run-tests-zkasm.js From ed4a0caa794df71ff5ee63524ed71caf54bf4f0a Mon Sep 17 00:00:00 2001 From: krlosMata Date: Tue, 4 Apr 2023 11:29:54 +0200 Subject: [PATCH 3/3] add test zkasm in GHA and tooling --- .eslintrc.js | 3 +- package.json | 12 +++-- tools/gen-parallel-tests.js | 2 +- tools/helpers/helpers.js | 47 ++++++++++++++++++ tools/run-tests-zkasm.js | 98 ++++++++++++++++--------------------- 5 files changed, 99 insertions(+), 63 deletions(-) create mode 100644 tools/helpers/helpers.js diff --git a/.eslintrc.js b/.eslintrc.js index ed33e20f..adf9abfd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,10 +21,9 @@ module.exports = { 'class-methods-use-this': [0], 'no-bitwise': [0], 'no-param-reassign': 'off', - 'no-console': [2, { allow: ['warn', 'error'] }], + 'no-console': 'off', 'import/prefer-default-export': [0], 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], - 'multiline-comment-style': 'error', 'no-await-in-loop': 'off', 'newline-before-return': 'error', }, diff --git a/package.json b/package.json index a592ea13..15e7297f 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,9 @@ "test:counters": "node counters/counters-executor.js", "test:calldatacopy": "mkdir -p build && npx zkasm test/opcalldatacopy.zkasm -o build/opcalldatacopy.test.json", "test:mstorex": "mkdir -p build && npx zkasm test/mstorex.zkasm -o build/mstorex.test.json", - "test:zkasm": "node test/helpers/tests-executor.js", - "eslint": "npx eslint tools/**.js", - "eslint:fix": "npx eslint tools/**.js --fix", + "test:zkasm": "node tools/run-tests-zkasm.js ./test", + "eslint": "npx eslint tools/**.js && npx eslint counters/counters-executor.js", + "eslint:fix": "npx eslint tools/**.js --fix && npx eslint counters/counters-executor.js --fix", "test:gen": "node tools/gen-parallel-tests.js", "test:start": "npx mocha --jobs $NUM_CPUS --timeout 0 --max-old-space-size=8192 --parallel tools/parallel-tests/*.test.js" }, @@ -41,11 +41,13 @@ "yargs": "^17.5.1" }, "devDependencies": { - "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs#95ca45eec5ae0a276c8f8feae7c89d8b06f2a385", + "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs#c9adbddba82cb1dcc3b03f3dcb0f317627ac05b8", "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#v1.1.0-fork.4", + "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v1.0.0", "chai": "^4.3.6", "chalk": "^3.0.0", "eslint": "^8.25.0", - "eslint-config-airbnb-base": "^15.0.0" + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-mocha": "^10.1.0" } } diff --git a/tools/gen-parallel-tests.js b/tools/gen-parallel-tests.js index 8617622e..edcb8672 100644 --- a/tools/gen-parallel-tests.js +++ b/tools/gen-parallel-tests.js @@ -59,7 +59,7 @@ async function main() { const pilConfig = { defines: { N: 4096 }, namespaces: ['Main', 'Global'], - disableUnusedError: true + disableUnusedError: true, }; const pil = await compile(F, pathMainPil, null, pilConfig); diff --git a/tools/helpers/helpers.js b/tools/helpers/helpers.js new file mode 100644 index 00000000..3a14df2e --- /dev/null +++ b/tools/helpers/helpers.js @@ -0,0 +1,47 @@ +/* eslint-disable import/no-extraneous-dependencies */ +const path = require('path'); +const fs = require('fs'); +const { compile, newCommitPolsArray } = require('pilcom'); + +const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon; + +// Global paths to build Main PIL to fill polynomials in tests +const pathMainPil = path.join(__dirname, '../../node_modules/@0xpolygonhermez/zkevm-proverjs/pil/main.pil'); +const fileCachePil = path.join(__dirname, '../../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json'); + +async function compilePil() { + if (!fs.existsSync(fileCachePil)) { + const poseidon = await buildPoseidon(); + const { F } = poseidon; + const pilConfig = { + defines: { N: 4096 }, + namespaces: ['Main', 'Global'], + disableUnusedError: true, + }; + const p = await compile(F, pathMainPil, null, pilConfig); + fs.writeFileSync(fileCachePil, `${JSON.stringify(p, null, 1)}\n`, 'utf8'); + } + + const pil = JSON.parse(fs.readFileSync(fileCachePil)); + + return newCommitPolsArray(pil); +} + +// Get all zkasm test files +function getTestFiles(pathZkasm) { + // check if path provided is a file or a directory + const stats = fs.statSync(pathZkasm); + + if (!stats.isDirectory()) { + return [pathZkasm]; + } + + const filesNames = fs.readdirSync(pathZkasm).filter((name) => name.endsWith('.zkasm')); + + return filesNames.map((fileName) => path.join(pathZkasm, fileName)); +} + +module.exports = { + compilePil, + getTestFiles, +}; diff --git a/tools/run-tests-zkasm.js b/tools/run-tests-zkasm.js index 6cdc0e6b..550cf5cd 100644 --- a/tools/run-tests-zkasm.js +++ b/tools/run-tests-zkasm.js @@ -1,33 +1,37 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable no-use-before-define */ const path = require('path'); -const fs = require('fs'); +const chalk = require('chalk'); +const zkasm = require('@0xpolygonhermez/zkasmcom'); const smMain = require('@0xpolygonhermez/zkevm-proverjs/src/sm/sm_main/sm_main'); -const fileCachePil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json'); -const no_empty_input = require('@0xpolygonhermez/zkevm-testvectors/inputs-executor/calldata/op-arith-final_0.json') -const empty_input = require('@0xpolygonhermez/zkevm-proverjs/test/inputs/empty_input.json') -const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon; -const pathMainPil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/pil/main.pil'); -const { newCommitPolsArray } = require('pilcom'); -const { compile } = require('pilcom'); -const zkasm = require("@0xpolygonhermez/zkasmcom"); -const testFilesDir = __dirname; -const { argv } = require('yargs'); -async function main() { +const nonEmptyInput = require('@0xpolygonhermez/zkevm-testvectors/inputs-executor/calldata/op-arith-final_0.json'); +const emptyInput = require('@0xpolygonhermez/zkevm-proverjs/test/inputs/empty_input.json'); + +const { argv } = require('yargs') + .alias('v', 'verbose'); +const { compilePil, getTestFiles } = require('./helpers/helpers'); + +async function main() { // Compile pil + console.log(chalk.yellow('--> Compile PIL')); const cmPols = await compilePil(); // Get all zkasm files - const files = getTestFiles(); + const pathZkasm = path.join(process.cwd(), process.argv[2]); + const files = await getTestFiles(pathZkasm); // Run all zkasm files - for (let file of files) { - await runTest(file, cmPols) + // eslint-disable-next-line no-restricted-syntax + console.log(chalk.yellow('--> Start running zkasm files')); + for (const file of files) { + await runTest(file, cmPols); } } -async function runTest(testName, cmPols) { - const zkasmFile = `${testFilesDir}/${testName}`; +async function runTest(pathTest, cmPols) { // Compile rom const configZkasm = { defines: [], @@ -35,49 +39,33 @@ async function runTest(testName, cmPols) { allowOverwriteLabels: true, }; - const rom = await zkasm.compile(zkasmFile, null, configZkasm); + const rom = await zkasm.compile(pathTest, null, configZkasm); const config = { debug: true, stepsN: 8388608, - } - const input = zkasmFile.includes("rotate.zkasm") ? no_empty_input : empty_input; - console.log(`Running ${testName}`) - // Execute test - try { - await smMain.execute(cmPols.Main, input, rom, config); - } catch(e) { - if(zkasmFile.includes("rotate.zkasm") && e.toString().includes("Assert Error: newStateRoot does not match")) { - console.log("Assert outputs run succesfully") - } else { - throw new Error(e); - } - } -} + assertOutputs: false, + }; -// Get all zkasm counter test files -function getTestFiles() { - if(argv.test){ - return [`${argv.test}.zkasm`]; - } - const files = fs.readdirSync(testFilesDir).filter(name => name.endsWith('.zkasm')) - return files; -} + // list test that needs a non empty input + const input = pathTest.includes('rotate.zkasm') ? nonEmptyInput : emptyInput; -async function compilePil() { - if (!fs.existsSync(fileCachePil)) { - const poseidon = await buildPoseidon(); - const { F } = poseidon; - const pilConfig = { - defines: { N: 4096 }, - namespaces: ['Main', 'Global'], - disableUnusedError: true - }; - const p = await compile(F, pathMainPil, null, pilConfig); - fs.writeFileSync(fileCachePil, `${JSON.stringify(p, null, 1)}\n`, 'utf8'); + // execute zkasm tests + try { + const result = await smMain.execute(cmPols.Main, input, rom, config); + console.log(chalk.green(' --> pass'), pathTest); + if (argv.verbose) { + console.log(chalk.blue(' --> verbose')); + console.log(chalk.blue(' --> counters')); + console.log(result.counters); + console.log(chalk.blue(' --> outputs')); + console.log(result.output); + console.log(chalk.blue(' --> logs')); + console.log(result.logs); + } + } catch (e) { + console.log(chalk.red(' --> fail'), pathTest); + throw new Error(e); } - - const pil = JSON.parse(fs.readFileSync(fileCachePil)); - return newCommitPolsArray(pil); } -main() \ No newline at end of file +main();