Skip to content

Commit 2ddeffb

Browse files
authored
Merge pull request #266 from 0xPolygonHermez/develop
Develop
2 parents b27579b + 7c2f57e commit 2ddeffb

File tree

91 files changed

+3287
-1162
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+3287
-1162
lines changed

.github/workflows/main.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ jobs:
2121
run: |
2222
npm i
2323
npm run build
24+
npm run test:build:gasLimit:v1
25+
npm run test:build:gasLimit:v2
26+
npm run test:build:gasLimit:v3
27+
- name: run counters tests
28+
run: |
29+
npm run test:counters
2430
- name: Generate tests
2531
run: |
2632
npm run test:gen

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,4 @@ build
7272

7373
# testvectors files
7474
tools/parallel-tests
75+

counters/README.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
## Counters testing tool
2+
3+
The purpose of this tool is to detect counters altertions in zkrom code.
4+
A unit test is created for each function and opcode of the zkEVM. The structure of the test is the following:
5+
`````
6+
INCLUDE "../initIncludes.zkasm" // Include the files imported at the beginning of the test
7+
8+
start:
9+
1000000 => GAS
10+
11+
operation:
12+
2 :MSTORE(SP++)
13+
2 :MSTORE(SP++)
14+
:JMP(opADD)
15+
// Assert counters. Check for each function, the exact number of each counter is matched
16+
checkCounters:
17+
%OPADD_STEP - STEP:JMPN(failedCounters)
18+
%OPADD_CNT_BINARY - CNT_BINARY :JMPNZ(failedCounters)
19+
%OPADD_CNT_ARITH - CNT_ARITH :JMPNZ(failedCounters)
20+
%OPADD_CNT_KECCAK_F - CNT_KECCAK_F :JMPNZ(failedCounters)
21+
%OPADD_CNT_MEM_ALIGN - CNT_MEM_ALIGN :JMPNZ(failedCounters)
22+
%OPADD_CNT_PADDING_PG - CNT_PADDING_PG :JMPNZ(failedCounters)
23+
%OPADD_CNT_POSEIDON_G - CNT_POSEIDON_G :JMPNZ(failedCounters)
24+
// Finalize execution
25+
0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0
26+
finalizeExecution:
27+
:JMP(finalWait)
28+
readCode:
29+
txType:
30+
:JMP(checkCounters)
31+
failedCounters: // Force failed assert
32+
2 => A
33+
1 :ASSERT
34+
INCLUDE "../endIncludes.zkasm" // Include the files imported at the end of the test
35+
`````
36+
37+
Run all tests:
38+
`````
39+
node counters/counters-executor.js
40+
`````
41+
Limitations:
42+
- Not all the tests are implemented yet, just the most complex ones
43+
- 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.
44+
- 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.
45+
- 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)

counters/counters-executor.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const path = require('path');
2+
const fs = require('fs');
3+
const smMain = require('@0xpolygonhermez/zkevm-proverjs/src/sm/sm_main/sm_main');
4+
const fileCachePil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json');
5+
const empty_input = require('@0xpolygonhermez/zkevm-proverjs/test/inputs/empty_input.json')
6+
const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon;
7+
const pathMainPil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/pil/main.pil');
8+
const { newCommitPolsArray } = require('pilcom');
9+
const { compile } = require('pilcom');
10+
const zkasm = require("@0xpolygonhermez/zkasmcom");
11+
const testFilesDir = path.join(__dirname, './tests');
12+
const { argv } = require('yargs');
13+
14+
async function main() {
15+
16+
// Compile pil
17+
const cmPols = await compilePil();
18+
19+
// Get all zkasm files
20+
const files = getTestFiles();
21+
22+
// Run all zkasm files
23+
for (let file of files) {
24+
await runTest(file, cmPols)
25+
}
26+
}
27+
28+
async function runTest(testName, cmPols) {
29+
const zkasmFile = `${testFilesDir}/${testName}`;
30+
// Compile rom
31+
const configZkasm = {
32+
defines: [],
33+
allowUndefinedLabels: true
34+
};
35+
36+
const rom = await zkasm.compile(zkasmFile, null, configZkasm);
37+
const config = {
38+
debug: true,
39+
stepsN: 8388608,
40+
}
41+
console.log(`Running ${testName}`)
42+
// Execute test
43+
const res = await smMain.execute(cmPols.Main, empty_input, rom, config);
44+
console.log(res.counters)
45+
}
46+
47+
// Get all zkasm counter test files
48+
function getTestFiles() {
49+
if(argv.test){
50+
return [`${argv.test}.zkasm`]
51+
}
52+
const files = fs.readdirSync(testFilesDir).filter(name => name.endsWith('.zkasm'))
53+
return files
54+
}
55+
56+
async function compilePil() {
57+
if (!fs.existsSync(fileCachePil)) {
58+
const poseidon = await buildPoseidon();
59+
const { F } = poseidon;
60+
const pilConfig = {
61+
defines: { N: 4096 },
62+
namespaces: ['Main', 'Global'],
63+
disableUnusedError: true
64+
};
65+
const p = await compile(F, pathMainPil, null, pilConfig);
66+
fs.writeFileSync(fileCachePil, `${JSON.stringify(p, null, 1)}\n`, 'utf8');
67+
}
68+
69+
const pil = JSON.parse(fs.readFileSync(fileCachePil));
70+
return newCommitPolsArray(pil);
71+
}
72+
73+
main()

0 commit comments

Comments
 (0)