Skip to content

Commit

Permalink
Merge pull request #223 from 0xPolygonHermez/feature/counter-tests
Browse files Browse the repository at this point in the history
Feature/counter tests
  • Loading branch information
krlosMata committed Jan 13, 2023
2 parents 14c5ca7 + 7346302 commit 5c05b98
Show file tree
Hide file tree
Showing 70 changed files with 2,189 additions and 286 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ jobs:
run: |
npm i
npm run build
- name: run counters tests
run: |
npm run test:counters
- name: Generate tests
run: |
npm run test:gen
Expand Down
45 changes: 45 additions & 0 deletions counters/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Counters testing tool

The purpose of this tool is to detect counters altertions in zkrom code.
A unit test is created for each function and opcode of the zkEVM. The structure of the test is the following:
`````
INCLUDE "../initIncludes.zkasm" // Include the files imported at the beginning of the test
start:
1000000 => GAS
operation:
2 :MSTORE(SP++)
2 :MSTORE(SP++)
:JMP(opADD)
// Assert counters. Check for each function, the exact number of each counter is matched
checkCounters:
%OPADD_STEP - STEP:JMPN(failedCounters)
%OPADD_CNT_BINARY - CNT_BINARY :JMPNZ(failedCounters)
%OPADD_CNT_ARITH - CNT_ARITH :JMPNZ(failedCounters)
%OPADD_CNT_KECCAK_F - CNT_KECCAK_F :JMPNZ(failedCounters)
%OPADD_CNT_MEM_ALIGN - CNT_MEM_ALIGN :JMPNZ(failedCounters)
%OPADD_CNT_PADDING_PG - CNT_PADDING_PG :JMPNZ(failedCounters)
%OPADD_CNT_POSEIDON_G - CNT_POSEIDON_G :JMPNZ(failedCounters)
// Finalize execution
0 => A,B,C,D,E,CTX, SP, PC, GAS, MAXMEM, SR, HASHPOS, RR ; Set all registers to 0
finalizeExecution:
:JMP(finalWait)
readCode:
txType:
:JMP(checkCounters)
failedCounters: // Force failed assert
2 => A
1 :ASSERT
INCLUDE "../endIncludes.zkasm" // Include the files imported at the end of the test
`````

Run all tests:
`````
node counters/counters-executor.js
`````
Limitations:
- Not all the tests are implemented yet, just the most complex ones
- For some test (the simplest ones), the counters it should spend are stored in `countersConstants.zkasm` file. For tests with a lot of utils calls or a lot of complexity, the values of the counters are hardcoded in the test.
- The tests always try to cover as much coverage as posible and always with the worst case counters scenario but this approach gets a bit tricky for complex opcodes as they have different contexts and behaviours.
- The objective is to keep adding tests with already not implemented functions but also adding tests for already implemented opcodes but with different scenarios (Example: calldatacopy from a call or from a create2)
68 changes: 68 additions & 0 deletions counters/counters-executor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
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 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 = path.join(__dirname, './tests');
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 rom = await zkasm.compile(zkasmFile);
const config = {
debug: true,
stepsN: 8388608,
}
console.log(`Running ${testName}`)
// Execute test
const res = await smMain.execute(cmPols.Main, empty_input, rom, config);
console.log(res.counters)
}

// 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()
Loading

0 comments on commit 5c05b98

Please sign in to comment.