From 6a712b7619429400b08947f1c5fb0acb4214501e Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Sat, 9 Nov 2024 10:27:56 +0200 Subject: [PATCH 1/3] Added context of the resolved circuit to the cache --- package-lock.json | 4 +-- package.json | 2 +- src/cache/BaseCache.ts | 25 ++++++++++--------- .../mock-circuits/newMul2.circom | 5 ++++ test/integration/tasks.test.ts | 1 + .../unit/cache/circuits-compile-cache.test.ts | 19 +++++++++++++- 6 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 test/fixture-projects/hardhat-project-with-circuits/mock-circuits/newMul2.circom diff --git a/package-lock.json b/package-lock.json index 2a0d0ad..36b3d27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@solarity/hardhat-zkit", - "version": "0.4.13", + "version": "0.4.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@solarity/hardhat-zkit", - "version": "0.4.13", + "version": "0.4.14", "license": "MIT", "workspaces": [ "test/fixture-projects/*" diff --git a/package.json b/package.json index e78a9cf..a5d5350 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@solarity/hardhat-zkit", - "version": "0.4.13", + "version": "0.4.14", "description": "The ultimate TypeScript environment for Circom development", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/src/cache/BaseCache.ts b/src/cache/BaseCache.ts index f064c42..8d17bba 100644 --- a/src/cache/BaseCache.ts +++ b/src/cache/BaseCache.ts @@ -113,21 +113,22 @@ export class BaseCache { * @param cacheFilePath The full path to the cache file where the state will be written. */ public async writeToFile(cacheFilePath: string) { - const jsonContent = JSON.stringify( - this._cache, - (key, value) => { - if (key === "context") { - return; - } + const seen = new WeakSet(); + + const jsonContent = JSON.stringify(this._cache, (key, value) => { + if (typeof value === "bigint") { + return { __bigintval__: value.toString() }; + } - if (typeof value === "bigint") { - return { __bigintval__: value.toString() }; + if (typeof value === "object" && value !== null) { + if (seen.has(value)) { + return "[Circular]"; } + seen.add(value); + } - return value; - }, - 2, - ); + return value; + }); await fsExtra.outputFile(cacheFilePath, jsonContent); } diff --git a/test/fixture-projects/hardhat-project-with-circuits/mock-circuits/newMul2.circom b/test/fixture-projects/hardhat-project-with-circuits/mock-circuits/newMul2.circom new file mode 100644 index 0000000..0d36477 --- /dev/null +++ b/test/fixture-projects/hardhat-project-with-circuits/mock-circuits/newMul2.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "base/mul2Base.circom"; + +component main = Multiplier2(); diff --git a/test/integration/tasks.test.ts b/test/integration/tasks.test.ts index 50b1bb2..7e61f9d 100644 --- a/test/integration/tasks.test.ts +++ b/test/integration/tasks.test.ts @@ -376,6 +376,7 @@ describe("ZKit tasks", async function () { expect(fsExtra.readdirSync(this.hre.config.paths.root)).to.be.deep.eq([ ".gitignore", "circuits", + "mock-circuits", "contracts", "generated-types", "hardhat.config.ts", diff --git a/test/unit/cache/circuits-compile-cache.test.ts b/test/unit/cache/circuits-compile-cache.test.ts index c299241..cd6d8f5 100644 --- a/test/unit/cache/circuits-compile-cache.test.ts +++ b/test/unit/cache/circuits-compile-cache.test.ts @@ -9,7 +9,7 @@ import { getNormalizedFullPath } from "@src/utils/path-utils"; import { defaultCompileFlags } from "../../constants"; import { CompileCacheEntry } from "@src/types/cache"; -import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "@src/task-names"; +import { TASK_CIRCUITS_COMPILE, TASK_CIRCUITS_MAKE, ZKIT_SCOPE_NAME } from "@src/task-names"; import { CIRCUITS_COMPILE_CACHE_FILENAME, CIRCUIT_COMPILE_CACHE_VERSION } from "@src/constants"; import { CircuitsCompileCache, createCircuitsCompileCache, resetCircuitsCompileCache } from "@src/cache"; @@ -107,4 +107,21 @@ describe("CircuitsCompileCache", () => { fsExtra.rmSync(typesDir, { recursive: true, force: true }); }); }); + + describe("context-caching", () => { + useEnvironment("with-circuits", true); + + it("should correctly cache the context", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE }); + + const mockCircuitSourcePath = getNormalizedFullPath(this.hre.config.paths.root, "mock-circuits/newMul2.circom"); + const mockCircuitDestinationPath = getNormalizedFullPath(this.hre.config.paths.root, "circuits/newMul2.circom"); + + fsExtra.copyFileSync(mockCircuitSourcePath, mockCircuitDestinationPath); + + await expect(this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE })).to.be.fulfilled; + + fsExtra.rmSync(mockCircuitDestinationPath); + }); + }); }); From a949a3726e6623aa8bcb16b65891c7efca00779d Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Sat, 9 Nov 2024 10:30:33 +0200 Subject: [PATCH 2/3] Fixed typo in test --- test/integration/tasks.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/tasks.test.ts b/test/integration/tasks.test.ts index 7e61f9d..cfce2e1 100644 --- a/test/integration/tasks.test.ts +++ b/test/integration/tasks.test.ts @@ -376,10 +376,10 @@ describe("ZKit tasks", async function () { expect(fsExtra.readdirSync(this.hre.config.paths.root)).to.be.deep.eq([ ".gitignore", "circuits", - "mock-circuits", "contracts", "generated-types", "hardhat.config.ts", + "mock-circuits", "package.json", ]); From f12c28c14099a4386f3d60828d64a8269912c501 Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Sat, 9 Nov 2024 11:15:26 +0200 Subject: [PATCH 3/3] Reverted changes. Reverted context caching. Cached parsing result --- src/cache/BaseCache.ts | 25 +++++++++---------- src/cache/schemas/compile-schemas.ts | 1 + src/core/dependencies/CircomFilesResolver.ts | 15 +++++------ .../parser/circom-files-visitor.ts | 1 + 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/cache/BaseCache.ts b/src/cache/BaseCache.ts index 8d17bba..f064c42 100644 --- a/src/cache/BaseCache.ts +++ b/src/cache/BaseCache.ts @@ -113,22 +113,21 @@ export class BaseCache { * @param cacheFilePath The full path to the cache file where the state will be written. */ public async writeToFile(cacheFilePath: string) { - const seen = new WeakSet(); - - const jsonContent = JSON.stringify(this._cache, (key, value) => { - if (typeof value === "bigint") { - return { __bigintval__: value.toString() }; - } + const jsonContent = JSON.stringify( + this._cache, + (key, value) => { + if (key === "context") { + return; + } - if (typeof value === "object" && value !== null) { - if (seen.has(value)) { - return "[Circular]"; + if (typeof value === "bigint") { + return { __bigintval__: value.toString() }; } - seen.add(value); - } - return value; - }); + return value; + }, + 2, + ); await fsExtra.outputFile(cacheFilePath, jsonContent); } diff --git a/src/cache/schemas/compile-schemas.ts b/src/cache/schemas/compile-schemas.ts index a14e4cf..762ff75 100644 --- a/src/cache/schemas/compile-schemas.ts +++ b/src/cache/schemas/compile-schemas.ts @@ -28,6 +28,7 @@ export const TemplateSchema = z.object({ parameters: z.string().array(), isCustom: z.boolean(), parallel: z.boolean(), + parsedInputs: z.record(z.string(), InputDataSchema).optional(), }); export const TemplatesSchema = z.record(z.string(), TemplateSchema); diff --git a/src/core/dependencies/CircomFilesResolver.ts b/src/core/dependencies/CircomFilesResolver.ts index d0d0b28..d021ebc 100644 --- a/src/core/dependencies/CircomFilesResolver.ts +++ b/src/core/dependencies/CircomFilesResolver.ts @@ -13,7 +13,7 @@ import { validateSourceNameFormat, } from "hardhat/utils/source-names"; -import { HardhatError, assertHardhatInvariant } from "hardhat/internal/core/errors"; +import { assertHardhatInvariant, HardhatError } from "hardhat/internal/core/errors"; import { ERRORS } from "hardhat/internal/core/errors-list"; import { getRealPath } from "hardhat/internal/util/fs-utils"; import { createNonCryptographicHashBasedIdentifier } from "hardhat/internal/util/hash"; @@ -24,8 +24,8 @@ import { HardhatZKitError } from "../../errors"; import { CircomResolvedFile as ICircomResolvedFile, - ResolvedMainComponentData, ResolvedFileData, + ResolvedMainComponentData, SignalType, VisibilityType, } from "../../types/core"; @@ -249,11 +249,12 @@ export class CircomFilesResolver { }, ); - const parsedInputs = this._parser.parseTemplateInputs( - fileWithTemplate, - templateName, - mainComponentData.parameters, - ); + if (!fileWithTemplate.fileData.parsedFileData.templates[templateName].parsedInputs) { + fileWithTemplate.fileData.parsedFileData.templates[templateName].parsedInputs = + this._parser.parseTemplateInputs(fileWithTemplate, templateName, mainComponentData.parameters); + } + + const parsedInputs = fileWithTemplate.fileData.parsedFileData.templates[templateName].parsedInputs!; for (const key of Object.keys(parsedInputs)) { const signalType: SignalType = this._getSignalType(parsedInputs[key].type); diff --git a/src/types/core/dependencies/parser/circom-files-visitor.ts b/src/types/core/dependencies/parser/circom-files-visitor.ts index aed9dfd..af02521 100644 --- a/src/types/core/dependencies/parser/circom-files-visitor.ts +++ b/src/types/core/dependencies/parser/circom-files-visitor.ts @@ -59,6 +59,7 @@ export type Template = { isCustom: boolean; parallel: boolean; context: TemplateDefinitionContext; + parsedInputs?: Record; }; export type Templates = {