diff --git a/circuits.bn128/gl.circom b/circuits.bn128/gl.circom index a58253b1..73f70eee 100644 --- a/circuits.bn128/gl.circom +++ b/circuits.bn128/gl.circom @@ -152,7 +152,7 @@ template GLCMulAdd() { // = a0b2 + a2b0 + a2b2 + a1b1 -> 4*ina.maxNum * inb.maxNum //Since all the elements of the array takes the same tag value, we set as the max value 5*ina.maxNum * inb.maxNum - var maxQuotientBits = log2((5*ina.maxNum * inb.maxNum - 1) \ p) + 1; + var maxQuotientBits = log2((5*ina.maxNum * inb.maxNum + inc.maxNum - 1) \ p) + 1; signal k[3]; diff --git a/circuits.bn128/stark_verifier.circom.ejs b/circuits.bn128/stark_verifier.circom.ejs index 6e6a0af8..39387b7f 100644 --- a/circuits.bn128/stark_verifier.circom.ejs +++ b/circuits.bn128/stark_verifier.circom.ejs @@ -279,7 +279,7 @@ template GLC3() { */ template Transcript() { - signal input {maxNum} publics[<%- pil.publics.length %>]; + signal input {maxNum} publics[<%- starkInfo.nPublics %>]; signal input rootC; signal input root1; signal input root2; @@ -300,7 +300,7 @@ template Transcript() { <% const transcript = new Transcript(); transcript.put("rootC"); -transcript.put("publics", pil.publics.length); +transcript.put("publics", starkInfo.nPublics); transcript.put("root1"); transcript.getField("challenges[0]", 3); transcript.getField("challenges[1]", 3); @@ -385,7 +385,7 @@ template parallel VerifyFRI(prevStepBits, currStepBits, nextStepBits, e0, e1) { signal {maxNum} coefs[1 << step][3] <== FFT(step, 1)(s_vals_curr); signal {maxNum} evalXprime[3] <== GLCMul()(s_specialX, s_X); - signal evalPol[3] <== EvalPol(1 << step)(coefs, evalXprime); + signal {maxNum} evalPol[3] <== EvalPol(1 << step)(coefs, evalXprime); signal s_keys_lowValues[nextStep]; for(var i = 0; i < nextStep; i++) { s_keys_lowValues[i] <== ys[i + nextStepBits]; } @@ -412,7 +412,7 @@ template parallel VerifyEvaluations() { signal input {maxNum} challenges4[3]; signal input {maxNum} challenges7[3]; signal input {maxNum} evals[<%- starkInfo.evMap.length %>][3]; - signal input {maxNum} publics[<%- pil.publics.length %>]; + signal input {maxNum} publics[<%- starkInfo.nPublics %>]; signal input enable; var q = 0xFFFFFFFFFFFFFFFF; @@ -639,7 +639,7 @@ template parallel VerifyFinalPol() { } template StarkVerifier() { - signal input publics[<%- pil.publics.length %>]; // constant polynomials + signal input publics[<%- starkInfo.nPublics %>]; // constant polynomials signal input root1; // Merkle tree root of the evaluations of all trace polynomials signal input root2; // Merkle tree root of the evaluations of polynomials h1 and h2 used for the plookup signal input root3; // Merkle tree root of the evaluations of the grand product polynomials (Z) @@ -704,7 +704,7 @@ template StarkVerifier() { enable <== 1; <% } -%> - signal {maxNum} publicsGL[<%- pil.publics.length %>]; + signal {maxNum} publicsGL[<%- starkInfo.nPublics %>]; for(var i = 0; i < <%- starkInfo.nPublics %>; i++){ publicsGL[i] <== LessThan64Bits()(publics[i]); } @@ -950,7 +950,7 @@ template Main() { signal input proverAddr; signal output publicsHash; - signal input publics[<%- pil.publics.length %>]; + signal input publics[<%- starkInfo.nPublics %>]; signal input root1; signal input root2; signal input root3; @@ -1035,10 +1035,10 @@ template Main() { // Calculate Publics Hash ////// - component publicsHasher = Sha256(<%- 160 + 64*pil.publics.length %>); + component publicsHasher = Sha256(<%- 160 + 64*starkInfo.nPublics %>); component n2bProverAddr = Num2Bits(160); - component n2bPublics[<%- pil.publics.length %> ]; - component cmpPublics[<%- pil.publics.length %> ]; + component n2bPublics[<%- starkInfo.nPublics %> ]; + component cmpPublics[<%- starkInfo.nPublics %> ]; n2bProverAddr.in <== proverAddr; for (var i=0; i<160; i++) { @@ -1047,7 +1047,7 @@ template Main() { var offset = 160; - for (var i=0; i<<%- pil.publics.length %>; i++) { + for (var i=0; i<<%- starkInfo.nPublics %>; i++) { n2bPublics[i] = Num2Bits(64); cmpPublics[i] = CompConstant64(0xFFFFFFFF00000000); n2bPublics[i].in <== publics[i]; diff --git a/circuits.gl/mux1.circom b/circuits.gl/mux1.circom index 5edd9152..5cde8276 100644 --- a/circuits.gl/mux1.circom +++ b/circuits.gl/mux1.circom @@ -13,4 +13,12 @@ template MultiMux1(n) { out[i] <== (c[1][i] - c[0][i])*s + c[0][i]; } +} + +template Mux1() { + signal input c[2]; // Constants + signal input s; // Selector + signal output out; + + out <== (c[1] - c[0])*s + c[0]; } \ No newline at end of file diff --git a/circuits.gl/stark_verifier.circom.ejs b/circuits.gl/stark_verifier.circom.ejs index fece68a7..63403441 100644 --- a/circuits.gl/stark_verifier.circom.ejs +++ b/circuits.gl/stark_verifier.circom.ejs @@ -251,7 +251,7 @@ class Transcript { */ template Transcript() { - signal input publics[<%- pil.publics.length %>]; + signal input publics[<%- starkInfo.nPublics %>]; signal input rootC[4]; signal input root1[4]; signal input root2[4]; @@ -272,7 +272,7 @@ template Transcript() { <% const transcript = new Transcript(); transcript.put("rootC", 4); - transcript.put("publics", pil.publics.length); + transcript.put("publics", starkInfo.nPublics); transcript.put("root1", 4); transcript.getField("challenges[0]", 3); transcript.getField("challenges[1]", 3); @@ -351,7 +351,7 @@ template parallel VerifyEvaluations() { signal input challenges4[3]; signal input challenges7[3]; signal input evals[<%- starkInfo.evMap.length %>][3]; - signal input publics[<%- pil.publics.length %>]; + signal input publics[<%- starkInfo.nPublics %>]; signal input enable; // zMul stores all the powers of z (which is stored in challenge7) up to nBits, i.e, [z, z^2, ..., z^nBits] @@ -530,7 +530,7 @@ template parallel VerifyFinalPol() { } } template StarkVerifier() { - signal input publics[<%- pil.publics.length %>]; // constant polynomials + signal input publics[<%- starkInfo.nPublics %>]; // constant polynomials signal input root1[4]; // Merkle tree root of the evaluations of all trace polynomials signal input root2[4]; // Merkle tree root of the evaluations of polynomials h1 and h2 used for the plookup signal input root3[4]; // Merkle tree root of the evaluations of the grand product polynomials (Z) diff --git a/index.js b/index.js index abcd007e..5ceea2c3 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,10 @@ -const FGL = require("./src/f3g"); +const F3g = require("./src/helpers/f3g"); -module.exports.FGL = new FGL(); -module.exports.starkSetup = require("./src/stark_setup.js"); -module.exports.starkGen = require("./src/stark_gen.js"); -module.exports.starkVerify = require("./src/stark_verify.js"); -module.exports.r1cs2plonk = require("./src/r1cs2plonk"); \ No newline at end of file +module.exports.F3g = new F3g(); +module.exports.pil2circom = require("./src/pil2circom.js"); +module.exports.starkSetup = require("./src/stark/stark_setup.js"); +module.exports.starkGen = require("./src/stark/stark_gen.js"); +module.exports.starkVerify = require("./src/stark/stark_verify.js"); +module.exports.r1cs2plonk = require("./src/r1cs2plonk"); +module.exports.starkInfo = require("./src/stark/stark_info"); diff --git a/src/compressor/compressor_exec.js b/src/compressor/compressor_exec.js new file mode 100644 index 00000000..63398e47 --- /dev/null +++ b/src/compressor/compressor_exec.js @@ -0,0 +1,52 @@ +const { newCommitPolsArray } = require("pilcom"); +const { WitnessCalculatorBuilder } = require("circom_runtime"); +const fs = require("fs"); + +module.exports.compressorExec = async function compressorExec(F, pil, wasm, input, exec) { + const cmPols = newCommitPolsArray(pil); + + const nCols = cmPols.Compressor.a.length; + + const { nAdds, nSMap, addsBuff, sMapBuff } = exec; + + const wc = await WitnessCalculatorBuilder(wasm); + const w = await wc.calculateWitness(input); + + for (let i=0; i { console.log(err.message); console.log(err.stack); process.exit(1); -}); - - -async function readExecFile(execFile, nCols) { - - const fd =await fs.promises.open(execFile, "r"); - const buffH = new BigUint64Array(2); - await fd.read(buffH, 0, 2*8); - const nAdds= Number(buffH[0]); - const nSMap= Number(buffH[1]); - - - const addsBuff = new BigUint64Array(nAdds*4); - await fd.read(addsBuff, 0, nAdds*4*8); - - const sMapBuff = new BigUint64Array(nSMap*nCols); - await fd.read(sMapBuff, 0, nSMap*nCols*8); - - await fd.close(); - - return { nAdds, nSMap, addsBuff, sMapBuff }; - -} +}); \ No newline at end of file diff --git a/src/compressor/main_compressor_setup.js b/src/compressor/main_compressor_setup.js index 04c134a0..6cbcd4f6 100644 --- a/src/compressor/main_compressor_setup.js +++ b/src/compressor/main_compressor_setup.js @@ -2,10 +2,7 @@ const fs = require("fs"); const version = require("../../package").version; const F3g = require("../helpers/f3g.js"); -const {readR1cs} = require("r1csfile"); -const plonkSetupC18 = require("./compressor18_setup.js"); -const plonkSetupC12 = require("./compressor12_setup.js"); - +const { compressorSetup } = require("./compressor_setup"); const argv = require("yargs") .version(version) @@ -25,28 +22,21 @@ async function run() { const pilFile = typeof(argv.pil) === "string" ? argv.pil.trim() : "mycircuit.c12.pil"; const execFile = typeof(argv.exec) === "string" ? argv.exec.trim() : "mycircuit.c12.exec"; - const r1cs = await readR1cs(r1csFile, {F: F, logger:console }); + let cols = argv.cols ? Number(argv.cols) : 12; const options = { forceNBits: argv.forceNBits }; - - let cols = argv.cols ? Number(argv.cols) : 12; - if(![12,18].includes(cols)) throw new Error("Invalid number of cols"); - - let res; - if(cols === 12) { - res = await plonkSetupC12(F, r1cs, options); - } else { - res = await plonkSetupC18(F, r1cs, options); - } + const {exec, pilStr, constPols} = await compressorSetup(F, r1csFile, cols, options); - await fs.promises.writeFile(pilFile, res.pilStr, "utf8"); - - await res.constPols.saveToFile(constFile); + const fd =await fs.promises.open(execFile, "w+"); + await fd.write(exec); + await fd.close(); - await writeExecFile(execFile,res.plonkAdditions, res.sMap); + await fs.promises.writeFile(pilFile, pilStr, "utf8"); + + await constPols.saveToFile(constFile); console.log("files Generated Correctly"); @@ -58,32 +48,4 @@ run().then(()=> { console.log(err.message); console.log(err.stack); process.exit(1); -}); - - -async function writeExecFile(execFile, adds, sMap) { - - const size = 2 + adds.length*4 + sMap.length*sMap[0].length; - const buff = new BigUint64Array(size); - - buff[0] = BigInt(adds.length); - buff[1] = BigInt(sMap[0].length); - - for (let i=0; i< adds.length; i++) { - buff[2 + i*4 ] = BigInt(adds[i][0]); - buff[2 + i*4 + 1 ] = BigInt(adds[i][1]); - buff[2 + i*4 + 2 ] = adds[i][2]; - buff[2 + i*4 + 3 ] = adds[i][3]; - } - - for (let i=0; i { console.log(err.message); console.log(err.stack); process.exit(1); -}); - +}); \ No newline at end of file diff --git a/src/main_pil2circom.js b/src/main_pil2circom.js index 7dc43ece..a0f07d88 100644 --- a/src/main_pil2circom.js +++ b/src/main_pil2circom.js @@ -10,9 +10,7 @@ const JSONbig = require('json-bigint')({ useNativeBigInt: true, alwaysParseAsBig const argv = require("yargs") .version(version) - .usage("node main_pil2circom.js -o -p [-P ] -v -s [--skipMain] [--enableInput] [--verkeyInput]") - .alias("p", "pil") - .alias("P", "pilconfig") + .usage("node main_pil2circom.js -o -v -s [--skipMain] [--enableInput] [--verkeyInput]") .alias("s", "starkinfo") .alias("v", "verkey") .alias("o", "output") @@ -21,13 +19,10 @@ const argv = require("yargs") async function run() { const F = new F3g(); - const pilFile = typeof(argv.pil) === "string" ? argv.pil.trim() : "mycircuit.pil"; - const pilConfig = typeof(argv.pilconfig) === "string" ? JSON.parse(fs.readFileSync(argv.pilconfig.trim())) : {}; const starkInfoFIle = typeof(argv.starkinfo) === "string" ? argv.starkinfo.trim() : "starkinfo.json"; const verKeyFile = typeof(argv.verkey) === "string" ? argv.verkey.trim() : "mycircuit.verkey.json"; const outputFile = typeof(argv.output) === "string" ? argv.output.trim() : "mycircuit.verifier.circom"; - const pil = await compile(F, pilFile, null, pilConfig); const verKey = JSONbig.parse(await fs.promises.readFile(verKeyFile, "utf8")); const constRoot = verKey.constRoot; @@ -39,7 +34,7 @@ async function run() { verkeyInput: argv.verkeyInput || false } - const verifier = await pil2circom(pil, constRoot, starkInfo, options); + const verifier = await pil2circom(constRoot, starkInfo, options); await fs.promises.writeFile(outputFile, verifier, "utf8"); diff --git a/src/pil2circom.js b/src/pil2circom.js index 5b5fefbe..ce6b8e35 100644 --- a/src/pil2circom.js +++ b/src/pil2circom.js @@ -4,7 +4,7 @@ const fs = require("fs"); const path = require("path"); -module.exports = async function pil2circom(pil, constRoot, starkInfo, options) { +module.exports = async function pil2circom(constRoot, starkInfo, options) { options = options || {}; starkStruct = starkInfo.starkStruct; @@ -29,7 +29,6 @@ module.exports = async function pil2circom(pil, constRoot, starkInfo, options) { starkInfo: starkInfo, starkStruct: starkStruct, constRoot: constRoot, - pil: pil, options: options }; diff --git a/src/pil_info/cp_prover.js b/src/pil_info/cp_prover.js index e3933e5e..4e9e05ba 100644 --- a/src/pil_info/cp_prover.js +++ b/src/pil_info/cp_prover.js @@ -64,6 +64,9 @@ module.exports = function generateConstraintPolynomial(res, pil, ctx, ctx2ns) { pilCodeGen(ctx, res.imExpsList[i]); } + res.nImPols = res.imExpsList.length; + res.nConstraints = pil.polIdentities.length + res.nImPols; + res.step3 = buildCode(ctx); // This variables are already calculated by expanding the ones in deg n @@ -193,12 +196,8 @@ function getExpDim(pil, exp, maxDeg) { case "addc": case "mulc": case "neg": - let md = 1; - for (let i=0; imd) md=d; - } - return md; + const d = Math.max(...exp.values.map(v => getExpDim(pil, v, maxDeg))); + return d; case "mul": return getExpDim(pil, exp.values[0], maxDeg) + getExpDim(pil, exp.values[1], maxDeg) case "muladd": diff --git a/src/stark/chelpers/compileCode_42ns.js b/src/stark/chelpers/compileCode_42ns.js index 58ca7b7e..0a9c6d77 100644 --- a/src/stark/chelpers/compileCode_42ns.js +++ b/src/stark/chelpers/compileCode_42ns.js @@ -34,7 +34,7 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { var cont_args = 0; var argsString = "{ " - var counters_ops = new Array(84).fill(0); + var counters_ops = new Array(93).fill(0); const nBits = starkInfo.starkStruct.nBits; const nBitsExt = starkInfo.starkStruct.nBitsExt; @@ -441,21 +441,28 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { ops.push(38); opsString += "38, "; cont_ops += 1; - } else if ((r.src[0].type === 'const') && (r.src[1].type === 'cm')) { + } else if ((r.src[0].type === 'const' && !r.src[0].prime) && (r.src[1].type === 'cm' && !r.src[1].prime)) { counters_ops[39] += 1; ops.push(39); opsString += "39, "; cont_ops += 1; - assert(!r.src[0].prime); - assert(!r.src[1].prime); - } else if ((r.src[0].type === 'tmp') && (r.src[1].type === 'const')) { + } else if ((r.src[1].type === 'const' && !r.src[1].prime) && (r.src[0].type === 'cm' && !r.src[0].prime)) { + counters_ops[91] += 1; + ops.push(91); + opsString += "91, "; + cont_ops += 1; + } else if ((r.src[0].type === 'tmp') && (r.src[1].type === 'const' && !r.src[1].prime)) { counters_ops[40] += 1; ops.push(40); opsString += "40, "; cont_ops += 1; - assert(!r.src[1].prime); + } else if ((r.src[1].type === 'tmp') && (r.src[0].type === 'const' && !r.src[0].prime)) { + counters_ops[92] += 1; + ops.push(92); + opsString += "92, "; + cont_ops += 1; } else { - console.log(src[0], src[1]); + console.log(r.src[0], r.src[1]); throw new Error("Option not considered!"); } @@ -463,12 +470,16 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { if (r.src[0].dim == 1 || r.src[1].dim == 1) { counters_sub[1] += 1; - if ((r.src[0].type === 'cm') && (r.src[1].type === 'number')) { - assert(!r.src[0].prime); + if ((r.src[0].type === 'cm' && !r.src[0].prime) && (r.src[1].type === 'number')) { counters_ops[41] += 1; ops.push(41); opsString += "41, "; cont_ops += 1; + } else if ((r.src[0].type === 'cm' && r.src[0].prime) && (r.src[1].type === 'number')) { + counters_ops[89] += 1; + ops.push(89); + opsString += "89, "; + cont_ops += 1; } else { console.log(src[0], src[1]); throw new Error("Option not considered!"); @@ -618,8 +629,7 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); body.push(` Goldilocks::mul(${lexp}, ${src[0]}, ${src[1]});`) - } else if ((r.src[0].type == 'const') && (r.src[1].type == 'cm' && !r.src[1].prime)) { - assert(!r.src[0].prime); + } else if ((r.src[0].type == 'const' && !r.src[0].prime) && (r.src[1].type == 'cm' && !r.src[1].prime)) { counters_ops[54] += 1; ops.push(54); opsString += "54, "; @@ -627,7 +637,14 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { pushSrcArg(r.src[1]); pushSrcArg(r.src[0]); body.push(` Goldilocks::mul(${lexp}, ${src[1]}, ${src[0]});`) - + } else if ((r.src[1].type == 'const' && !r.src[1].prime) && (r.src[0].type == 'cm' && !r.src[0].prime)) { + counters_ops[54] += 1; + ops.push(54); + opsString += "54, "; + cont_ops += 1; + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); + body.push(` Goldilocks::mul(${lexp}, ${src[1]}, ${src[0]});`) } else if ((r.src[0].type == 'cm' && r.src[0].prime) && (r.src[1].type == 'const' && !r.src[1].prime)) { counters_ops[55] += 1; ops.push(55); @@ -637,6 +654,14 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { pushSrcArg(r.src[1]); body.push(` Goldilocks::mul(${lexp}, ${src[0]}, ${src[1]});`) + } else if ((r.src[1].type == 'cm' && r.src[1].prime) && (r.src[0].type == 'const' && !r.src[0].prime)) { + counters_ops[55] += 1; + ops.push(55); + opsString += "55, "; + cont_ops += 1; + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); + body.push(` Goldilocks::mul(${lexp}, ${src[0]}, ${src[1]});`) } else if ((r.src[0].type == 'tmp') && (r.src[1].type == 'cm' && !r.src[1].prime)) { counters_ops[56] += 1; ops.push(56); @@ -664,6 +689,14 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { pushSrcArg(r.src[1]); body.push(` Goldilocks::mul(${lexp}, ${src[0]}, ${src[1]});`) assert(!r.src[0].prime); + } else if ((r.src[0].type == 'cm' && r.src[0].prime) && (r.src[1].type == 'const' && r.src[1].prime)) { + counters_ops[90] += 1; + ops.push(90); + opsString += "90, "; + cont_ops += 1; + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); + body.push(` Goldilocks::mul(${lexp}, ${src[0]}, ${src[1]});`) } else { console.log(src[0], src[1]); throw new Error("Option not considered!"); @@ -859,7 +892,14 @@ module.exports = function compileCode_42ns(starkInfo, functionName, code, dom) { pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); body.push(` Goldilocks3::mul(${lexp}, ${src[0]}, ${src[1]});`) - + } else if ((r.src[1].type == 'cm' && !r.src[1].prime) && (r.src[0].type == 'tmp')) { + counters_ops[75] += 1; + ops.push(75); + opsString += "75, "; + cont_ops += 1; + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); + body.push(` Goldilocks3::mul(${lexp}, ${src[0]}, ${src[1]});`) } else if ((r.src[0].type == 'cm' && !r.src[0].prime) && (r.src[1].type == 'challenge')) { counters_ops[76] += 1; ops.push(76); diff --git a/src/stark/chelpers/compileCode_52ns.js b/src/stark/chelpers/compileCode_52ns.js index 8655e12f..dd713fbe 100644 --- a/src/stark/chelpers/compileCode_52ns.js +++ b/src/stark/chelpers/compileCode_52ns.js @@ -36,7 +36,7 @@ module.exports = function compileCode_52ns(starkInfo, functionName, code, dom) { var argsString = "{ " - var counters_ops = new Array(16).fill(0); + var counters_ops = new Array(22).fill(0); const nBits = starkInfo.starkStruct.nBits; const nBitsExt = starkInfo.starkStruct.nBitsExt; var counters_add = new Array(4).fill(0); @@ -72,7 +72,6 @@ module.exports = function compileCode_52ns(starkInfo, functionName, code, dom) { if (r.src[0].type == 'tmp' && r.src.length > 1 && r.src[1].type == 'tmp') { if (r.src[0].id - r.src[1].id > 2 || r.src[0].id - r.src[1].id < -2) { - //console.log("pivot: ", r.dest.id, r.src[0].id, r.src[1].id); let a1 = r.dest.id; let a2 = r.src[0].id; let a3 = r.src[1].id; @@ -211,24 +210,45 @@ module.exports = function compileCode_52ns(starkInfo, functionName, code, dom) { ++counters_ops[14]; } } else { - body.push(` Goldilocks3::sub0(${lexp}, ${src[0]}, ${src[1]});`) - ops.push(11); - ++counters_ops[11]; - opsString += "11, "; - str = src[0]; - size = parseInt(str.substring(str.lastIndexOf(" "))); - auxstr = str.substring(str.indexOf("[") + 1); - offset = parseInt(auxstr.substring(0, auxstr.indexOf(" "))); - str = src[1]; - auxstr = str.substring(str.indexOf("[") + 1); - evid = parseInt(auxstr.substring(0, auxstr.indexOf("]"))); - args.push(offset); - args.push(size); - args.push(evid); - argsString += `${offset}, `; - argsString += `${size}, `; - argsString += `${evid}, `; - cont_args += 3; + if(lexp === "tmp") { + body.push(` Goldilocks3::sub0(${lexp}, ${src[0]}, ${src[1]});`) + ops.push(21); + ++counters_ops[21]; + opsString += "21, "; + str = src[0]; + size = parseInt(str.substring(str.lastIndexOf(" "))); + auxstr = str.substring(str.indexOf("[") + 1); + offset = parseInt(auxstr.substring(0, auxstr.indexOf(" "))); + str = src[1]; + auxstr = str.substring(str.indexOf("[") + 1); + evid = parseInt(auxstr.substring(0, auxstr.indexOf("]"))); + args.push(offset); + args.push(size); + args.push(evid); + argsString += `${offset}, `; + argsString += `${size}, `; + argsString += `${evid}, `; + cont_args += 3; + } else if(lexp === "tmp2") { + body.push(` Goldilocks3::sub0(${lexp}, ${src[0]}, ${src[1]});`) + ops.push(11); + ++counters_ops[11]; + opsString += "11, "; + str = src[0]; + size = parseInt(str.substring(str.lastIndexOf(" "))); + auxstr = str.substring(str.indexOf("[") + 1); + offset = parseInt(auxstr.substring(0, auxstr.indexOf(" "))); + str = src[1]; + auxstr = str.substring(str.indexOf("[") + 1); + evid = parseInt(auxstr.substring(0, auxstr.indexOf("]"))); + args.push(offset); + args.push(size); + args.push(evid); + argsString += `${offset}, `; + argsString += `${size}, `; + argsString += `${evid}, `; + cont_args += 3; + } else throw new Error("Case not considered"); } } else { throw new Error("Invalid dim"); @@ -667,4 +687,4 @@ module.exports = function compileCode_52ns(starkInfo, functionName, code, dom) { } } -} \ No newline at end of file +} diff --git a/src/stark/chelpers/compileCode_parser.js b/src/stark/chelpers/compileCode_parser.js index 58260411..96a89058 100644 --- a/src/stark/chelpers/compileCode_parser.js +++ b/src/stark/chelpers/compileCode_parser.js @@ -33,7 +33,7 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co var cont_args = 0; var argsString = "{ " - var counters_ops = new Array(115).fill(0); + var counters_ops = new Array(121).fill(0); const nBits = starkInfo.starkStruct.nBits; const nBitsExt = starkInfo.starkStruct.nBitsExt; @@ -362,6 +362,14 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); + } else if ((r.src[1].type === 'tmpExp') && (r.src[0].type === 'tmp')) { + assert(!r.src[1].prime); + counters_ops[15] += 1; + ops.push(15); + opsString += "15, "; + pushResArg(r); + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); } else { console.log(src[0], src[1]); console.log(r.src[0].type, r.src[1].type); @@ -545,6 +553,11 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co counters_ops[22] += 1; ops.push(22); opsString += "22, "; + } else if ((r.src[1].type === 'tmp') && (r.src[0].type === 'tmpExp')) { + assert(!r.src[0].prime); + counters_ops[24] += 1; + ops.push(24); + opsString += "24, "; } else { console.log(src[0], src[1]); console.log(r.src[0].type, r.src[1].type); @@ -740,6 +753,13 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); + } else if ((r.src[0].type == 'tmp') && (r.src[1].type == 'tmpExp' && !r.src[1].prime)) { + counters_ops[56] += 1; + ops.push(56); + opsString += "56, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); } else if ((r.src[0].type == 'const' && !r.src[0].prime) && (r.src[1].type == 'tmp')) { counters_ops[58] += 1; ops.push(58); @@ -788,6 +808,14 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[1]); pushSrcArg(r.src[0]); + } else if ((r.src[0].type == 'tmp') && (r.src[1].type == 'tmpExp' && r.src[1].dim == 1)) { + assert(!r.src[1].prime); + counters_ops[64] += 1; + ops.push(64); + opsString += "64, "; + pushResArg(r); + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); } else if ((r.src[0].type == 'cm' && !r.src[0].prime) && (r.src[1].type == 'challenge')) { assert(r.src[0].dim == 1); @@ -858,6 +886,13 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); + } else if ((r.src[0].type === 'tmpExp' && !r.src[0].prime) && (r.src[1].type === 'challenge')) { + counters_ops[62] += 1; + ops.push(62); + opsString += "62, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); } else { console.log(src[0], src[1]); console.log(r.src[0].type, r.src[1].type); @@ -995,6 +1030,10 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co counters_ops[83] += 1; ops.push(83); opsString += "83, "; + } else if (r.src[0].type == 'tmpExp' && !r.src[0].prime) { + counters_ops[79] += 1; + ops.push(79); + opsString += "79, "; } else { console.log(r.src[0].type); console.log(r.src[0].type); @@ -1101,6 +1140,37 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co break; } } + } else if (r.src[1].type === "cm") { + switch (r.src[0].type) { + case "cm": { + if (!r.src[0].prime) { + pushResArg(r); + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); + counters_ops[118] += 1; + ops.push(118); + opsString += "118, "; + } else { + assert(0); + } + break; + } case "tmpExp": { + assert(!r.src[0].prime); + pushResArg(r); + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); + counters_ops[118] += 1; + ops.push(118); + opsString += "118, "; + break; + } + default: { + console.log(src[0], src[1]); + console.log(r.src[0].type, r.src[1].type); + throw new Error("Option not considered!"); + break; + } + } } else { throw new Error("Option not considered!"); } @@ -1167,7 +1237,13 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); - + } else if ((r.src[1].type === 'tmp') && (r.src[0].type === 'tmp')) { + counters_ops[116] += 1; + ops.push(116); + opsString += "116, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); } else { console.log(src[0], src[1]); console.log(r.src[0].type, r.src[1].type); @@ -1204,7 +1280,16 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co } } else if (r.dest.dim == 3) { - assert(0); + counters_sub[2] += 1; + if(r.src[0].type === "tmp" && r.src[1].type === "tmp") { + assert(r.src[0].dim == 3 && r.src[1].dim == 3); + counters_ops[97] += 1; + ops.push(97); + opsString += "97, "; + } else { + console.log(r.src[0], r.src[1]); + throw new Error("Option not considered!"); + } } else { throw new Error("Invalid dim"); } @@ -1239,6 +1324,13 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[1]); pushSrcArg(r.src[0]); + } else if ((r.src[0].type == 'tmp') && (r.src[1].type == 'tmpExp' && !r.src[1].prime)) { + counters_ops[95] += 1; + ops.push(95); + opsString += "95, "; + pushResArg(r); + pushSrcArg(r.src[1]); + pushSrcArg(r.src[0]); } else if ((r.src[0].type == 'tmp') && (r.src[1].type == 'const' && !r.src[1].prime)) { counters_ops[96] += 1; @@ -1247,6 +1339,21 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); + } else if ((r.src[0].type == 'tmpExp' && !r.src[0].prime) && (r.src[1].type == 'const' && !r.src[1].prime)) { + counters_ops[99] += 1; + ops.push(99); + opsString += "99, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); + } else if ((r.src[0].type == 'cm' && !r.src[0].prime) && (r.src[1].type == 'const' && !r.src[1].prime)) { + counters_ops[99] += 1; + ops.push(99); + opsString += "99, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); + } else if ((r.src[0].type == 'const' && !r.src[0].prime) && (r.src[1].type == 'tmp')) { counters_ops[96] += 1; @@ -1278,7 +1385,13 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[0]); pushSrcArg(r.src[1]); - + } else if ((r.src[0].type == 'cm' && !r.src[0].prime) && (r.src[1].type == 'tmp')) { + counters_ops[120] += 1; + ops.push(120); + opsString += "120, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); } else { console.log(src[0], src[1]); console.log(r.src[0].type, r.src[1].type); @@ -1306,6 +1419,14 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co counters_ops[100] += 1; ops.push(100); opsString += "100, "; + } else if (r.dest.type == 'tmpExp' && !r.dest.prime && r.src[0].type == 'cm' && !r.src[0].prime) { + counters_ops[117] += 1; + ops.push(117); + opsString += "117, "; + } else if (r.dest.type == 'tmpExp' && !r.dest.prime && r.src[0].type == 'const' && !r.src[0].prime) { + counters_ops[91] += 1; + ops.push(91); + opsString += "91, "; } else { console.log(r.dest.type, r.src[0].type); throw new Error("Option not considered!"); @@ -1588,6 +1709,13 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co pushResArg(r); pushSrcArg(r.src[1]); pushSrcArg(r.src[0]); + } else if ((r.src[0].type == 'cm' && r.src[0].prime) && (r.src[1].type == 'const' && r.src[1].prime)) { + counters_ops[119] += 1; + ops.push(119); + opsString += "119, "; + pushResArg(r); + pushSrcArg(r.src[0]); + pushSrcArg(r.src[1]); } else { console.log(src[0], src[1]); console.log(r.src[0].type, r.src[1].type); @@ -2310,4 +2438,4 @@ module.exports = function compileCode_parser(starkInfo, config, functionName, co } -} \ No newline at end of file +} diff --git a/src/stark/stark_buildConstTree.js b/src/stark/stark_buildConstTree.js new file mode 100644 index 00000000..96876618 --- /dev/null +++ b/src/stark/stark_buildConstTree.js @@ -0,0 +1,42 @@ +const { BigBuffer } = require("pilcom"); +const buildMerkleHashGL = require("../helpers/hash/merklehash/merklehash_p.js"); +const buildMerkleHashBN128 = require("../helpers/hash/merklehash/merklehash_bn128_p.js"); +const {interpolate} = require("../helpers/fft/fft_p"); + +module.exports.buildConstTree = async function buildConstTree(starkStruct, pil, constPols) { + const nBits = starkStruct.nBits; + const nBitsExt = starkStruct.nBitsExt; + const extN = 1 << nBitsExt; + + const constBuff = constPols.writeToBuff(); + + const constPolsArrayE = new BigBuffer(extN*pil.nConstants); + + await interpolate(constBuff, pil.nConstants, nBits, constPolsArrayE, nBitsExt ); + + let MH; + if (starkStruct.verificationHashType == "GL") { + MH = await buildMerkleHashGL(starkStruct.splitLinearHash); + } else if (starkStruct.verificationHashType == "BN128") { + MH = await buildMerkleHashBN128(); + } else { + throw new Error("Invalid Hash Type: "+ starkStruct.verificationHashType); + } + + + console.log("Start merkelizing.."); + const constTree = await MH.merkelize(constPolsArrayE, pil.nConstants, extN); + + const constRoot = MH.root(constTree); + + const verKey = { + constRoot: constRoot + }; + + return { + MH, + constTree, + verKey, + } + +} \ No newline at end of file diff --git a/src/stark/stark_info.js b/src/stark/stark_info.js index e435fee0..c45e828a 100644 --- a/src/stark/stark_info.js +++ b/src/stark/stark_info.js @@ -74,6 +74,16 @@ module.exports = function starkInfoGen(_pil, starkStruct) { res.publics = pil.publics; + console.log("--------------------- POLINOMIALS INFO ---------------------") + console.log(`Columns stage 1: ${res.nCm1} -> Columns in the basefield: ${res.mapSectionsN.cm1_2ns}`); + console.log(`Columns stage 2: ${res.nCm2} -> Columns in the basefield: ${res.mapSectionsN.cm2_2ns}`); + console.log(`Columns stage 3: ${res.nCm3} (${res.nImPols} intermediate polinomials) -> Columns in the basefield: ${res.mapSectionsN.cm3_2ns}`); + console.log(`Columns stage 4: ${res.nCm4} -> Columns in the basefield: ${res.mapSectionsN.cm4_2ns}`); + console.log(`Total Columns: ${res.nCm1 + res.nCm2 + res.nCm3 + res.nCm4} -> Total Columns in the basefield: ${res.mapSectionsN.cm1_2ns + res.mapSectionsN.cm2_2ns + res.mapSectionsN.cm3_2ns + res.mapSectionsN.cm4_2ns}`); + console.log(`Total Constraints: ${res.nConstraints}`) + console.log(`Number of evaluations: ${res.evMap.length}`) + console.log("------------------------------------------------------------") + return res; } diff --git a/test/stark/all_gl_verifier.circuit.test.js b/test/stark/all_gl_verifier.circuit.test.js index df61c351..49bb230f 100644 --- a/test/stark/all_gl_verifier.circuit.test.js +++ b/test/stark/all_gl_verifier.circuit.test.js @@ -42,7 +42,7 @@ describe("Stark Verification Circuit Test", function () { const publics = JSONbig.parse(await fs.promises.readFile(publicsFile, "utf8")); const starkInfo = starkInfoGen(pil, starkStruct); - const circuitSrc = await pil2circom(pil, constRoot, starkInfo) + const circuitSrc = await pil2circom(constRoot, starkInfo) await fs.promises.writeFile(circomFile, circuitSrc, "utf8"); diff --git a/test/stark/all_gl_verifier_gpu.circuit.test.js b/test/stark/all_gl_verifier_gpu.circuit.test.js index f10993e0..9e1e9c51 100644 --- a/test/stark/all_gl_verifier_gpu.circuit.test.js +++ b/test/stark/all_gl_verifier_gpu.circuit.test.js @@ -42,7 +42,7 @@ describe("Stark Verification Circuit Test", function () { const publics = JSONbig.parse(await fs.promises.readFile(publicsFile, "utf8")); const starkInfo = starkInfoGen(pil, starkStruct); - const circuitSrc = await pil2circom(pil, constRoot, starkInfo) + const circuitSrc = await pil2circom(constRoot, starkInfo) await fs.promises.writeFile(circomFile, circuitSrc, "utf8"); diff --git a/test/stark/fibonacci_gl_verifier.circuit.test.js b/test/stark/fibonacci_gl_verifier.circuit.test.js index d689d6b5..882016c0 100644 --- a/test/stark/fibonacci_gl_verifier.circuit.test.js +++ b/test/stark/fibonacci_gl_verifier.circuit.test.js @@ -41,7 +41,7 @@ describe("Stark Verification Circuit Test", function () { const publics = JSONbig.parse(await fs.promises.readFile(publicsFile, "utf8")); const starkInfo = starkInfoGen(pil, starkStruct); - const circuitSrc = await pil2circom(pil, constRoot, starkInfo); + const circuitSrc = await pil2circom(constRoot, starkInfo); await fs.promises.writeFile(circomFile, circuitSrc, "utf8"); diff --git a/test/stark/fibonacci_gl_verifier_gpu.circuit.test.js b/test/stark/fibonacci_gl_verifier_gpu.circuit.test.js index 707ca198..761d28f6 100644 --- a/test/stark/fibonacci_gl_verifier_gpu.circuit.test.js +++ b/test/stark/fibonacci_gl_verifier_gpu.circuit.test.js @@ -41,7 +41,7 @@ describe("Stark Verification Circuit Test", function () { const publics = JSONbig.parse(await fs.promises.readFile(publicsFile, "utf8")); const starkInfo = starkInfoGen(pil, starkStruct); - const circuitSrc = await pil2circom(pil, constRoot, starkInfo); + const circuitSrc = await pil2circom(constRoot, starkInfo); await fs.promises.writeFile(circomFile, circuitSrc, "utf8");