Skip to content

Commit

Permalink
Merge pull request #321 from 0xPolygonHermez/feature/vcounters-2
Browse files Browse the repository at this point in the history
Feature/vcounters 2
  • Loading branch information
krlosMata authored Feb 2, 2024
2 parents 762231c + 88577f0 commit af93940
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 76 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ jobs:
run: |
export NUM_CPUS=31
npm run test:start
sh tools/checker.sh
sh tools/parallel-testing/checker.sh
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ stats.html
build

# testvectors files
tools/parallel-tests
tools/parallel-testing/parallel-tests
tools/parallel-testing/countersDiffs.csv


.vscode/launch.json
Expand Down
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@0xpolygonhermez/zkevm-rom",
"version": "3.0.0",
"version": "4.0.0",
"description": "zkROM source code",
"main": "index.js",
"scripts": {
Expand All @@ -21,8 +21,10 @@
"test:zkasm": "node tools/run-tests-zkasm.js ./test --helpers ../main/helper.js",
"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\""
"test:gen": "node tools/parallel-testing/gen-parallel-tests.js",
"test:start": "npx mocha --jobs $NUM_CPUS --timeout 0 --max-old-space-size=8192 --parallel \"tools/parallel-testing/parallel-tests/*.test.js\"",
"report:free-inputs": "node tools/audit-tools/free-inputs-checker.js",
"report:registry-op": "node tools/audit-tools/registry-op-checker.js"
},
"keywords": [
"zkrom",
Expand All @@ -41,9 +43,9 @@
"yargs": "^17.5.1"
},
"devDependencies": {
"@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v4.0.0-rc.4-fork.7",
"@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v4.0.0-fork.7",
"@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs#b1540abf1fd1306e5eb11817abe40145b27a48ae",
"@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#v4.0.0-rc.4-fork.7",
"@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#v4.0.0-fork.7",
"chai": "^4.3.6",
"chalk": "^3.0.0",
"eslint": "^8.25.0",
Expand Down
71 changes: 71 additions & 0 deletions tools/audit-tools/registry-op-checker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-disable no-use-before-define */
/* eslint-disable no-continue */
/* eslint-disable no-restricted-syntax */
const rom = require('../../build/rom.json');
const argv = require('yargs');

/**
* This script checks if there are new registry operations in the rom build. It compares it with the rom input selected
* The result is logged in the console.
*/
async function main() {
// load rom input
let input = {};

if (argv._.length === 0) {
console.log('You need to specify an input file');
process.exit(1);
} else if (argv._.length === 1) {
console.log('path input: ', argv._[0]);
input = JSON.parse(await fs.promises.readFile(argv._[0], 'utf8'));
} else {
console.log('Only one input file at a time is permitted');
process.exit(1);
}

// Find free inputs at rom's build
const regOpFound = getRegOpFromBuild(rom.program);
const prevRegOpFound = getRegOpFromBuild(input.program);
const diffFound = [];
// Compare found registers with previous rom
for (const op of regOpFound) {
const found = prevRegOpFound.find((item) => item.key === op.key);
if (!found) {
diffFound.push(op);
}
}
// Log warnings, f.e. a free input with more than one occurrence
for (const op of diffFound) {
console.log(`WARNING: Found new registry operation at ${op.fileName}:${op.line}->${op.lineStr}`);
}
console.log('FINISHED');
}

function getRegOpFromBuild(build) {
const regOpFound = [];
// Check all steps
for (const step of build) {
let count = 0;
// Get steps where we operate with registers
for (const key of Object.keys(step)) {
if (key === 'inA' || key === 'inB' || key === 'inC' || key === 'inD' || key === 'inE' || key === 'inF') {
if (step.lineStr.includes('*')) {
count += 1;
}
if (Object.keys(step).includes('CONST')) {
count += 1;
}
count += 1;
}
}
// Save steps with more than one register operation
if (count > 1) {
// Remove spaces from string
step.key = `${step.lineStr.replace(/\s/g, '')}-${step.fileName}`;
regOpFound.push(step);
}
}

return regOpFound;
}
main();
2 changes: 1 addition & 1 deletion tools/checker.sh → tools/parallel-testing/checker.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh
FILE=$PWD/tools/parallel-tests/checker.txt
FILE=$PWD/tools/parallel-testing/parallel-tests/checker.txt
if [ -f "$FILE" ]; then
cat "$FILE"
exit 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ const { compile } = require('pilcom');
const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon;

const folderPaths = [
'../node_modules/@0xpolygonhermez/zkevm-testvectors/inputs-executor',
'../node_modules/@0xpolygonhermez/zkevm-testvectors/inputs-executor/ethereum-tests/GeneralStateTests',
'../../node_modules/@0xpolygonhermez/zkevm-testvectors/inputs-executor',
'../../node_modules/@0xpolygonhermez/zkevm-testvectors/inputs-executor/ethereum-tests/GeneralStateTests',
];

const fileCachePil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json');
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');
const pathMainPil = path.join(__dirname, '../../node_modules/@0xpolygonhermez/zkevm-proverjs/pil/main.pil');
const inputs = [];
const testsFolder = path.join(__dirname, 'parallel-tests');
const sampleDir = path.join(__dirname, 'parallel-tests-sample/sample.test.js');
Expand Down Expand Up @@ -42,12 +42,12 @@ async function main() {
fs.readdirSync(inputsPath).forEach((file) => {
const filePath = path.join(inputsPath, file);
// Remove json lists that are generated with gen inputs script and are not inputs
if (file.endsWith('.json') && !file.includes('testsOOC-list.json') && !file.includes('tests30M-list.json')) {
if (file.endsWith('.json') && !file.includes('testsOOC-list.json') && !file.includes('tests30M-list.json') && !file.includes('no-exec')) {
inputs.push(filePath);
} else if (fs.statSync(filePath).isDirectory() && !filePath.includes('tests-OOC')) {
fs.readdirSync(filePath).forEach((subFile) => {
const subFilePath = path.join(filePath, subFile);
if (subFile.endsWith('.json') && !subFile.includes('testsOOC-list.json') && !subFile.includes('tests30M-list.json')) {
if (subFile.endsWith('.json') && !subFile.includes('testsOOC-list.json') && !subFile.includes('tests30M-list.json') && !subFile.includes('no-exec')) {
inputs.push(subFilePath);
}
});
Expand All @@ -66,6 +66,8 @@ async function main() {
const pil = await compile(F, pathMainPil, null, pilConfig);
fs.writeFileSync(fileCachePil, `${JSON.stringify(pil, null, 1)}\n`, 'utf8');
genTestsFiles();
// Generate counters diff table csv file
fs.writeFileSync(path.join(__dirname, 'countersDiffs.csv'), 'Test name,vSteps,rSteps,StepsDiff,vArith,rArith,ArithDiff,vBinary,rBinary,BinaryDiff,vMemAlign,rMemAlign,memAlignDiff,vKeccaks,rKeccaks,keccaksDiff,vPoseidon,rPoseidon,PoseidonDiff,vPadding,rPadding,PaddingDiff,vSHA256,rSHA256,SHA256Diff\n', 'utf8');
}

main();
133 changes: 133 additions & 0 deletions tools/parallel-testing/parallel-tests-sample/sample.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
/* eslint-disable no-use-before-define */
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable import/extensions */
/* eslint-disable import/no-unresolved */
const { expect } = require('chai');
const fs = require('fs');
const path = require('path');

const { newCommitPolsArray } = require('pilcom');
const smMain = require('@0xpolygonhermez/zkevm-proverjs/src/sm/sm_main/sm_main');

let rom = require('../../../build/rom.json');

let stepsN = 2 ** 23;
let counters = false;

const fileCachePil = path.join(__dirname, '../../../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json');

const checkerDir = path.join(__dirname, 'checker.txt');

const inputPath = '%%INPUT_PATH%%';
const nameFile = path.basename(inputPath);
const input = JSON.parse(fs.readFileSync(inputPath, 'utf8'));

it(`${nameFile}`, async () => {
if (fs.existsSync(checkerDir)) {
process.exit(1);
}
const pil = JSON.parse(fs.readFileSync(fileCachePil));
const cmPols = newCommitPolsArray(pil);
if (input.gasLimit) {
rom = require(`../../../build/rom-${input.gasLimit}.test.json`);
}
if (input.stepsN) {
stepsN = input.stepsN;
counters = true;
}
await runTest(cmPols, stepsN);

expect(true).to.be.equal(true);
});

async function runTest(cmPols, steps) {
try {
const config = {
debug: true,
debugInfo: {
inputName: path.basename(inputPath),
},
stepsN: steps,
counters,
assertOutputs: true,
};

const res = await smMain.execute(cmPols.Main, input, rom, config);
compareCounters(input.virtualCounters, res.counters);
} catch (err) {
fs.writeFileSync(checkerDir, `Failed test ${inputPath} - ${err}}`);
throw err;
}
}

function compareCounters(virtualCounters, result) {
const countersDiff = {
steps: {
virtual: virtualCounters.steps,
real: Number(result.cntSteps),
diff: getPercentageDiff(virtualCounters.steps, Number(result.cntSteps)),
},
arith: {
virtual: virtualCounters.arith,
real: Number(result.cntArith),
diff: getPercentageDiff(virtualCounters.arith, Number(result.cntArith)),
},
binary: {
virtual: virtualCounters.binary,
real: Number(result.cntBinary),
diff: getPercentageDiff(virtualCounters.binary, Number(result.cntBinary)),
},
memAlign: {
virtual: virtualCounters.memAlign,
real: Number(result.cntMemAlign),
diff: getPercentageDiff(virtualCounters.memAlign, Number(result.cntMemAlign)),
},
keccaks: {
virtual: virtualCounters.keccaks,
real: Number(result.cntKeccakF),
diff: getPercentageDiff(virtualCounters.keccaks, Number(result.cntKeccakF)),
},
poseidon: {
virtual: virtualCounters.poseidon,
real: Number(result.cntPoseidonG),
diff: getPercentageDiff(virtualCounters.poseidon, Number(result.cntPoseidonG)),
},
padding: {
virtual: virtualCounters.padding,
real: Number(result.cntPaddingPG),
diff: getPercentageDiff(virtualCounters.padding, Number(result.cntPaddingPG)),
},
sha256: {
virtual: virtualCounters.sha256,
real: Number(result.cntSha256F),
diff: getPercentageDiff(virtualCounters.sha256, Number(result.cntSha256F)),
},
};
fs.appendFileSync(path.join(__dirname, '../countersDiffs.csv'), `${nameFile},${countersDiff.steps.virtual},${countersDiff.steps.real},${String(countersDiff.steps.diff).replace('.', ',')},${countersDiff.arith.virtual},${countersDiff.arith.real},${String(countersDiff.arith.diff).replace('.', ',')},${countersDiff.binary.virtual},${countersDiff.binary.real},${String(countersDiff.binary.diff).replace('.', ',')},${countersDiff.memAlign.virtual},${countersDiff.memAlign.real},${String(countersDiff.memAlign.diff).replace('.', ',')},${countersDiff.keccaks.virtual},${countersDiff.keccaks.real},${String(countersDiff.keccaks.diff).replace('.', ',')},${countersDiff.poseidon.virtual},${countersDiff.poseidon.real},${String(countersDiff.poseidon.diff).replace('.', ',')},${countersDiff.padding.virtual},${countersDiff.padding.real},${String(countersDiff.padding.diff).replace('.', ',')},${countersDiff.sha256.virtual},${countersDiff.sha256.real},${String(countersDiff.sha256.diff).replace('.', ',')}\n`);
// Check percentages are greater than 0
Object.keys(countersDiff).forEach((key) => {
if (Number(countersDiff[key].diff) < 0) {
throw new Error(`Negative percentage diff: ${countersDiff[key].virtual}/${countersDiff[key].real}/${countersDiff[key].diff}% at ${key}}`);
}
});
}

function getPercentageDiff(a, b) {
if (a === 0) {
// a and b are 0
if (b === 0) {
return 0;
}
// a is 0 but b is not -> fail test

return -100;
}
// a is not 0 but b is -> passed
if (b === 0) {
return 0;
}

return (((a - b) / b) * 100).toFixed(2);
}
62 changes: 0 additions & 62 deletions tools/parallel-tests-sample/sample.test.js

This file was deleted.

0 comments on commit af93940

Please sign in to comment.