diff --git a/package.json b/package.json index 968f7d32..a6002048 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "license": "UNLICENSED", "dependencies": { "@0xpolygonhermez/zkasmcom": "https://github.com/0xPolygonHermez/zkasmcom.git#v0.4.0.0", - "@0xpolygonhermez/zkevm-commonjs": "https://github.com/0xpolygonhermez/zkevm-commonjs.git#v0.4.0.0", + "@0xpolygonhermez/zkevm-commonjs": "https://github.com/0xpolygonhermez/zkevm-commonjs.git#v0.4.0.1", "@0xpolygonhermez/zkevm-rom": "https://github.com/0xpolygonhermez/zkevm-rom.git#v0.4.0.0-rc.1", "chalk": "^3.0.0", "circomlib": "^2.0.3", diff --git a/test/counters/storage.js b/test/counters/storage.js index 11150788..8e880bf3 100644 --- a/test/counters/storage.js +++ b/test/counters/storage.js @@ -10,7 +10,16 @@ describe("Test Storage Counters", async function () { it("Verify Storage Zkasm Test", async () => { await verifyZkasm("../zkasm/counters/storage.zkasm", true, - { defines: {N: 2 ** 21}, + { defines: {N: 2 ** 16}, + namespaces: ['Global', 'Main', 'Storage'], + verbose: true, + color: true, + disableUnusedError: true}); + }); + + it("Verify Storage Zkasm Test (some delete edge cases)", async () => { + await verifyZkasm("../zkasm/counters/storage2.zkasm", true, + { defines: {N: 2 ** 16}, namespaces: ['Global', 'Main', 'Rom', 'Byte4', 'Storage', 'PoseidonG'], verbose: true, color: true, diff --git a/test/sm/sm_storage/sm_storage_test.js b/test/sm/sm_storage/sm_storage_test.js index 07ab6b6c..f64f8a4e 100644 --- a/test/sm/sm_storage/sm_storage_test.js +++ b/test/sm/sm_storage/sm_storage_test.js @@ -63,6 +63,16 @@ describe("Test storage operations", async function () { cmPols.Main.op5[index] = 0n; cmPols.Main.op6[index] = 0n; cmPols.Main.op7[index] = 0n; + cmPols.Main.incCounter[index] = 0n; + cmPols.Main.sWR[index] = 0n; + cmPols.Main.D0[index] = 0n; + cmPols.Main.D1[index] = 0n; + cmPols.Main.D2[index] = 0n; + cmPols.Main.D3[index] = 0n; + cmPols.Main.D4[index] = 0n; + cmPols.Main.D5[index] = 0n; + cmPols.Main.D6[index] = 0n; + cmPols.Main.D7[index] = 0n; } db = new MemDB(fr); @@ -71,6 +81,59 @@ describe("Test storage operations", async function () { async function smtSet (oldRoot, key, value) { const r = await smt.set(oldRoot, key, value); + const index = plookUpIndex++; + cmPols.Main.sRD[index] = fr.zero; + cmPols.Main.sWR[index] = fr.e(1n); + cmPols.Main.SR0[index] = fr.e(oldRoot[0] & 0xFFFFFFFFn); + cmPols.Main.SR1[index] = fr.e(oldRoot[0] >> 32n); + cmPols.Main.SR2[index] = fr.e(oldRoot[1] & 0xFFFFFFFFn); + cmPols.Main.SR3[index] = fr.e(oldRoot[1] >> 32n); + cmPols.Main.SR4[index] = fr.e(oldRoot[2] & 0xFFFFFFFFn); + cmPols.Main.SR5[index] = fr.e(oldRoot[2] >> 32n); + cmPols.Main.SR6[index] = fr.e(oldRoot[3] & 0xFFFFFFFFn); + cmPols.Main.SR7[index] = fr.e(oldRoot[3] >> 32n); + cmPols.Main.D0[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D1[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D2[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D3[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D4[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D5[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D6[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.D7[index] = value & 0xFFFFFFFFn; + value = value >> 32n; + cmPols.Main.sKey[0][index] = key[0]; + cmPols.Main.sKey[1][index] = key[1]; + cmPols.Main.sKey[2][index] = key[2]; + cmPols.Main.sKey[3][index] = key[3]; + cmPols.Main.op0[index] = fr.e(r.newRoot[0] & 0xFFFFFFFFn); + cmPols.Main.op1[index] = fr.e(r.newRoot[0] >> 32n); + cmPols.Main.op2[index] = fr.e(r.newRoot[1] & 0xFFFFFFFFn); + cmPols.Main.op3[index] = fr.e(r.newRoot[1] >> 32n); + cmPols.Main.op4[index] = fr.e(r.newRoot[2] & 0xFFFFFFFFn); + cmPols.Main.op5[index] = fr.e(r.newRoot[2] >> 32n); + cmPols.Main.op6[index] = fr.e(r.newRoot[3] & 0xFFFFFFFFn); + cmPols.Main.op7[index] = fr.e(r.newRoot[3] >> 32n); + cmPols.Main.incCounter = r.proofHashCounter; +/* console.log(index+' '+[ + fr.e(cmPols.Main.SR0[index] + cmPols.Main.SR1[index] * 2n**32n), + fr.e(cmPols.Main.SR2[index] + cmPols.Main.SR3[index] * 2n**32n), + fr.e(cmPols.Main.SR4[index] + cmPols.Main.SR5[index] * 2n**32n), + fr.e(cmPols.Main.SR6[index] + cmPols.Main.SR7[index] * 2n**32n), + cmPols.Main.sKey[0][index], cmPols.Main.sKey[1][index], cmPols.Main.sKey[2][index], cmPols.Main.sKey[3][index], + cmPols.Main.D0[index], cmPols.Main.D1[index], cmPols.Main.D2[index], cmPols.Main.D3[index], + cmPols.Main.D4[index], cmPols.Main.D5[index], cmPols.Main.D6[index], cmPols.Main.D7[index], + fr.e(cmPols.Main.op0[index] + cmPols.Main.op1[index] * 2n**32n), + fr.e(cmPols.Main.op2[index] + cmPols.Main.op3[index] * 2n**32n), + fr.e(cmPols.Main.op4[index] + cmPols.Main.op5[index] * 2n**32n), + fr.e(cmPols.Main.op6[index] + cmPols.Main.op7[index] * 2n**32n), + cmPols.Main.incCounter].join(','));*/ required.Storage.push({bIsSet: true, setResult: { oldRoot: [...r.oldRoot], @@ -90,9 +153,9 @@ describe("Test storage operations", async function () { async function smtGet (root, key) { const r = await smt.get(root, key); - console.log(['r', r, root, key]); const index = plookUpIndex++; cmPols.Main.sRD[index] = fr.e(1n); + cmPols.Main.sWR[index] = fr.zero; cmPols.Main.SR0[index] = fr.e(r.root[0] & 0xFFFFFFFFn); cmPols.Main.SR1[index] = fr.e(r.root[0] >> 32n); cmPols.Main.SR2[index] = fr.e(r.root[1] & 0xFFFFFFFFn); @@ -101,6 +164,14 @@ describe("Test storage operations", async function () { cmPols.Main.SR5[index] = fr.e(r.root[2] >> 32n); cmPols.Main.SR6[index] = fr.e(r.root[3] & 0xFFFFFFFFn); cmPols.Main.SR7[index] = fr.e(r.root[3] >> 32n); + cmPols.Main.D0[index] = fr.zero; + cmPols.Main.D1[index] = fr.zero; + cmPols.Main.D2[index] = fr.zero; + cmPols.Main.D3[index] = fr.zero; + cmPols.Main.D4[index] = fr.zero; + cmPols.Main.D5[index] = fr.zero; + cmPols.Main.D6[index] = fr.zero; + cmPols.Main.D7[index] = fr.zero; cmPols.Main.sKey[0][index] = key[0]; cmPols.Main.sKey[1][index] = key[1]; cmPols.Main.sKey[2][index] = key[2]; @@ -122,6 +193,7 @@ describe("Test storage operations", async function () { rvalue = rvalue >> 32n; cmPols.Main.op7[index] = rvalue & 0xFFFFFFFFn; rvalue = rvalue >> 32n; + cmPols.Main.incCounter = r.proofHashCounter; required.Storage.push({bIsSet: false, getResult: { root: [...r.root], diff --git a/test/sm/sm_storage/storage_main.pil b/test/sm/sm_storage/storage_main.pil index 9cd89e45..ec1dae15 100644 --- a/test/sm/sm_storage/storage_main.pil +++ b/test/sm/sm_storage/storage_main.pil @@ -4,20 +4,41 @@ include "../../../pil/storage.pil"; namespace Main(%N); -pol commit sRD; +pol commit sRD, sWR; pol commit SR0, SR1, SR2, SR3, SR4, SR5, SR6, SR7; +pol commit D0, D1, D2, D3, D4, D5, D6, D7; pol commit sKey[4]; pol commit op0, op1, op2, op3, op4, op5, op6, op7; +pol commit incCounter; sRD { SR0 + 2**32*SR1, SR2 + 2**32*SR3, SR4 + 2**32*SR5, SR6 + 2**32*SR7, sKey[0], sKey[1], sKey[2], sKey[3], op0, op1, op2, op3, - op4, op5, op6, op7 + op4, op5, op6, op7, + incCounter } in Storage.iLatchGet { Storage.oldRoot0, Storage.oldRoot1, Storage.oldRoot2, Storage.oldRoot3, Storage.rkey0, Storage.rkey1, Storage.rkey2, Storage.rkey3, Storage.valueLow0, Storage.valueLow1, Storage.valueLow2, Storage.valueLow3, - Storage.valueHigh0, Storage.valueHigh1, Storage.valueHigh2, Storage.valueHigh3 + Storage.valueHigh0, Storage.valueHigh1, Storage.valueHigh2, Storage.valueHigh3, + incCounter +}; + +sWR { + SR0 + 2**32*SR1, SR2 + 2**32*SR3, SR4 + 2**32*SR5, SR6 + 2**32*SR7, + sKey[0], sKey[1], sKey[2], sKey[3], + D0, D1, D2, D3, + D4, D5, D6, D7, + op0 + 2**32*op1, op2 + 2**32*op3, op4 + 2**32*op5, op6 + 2**32*op7, + incCounter +} in +Storage.iLatchSet { + Storage.oldRoot0, Storage.oldRoot1, Storage.oldRoot2, Storage.oldRoot3, + Storage.rkey0, Storage.rkey1, Storage.rkey2, Storage.rkey3, + Storage.valueLow0, Storage.valueLow1, Storage.valueLow2, Storage.valueLow3, + Storage.valueHigh0, Storage.valueHigh1, Storage.valueHigh2, Storage.valueHigh3, + Storage.newRoot0, Storage.newRoot1, Storage.newRoot2, Storage.newRoot3, + Storage.incCounter }; diff --git a/test/zkasm/counters/storage2.zkasm b/test/zkasm/counters/storage2.zkasm new file mode 100644 index 00000000..18cad895 --- /dev/null +++ b/test/zkasm/counters/storage2.zkasm @@ -0,0 +1,66 @@ +; key bits with A,B = 0 C = # +CONST %_0000101 = 8 ; 0000101....1010 #8 +CONST %_0000111 = 4 ; 0000111....0001 #4 +CONST %_0010001 = 13 ; 0010001....0111 #13 +CONST %_0011010 = 1 ; 0011010....1110 #1 +CONST %_0011101 = 5 ; 0011101....0001 #5 +CONST %_0100101 = 7 ; 0100101....0110 #7 +CONST %_0101011 = 10 ; 0101011....1001 #10 +CONST %_0110101 = 3 ; 0110101....0010 #3 +CONST %_0110110 = 9 ; 0110110....0110 #9 +CONST %_0111001 = 6 ; 0111001....0000 #6 +CONST %_1010110 = 15 ; 1010110....0101 #15 +CONST %_1010111 = 14 ; 1010111....1101 #14 +CONST %_1100011 = 12 ; 1100011....1010 #12 +CONST %_1101000 = 0 ; 1101000....0010 #0 +CONST %_1101010 = 2 ; 1101010....1001 #2 +CONST %_1111001 = 11 ; 1111001....0110 #11 + +start: + + STEP => A + 0 :ASSERT + + ; to verify that there are no correlations between counters + 0 => A + CNT_ARITH :ASSERT + CNT_BINARY :ASSERT + CNT_KECCAK_F: ASSERT + CNT_MEM_ALIGN :ASSERT + CNT_POSEIDON_G :ASSERT + CNT_PADDING_PG :ASSERT + + 0 => SR + + %_1111001 => A + 0x10n => D + $ => SR :SSTORE + + %_1100011 => A + 0x20n => D + $ => SR :SSTORE + + %_1101000 => A + 0x40n => D + $ => SR :SSTORE + + %_1111001 => A + 0n => D + $ => SR :SSTORE + + %_1101000 => A + 0n => D + $ => SR :SSTORE + + %_1100011 => A + 0n => D + $ => SR :SSTORE + +end: + 0 => A,B,C,D,E,CTX, SP, PC, GAS, MAXMEM, SR + +finalWait: + ${beforeLast()} : JMPN(finalWait) + + : JMP(start) +opINVALID: \ No newline at end of file diff --git a/tools/gen_store_keys.js b/tools/gen_store_keys.js new file mode 100644 index 00000000..45c12fd0 --- /dev/null +++ b/tools/gen_store_keys.js @@ -0,0 +1,64 @@ +const fs = require("fs") +const { Scalar } = require('ffjavascript'); +const buildPoseidon = require("@0xpolygonhermez/zkevm-commonjs").getPoseidon; + +const argv = require("yargs") + .usage("node gen_store_keys.js [-c ] [-o ]") + .help('h') + .alias("o", "output") + .alias("c", "count") + .argv; + +async function main(){ + const output = typeof(argv.output) === "string" ? argv.output.trim() : "-"; + const count = typeof(argv.count) === "number" ? argv.count : 100; + + const poseidon = await buildPoseidon(); + const F = poseidon.F; + + // set A, B = 0 + const A012345B01 = [F.zero, F.zero, F.zero, F.zero, F.zero, F.zero, F.zero, F.zero]; + let hashes = []; + for (let i = 0; i < count; ++i) { + const C = [i, F.zero, F.zero, F.zero, F.zero, F.zero, F.zero, F.zero]; + + const keyI = poseidon(A012345B01); // Kin0 + const key = poseidon(C, keyI); // Kin1 + hashes.push(splitKey(key).join('') + ' #'+i); + } + hashes.sort(); + let maxDepth = 0; + for (let i = 1; i < count; ++i) { + const depth = [...hashes[i]].findIndex((bit, index) => bit !== hashes[i-1][index]); + maxDepth = depth > maxDepth ? depth : maxDepth; + } + const content = hashes.join("\n") + "\n"; + if (output == '-') { + console.log(content); + } else { + fs.writeFileSync(output, content , "utf8"); + } + console.log('max depth:' + maxDepth); + + + function splitKey(k) { + const res = []; + const auxk = [F.toObject(k[0]), F.toObject(k[1]), F.toObject(k[2]), F.toObject(k[3])]; + for (let i = 0; i < 64; i++) { + for (let j = 0; j < 4; j++) { + res.push(Scalar.toNumber(Scalar.band(auxk[j], Scalar.e(1)))); + auxk[j] = Scalar.shr(auxk[j], 1); + } + } + + return res; + } +} + +main().then(()=> { + process.exit(0); +}, (err) => { + console.log(err.message); + console.log(err.stack); + process.exit(1); +}); \ No newline at end of file