From 2a9243c89e7fc62f29e52f7c5b9ac0b71b52065e Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Mon, 23 Dec 2024 15:42:21 +0200 Subject: [PATCH] Fixed issue with caching parsedInputs --- src/core/dependencies/CircomFilesResolver.ts | 19 ++++-- src/core/dependencies/utils.ts | 16 +++++ .../.gitignore | 6 ++ .../circuits/mul3Arr.circom | 5 ++ .../circuits/mul3Arr2.circom | 5 ++ .../circuits/templates/mul3Arr.circom | 12 ++++ .../hardhat.config.ts | 24 ++++++++ .../package.json | 8 +++ .../core/compile/types-generation.test.ts | 59 +++++++++++++++++++ 9 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 src/core/dependencies/utils.ts create mode 100644 test/fixture-projects/hardhat-project-with-duplicated-circuits/.gitignore create mode 100644 test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr.circom create mode 100644 test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr2.circom create mode 100644 test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/templates/mul3Arr.circom create mode 100644 test/fixture-projects/hardhat-project-with-duplicated-circuits/hardhat.config.ts create mode 100644 test/fixture-projects/hardhat-project-with-duplicated-circuits/package.json create mode 100644 test/unit/core/compile/types-generation.test.ts diff --git a/src/core/dependencies/CircomFilesResolver.ts b/src/core/dependencies/CircomFilesResolver.ts index 8ebe015..2508796 100644 --- a/src/core/dependencies/CircomFilesResolver.ts +++ b/src/core/dependencies/CircomFilesResolver.ts @@ -21,7 +21,7 @@ import { CircomFilesParser } from "./parser/CircomFilesParser"; import { CIRCOM_FILE_REG_EXP, NODE_MODULES, NODE_MODULES_REG_EXP, URI_SCHEME_REG_EXP } from "../../constants"; import { getFileHash } from "../../utils"; import { HardhatZKitError } from "../../errors"; - +import { deepClone } from "../../core/dependencies/utils"; import { CircomResolvedFile as ICircomResolvedFile, ResolvedFileData, @@ -249,12 +249,21 @@ export class CircomFilesResolver { }, ); - if (!fileWithTemplate.fileData.parsedFileData.templates[templateName].parsedInputs) { - fileWithTemplate.fileData.parsedFileData.templates[templateName].parsedInputs = - this._parser.parseTemplateInputs(fileWithTemplate, templateName, mainComponentData.parameters); + if (!resolvedFile.fileData.parsedFileData.templates[templateName]) { + resolvedFile.fileData.parsedFileData.templates[templateName] = deepClone( + fileWithTemplate.fileData.parsedFileData.templates[templateName], + ); + } + + if (!resolvedFile.fileData.parsedFileData.templates[templateName].parsedInputs) { + resolvedFile.fileData.parsedFileData.templates[templateName].parsedInputs = this._parser.parseTemplateInputs( + fileWithTemplate, + templateName, + mainComponentData.parameters, + ); } - const parsedInputs = fileWithTemplate.fileData.parsedFileData.templates[templateName].parsedInputs!; + const parsedInputs = resolvedFile.fileData.parsedFileData.templates[templateName].parsedInputs!; for (const key of Object.keys(parsedInputs)) { const signalType: SignalType = this._getSignalType(parsedInputs[key].type); diff --git a/src/core/dependencies/utils.ts b/src/core/dependencies/utils.ts new file mode 100644 index 0000000..899b85c --- /dev/null +++ b/src/core/dependencies/utils.ts @@ -0,0 +1,16 @@ +export function deepClone(value: T): T { + const visited = new WeakSet(); + + const replacer = (_: any, obj: any) => { + if (typeof obj === "object" && obj !== null) { + if (visited.has(obj)) { + return "[Circular]"; + } + visited.add(obj); + } + + return obj; + }; + + return JSON.parse(JSON.stringify(value, replacer)); +} diff --git a/test/fixture-projects/hardhat-project-with-duplicated-circuits/.gitignore b/test/fixture-projects/hardhat-project-with-duplicated-circuits/.gitignore new file mode 100644 index 0000000..aca0c00 --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-duplicated-circuits/.gitignore @@ -0,0 +1,6 @@ +/cache +/artifacts + +compilers +contracts/verifiers +zkit diff --git a/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr.circom b/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr.circom new file mode 100644 index 0000000..9bf731c --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "templates/mul3Arr.circom"; + +component main = Multiplier3Arr(3); diff --git a/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr2.circom b/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr2.circom new file mode 100644 index 0000000..141e342 --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/mul3Arr2.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "templates/mul3Arr.circom"; + +component main = Multiplier3Arr(6); diff --git a/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/templates/mul3Arr.circom b/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/templates/mul3Arr.circom new file mode 100644 index 0000000..1bcf4fd --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-duplicated-circuits/circuits/templates/mul3Arr.circom @@ -0,0 +1,12 @@ +pragma circom 2.0.0; + +template Multiplier3Arr(count){ + signal input in[count]; + + signal output out; + signal output result[count]; + + signal tmp <-- in[0] * in[1]; + + out <== tmp * in[2]; +} diff --git a/test/fixture-projects/hardhat-project-with-duplicated-circuits/hardhat.config.ts b/test/fixture-projects/hardhat-project-with-duplicated-circuits/hardhat.config.ts new file mode 100644 index 0000000..b15dfa9 --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-duplicated-circuits/hardhat.config.ts @@ -0,0 +1,24 @@ +import { HardhatUserConfig } from "hardhat/config"; + +import config from "../hardhat.config"; + +const defaultConfig: HardhatUserConfig = { + ...config, + zkit: { + circuitsDir: "circuits", + compilationSettings: { + artifactsDir: "zkit/artifacts", + skipFiles: ["vendor"], + }, + setupSettings: { + ptauDir: "zkit/ptau", + ptauDownload: true, + }, + quiet: true, + verifiersSettings: { + verifiersDir: "contracts/verifiers", + }, + }, +}; + +export default defaultConfig; diff --git a/test/fixture-projects/hardhat-project-with-duplicated-circuits/package.json b/test/fixture-projects/hardhat-project-with-duplicated-circuits/package.json new file mode 100644 index 0000000..0be3848 --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-duplicated-circuits/package.json @@ -0,0 +1,8 @@ +{ + "name": "hardhat-project-with-complex-circuits", + "version": "1.0.0", + "scripts": { + "compile": "hardhat compile --force", + "clean": "hardhat clean && rm -rf artifacts && rm -rf cache" + } +} diff --git a/test/unit/core/compile/types-generation.test.ts b/test/unit/core/compile/types-generation.test.ts new file mode 100644 index 0000000..b17ec52 --- /dev/null +++ b/test/unit/core/compile/types-generation.test.ts @@ -0,0 +1,59 @@ +import { useEnvironment } from "@test-helpers"; +import { TASK_CIRCUITS_MAKE, ZKIT_SCOPE_NAME } from "../../../../src/task-names"; +import fsExtra from "fs-extra"; +import path from "path"; +import { CircuitArtifact } from "../../../../src/types/artifacts/circuit-artifacts"; +import { expect } from "chai"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +describe.only("Types Generation", () => { + describe("types generation:with duplicated main components", () => { + useEnvironment("with-duplicated-circuits"); + + beforeEach(async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE }); + }); + + function getCircuitArtifact(hre: HardhatRuntimeEnvironment, pathToCircuit: string): CircuitArtifact { + return JSON.parse(fsExtra.readFileSync(path.join(hre.config.paths.root, pathToCircuit)) as any); + } + + it("should correctly resolve dimensions for circuits with multiple main components", async function () { + const artifact1: CircuitArtifact = getCircuitArtifact( + this.hre, + "zkit/artifacts/circuits/mul3Arr.circom/Multiplier3Arr_artifacts.json", + ); + const artifact2: CircuitArtifact = getCircuitArtifact( + this.hre, + "zkit/artifacts/circuits/mul3Arr2.circom/Multiplier3Arr_artifacts.json", + ); + + expect(artifact1.baseCircuitInfo.signals[0].dimension).to.be.deep.eq([3]); + expect(artifact2.baseCircuitInfo.signals[0].dimension).to.be.deep.eq([6]); + }); + + it.only("should correctly resolve dimensions for circuits with multiple main components from cache", async function () { + const initialFileContent = fsExtra + .readFileSync(path.join(this.hre.config.paths.root, "circuits/mul3Arr.circom")) + .toString(); + + fsExtra.appendFileSync(path.join(this.hre.config.paths.root, "circuits/mul3Arr.circom"), "// comment"); + + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE }); + + const artifact2: CircuitArtifact = getCircuitArtifact( + this.hre, + "zkit/artifacts/circuits/mul3Arr2.circom/Multiplier3Arr_artifacts.json", + ); + const artifact1: CircuitArtifact = getCircuitArtifact( + this.hre, + "zkit/artifacts/circuits/mul3Arr.circom/Multiplier3Arr_artifacts.json", + ); + + expect(artifact1.baseCircuitInfo.signals[0].dimension).to.be.deep.eq([3]); + expect(artifact2.baseCircuitInfo.signals[0].dimension).to.be.deep.eq([6]); + + fsExtra.writeFileSync(path.join(this.hre.config.paths.root, "circuits/mul3Arr.circom"), initialFileContent); + }); + }); +});