From b8545bf6e5e14c86c5c259ce8d4994798f1e87c4 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Tue, 29 Oct 2024 15:53:38 +0200 Subject: [PATCH 01/13] Add base plonk implementation --- package-lock.json | 824 +++++++++++-------- package.json | 6 +- src/artifacts/CircuitArtifacts.ts | 57 +- src/cache/CircuitsSetupCache.ts | 37 +- src/cache/schemas/setup-schemas.ts | 10 +- src/config/config.ts | 2 +- src/constants.ts | 5 + src/core/compile/CompilationProcessor.ts | 25 +- src/core/compiler/index.ts | 3 + src/core/setup/SetupFilesResolver.ts | 72 +- src/core/setup/SetupProcessor.ts | 179 ++-- src/index.ts | 124 ++- src/reporter/ReporterFacade.ts | 5 +- src/reporter/reporters/SetupReporter.ts | 29 +- src/types/artifacts/circuit-artifacts.ts | 16 +- src/types/cache/circuits-setup-cache.ts | 11 +- src/types/core/setup/setup-files-resolver.ts | 3 + src/types/core/setup/setup-processor.ts | 6 +- src/types/hardhat-zkit.ts | 8 +- src/types/tasks.ts | 4 +- src/types/zkit-config.ts | 9 +- src/utils/index.ts | 2 + src/utils/utils.ts | 10 + test/constants.ts | 8 +- test/integration/setup/config.ts | 4 +- test/integration/tasks.test.ts | 10 +- test/unit/cache/circuits-setup-cache.test.ts | 18 +- test/utils.ts | 20 +- 28 files changed, 965 insertions(+), 542 deletions(-) create mode 100644 src/utils/index.ts diff --git a/package-lock.json b/package-lock.json index c59d7d2..f14ed81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,8 @@ "dependencies": { "@distributedlab/circom-parser": "0.1.2", "@distributedlab/circom2": "0.2.18-rc.4", - "@solarity/zkit": "0.2.6", - "@solarity/zktype": "0.3.1", + "@solarity/zkit": "0.3.0-rc.1", + "@solarity/zktype": "0.4.0-rc.0", "chalk": "4.1.2", "cli-progress": "3.12.0", "cli-table3": "0.6.5", @@ -24,7 +24,7 @@ "ora": "5.4.1", "resolve": "1.22.8", "semver": "7.6.3", - "snarkjs": "0.7.3", + "snarkjs": "0.7.5", "uuid": "9.0.1", "zod": "3.23.8" }, @@ -90,12 +90,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", + "integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", "dev": true, "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -103,30 +104,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", + "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -157,29 +158,30 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", + "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", "dev": true, "dependencies": { - "@babel/types": "^7.25.6", + "@babel/parser": "^7.26.0", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -212,28 +214,27 @@ "dev": true }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -242,152 +243,53 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.26.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", + "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", "dev": true, "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -397,30 +299,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -438,14 +340,13 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -511,24 +412,27 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -580,9 +484,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -990,13 +894,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -1052,12 +956,12 @@ "integrity": "sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==" }, "node_modules/@iden3/binfileutils": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.11.tgz", - "integrity": "sha512-LylnJoZ0CTdgErnKY8OxohvW4K+p6UHD3sxt+3P9AmMyBQjYR4IpoqoYZZ+9aMj89cmCQ21UvdhndAx04er3NA==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.12.tgz", + "integrity": "sha512-naAmzuDufRIcoNfQ1d99d7hGHufLA3wZSibtr4dMe6ZeiOPV1KwOZWTJ1YVz4HbaWlpDuzVU72dS4ATQS4PXBQ==", "dependencies": { "fastfile": "0.0.20", - "ffjavascript": "^0.2.48" + "ffjavascript": "^0.3.0" } }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1878,9 +1782,9 @@ "dev": true }, "node_modules/@scure/base": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.8.tgz", - "integrity": "sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", "dev": true, "funding": { "url": "https://paulmillr.com/funding/" @@ -2100,9 +2004,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", - "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.1" @@ -2152,44 +2056,76 @@ } }, "node_modules/@solarity/hardhat-zkit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@solarity/hardhat-zkit/-/hardhat-zkit-0.4.1.tgz", - "integrity": "sha512-dA2jJtnM1m01v1EKQJFCf0Fr8OB59Ep/8CpW3ZJYOudQZWiVo+qgfWao7Y4P9cH2qPC3XJmQlIggkOvOMESjfw==", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@solarity/hardhat-zkit/-/hardhat-zkit-0.4.9.tgz", + "integrity": "sha512-+NnY6jBA/skFu3+KT6bJoK4HNuX97Oc86HvHXNjl1PtyBoMxxs81ZUMVKWPZPdgsKJvtPVybKaQ99fXPThAmaw==", "dev": true, "peer": true, "dependencies": { - "@distributedlab/circom-parser": "0.1.2", - "@distributedlab/circom2": "0.2.18-rc.4", + "@distributedlab/circom-parser": "0.1.5", "@solarity/zkit": "0.2.6", "@solarity/zktype": "0.3.1", + "@wasmer/wasi": "0.12.0", "chalk": "4.1.2", "cli-progress": "3.12.0", "cli-table3": "0.6.5", "debug": "4.3.5", + "is-typed-array": "1.1.13", "lodash": "4.17.21", "ora": "5.4.1", + "path-browserify": "1.0.1", "resolve": "1.22.8", + "semver": "7.6.3", "snarkjs": "0.7.3", "uuid": "9.0.1", "zod": "3.23.8" }, + "engines": { + "node": ">=16" + }, "peerDependencies": { "hardhat": "^2.16.0" } }, - "node_modules/@solarity/zkit": { + "node_modules/@solarity/hardhat-zkit/node_modules/@distributedlab/circom-parser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@distributedlab/circom-parser/-/circom-parser-0.1.5.tgz", + "integrity": "sha512-+IFqzYhIXQ1jnksBjuTXrzkF8PIGn/WMc+kJM0JyhVwLJrxPoE23+4rZFIgq3q3RWXRO94KIS49cyk+UnCRzWA==", + "dev": true, + "peer": true, + "dependencies": { + "antlr4": "4.13.1-patch-1", + "ejs": "3.1.10" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/@iden3/binfileutils": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.11.tgz", + "integrity": "sha512-LylnJoZ0CTdgErnKY8OxohvW4K+p6UHD3sxt+3P9AmMyBQjYR4IpoqoYZZ+9aMj89cmCQ21UvdhndAx04er3NA==", + "dev": true, + "peer": true, + "dependencies": { + "fastfile": "0.0.20", + "ffjavascript": "^0.2.48" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/@solarity/zkit": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@solarity/zkit/-/zkit-0.2.6.tgz", "integrity": "sha512-qUorYE4L5SoBZl7kTaCnuJ2hKPsEGJZurYoHMRIuUl8T6xXNP5gcJQ4PsFfLB/eLRFYa7fVPGbeT0D3RJTIUYQ==", + "dev": true, + "peer": true, "dependencies": { "ejs": "3.1.10", "snarkjs": "0.7.3" } }, - "node_modules/@solarity/zktype": { + "node_modules/@solarity/hardhat-zkit/node_modules/@solarity/zktype": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@solarity/zktype/-/zktype-0.3.1.tgz", "integrity": "sha512-MPpnqE6dg1gobaLYdIV1IYzxiGxeQDfNnewDcnPr9nhDxIOGb8T+YMXI5JhRITRMQJHwjdfX/feyQIgjiGab1Q==", + "dev": true, + "peer": true, "dependencies": { "ejs": "3.1.10", "prettier": "3.3.3", @@ -2202,6 +2138,210 @@ "@solarity/zkit": "^0.2.4" } }, + "node_modules/@solarity/hardhat-zkit/node_modules/circom_runtime": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.24.tgz", + "integrity": "sha512-H7/7I2J/cBmRnZm9docOCGhfxzS61BEm4TMCWcrZGsWNBQhePNfQq88Oj2XpUfzmBTCd8pRvRb3Mvazt3TMrJw==", + "dev": true, + "peer": true, + "dependencies": { + "ffjavascript": "0.2.60" + }, + "bin": { + "calcwit": "calcwit.js" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/circom_runtime/node_modules/ffjavascript": { + "version": "0.2.60", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", + "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", + "dev": true, + "peer": true, + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "^1.2.0" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/ffjavascript": { + "version": "0.2.63", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", + "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", + "dev": true, + "peer": true, + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "1.2.0" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/r1csfile": { + "version": "0.0.47", + "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.47.tgz", + "integrity": "sha512-oI4mAwuh1WwuFg95eJDNDDL8hCaZkwnPuNZrQdLBWvDoRU7EG+L/MOHL7SwPW2Y+ZuYcTLpj3rBkgllBQZN/JA==", + "dev": true, + "peer": true, + "dependencies": { + "@iden3/bigarray": "0.0.2", + "@iden3/binfileutils": "0.0.11", + "fastfile": "0.0.20", + "ffjavascript": "0.2.60" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/r1csfile/node_modules/ffjavascript": { + "version": "0.2.60", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", + "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", + "dev": true, + "peer": true, + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "^1.2.0" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/snarkjs": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.3.tgz", + "integrity": "sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==", + "dev": true, + "peer": true, + "dependencies": { + "@iden3/binfileutils": "0.0.11", + "bfj": "^7.0.2", + "blake2b-wasm": "^2.4.0", + "circom_runtime": "0.1.24", + "ejs": "^3.1.6", + "fastfile": "0.0.20", + "ffjavascript": "0.2.63", + "js-sha3": "^0.8.0", + "logplease": "^1.2.15", + "r1csfile": "0.0.47" + }, + "bin": { + "snarkjs": "build/cli.cjs" + } + }, + "node_modules/@solarity/hardhat-zkit/node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@solarity/zkit": { + "version": "0.3.0-rc.1", + "resolved": "https://registry.npmjs.org/@solarity/zkit/-/zkit-0.3.0-rc.1.tgz", + "integrity": "sha512-Gd+uBHHPCqFxBgi0Pog2Iyz90QbyEwhIdhVWZ67oGoLq4aCzGwRDeGZWOclF/1YwIFaPlcg1WTm/GrKIv1WLUw==", + "dependencies": { + "ejs": "3.1.10", + "snarkjs": "0.7.3" + } + }, + "node_modules/@solarity/zkit/node_modules/@iden3/binfileutils": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.11.tgz", + "integrity": "sha512-LylnJoZ0CTdgErnKY8OxohvW4K+p6UHD3sxt+3P9AmMyBQjYR4IpoqoYZZ+9aMj89cmCQ21UvdhndAx04er3NA==", + "dependencies": { + "fastfile": "0.0.20", + "ffjavascript": "^0.2.48" + } + }, + "node_modules/@solarity/zkit/node_modules/circom_runtime": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.24.tgz", + "integrity": "sha512-H7/7I2J/cBmRnZm9docOCGhfxzS61BEm4TMCWcrZGsWNBQhePNfQq88Oj2XpUfzmBTCd8pRvRb3Mvazt3TMrJw==", + "dependencies": { + "ffjavascript": "0.2.60" + }, + "bin": { + "calcwit": "calcwit.js" + } + }, + "node_modules/@solarity/zkit/node_modules/circom_runtime/node_modules/ffjavascript": { + "version": "0.2.60", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", + "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "^1.2.0" + } + }, + "node_modules/@solarity/zkit/node_modules/ffjavascript": { + "version": "0.2.63", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", + "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "1.2.0" + } + }, + "node_modules/@solarity/zkit/node_modules/r1csfile": { + "version": "0.0.47", + "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.47.tgz", + "integrity": "sha512-oI4mAwuh1WwuFg95eJDNDDL8hCaZkwnPuNZrQdLBWvDoRU7EG+L/MOHL7SwPW2Y+ZuYcTLpj3rBkgllBQZN/JA==", + "dependencies": { + "@iden3/bigarray": "0.0.2", + "@iden3/binfileutils": "0.0.11", + "fastfile": "0.0.20", + "ffjavascript": "0.2.60" + } + }, + "node_modules/@solarity/zkit/node_modules/r1csfile/node_modules/ffjavascript": { + "version": "0.2.60", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", + "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "^1.2.0" + } + }, + "node_modules/@solarity/zkit/node_modules/snarkjs": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.3.tgz", + "integrity": "sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==", + "dependencies": { + "@iden3/binfileutils": "0.0.11", + "bfj": "^7.0.2", + "blake2b-wasm": "^2.4.0", + "circom_runtime": "0.1.24", + "ejs": "^3.1.6", + "fastfile": "0.0.20", + "ffjavascript": "0.2.63", + "js-sha3": "^0.8.0", + "logplease": "^1.2.15", + "r1csfile": "0.0.47" + }, + "bin": { + "snarkjs": "build/cli.cjs" + } + }, + "node_modules/@solarity/zktype": { + "version": "0.4.0-rc.0", + "resolved": "https://registry.npmjs.org/@solarity/zktype/-/zktype-0.4.0-rc.0.tgz", + "integrity": "sha512-AdwPV/wN6EOieI0MFCUv/OS/uksuVZLXVTeD+pQSp0Nq9CtUXf417PFTEMW2zG0TjdeVtNegSSiCRBaSQ4DTBA==", + "dependencies": { + "ejs": "3.1.10", + "prettier": "3.3.3", + "typescript": "5.5.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@solarity/zkit": "^0.3.0-rc.0" + } + }, "node_modules/@solarity/zktype/node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -2269,18 +2409,18 @@ } }, "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/chai": { - "version": "4.3.19", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.19.tgz", - "integrity": "sha512-2hHHvQBVE2FiSK4eN0Br6snX9MtolHaTo/batnLjlGRhoQzlCL61iVpxoqO7SfFyOw+P/pwv+0zNHzKoGWz9Cw==", + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", "dev": true }, "node_modules/@types/chai-as-promised": { @@ -2360,9 +2500,9 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", - "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", "dev": true }, "node_modules/@types/ms": { @@ -2372,12 +2512,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "version": "22.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.2.tgz", + "integrity": "sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==", "dev": true, "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/pbkdf2": { @@ -2661,9 +2801,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2682,9 +2822,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "dependencies": { "acorn": "^8.11.0" @@ -3047,9 +3187,9 @@ } }, "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -3244,9 +3384,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -3263,10 +3403,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -3399,9 +3539,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001658", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001658.tgz", - "integrity": "sha512-N2YVqWbJELVdrnsW5p+apoQyYt51aBMSsBZki1XZEfeBCexcM/sf4xiAHcXQBkuOwJBXtWF7aW1sYX6tKebPHw==", + "version": "1.0.30001674", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001674.tgz", + "integrity": "sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw==", "dev": true, "funding": [ { @@ -3539,26 +3679,16 @@ } }, "node_modules/circom_runtime": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.24.tgz", - "integrity": "sha512-H7/7I2J/cBmRnZm9docOCGhfxzS61BEm4TMCWcrZGsWNBQhePNfQq88Oj2XpUfzmBTCd8pRvRb3Mvazt3TMrJw==", + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.28.tgz", + "integrity": "sha512-ACagpQ7zBRLKDl5xRZ4KpmYIcZDUjOiNRuxvXLqhnnlLSVY1Dbvh73TI853nqoR0oEbihtWmMSjgc5f+pXf/jQ==", "dependencies": { - "ffjavascript": "0.2.60" + "ffjavascript": "0.3.1" }, "bin": { "calcwit": "calcwit.js" } }, - "node_modules/circom_runtime/node_modules/ffjavascript": { - "version": "0.2.60", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", - "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "0.2.2", - "web-worker": "^1.2.0" - } - }, "node_modules/circomlib": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/circomlib/-/circomlib-2.0.5.tgz", @@ -4089,9 +4219,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.18", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz", - "integrity": "sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ==", + "version": "1.5.49", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.49.tgz", + "integrity": "sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A==", "dev": true }, "node_modules/elliptic": { @@ -4402,16 +4532,17 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -4512,9 +4643,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", - "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -4538,9 +4669,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "dependencies": { "@rtsao/scc": "^1.1.0", @@ -4551,7 +4682,7 @@ "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", + "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", @@ -4560,13 +4691,14 @@ "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { @@ -5036,9 +5168,9 @@ } }, "node_modules/ffjavascript": { - "version": "0.2.63", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", - "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.1.tgz", + "integrity": "sha512-4PbK1WYodQtuF47D4pRI5KUg3Q392vuP5WjE1THSnceHdXwU3ijaoS0OqxTzLknCtz4Z2TtABzkBdBdMn3B/Aw==", "dependencies": { "wasmbuilder": "0.0.16", "wasmcurves": "0.2.2", @@ -6073,9 +6205,9 @@ } }, "node_modules/husky": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.5.tgz", - "integrity": "sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true, "bin": { "husky": "bin.js" @@ -6774,15 +6906,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -7782,9 +7914,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.1.0.tgz", - "integrity": "sha512-Bqn3vc8CMHty6zuD+tG23s6v2kwxslHEhTj4eYaVKGIEB+YX/2wd0/rgXLFD9G9id9KCtbVy/3ZgmvZjpa0UdQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", "dev": true, "engines": { "node": ">=16" @@ -7825,9 +7957,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "node_modules/picomatch": { @@ -7991,24 +8123,24 @@ ] }, "node_modules/r1csfile": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.47.tgz", - "integrity": "sha512-oI4mAwuh1WwuFg95eJDNDDL8hCaZkwnPuNZrQdLBWvDoRU7EG+L/MOHL7SwPW2Y+ZuYcTLpj3rBkgllBQZN/JA==", + "version": "0.0.48", + "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.48.tgz", + "integrity": "sha512-kHRkKUJNaor31l05f2+RFzvcH5XSa7OfEfd/l4hzjte6NL6fjRkSMfZ4BjySW9wmfdwPOtq3mXurzPvPGEf5Tw==", "dependencies": { "@iden3/bigarray": "0.0.2", - "@iden3/binfileutils": "0.0.11", + "@iden3/binfileutils": "0.0.12", "fastfile": "0.0.20", - "ffjavascript": "0.2.60" + "ffjavascript": "0.3.0" } }, "node_modules/r1csfile/node_modules/ffjavascript": { - "version": "0.2.60", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", - "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.0.tgz", + "integrity": "sha512-l7sR5kmU3gRwDy8g0Z2tYBXy5ttmafRPFOqY7S6af5cq51JqJWt5eQ/lSR/rs2wQNbDYaYlQr5O+OSUf/oMLoQ==", "dependencies": { "wasmbuilder": "0.0.16", "wasmcurves": "0.2.2", - "web-worker": "^1.2.0" + "web-worker": "1.2.0" } }, "node_modules/randombytes": { @@ -8078,15 +8210,15 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -8329,20 +8461,47 @@ "dev": true }, "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", "dev": true, "hasInstallScript": true, "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/secp256k1/node_modules/elliptic": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -8506,20 +8665,20 @@ } }, "node_modules/snarkjs": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.3.tgz", - "integrity": "sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.5.tgz", + "integrity": "sha512-h+3c4rXZKLhLuHk4LHydZCk/h5GcNvk5GjVKRRkHmfb6Ntf8gHOA9zea3g656iclRuhqQ3iKDWFgiD9ypLrKiA==", "dependencies": { - "@iden3/binfileutils": "0.0.11", + "@iden3/binfileutils": "0.0.12", "bfj": "^7.0.2", "blake2b-wasm": "^2.4.0", - "circom_runtime": "0.1.24", + "circom_runtime": "0.1.28", "ejs": "^3.1.6", "fastfile": "0.0.20", - "ffjavascript": "0.2.63", + "ffjavascript": "0.3.1", "js-sha3": "^0.8.0", "logplease": "^1.2.15", - "r1csfile": "0.0.47" + "r1csfile": "0.0.48" }, "bin": { "snarkjs": "build/cli.cjs" @@ -8855,9 +9014,9 @@ } }, "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -8871,9 +9030,9 @@ } }, "node_modules/synckit/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/table-layout": { @@ -8989,15 +9148,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9501,9 +9651,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -9520,8 +9670,8 @@ } ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/package.json b/package.json index 458d631..3e373a2 100644 --- a/package.json +++ b/package.json @@ -52,8 +52,8 @@ "dependencies": { "@distributedlab/circom-parser": "0.1.2", "@distributedlab/circom2": "0.2.18-rc.4", - "@solarity/zkit": "0.2.6", - "@solarity/zktype": "0.3.1", + "@solarity/zkit": "0.3.0-rc.1", + "@solarity/zktype": "0.4.0-rc.0", "chalk": "4.1.2", "cli-progress": "3.12.0", "cli-table3": "0.6.5", @@ -62,7 +62,7 @@ "ora": "5.4.1", "resolve": "1.22.8", "semver": "7.6.3", - "snarkjs": "0.7.3", + "snarkjs": "0.7.5", "uuid": "9.0.1", "zod": "3.23.8" }, diff --git a/src/artifacts/CircuitArtifacts.ts b/src/artifacts/CircuitArtifacts.ts index dfdeaec..e419a74 100644 --- a/src/artifacts/CircuitArtifacts.ts +++ b/src/artifacts/CircuitArtifacts.ts @@ -7,6 +7,8 @@ import { replaceBackslashes } from "hardhat/utils/source-names"; import { ERRORS } from "hardhat/internal/core/errors-list"; import { HardhatError, NomicLabsHardhatPluginError } from "hardhat/internal/core/errors"; +import { ProvingSystemType } from "@solarity/zkit"; + import { HardhatZKitError } from "../errors"; import { CIRCUIT_ARTIFACTS_SUFFIX } from "../constants"; import { Reporter } from "../reporter"; @@ -34,6 +36,14 @@ export class CircuitArtifacts implements ICircuitArtifacts { constructor(private readonly _artifactsPath: string) {} + public static getArtifactOutputFileKey(fileType: ArtifactsFileType, provingSystem: ProvingSystemType): string { + if (fileType === "zkey" || fileType === "vkey") { + return `${provingSystem}.${fileType}`; + } + + return fileType; + } + /** * Retrieves a {@link CircuitArtifact} object based on the provided short name or fully qualified name * @@ -148,11 +158,15 @@ export class CircuitArtifacts implements ICircuitArtifacts { * for which to retrieve the path * @returns The full path of the specified artifact file associated with the provided {@link CircuitArtifact} object */ - public getCircuitArtifactFileFullPath(circuitArtifact: CircuitArtifact, fileType: ArtifactsFileType): string { + public getCircuitArtifactFileFullPath( + circuitArtifact: CircuitArtifact, + fileType: ArtifactsFileType, + provingSystem: ProvingSystemType = "groth16", + ): string { return path.join( this._artifactsPath, circuitArtifact.circuitSourceName, - this._getOutputFileSourcePath(circuitArtifact.circuitTemplateName, fileType), + this._getOutputFileSourcePath(circuitArtifact.circuitTemplateName, fileType, provingSystem), ); } @@ -164,7 +178,11 @@ export class CircuitArtifacts implements ICircuitArtifacts { * during the most recent session, such as during compilation * @returns A promise that resolves once the save operation is complete */ - public async saveCircuitArtifact(circuitArtifact: CircuitArtifact, updatedFileTypes: ArtifactsFileType[]) { + public async saveCircuitArtifact( + circuitArtifact: CircuitArtifact, + updatedFileTypes: ArtifactsFileType[], + provingSystems: ProvingSystemType[], + ) { const fullyQualifiedName = this.getCircuitFullyQualifiedName( circuitArtifact.circuitSourceName, circuitArtifact.circuitTemplateName, @@ -172,14 +190,23 @@ export class CircuitArtifacts implements ICircuitArtifacts { const artifactPath = this.formCircuitArtifactPathFromFullyQualifiedName(fullyQualifiedName); - // Updates the data for files that have been recently modified - for (const fileType of updatedFileTypes) { - const fileSourcePath: string = this.getCircuitArtifactFileFullPath(circuitArtifact, fileType); + const allArtifactProvingSystems = new Set([ + ...circuitArtifact.baseCircuitInfo.protocol, + ...provingSystems, + ]); + + circuitArtifact.baseCircuitInfo.protocol = [...allArtifactProvingSystems]; - circuitArtifact.compilerOutputFiles[fileType] = { - fileSourcePath, - fileHash: getFileHash(fileSourcePath), - }; + // Updates the data for files that have been recently modified + for (const provingSystem of provingSystems) { + for (const fileType of updatedFileTypes) { + const fileSourcePath: string = this.getCircuitArtifactFileFullPath(circuitArtifact, fileType, provingSystem); + + circuitArtifact.compilerOutputFiles[CircuitArtifacts.getArtifactOutputFileKey(fileType, provingSystem)] = { + fileSourcePath, + fileHash: getFileHash(fileSourcePath), + }; + } } Reporter!.verboseLog("circuit-artifacts", "Saving circuit artifact: %o", [circuitArtifact]); @@ -291,7 +318,11 @@ export class CircuitArtifacts implements ICircuitArtifacts { return this.getCircuitFullyQualifiedName(sourceName, circuitName); } - private _getOutputFileSourcePath(circuitTemplateName: string, fileType: ArtifactsFileType): string { + private _getOutputFileSourcePath( + circuitTemplateName: string, + fileType: ArtifactsFileType, + provingSystem: ProvingSystemType, + ): string { switch (fileType) { case "wasm": return path.join(`${circuitTemplateName}_js`, `${circuitTemplateName}.wasm`); @@ -304,9 +335,9 @@ export class CircuitArtifacts implements ICircuitArtifacts { case "json": return `${circuitTemplateName}_constraints.json`; case "vkey": - return `${circuitTemplateName}.vkey.json`; + return `${circuitTemplateName}.${provingSystem}.vkey.json`; case "zkey": - return `${circuitTemplateName}.zkey`; + return `${circuitTemplateName}.${provingSystem}.zkey`; default: throw new HardhatZKitError(`Invalid artifacts file type ${fileType}`); diff --git a/src/cache/CircuitsSetupCache.ts b/src/cache/CircuitsSetupCache.ts index 851d064..aced9ce 100644 --- a/src/cache/CircuitsSetupCache.ts +++ b/src/cache/CircuitsSetupCache.ts @@ -1,12 +1,12 @@ -import { isEqual } from "lodash"; +import { ProvingSystemType } from "@solarity/zkit"; import { SetupCacheSchema } from "./schemas"; import { CIRCUIT_SETUP_CACHE_VERSION } from "../constants"; import { BaseCache } from "../cache/BaseCache"; -import { SetupCacheEntry } from "../types/cache"; -import { ContributionSettings } from "../types/core"; +import { ProvingSystemData, SetupCacheEntry } from "../types/cache"; +import { SetupContributionSettings } from "../types/core"; /** * Class that implements the caching logic for setting up circuits. @@ -37,23 +37,36 @@ class BaseCircuitsSetupCache extends BaseCache { public hasFileChanged( artifactAbsolutePath: string, r1csContentHash: string, - contributionSettings: ContributionSettings, - ): boolean { + contributionSettings: SetupContributionSettings, + ): ProvingSystemType[] { const cacheEntry = this.getEntry(artifactAbsolutePath); if (cacheEntry === undefined) { - return true; + return contributionSettings.provingSystems; } - if (cacheEntry.r1csContentHash !== r1csContentHash) { - return true; - } + const obsoleteProvingSystems: ProvingSystemType[] = []; + + for (const provingSystem of contributionSettings.provingSystems) { + const provingSystemData: ProvingSystemData | undefined = cacheEntry.provingSystemsData.find( + (data: ProvingSystemData) => data.provingSystem === provingSystem, + ); + + if (!provingSystemData) { + obsoleteProvingSystems.push(provingSystem); + + continue; + } - if (!isEqual(cacheEntry.contributionSettings, contributionSettings)) { - return true; + if ( + provingSystemData.lastR1CSFileHash !== r1csContentHash || + (provingSystem === "groth16" && cacheEntry.contributionsNumber !== contributionSettings.contributions) + ) { + obsoleteProvingSystems.push(provingSystem); + } } - return false; + return obsoleteProvingSystems; } } diff --git a/src/cache/schemas/setup-schemas.ts b/src/cache/schemas/setup-schemas.ts index be59b27..bf888fd 100644 --- a/src/cache/schemas/setup-schemas.ts +++ b/src/cache/schemas/setup-schemas.ts @@ -1,17 +1,17 @@ import { z } from "zod"; -export const ProvingSystemTypeSchema = z.literal("groth16"); +export const ProvingSystemTypeSchema = z.literal("groth16").or(z.literal("plonk")); -export const ContributionSettingsSchema = z.object({ +export const ProvingSystemDataSchema = z.object({ provingSystem: ProvingSystemTypeSchema, - contributions: z.number(), + lastR1CSFileHash: z.string(), }); export const SetupCacheEntrySchema = z.object({ circuitSourceName: z.string(), - r1csContentHash: z.string(), r1csSourcePath: z.string(), - contributionSettings: ContributionSettingsSchema, + provingSystemsData: ProvingSystemDataSchema.array(), + contributionsNumber: z.number(), }); export const SetupCacheSchema = z.object({ diff --git a/src/config/config.ts b/src/config/config.ts index 0238c05..23251e7 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -18,7 +18,7 @@ const defaultConfig: ZKitConfig = { setupSettings: { contributionSettings: { provingSystem: "groth16", - contributions: 1, + contributions: 2, }, ptauDir: undefined, ptauDownload: true, diff --git a/src/constants.ts b/src/constants.ts index 919c557..373e6d1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,6 +16,11 @@ export const BYTES_IN_MB = 1048576; export const MAX_PTAU_ID = 27; export const PTAU_FILE_REG_EXP = /^(?:.+-|)(\d{1,2}).ptau$/; +export const PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS: { [key: string]: number } = { + groth16: 1, + plonk: 11, +}; + export const CIRCOM_FILE_REG_EXP = /\w+\.circom/; export const NODE_MODULES_REG_EXP = /^node_modules\//; diff --git a/src/core/compile/CompilationProcessor.ts b/src/core/compile/CompilationProcessor.ts index fe2fe18..9662a48 100644 --- a/src/core/compile/CompilationProcessor.ts +++ b/src/core/compile/CompilationProcessor.ts @@ -7,12 +7,12 @@ import { v4 as uuid } from "uuid"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { CircomCompilerFactory, createCircomCompilerFactory } from "../compiler"; +import { ProvingSystemType } from "@solarity/zkit"; + +import { CircomCompilerFactory, createCircomCompilerFactory, getHighestVersion, isVersionValid } from "../compiler"; import { HardhatZKitError } from "../../errors"; import { CIRCUIT_ARTIFACT_VERSION, NODE_MODULES } from "../../constants"; import { Reporter } from "../../reporter"; - -import { getHighestVersion, isVersionValid } from "../compiler/versioning"; import { getNormalizedFullPath, renameFilesRecursively, readDirRecursively } from "../../utils/path-utils"; import { ZKitConfig } from "../../types/zkit-config"; @@ -68,7 +68,7 @@ export class CompilationProcessor { * * @param filesInfoToCompile Information about circuit files needed for compilation */ - public async compile(filesInfoToCompile: CircomResolvedFileInfo[]) { + public async compile(filesInfoToCompile: CircomResolvedFileInfo[], provingSystems: ProvingSystemType[]) { const tempDir: string = path.join(os.tmpdir(), ".zkit", uuid()); try { @@ -109,7 +109,7 @@ export class CompilationProcessor { await this._moveFromTempDirToArtifacts(compilationInfoArr); - await this._emitArtifacts(compilationInfoArr); + await this._emitArtifacts(compilationInfoArr, provingSystems); Reporter!.reportCompilationResult(compilationInfoArr); } finally { @@ -167,7 +167,7 @@ export class CompilationProcessor { } } - private async _emitArtifacts(compilationInfoArr: CompilationInfo[]) { + private async _emitArtifacts(compilationInfoArr: CompilationInfo[], provingSystems: ProvingSystemType[]) { for (const info of compilationInfoArr) { const fullyQualifiedName: string = this._circuitArtifacts.getCircuitFullyQualifiedName( info.resolvedFile.sourceName, @@ -185,6 +185,7 @@ export class CompilationProcessor { circuitFileName: info.circuitFileName, circuitSourceName: info.resolvedFile.sourceName, baseCircuitInfo: { + protocol: [], constraintsNumber: 0, signals: [], }, @@ -196,12 +197,14 @@ export class CompilationProcessor { throw new HardhatZKitError("Unable to emit artifacts for resolved file without main component data"); } - circuitArtifact.baseCircuitInfo = { - constraintsNumber: info.constraintsNumber, - signals: info.resolvedFile.fileData.mainComponentData.signals, - }; + circuitArtifact.baseCircuitInfo.constraintsNumber = info.constraintsNumber; + circuitArtifact.baseCircuitInfo.signals = info.resolvedFile.fileData.mainComponentData.signals; - await this._circuitArtifacts.saveCircuitArtifact(circuitArtifact, this._getUpdatedArtifactFileTypes()); + await this._circuitArtifacts.saveCircuitArtifact( + circuitArtifact, + this._getUpdatedArtifactFileTypes(), + provingSystems, + ); } } diff --git a/src/core/compiler/index.ts b/src/core/compiler/index.ts index 40d7444..9b38684 100644 --- a/src/core/compiler/index.ts +++ b/src/core/compiler/index.ts @@ -1,2 +1,5 @@ export * from "./CircomCompiler"; export * from "./CircomCompilerFactory"; +export * from "./CircomCompilerDownloader"; + +export * from "./versioning"; diff --git a/src/core/setup/SetupFilesResolver.ts b/src/core/setup/SetupFilesResolver.ts index 9d35118..0bd6885 100644 --- a/src/core/setup/SetupFilesResolver.ts +++ b/src/core/setup/SetupFilesResolver.ts @@ -2,14 +2,16 @@ import fsExtra from "fs-extra"; import { HardhatConfig } from "hardhat/types"; +import { ProvingSystemType } from "@solarity/zkit"; + import { Reporter } from "../../reporter"; import { HardhatZKitError } from "../../errors"; import { CircuitsSetupCache } from "../../cache"; import { filterCircuitFiles, getNormalizedFullPath } from "../../utils/path-utils"; -import { FileFilterSettings, SetupSettings, ZKitConfig } from "../../types/zkit-config"; +import { FileFilterSettings, ZKitConfig } from "../../types/zkit-config"; import { CircuitArtifact, CompilerOutputFileInfo, ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; -import { CircuitSetupInfo } from "../../types/core"; +import { CircuitSetupInfo, SetupContributionSettings } from "../../types/core"; /** * Class responsible for resolving setup files for circuits in a given project. @@ -47,28 +49,39 @@ export class SetupFilesResolver { * @param force A boolean flag that, when true, skips filtering by file changes during setup * @returns An array of {@link CircuitSetupInfo} objects containing information about the circuits to be set up */ - public async getCircuitsInfoToSetup(setupSettings: SetupSettings, force: boolean): Promise { + public async getCircuitsInfoToSetup( + contributionSettings: SetupContributionSettings, + setupFilterSettings: FileFilterSettings, + force: boolean, + ): Promise { const allFullyQualifiedNames: string[] = await this._circuitArtifacts.getAllCircuitFullyQualifiedNames(); - let circuitSetupInfoArr: CircuitSetupInfo[] = await this._getCircuitSetupInfoArr(allFullyQualifiedNames); + let circuitSetupInfoArr: CircuitSetupInfo[] = await this._getCircuitSetupInfoArr( + allFullyQualifiedNames, + contributionSettings.provingSystems, + ); - this._invalidateCacheMissingArtifacts(circuitSetupInfoArr); + this._invalidateCacheMissingArtifacts(circuitSetupInfoArr, contributionSettings.provingSystems); if (!force) { Reporter!.verboseLog("setup-file-resolver", "Force flag disabled. Start filtering circuits to setup..."); - circuitSetupInfoArr = circuitSetupInfoArr.filter((setupInfo) => - CircuitsSetupCache!.hasFileChanged( + circuitSetupInfoArr = circuitSetupInfoArr.filter((setupInfo, index) => { + const changedProvingSystems: ProvingSystemType[] = CircuitsSetupCache!.hasFileChanged( setupInfo.circuitArtifactFullPath, setupInfo.r1csContentHash, - setupSettings.contributionSettings, - ), - ); + contributionSettings, + ); + + circuitSetupInfoArr[index].provingSystems = changedProvingSystems; + + return changedProvingSystems.length > 0; + }); } const filteredCircuitsSetupInfo: CircuitSetupInfo[] = await this._filterCircuitSetupInfoArr( circuitSetupInfoArr, - setupSettings, + setupFilterSettings, ); Reporter!.reportCircuitListToSetup(circuitSetupInfoArr, filteredCircuitsSetupInfo); @@ -76,7 +89,10 @@ export class SetupFilesResolver { return filteredCircuitsSetupInfo; } - private async _getCircuitSetupInfoArr(fullyQualifiedNames: string[]): Promise { + private async _getCircuitSetupInfoArr( + fullyQualifiedNames: string[], + provingSystems: ProvingSystemType[], + ): Promise { return Promise.all( fullyQualifiedNames.map(async (name: string): Promise => { const circuitArtifact: CircuitArtifact = await this._circuitArtifacts.readCircuitArtifact(name); @@ -91,6 +107,7 @@ export class SetupFilesResolver { r1csSourcePath: r1csInfo.fileSourcePath, r1csContentHash: r1csInfo.fileHash, circuitArtifactFullPath: this._circuitArtifacts.formCircuitArtifactPathFromFullyQualifiedName(name), + provingSystems, }; }), ); @@ -112,7 +129,10 @@ export class SetupFilesResolver { ); } - protected _invalidateCacheMissingArtifacts(circuitSetupInfoArr: CircuitSetupInfo[]) { + protected _invalidateCacheMissingArtifacts( + circuitSetupInfoArr: CircuitSetupInfo[], + provingSystems: ProvingSystemType[], + ) { for (const setupInfo of circuitSetupInfoArr) { const cacheEntry = CircuitsSetupCache!.getEntry(setupInfo.circuitArtifactFullPath); @@ -120,10 +140,28 @@ export class SetupFilesResolver { continue; } - if ( - !fsExtra.existsSync(this._circuitArtifacts.getCircuitArtifactFileFullPath(setupInfo.circuitArtifact, "zkey")) || - !fsExtra.existsSync(this._circuitArtifacts.getCircuitArtifactFileFullPath(setupInfo.circuitArtifact, "vkey")) - ) { + const provingSystemsToRemove: ProvingSystemType[] = []; + + for (const provingSystem of provingSystems) { + if ( + !fsExtra.existsSync( + this._circuitArtifacts.getCircuitArtifactFileFullPath(setupInfo.circuitArtifact, "zkey", provingSystem), + ) || + !fsExtra.existsSync( + this._circuitArtifacts.getCircuitArtifactFileFullPath(setupInfo.circuitArtifact, "vkey", provingSystem), + ) + ) { + provingSystemsToRemove.push(provingSystem); + } + } + + cacheEntry.provingSystemsData = cacheEntry.provingSystemsData.filter( + (data) => !provingSystemsToRemove.includes(data.provingSystem), + ); + + if (cacheEntry.provingSystemsData.length > 0) { + CircuitsSetupCache!.addFile(setupInfo.circuitArtifactFullPath, cacheEntry); + } else { CircuitsSetupCache!.removeEntry(setupInfo.circuitArtifactFullPath); } } diff --git a/src/core/setup/SetupProcessor.ts b/src/core/setup/SetupProcessor.ts index 852b7fe..895070e 100644 --- a/src/core/setup/SetupProcessor.ts +++ b/src/core/setup/SetupProcessor.ts @@ -5,14 +5,16 @@ import { randomBytes } from "crypto"; import { v4 as uuid } from "uuid"; import * as snarkjs from "snarkjs"; -import { PtauDownloader } from "../utils/PtauDownloader"; +import { ProvingSystemType } from "@solarity/zkit"; + import { HardhatZKitError } from "../../errors"; -import { PTAU_FILE_REG_EXP } from "../../constants"; +import { PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS, PTAU_FILE_REG_EXP } from "../../constants"; import { Reporter } from "../../reporter"; +import { PtauDownloader } from "../utils/PtauDownloader"; import { getNormalizedFullPath } from "../../utils/path-utils"; -import { CircuitArtifact, ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; -import { ContributionSettings, ProvingSystemType } from "../../types/core"; +import { ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; +import { CircuitSetupInfo, SetupContributionSettings } from "../../types/core"; /** * Class responsible for processing the setup of circuit artifacts. @@ -45,7 +47,7 @@ export class SetupProcessor { * @param circuitArtifacts An array of circuit artifacts that need to be set up * @param contributionSettings The contribution settings to be used during the setup process */ - public async setup(circuitArtifacts: CircuitArtifact[], contributionSettings: ContributionSettings) { + public async setup(circuitSetupInfoArr: CircuitSetupInfo[], contributionSettings: SetupContributionSettings) { const tempDir: string = path.join(os.tmpdir(), ".zkit", uuid()); try { @@ -53,109 +55,156 @@ export class SetupProcessor { Reporter!.reportSetupProcessHeader(); - const ptauFilePath: string = await this._getPtauFile(circuitArtifacts); + const ptauFilePath: string = await this._getPtauFile(circuitSetupInfoArr, contributionSettings.provingSystems); - await this._generateZKeyFiles(circuitArtifacts, contributionSettings, ptauFilePath); - await this._generateVKeyFiles(circuitArtifacts); + await this._generateZKeyFiles(circuitSetupInfoArr, contributionSettings, ptauFilePath); + await this._generateVKeyFiles(circuitSetupInfoArr); await Promise.all( - circuitArtifacts.map(async (circuitArtifact: CircuitArtifact) => { - await this._circuitArtifacts.saveCircuitArtifact(circuitArtifact, ["zkey", "vkey"]); + circuitSetupInfoArr.map(async (setupInfo: CircuitSetupInfo) => { + await this._circuitArtifacts.saveCircuitArtifact( + setupInfo.circuitArtifact, + ["zkey", "vkey"], + setupInfo.provingSystems, + ); }), ); - Reporter!.reportSetupResult(circuitArtifacts); + Reporter!.reportSetupResult(circuitSetupInfoArr); } finally { fsExtra.rmSync(tempDir, { recursive: true, force: true }); } } private async _generateZKeyFiles( - circuitArtifacts: CircuitArtifact[], - contributionSettings: ContributionSettings, + circuitSetupInfoArr: CircuitSetupInfo[], + contributionSettings: SetupContributionSettings, ptauFilePath: string, ) { const contributions: number = contributionSettings.contributions; - const provingSystem: ProvingSystemType = contributionSettings.provingSystem; Reporter!.reportZKeyFilesGenerationHeader(contributions); - for (const circuitArtifact of circuitArtifacts) { - const r1csFilePath = circuitArtifact.compilerOutputFiles.r1cs?.fileSourcePath; - const zkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath(circuitArtifact, "zkey"); - - if (!r1csFilePath) { - throw new HardhatZKitError(`R1CS file for ${name} circuit not found. Compile circuits and try again.`); - } - - Reporter!.verboseLog("setup-processor:zkey", "Generating ZKey file for %s circuit with params %o", [ - circuitArtifact.circuitTemplateName, - { r1csFilePath, zkeyFilePath }, - ]); + for (const setupInfo of circuitSetupInfoArr) { + const r1csFilePath = setupInfo.circuitArtifact.compilerOutputFiles.r1cs!.fileSourcePath; const spinnerId: string | null = Reporter!.reportZKeyFileGenerationStartWithSpinner( - circuitArtifact.circuitTemplateName, + setupInfo.circuitArtifact.circuitTemplateName, ); - if (provingSystem === "groth16") { - await snarkjs.zKey.newZKey(r1csFilePath, ptauFilePath, zkeyFilePath); - - const zKeyFileNext = `${zkeyFilePath}.next.zkey`; - - for (let i = 0; i < contributions; ++i) { - await snarkjs.zKey.contribute( - zkeyFilePath, - zKeyFileNext, - `${zkeyFilePath}_contribution_${i}`, - randomBytes(32).toString("hex"), - ); - - fsExtra.rmSync(zkeyFilePath); - fsExtra.renameSync(zKeyFileNext, zkeyFilePath); + for (const provingSystem of setupInfo.provingSystems) { + const zkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath( + setupInfo.circuitArtifact, + "zkey", + provingSystem, + ); + + Reporter!.verboseLog( + "setup-processor:zkey", + "Generating ZKey file for %s circuit with %s proving system and params %o", + [setupInfo.circuitArtifact.circuitTemplateName, provingSystem, { r1csFilePath, zkeyFilePath }], + ); + + switch (provingSystem) { + case "groth16": + await this._generateGroth16ZKeyFile(r1csFilePath, ptauFilePath, zkeyFilePath, contributions); + break; + case "plonk": + await this._generatePlonkZKeyFile(r1csFilePath, ptauFilePath, zkeyFilePath); + break; + default: + throw new HardhatZKitError(`Unsupported proving system - ${provingSystem}`); } - } else { - throw new HardhatZKitError(`Unsupported proving system - ${provingSystem}`); } - Reporter!.reportZKeyFileGenerationResult(spinnerId, circuitArtifact.circuitTemplateName, contributions); + Reporter!.reportZKeyFileGenerationResult(spinnerId, setupInfo.circuitArtifact.circuitTemplateName, contributions); } - - return circuitArtifacts; } - private async _generateVKeyFiles(circuitArtifacts: CircuitArtifact[]) { + private async _generateVKeyFiles(circuitSetupInfoArr: CircuitSetupInfo[]) { Reporter!.reportVKeyFilesGenerationHeader(); - for (const circuitArtifact of circuitArtifacts) { - const zkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath(circuitArtifact, "zkey"); - const vkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath(circuitArtifact, "vkey"); - - Reporter!.verboseLog("setup-processor:vkey", "Generating VKey file for %s circuit with params %o", [ - circuitArtifact.circuitTemplateName, - { zkeyFilePath, vkeyFilePath }, - ]); - + for (const setupInfo of circuitSetupInfoArr) { const spinnerId: string | null = Reporter!.reportVKeyFileGenerationStartWithSpinner( - circuitArtifact.circuitTemplateName, + setupInfo.circuitArtifact.circuitTemplateName, ); - const vKeyData = await snarkjs.zKey.exportVerificationKey(zkeyFilePath); + for (const provingSystem of setupInfo.provingSystems) { + const zkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath( + setupInfo.circuitArtifact, + "zkey", + provingSystem, + ); + const vkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath( + setupInfo.circuitArtifact, + "vkey", + provingSystem, + ); + + Reporter!.verboseLog( + "setup-processor:vkey", + "Generating VKey file for %s circuit with %s proving system and params %o", + [setupInfo.circuitArtifact.circuitTemplateName, provingSystem, { zkeyFilePath, vkeyFilePath }], + ); + + const vKeyData = await snarkjs.zKey.exportVerificationKey(zkeyFilePath); + + fsExtra.outputFileSync(vkeyFilePath, JSON.stringify(vKeyData)); + } + + Reporter!.reportVKeyFileGenerationResult(spinnerId, setupInfo.circuitArtifact.circuitTemplateName); + } + } + + private async _generateGroth16ZKeyFile( + r1csFilePath: string, + ptauFilePath: string, + zkeyFilePath: string, + contributions: number, + ) { + await snarkjs.zKey.newZKey(r1csFilePath, ptauFilePath, zkeyFilePath); - fsExtra.outputFileSync(vkeyFilePath, JSON.stringify(vKeyData)); + const zKeyFileNext = `${zkeyFilePath}.next.zkey`; + + for (let i = 0; i < contributions; ++i) { + await snarkjs.zKey.contribute( + zkeyFilePath, + zKeyFileNext, + `${zkeyFilePath}_contribution_${i}`, + randomBytes(32).toString("hex"), + ); - Reporter!.reportVKeyFileGenerationResult(spinnerId, circuitArtifact.circuitTemplateName); + fsExtra.rmSync(zkeyFilePath); + fsExtra.renameSync(zKeyFileNext, zkeyFilePath); } } - private async _getPtauFile(circuitArtifacts: CircuitArtifact[]): Promise { + private async _generatePlonkZKeyFile(r1csFilePath: string, ptauFilePath: string, zkeyFilePath: string) { + await snarkjs.plonk.setup(r1csFilePath, ptauFilePath, zkeyFilePath); + } + + private async _getPtauFile( + circuitSetupInfoArr: CircuitSetupInfo[], + provingSystems: ProvingSystemType[], + ): Promise { const circuitsConstraintsNumber: number[] = await Promise.all( - circuitArtifacts.map(async (circuitArtifact: CircuitArtifact) => { - return circuitArtifact.baseCircuitInfo.constraintsNumber; + circuitSetupInfoArr.map(async (setupInfo: CircuitSetupInfo) => { + return setupInfo.circuitArtifact.baseCircuitInfo.constraintsNumber; }), ); const maxConstraintsNumber = Math.max(...circuitsConstraintsNumber); - const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber)), 8); + let provingSystemMultiplier = 1; + + for (const provingSystem of provingSystems) { + const currentMultiplier = PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS[provingSystem]; + + if (currentMultiplier && currentMultiplier > provingSystemMultiplier) { + provingSystemMultiplier = currentMultiplier; + } + } + + const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber * provingSystemMultiplier)), 8); let entries: fsExtra.Dirent[] = []; diff --git a/src/index.ts b/src/index.ts index daa86a1..ee0e6aa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,15 @@ import { ActionType, HardhatRuntimeEnvironment, RunSuperFunction } from "hardhat import { TASK_CLEAN, TASK_COMPILE_SOLIDITY_READ_FILE as TASK_READ_FILE } from "hardhat/builtin-tasks/task-names"; import { willRunWithTypescript } from "hardhat/internal/core/typescript-support"; -import { CircuitZKit, CircuitZKitConfig, VerifierLanguageType } from "@solarity/zkit"; +import { + CircuitZKit, + CircuitZKitConfig, + VerifierLanguageType, + ProvingSystemType, + IProtocolImplementer, + Groth16Implementer, + PlonkImplementer, +} from "@solarity/zkit"; import { CircuitTypesGenerator } from "@solarity/zktype"; import "./type-extensions"; @@ -43,7 +51,7 @@ import { HardhatZKitError } from "./errors"; import { Reporter, createReporter } from "./reporter"; import { CircuitArtifacts } from "./artifacts/CircuitArtifacts"; import { CIRCUITS_COMPILE_CACHE_FILENAME, CIRCUITS_SETUP_CACHE_FILENAME } from "./constants"; -import { getNormalizedFullPath } from "./utils/path-utils"; +import { getNormalizedFullPath, getUniqueProvingSystems } from "./utils"; import { isVersionValid } from "./core/compiler/versioning"; import { @@ -54,7 +62,8 @@ import { SetupTaskConfig, } from "./types/tasks"; import { CircuitArtifact } from "./types/artifacts/circuit-artifacts"; -import { CompileFlags, CircomResolvedFileInfo, CircuitSetupInfo } from "./types/core"; +import { CompileFlags, CircomResolvedFileInfo, CircuitSetupInfo, SetupContributionSettings } from "./types/core"; +import { ProvingSystemData } from "./types/cache"; const zkitScope = scope(ZKIT_SCOPE_NAME, "The ultimate TypeScript environment for Circom development"); @@ -68,8 +77,11 @@ extendEnvironment((hre) => { return { circuitArtifacts, - getCircuit: async (circuitName: string): Promise => { - return hre.run(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT, { circuitName }); + getCircuit: async ( + circuitName: string, + provingSystem: ProvingSystemType = "groth16", + ): Promise> => { + return hre.run(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT, { circuitName, provingSystem }); }, }; }); @@ -91,7 +103,7 @@ const compile: ActionType = async (taskArgs: CompileTaskConfi ); // Flags for specifying the necessary configurations during the setup process. - // R1CS, Wasm, and sym flags are mandatory + // R1CS, Wasm, and Sym flags are mandatory const compileFlags: CompileFlags = { r1cs: true, wasm: true, @@ -124,11 +136,13 @@ const compile: ActionType = async (taskArgs: CompileTaskConfi env, ); - await compilationProcessor.compile(resolvedFilesInfo); + const provingSystems: ProvingSystemType[] = getUniqueProvingSystems( + env.config.zkit.setupSettings.contributionSettings.provingSystem, + ); - const typeGenerationProcessor: TypeGenerationProcessor = new TypeGenerationProcessor(env); + await compilationProcessor.compile(resolvedFilesInfo, provingSystems); - await typeGenerationProcessor.generateAllTypes(); + await new TypeGenerationProcessor(env).generateAllTypes(); for (const fileInfo of resolvedFilesInfo) { for (const file of [fileInfo.resolvedFile, ...fileInfo.dependencies]) { @@ -158,8 +172,13 @@ const setup: ActionType = async (taskArgs: SetupTaskConfig, env await createCircuitsSetupCache(circuitsSetupCacheFullPath); const setupFileResolver: SetupFilesResolver = new SetupFilesResolver(env.zkit.circuitArtifacts, env.config); + const setupContributionSettings: SetupContributionSettings = { + provingSystems: getUniqueProvingSystems(env.config.zkit.setupSettings.contributionSettings.provingSystem), + contributions: env.config.zkit.setupSettings.contributionSettings.contributions, + }; const circuitSetupInfoArr: CircuitSetupInfo[] = await setupFileResolver.getCircuitsInfoToSetup( + setupContributionSettings, env.config.zkit.setupSettings, taskArgs.force, ); @@ -177,17 +196,34 @@ const setup: ActionType = async (taskArgs: SetupTaskConfig, env const setupProcessor: SetupProcessor = new SetupProcessor(ptauDir, env.zkit.circuitArtifacts); - await setupProcessor.setup( - circuitSetupInfoArr.map((setupInfo: CircuitSetupInfo) => setupInfo.circuitArtifact), - env.config.zkit.setupSettings.contributionSettings, - ); + await setupProcessor.setup(circuitSetupInfoArr, setupContributionSettings); + + await new TypeGenerationProcessor(env).generateAllTypes(); for (const setupInfo of circuitSetupInfoArr) { + const currentSetupCacheEntry = CircuitsSetupCache!.getEntry(setupInfo.circuitArtifactFullPath); + + let currentProvingSystemsData: ProvingSystemData[] = []; + + if (currentSetupCacheEntry) { + currentProvingSystemsData = currentSetupCacheEntry.provingSystemsData.filter((data: ProvingSystemData) => { + return !setupInfo.provingSystems.includes(data.provingSystem); + }); + } + CircuitsSetupCache!.addFile(setupInfo.circuitArtifactFullPath, { circuitSourceName: setupInfo.circuitArtifact.circuitSourceName, r1csSourcePath: setupInfo.r1csSourcePath, - r1csContentHash: setupInfo.r1csContentHash, - contributionSettings: env.config.zkit.setupSettings.contributionSettings, + provingSystemsData: [ + ...currentProvingSystemsData, + ...setupContributionSettings.provingSystems.map((provingSystem) => { + return { + provingSystem, + lastR1CSFileHash: setupInfo.r1csContentHash, + }; + }), + ], + contributionsNumber: setupContributionSettings.contributions, }); } } else { @@ -237,6 +273,11 @@ const generateVerifiers: ActionType = async ( if (allFullyQualifiedNames.length > 0) { Reporter!.reportVerifiersGenerationHeader(verifiersType); + const provingSystems: ProvingSystemType[] = getUniqueProvingSystems( + env.config.zkit.setupSettings.contributionSettings.provingSystem, + ); + const protocolImplementers = new Map>(); + for (const name of allFullyQualifiedNames) { const circuitArtifact: CircuitArtifact = await env.zkit.circuitArtifacts.readCircuitArtifact(name); @@ -245,13 +286,34 @@ const generateVerifiers: ActionType = async ( verifiersType, ); - await new CircuitZKit({ - circuitName: circuitArtifact.circuitTemplateName, - circuitArtifactsPath: path.dirname( - env.zkit.circuitArtifacts.formCircuitArtifactPathFromFullyQualifiedName(name), - ), - verifierDirPath: verifiersDirFullPath, - }).createVerifier(verifiersType); + for (const provingSystem of provingSystems) { + if (!protocolImplementers.has(provingSystem)) { + switch (provingSystem) { + case "groth16": + protocolImplementers.set(provingSystem, new Groth16Implementer()); + break; + case "plonk": + protocolImplementers.set(provingSystem, new PlonkImplementer()); + break; + default: + throw new HardhatZKitError(`Unsupported proving system - ${provingSystem}`); + } + } + + const protocolImplementer: IProtocolImplementer = + protocolImplementers.get(provingSystem)!; + + await new CircuitZKit( + { + circuitName: circuitArtifact.circuitTemplateName, + circuitArtifactsPath: path.dirname( + env.zkit.circuitArtifacts.formCircuitArtifactPathFromFullyQualifiedName(name), + ), + verifierDirPath: verifiersDirFullPath, + }, + protocolImplementer, + ).createVerifier(verifiersType); + } Reporter!.reportVerifierGenerationResult(spinnerId, circuitArtifact.circuitTemplateName, verifiersType); } @@ -286,7 +348,7 @@ const clean: ActionType = async (_taskArgs: any, env: HardhatRuntimeEnviron const getCircuitZKit: ActionType = async ( taskArgs: GetCircuitZKitConfig, env: HardhatRuntimeEnvironment, -): Promise => { +): Promise> => { const circuitArtifact: CircuitArtifact = await env.zkit.circuitArtifacts.readCircuitArtifact(taskArgs.circuitName); const verifiersDirFullPath: string = getNormalizedFullPath( @@ -309,7 +371,6 @@ const getCircuitZKit: ActionType = async ( circuitName: circuitArtifact.circuitTemplateName, circuitArtifactsPath: circuitArtifactsDirPath, verifierDirPath: verifiersDirFullPath, - provingSystem: taskArgs.verifierTemplateType ?? "groth16", }; if (willRunWithTypescript(env.hardhatArguments.config)) { @@ -317,7 +378,20 @@ const getCircuitZKit: ActionType = async ( return new module(circuitZKitConfig); } else { - return new CircuitZKit(circuitZKitConfig); + let protocolImplementer: IProtocolImplementer; + + switch (taskArgs.provingSystem) { + case "groth16": + protocolImplementer = new Groth16Implementer(); + break; + case "plonk": + protocolImplementer = new PlonkImplementer(); + break; + default: + throw new HardhatZKitError(`Unsupported proving system - ${taskArgs.provingSystem}`); + } + + return new CircuitZKit(circuitZKitConfig, protocolImplementer); } }; diff --git a/src/reporter/ReporterFacade.ts b/src/reporter/ReporterFacade.ts index 4575f0a..44b2d96 100644 --- a/src/reporter/ReporterFacade.ts +++ b/src/reporter/ReporterFacade.ts @@ -3,7 +3,6 @@ import debug from "debug"; import { VerifierLanguageType } from "@solarity/zkit"; -import { CircuitArtifact } from "../types/artifacts/circuit-artifacts"; import { CompilationInfo, CircuitSetupInfo } from "../types/core"; import { ProgressReporter, @@ -148,8 +147,8 @@ class ReporterFacade { this._setupReporter.reportHeader(); } - public reportSetupResult(circuitArtifacts: CircuitArtifact[]) { - this._setupReporter.reportResult(circuitArtifacts); + public reportSetupResult(circuitSetupInfoArr: CircuitSetupInfo[]) { + this._setupReporter.reportResult(circuitSetupInfoArr); } public reportZKeyFilesGenerationHeader(contributions: number) { diff --git a/src/reporter/reporters/SetupReporter.ts b/src/reporter/reporters/SetupReporter.ts index 9d2a602..a7058d5 100644 --- a/src/reporter/reporters/SetupReporter.ts +++ b/src/reporter/reporters/SetupReporter.ts @@ -3,11 +3,12 @@ import fs from "fs"; import chalk from "chalk"; import { BaseReporter } from "./BaseReporter"; -import { CircuitSetupInfo } from "../../types/core"; -import { CircuitArtifact } from "../../types/artifacts/circuit-artifacts"; +import { CircuitArtifacts } from "../../artifacts/CircuitArtifacts"; import { HardhatZKitError } from "../../errors"; import { BYTES_IN_MB } from "../../constants"; +import { CircuitSetupInfo } from "../../types/core"; + export class SetupReporter extends BaseReporter { public reportHeader() { if (this.isQuiet()) return; @@ -47,11 +48,12 @@ export class SetupReporter extends BaseReporter { } } - public reportResult(circuitArtifacts: CircuitArtifact[]) { + public reportResult(circuitSetupInfoArr: CircuitSetupInfo[]) { if (this.isQuiet()) return; let output: string = ""; - const circuitsMessage: string = circuitArtifacts.length > 1 ? `${circuitArtifacts.length} circuits` : `one circuit`; + const circuitsMessage: string = + circuitSetupInfoArr.length > 1 ? `${circuitSetupInfoArr.length} circuits` : `one circuit`; output += `\n${chalk.bold(`Successfully generated keys for ${circuitsMessage}.`)}\n`; @@ -59,11 +61,20 @@ export class SetupReporter extends BaseReporter { table.push([{ content: chalk.bold("Circuit Name") }, { content: chalk.bold(`ZKey file size (MB)`) }]); - for (const circuitArtifact of circuitArtifacts) { - table.push([ - { content: circuitArtifact.circuitTemplateName }, - { content: this._getFileSizeInMB(circuitArtifact.compilerOutputFiles.zkey?.fileSourcePath), hAlign: "right" }, - ]); + for (const setupInfo of circuitSetupInfoArr) { + for (const provingSystem of setupInfo.provingSystems) { + table.push([ + { content: `${setupInfo.circuitArtifact.circuitTemplateName} ${chalk.grey(`(${provingSystem})`)}` }, + { + content: this._getFileSizeInMB( + setupInfo.circuitArtifact.compilerOutputFiles[ + CircuitArtifacts.getArtifactOutputFileKey("zkey", provingSystem) + ]?.fileSourcePath, + ), + hAlign: "right", + }, + ]); + } } output += `\n${table.toString()}\n`; diff --git a/src/types/artifacts/circuit-artifacts.ts b/src/types/artifacts/circuit-artifacts.ts index 57fc101..ddf9166 100644 --- a/src/types/artifacts/circuit-artifacts.ts +++ b/src/types/artifacts/circuit-artifacts.ts @@ -1,3 +1,4 @@ +import { ProvingSystemType } from "@solarity/zkit"; import { SignalInfo } from "../core"; export interface ICircuitArtifacts { @@ -15,9 +16,17 @@ export interface ICircuitArtifacts { getCircuitArtifactsDirFullPath(): string; - getCircuitArtifactFileFullPath(circuitArtifact: CircuitArtifact, fileType: ArtifactsFileType): string; + getCircuitArtifactFileFullPath( + circuitArtifact: CircuitArtifact, + fileType: ArtifactsFileType, + provingSystem: ProvingSystemType, + ): string; - saveCircuitArtifact(circuitArtifact: CircuitArtifact, updatedFileTypes: ArtifactsFileType[]): Promise; + saveCircuitArtifact( + circuitArtifact: CircuitArtifact, + updatedFileTypes: ArtifactsFileType[], + provingSystems: ProvingSystemType[], + ): Promise; clearCache(): void; @@ -30,12 +39,13 @@ export type CircuitArtifact = { circuitTemplateName: string; circuitSourceName: string; baseCircuitInfo: BaseCircuitInfo; - compilerOutputFiles: Partial>; + compilerOutputFiles: Partial>; }; export type BaseCircuitInfo = { constraintsNumber: number; signals: SignalInfo[]; + protocol: ProvingSystemType[]; }; export type CompilerOutputFileInfo = { diff --git a/src/types/cache/circuits-setup-cache.ts b/src/types/cache/circuits-setup-cache.ts index 7ac8e19..c2700f6 100644 --- a/src/types/cache/circuits-setup-cache.ts +++ b/src/types/cache/circuits-setup-cache.ts @@ -1,8 +1,13 @@ -import { ContributionSettings } from "../core"; +import { ProvingSystemType } from "@solarity/zkit"; + +export type ProvingSystemData = { + provingSystem: ProvingSystemType; + lastR1CSFileHash: string; +}; export type SetupCacheEntry = { circuitSourceName: string; - r1csContentHash: string; r1csSourcePath: string; - contributionSettings: ContributionSettings; + provingSystemsData: ProvingSystemData[]; + contributionsNumber: number; }; diff --git a/src/types/core/setup/setup-files-resolver.ts b/src/types/core/setup/setup-files-resolver.ts index 81e02c8..12c98e1 100644 --- a/src/types/core/setup/setup-files-resolver.ts +++ b/src/types/core/setup/setup-files-resolver.ts @@ -1,3 +1,5 @@ +import { ProvingSystemType } from "@solarity/zkit"; + import { CircuitArtifact } from "../../artifacts/circuit-artifacts"; export type CircuitSetupInfo = { @@ -5,4 +7,5 @@ export type CircuitSetupInfo = { r1csSourcePath: string; r1csContentHash: string; circuitArtifactFullPath: string; + provingSystems: ProvingSystemType[]; }; diff --git a/src/types/core/setup/setup-processor.ts b/src/types/core/setup/setup-processor.ts index b92f97e..92f6817 100644 --- a/src/types/core/setup/setup-processor.ts +++ b/src/types/core/setup/setup-processor.ts @@ -1,6 +1,6 @@ -export type ProvingSystemType = "groth16"; +import { ProvingSystemType } from "@solarity/zkit"; -export type ContributionSettings = { - provingSystem: ProvingSystemType; +export type SetupContributionSettings = { + provingSystems: ProvingSystemType[]; contributions: number; }; diff --git a/src/types/hardhat-zkit.ts b/src/types/hardhat-zkit.ts index eb02622..9409dc6 100644 --- a/src/types/hardhat-zkit.ts +++ b/src/types/hardhat-zkit.ts @@ -1,7 +1,11 @@ -import { CircuitZKit } from "@solarity/zkit"; +import { CircuitZKit, ProvingSystemType } from "@solarity/zkit"; + import { ICircuitArtifacts } from "./artifacts/circuit-artifacts"; -export declare function getCircuit(circuitName: string): Promise; +export declare function getCircuit( + circuitName: string, + provingSystem: ProvingSystemType, +): Promise>; export interface HardhatZKit { circuitArtifacts: ICircuitArtifacts; diff --git a/src/types/tasks.ts b/src/types/tasks.ts index 65eb841..20bc030 100644 --- a/src/types/tasks.ts +++ b/src/types/tasks.ts @@ -1,4 +1,4 @@ -import { VerifierLanguageType, VerifierProvingSystem } from "@solarity/zkit"; +import { VerifierLanguageType, ProvingSystemType } from "@solarity/zkit"; export type MakeTaskConfig = { force: boolean; @@ -29,6 +29,6 @@ export type GenerateVerifiersTaskConfig = { export type GetCircuitZKitConfig = { verifiersDir?: string; - verifierTemplateType?: VerifierProvingSystem; circuitName: string; + provingSystem: ProvingSystemType; }; diff --git a/src/types/zkit-config.ts b/src/types/zkit-config.ts index f5c2d56..7ccd349 100644 --- a/src/types/zkit-config.ts +++ b/src/types/zkit-config.ts @@ -1,6 +1,4 @@ -import { VerifierLanguageType } from "@solarity/zkit"; - -import { ContributionSettings } from "./core"; +import { VerifierLanguageType, ProvingSystemType } from "@solarity/zkit"; export type ZKitConfig = { compilerVersion?: string; @@ -24,6 +22,11 @@ export type SetupSettings = FileFilterSettings & { contributionSettings: ContributionSettings; }; +export type ContributionSettings = { + provingSystem: ProvingSystemType | ProvingSystemType[]; + contributions: number; +}; + export type FileFilterSettings = { onlyFiles: string[]; skipFiles: string[]; diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..ac50f87 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./path-utils"; +export * from "./utils"; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 4174cfc..4acf154 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -4,6 +4,8 @@ import { exec } from "child_process"; import { createNonCryptographicHashBasedIdentifier } from "hardhat/internal/util/hash"; +import { ProvingSystemType } from "@solarity/zkit"; + import { Reporter } from "../reporter"; import { ExecCallResult } from "../types/utils"; @@ -101,3 +103,11 @@ export async function execCall(execFile: string, callArgs: string[]): Promise { setupSettings: { contributionSettings: { provingSystem: "groth16", - contributions: 1, + contributions: 2, }, ptauDir: "zkit/ptau", ptauDownload: true, @@ -75,7 +75,7 @@ describe("config", () => { setupSettings: { contributionSettings: { provingSystem: "groth16", - contributions: 1, + contributions: 2, }, ptauDir: undefined, ptauDownload: true, diff --git a/test/integration/tasks.test.ts b/test/integration/tasks.test.ts index ea7b185..aac25d6 100644 --- a/test/integration/tasks.test.ts +++ b/test/integration/tasks.test.ts @@ -72,10 +72,10 @@ describe("ZKit tasks", async function () { getZkitCircuitFullPaths(config).forEach((path, index) => { expect(fsExtra.readdirSync(path)).to.be.deep.eq([ + `${circuitNames[index]}.groth16.vkey.json`, + `${circuitNames[index]}.groth16.zkey`, `${circuitNames[index]}.r1cs`, `${circuitNames[index]}.sym`, - `${circuitNames[index]}.vkey.json`, - `${circuitNames[index]}.zkey`, `${circuitNames[index]}_artifacts.json`, `${circuitNames[index]}_js`, ]); @@ -84,7 +84,7 @@ describe("ZKit tasks", async function () { const ptauFullPath: string = getNormalizedFullPath(config.paths!.root!, "zkit/ptau"); expect(fsExtra.readdirSync(ptauFullPath)).to.be.deep.eq(["powers-of-tau-8.ptau"]); - const circuit = await zkit.getCircuit("Multiplier2"); + const circuit = await zkit.getCircuit("Multiplier2", "groth16"); await expect(circuit).with.witnessInputs({ in1: "3", in2: "7" }).to.have.witnessOutputs(["21"]); const proof = await circuit.generateProof({ in1: "4", in2: "2" }); @@ -303,7 +303,9 @@ describe("ZKit tasks", async function () { await checkMake(this.hre.config, this.hre.zkit); const verifiersFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "contracts/verifiers"); - expect(fsExtra.readdirSync(verifiersFullPath)).to.be.deep.eq(circuitNames.map((name) => `${name}Verifier.sol`)); + expect(fsExtra.readdirSync(verifiersFullPath)).to.be.deep.eq( + circuitNames.map((name) => `${name}Groth16Verifier.sol`), + ); }); }); diff --git a/test/unit/cache/circuits-setup-cache.test.ts b/test/unit/cache/circuits-setup-cache.test.ts index e05bf1a..561ddf5 100644 --- a/test/unit/cache/circuits-setup-cache.test.ts +++ b/test/unit/cache/circuits-setup-cache.test.ts @@ -90,7 +90,9 @@ describe("CircuitsSetupCache", () => { it("should return correct results", async function () { await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE }, { quiet: false }); - expect(CircuitsSetupCache!.hasFileChanged("invalid-path", "", defaultContributionSettings)).to.be.true; + expect(CircuitsSetupCache!.hasFileChanged("invalid-path", "", defaultContributionSettings)).to.be.deep.eq( + defaultContributionSettings.provingSystems, + ); const mul2FullName: string = "circuits/main/mul2.circom:Multiplier2"; @@ -104,17 +106,19 @@ describe("CircuitsSetupCache", () => { const contentHash = getFileHash(mul2R1CSFilePath); - expect(CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash + "1", defaultContributionSettings)) - .to.be.true; + expect( + CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash + "1", defaultContributionSettings), + ).to.be.deep.eq(defaultContributionSettings.provingSystems); expect( CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash, { ...defaultContributionSettings, - contributions: 2, + contributions: 1, }), - ).to.be.true; + ).to.be.deep.eq(defaultContributionSettings.provingSystems); - expect(CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash, defaultContributionSettings)).to.be - .false; + expect( + CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash, defaultContributionSettings), + ).to.be.deep.eq([]); const typesDir: string = getNormalizedFullPath(this.hre.config.paths.root, "generated-types/zkit"); diff --git a/test/utils.ts b/test/utils.ts index 0917b2d..6bd4fe6 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -4,8 +4,8 @@ import { CircomFilesParser } from "../src/core"; import { getFileHash } from "../src/utils/utils"; import { getNormalizedFullPath } from "../src/utils/path-utils"; -import { CompileCacheEntry, SetupCacheEntry } from "../src/types/cache"; -import { CompileFlags, ContributionSettings, ResolvedFileData } from "../src/types/core"; +import { CompileCacheEntry, ProvingSystemData, SetupCacheEntry } from "../src/types/cache"; +import { CompileFlags, ResolvedFileData } from "../src/types/core"; import { defaultCompileFlags, defaultContributionSettings } from "./constants"; export async function getCompileCacheEntry( @@ -38,17 +38,21 @@ export async function getCompileCacheEntry( export async function getSetupCacheEntry( sourceName: string, r1csSourcePath: string, - contributionSettings: ContributionSettings = defaultContributionSettings, - r1csContentHash?: string, + provingSystemsData?: ProvingSystemData[], ): Promise { - if (!r1csContentHash) { - r1csContentHash = getFileHash(r1csSourcePath); + if (!provingSystemsData) { + provingSystemsData = defaultContributionSettings.provingSystems.map((provingSystem) => { + return { + provingSystem: provingSystem, + lastR1CSFileHash: getFileHash(r1csSourcePath), + }; + }); } return { circuitSourceName: sourceName, r1csSourcePath, - r1csContentHash, - contributionSettings, + provingSystemsData, + contributionsNumber: defaultContributionSettings.contributions, }; } From f8e1661fcaef6637e9251047e5dfbe829df0d1ed Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Wed, 30 Oct 2024 13:41:51 +0200 Subject: [PATCH 02/13] Update doc comments --- package-lock.json | 161 +++++------------- package.json | 4 +- src/artifacts/CircuitArtifacts.ts | 15 +- src/cache/CircuitsSetupCache.ts | 4 +- src/core/compile/CompilationProcessor.ts | 1 + src/core/compile/index.ts | 1 - src/core/index.ts | 1 + src/core/setup/SetupFilesResolver.ts | 4 +- src/core/setup/SetupProcessor.ts | 6 +- .../TypeGenerationProcessor.ts | 0 10 files changed, 67 insertions(+), 130 deletions(-) rename src/core/{compile => zktype}/TypeGenerationProcessor.ts (100%) diff --git a/package-lock.json b/package-lock.json index ba43ba7..5b6cea8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ ], "dependencies": { "@distributedlab/circom-parser": "0.1.5", - "@solarity/zkit": "0.3.0-rc.1", + "@solarity/zkit": "0.3.0", "@solarity/zktype": "0.4.0-rc.0", "@wasmer/wasi": "0.12.0", "chalk": "4.1.2", @@ -2036,9 +2036,9 @@ } }, "node_modules/@solarity/hardhat-zkit": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@solarity/hardhat-zkit/-/hardhat-zkit-0.4.9.tgz", - "integrity": "sha512-+NnY6jBA/skFu3+KT6bJoK4HNuX97Oc86HvHXNjl1PtyBoMxxs81ZUMVKWPZPdgsKJvtPVybKaQ99fXPThAmaw==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@solarity/hardhat-zkit/-/hardhat-zkit-0.4.10.tgz", + "integrity": "sha512-6oSC9IZJwUHwdVnqlQyqQrDkaolHHv9PzqudXbPoijg6zVJcgASPBTS3DO1JMTkUDK8Yuf+U0kRyr+JkrBgAEw==", "dev": true, "peer": true, "dependencies": { @@ -2056,7 +2056,7 @@ "path-browserify": "1.0.1", "resolve": "1.22.8", "semver": "7.6.3", - "snarkjs": "0.7.3", + "snarkjs": "0.7.5", "uuid": "9.0.1", "zod": "3.23.8" }, @@ -2089,6 +2089,28 @@ "snarkjs": "0.7.3" } }, + "node_modules/@solarity/hardhat-zkit/node_modules/@solarity/zkit/node_modules/snarkjs": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.3.tgz", + "integrity": "sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==", + "dev": true, + "peer": true, + "dependencies": { + "@iden3/binfileutils": "0.0.11", + "bfj": "^7.0.2", + "blake2b-wasm": "^2.4.0", + "circom_runtime": "0.1.24", + "ejs": "^3.1.6", + "fastfile": "0.0.20", + "ffjavascript": "0.2.63", + "js-sha3": "^0.8.0", + "logplease": "^1.2.15", + "r1csfile": "0.0.47" + }, + "bin": { + "snarkjs": "build/cli.cjs" + } + }, "node_modules/@solarity/hardhat-zkit/node_modules/@solarity/zktype": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@solarity/zktype/-/zktype-0.3.1.tgz", @@ -2169,28 +2191,6 @@ "web-worker": "^1.2.0" } }, - "node_modules/@solarity/hardhat-zkit/node_modules/snarkjs": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.3.tgz", - "integrity": "sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==", - "dev": true, - "peer": true, - "dependencies": { - "@iden3/binfileutils": "0.0.11", - "bfj": "^7.0.2", - "blake2b-wasm": "^2.4.0", - "circom_runtime": "0.1.24", - "ejs": "^3.1.6", - "fastfile": "0.0.20", - "ffjavascript": "0.2.63", - "js-sha3": "^0.8.0", - "logplease": "^1.2.15", - "r1csfile": "0.0.47" - }, - "bin": { - "snarkjs": "build/cli.cjs" - } - }, "node_modules/@solarity/hardhat-zkit/node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -2206,93 +2206,12 @@ } }, "node_modules/@solarity/zkit": { - "version": "0.3.0-rc.1", - "resolved": "https://registry.npmjs.org/@solarity/zkit/-/zkit-0.3.0-rc.1.tgz", - "integrity": "sha512-Gd+uBHHPCqFxBgi0Pog2Iyz90QbyEwhIdhVWZ67oGoLq4aCzGwRDeGZWOclF/1YwIFaPlcg1WTm/GrKIv1WLUw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@solarity/zkit/-/zkit-0.3.0.tgz", + "integrity": "sha512-uIN5pXZeqXDPNuo0HVMZOcIXPc/AsVZ86KbmdIFb4YRQqzSl+si6+3sNVV69mq4Q8QpFm5mqeCGuU4l3wyCTEA==", "dependencies": { "ejs": "3.1.10", - "snarkjs": "0.7.3" - } - }, - "node_modules/@solarity/zkit/node_modules/@iden3/binfileutils": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.11.tgz", - "integrity": "sha512-LylnJoZ0CTdgErnKY8OxohvW4K+p6UHD3sxt+3P9AmMyBQjYR4IpoqoYZZ+9aMj89cmCQ21UvdhndAx04er3NA==", - "dependencies": { - "fastfile": "0.0.20", - "ffjavascript": "^0.2.48" - } - }, - "node_modules/@solarity/zkit/node_modules/circom_runtime": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.24.tgz", - "integrity": "sha512-H7/7I2J/cBmRnZm9docOCGhfxzS61BEm4TMCWcrZGsWNBQhePNfQq88Oj2XpUfzmBTCd8pRvRb3Mvazt3TMrJw==", - "dependencies": { - "ffjavascript": "0.2.60" - }, - "bin": { - "calcwit": "calcwit.js" - } - }, - "node_modules/@solarity/zkit/node_modules/circom_runtime/node_modules/ffjavascript": { - "version": "0.2.60", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", - "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "0.2.2", - "web-worker": "^1.2.0" - } - }, - "node_modules/@solarity/zkit/node_modules/ffjavascript": { - "version": "0.2.63", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", - "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "0.2.2", - "web-worker": "1.2.0" - } - }, - "node_modules/@solarity/zkit/node_modules/r1csfile": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.47.tgz", - "integrity": "sha512-oI4mAwuh1WwuFg95eJDNDDL8hCaZkwnPuNZrQdLBWvDoRU7EG+L/MOHL7SwPW2Y+ZuYcTLpj3rBkgllBQZN/JA==", - "dependencies": { - "@iden3/bigarray": "0.0.2", - "@iden3/binfileutils": "0.0.11", - "fastfile": "0.0.20", - "ffjavascript": "0.2.60" - } - }, - "node_modules/@solarity/zkit/node_modules/r1csfile/node_modules/ffjavascript": { - "version": "0.2.60", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", - "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "0.2.2", - "web-worker": "^1.2.0" - } - }, - "node_modules/@solarity/zkit/node_modules/snarkjs": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.3.tgz", - "integrity": "sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==", - "dependencies": { - "@iden3/binfileutils": "0.0.11", - "bfj": "^7.0.2", - "blake2b-wasm": "^2.4.0", - "circom_runtime": "0.1.24", - "ejs": "^3.1.6", - "fastfile": "0.0.20", - "ffjavascript": "0.2.63", - "js-sha3": "^0.8.0", - "logplease": "^1.2.15", - "r1csfile": "0.0.47" - }, - "bin": { - "snarkjs": "build/cli.cjs" + "snarkjs": "0.7.5" } }, "node_modules/@solarity/zktype": { @@ -2481,9 +2400,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.8.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.2.tgz", - "integrity": "sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==", + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", "dev": true, "dependencies": { "undici-types": "~6.19.8" @@ -3484,9 +3403,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001674", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001674.tgz", - "integrity": "sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw==", + "version": "1.0.30001675", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001675.tgz", + "integrity": "sha512-/wV1bQwPrkLiQMjaJF5yUMVM/VdRPOCU8QZ+PmG6uW6DvYSrNY1bpwHI/3mOcUosLaJCzYDi5o91IQB51ft6cg==", "dev": true, "funding": [ { @@ -7165,9 +7084,9 @@ } }, "node_modules/mocha": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", - "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.1.tgz", + "integrity": "sha512-WxSpEWgF03HfgNKBuysfK40DUaOSVX5zxgLDoieMGO+zyE69iq2eQ1vBypvIJ5mOPKpuVAqWiTbt4Orj7L6wVw==", "dev": true, "dependencies": { "ansi-colors": "^4.1.3", diff --git a/package.json b/package.json index 102404b..65b5a25 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@solarity/hardhat-zkit", - "version": "0.4.9", + "version": "0.5.0", "description": "The ultimate TypeScript environment for Circom development", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -54,7 +54,7 @@ }, "dependencies": { "@distributedlab/circom-parser": "0.1.5", - "@solarity/zkit": "0.3.0-rc.1", + "@solarity/zkit": "0.3.0", "@solarity/zktype": "0.4.0-rc.0", "@wasmer/wasi": "0.12.0", "chalk": "4.1.2", diff --git a/src/artifacts/CircuitArtifacts.ts b/src/artifacts/CircuitArtifacts.ts index e419a74..d5da47a 100644 --- a/src/artifacts/CircuitArtifacts.ts +++ b/src/artifacts/CircuitArtifacts.ts @@ -36,6 +36,14 @@ export class CircuitArtifacts implements ICircuitArtifacts { constructor(private readonly _artifactsPath: string) {} + /** + * Generates a unique artifact file key using the specified {@link ArtifactsFileType | fileType} + * and {@link ProvingSystemType | provingSystem} + * + * @param fileType The type of the artifact file + * @param provingSystem The type of the proving system + * @returns A generated key for the artifact file + */ public static getArtifactOutputFileKey(fileType: ArtifactsFileType, provingSystem: ProvingSystemType): string { if (fileType === "zkey" || fileType === "vkey") { return `${provingSystem}.${fileType}`; @@ -151,7 +159,10 @@ export class CircuitArtifacts implements ICircuitArtifacts { /** * Constructs and returns the full path for a specific artifact file based on the provided - * {@link CircuitArtifact} object and the specified {@link ArtifactsFileType | file type} + * {@link CircuitArtifact} object, the specified {@link ArtifactsFileType | file type} + * and {@link ProvingSystemType | proving system type}. + * + * The {@link ProvingSystemType | provingSystem} parameter has `groth16` value by default * * @param circuitArtifact The {@link CircuitArtifact} object representing the artifact * @param fileType The {@link ArtifactsFileType | file type} indicating the type of artifact file @@ -176,6 +187,8 @@ export class CircuitArtifacts implements ICircuitArtifacts { * @param circuitArtifact The {@link CircuitArtifact} object to be saved * @param updatedFileTypes An array of {@link ArtifactsFileType | file types} that have been modified * during the most recent session, such as during compilation + * @param provingSystems An array of {@link ProvingSystemType | proving systems} that have been added + * during the most recent session * @returns A promise that resolves once the save operation is complete */ public async saveCircuitArtifact( diff --git a/src/cache/CircuitsSetupCache.ts b/src/cache/CircuitsSetupCache.ts index aced9ce..418d539 100644 --- a/src/cache/CircuitsSetupCache.ts +++ b/src/cache/CircuitsSetupCache.ts @@ -31,8 +31,8 @@ class BaseCircuitsSetupCache extends BaseCache { * * @param artifactAbsolutePath The absolute path of the artifact file to check * @param r1csContentHash The content hash of the R1CS file to compare - * @param contributionSettings The contribution settings to compare - * @returns True if the file has changed, false otherwise. + * @param contributionSettings The setup contribution settings to compare + * @returns An array of {@link ProvingSystemType | proving systems} that were modified or required for setup */ public hasFileChanged( artifactAbsolutePath: string, diff --git a/src/core/compile/CompilationProcessor.ts b/src/core/compile/CompilationProcessor.ts index 9662a48..b5e2a1e 100644 --- a/src/core/compile/CompilationProcessor.ts +++ b/src/core/compile/CompilationProcessor.ts @@ -67,6 +67,7 @@ export class CompilationProcessor { * 6. Saves the artifact information using {@link ICircuitArtifacts | CircuitArtifacts} * * @param filesInfoToCompile Information about circuit files needed for compilation + * @param provingSystems An array of {@link ProvingSystemType | proving systems} from the plugin config */ public async compile(filesInfoToCompile: CircomResolvedFileInfo[], provingSystems: ProvingSystemType[]) { const tempDir: string = path.join(os.tmpdir(), ".zkit", uuid()); diff --git a/src/core/compile/index.ts b/src/core/compile/index.ts index fefebec..ec39baf 100644 --- a/src/core/compile/index.ts +++ b/src/core/compile/index.ts @@ -1,3 +1,2 @@ export * from "./CompilationFilesResolver"; export * from "./CompilationProcessor"; -export * from "./TypeGenerationProcessor"; diff --git a/src/core/index.ts b/src/core/index.ts index 0e1a831..910050f 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -2,4 +2,5 @@ export * from "./compile"; export * from "./compiler"; export * from "./setup"; export * from "./dependencies"; +export * from "./zktype/TypeGenerationProcessor"; export * from "./utils/PtauDownloader"; diff --git a/src/core/setup/SetupFilesResolver.ts b/src/core/setup/SetupFilesResolver.ts index 0bd6885..04e4b19 100644 --- a/src/core/setup/SetupFilesResolver.ts +++ b/src/core/setup/SetupFilesResolver.ts @@ -45,7 +45,9 @@ export class SetupFilesResolver { * 4. Applies additional filtering based on the provided setup settings to finalize the list of circuits * 5. Returns an array of {@link CircuitSetupInfo} objects * - * @param setupSettings The settings that dictate how the circuit setup should be performed + * @param contributionSettings The setup configuration settings, including the required proving systems + * and the number of contributions for the `Groth16` proving system + * @param setupFilterSettings The file filtering settings to be applied during the setup procedure * @param force A boolean flag that, when true, skips filtering by file changes during setup * @returns An array of {@link CircuitSetupInfo} objects containing information about the circuits to be set up */ diff --git a/src/core/setup/SetupProcessor.ts b/src/core/setup/SetupProcessor.ts index 895070e..0969579 100644 --- a/src/core/setup/SetupProcessor.ts +++ b/src/core/setup/SetupProcessor.ts @@ -44,8 +44,10 @@ export class SetupProcessor { * 4. Generates VKey files for the circuit artifacts * 5. Saves the circuit artifacts with the generated ZKey and VKey files * - * @param circuitArtifacts An array of circuit artifacts that need to be set up - * @param contributionSettings The contribution settings to be used during the setup process + * @param circuitSetupInfoArr An array of {@link CircuitSetupInfo} objects, + * each containing the information required to set up specific circuits + * @param contributionSettings The settings for the setup process, specifying the necessary proving systems + * and the number of contributions for the `Groth16` proving system */ public async setup(circuitSetupInfoArr: CircuitSetupInfo[], contributionSettings: SetupContributionSettings) { const tempDir: string = path.join(os.tmpdir(), ".zkit", uuid()); diff --git a/src/core/compile/TypeGenerationProcessor.ts b/src/core/zktype/TypeGenerationProcessor.ts similarity index 100% rename from src/core/compile/TypeGenerationProcessor.ts rename to src/core/zktype/TypeGenerationProcessor.ts From 367d75738ccfa56ea04377048de45cbf8abf6ed4 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Wed, 30 Oct 2024 18:14:11 +0200 Subject: [PATCH 03/13] Fix Reporter logs --- package-lock.json | 4 +- src/core/setup/SetupProcessor.ts | 46 ++++++++++++------- src/index.ts | 22 +++++---- src/reporter/ReporterFacade.ts | 45 ++++++++++++------ src/reporter/reporters/SetupReporter.ts | 10 +++- .../reporters/VKeyFilesGenerationReporter.ts | 16 +++++-- .../reporters/VerifiersGenerationReporter.ts | 22 +++++++-- .../reporters/ZKeyFilesGenerationReporter.ts | 37 +++++++++++---- 8 files changed, 142 insertions(+), 60 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b6cea8..31b10a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@solarity/hardhat-zkit", - "version": "0.4.9", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@solarity/hardhat-zkit", - "version": "0.4.9", + "version": "0.5.0", "license": "MIT", "workspaces": [ "test/fixture-projects/*" diff --git a/src/core/setup/SetupProcessor.ts b/src/core/setup/SetupProcessor.ts index 0969579..15d4f7a 100644 --- a/src/core/setup/SetupProcessor.ts +++ b/src/core/setup/SetupProcessor.ts @@ -83,18 +83,17 @@ export class SetupProcessor { contributionSettings: SetupContributionSettings, ptauFilePath: string, ) { - const contributions: number = contributionSettings.contributions; - - Reporter!.reportZKeyFilesGenerationHeader(contributions); + Reporter!.reportZKeyFilesGenerationHeader(contributionSettings); for (const setupInfo of circuitSetupInfoArr) { const r1csFilePath = setupInfo.circuitArtifact.compilerOutputFiles.r1cs!.fileSourcePath; - const spinnerId: string | null = Reporter!.reportZKeyFileGenerationStartWithSpinner( - setupInfo.circuitArtifact.circuitTemplateName, - ); - for (const provingSystem of setupInfo.provingSystems) { + const spinnerId: string | null = Reporter!.reportZKeyFileGenerationStartWithSpinner( + setupInfo.circuitArtifact.circuitTemplateName, + provingSystem, + ); + const zkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath( setupInfo.circuitArtifact, "zkey", @@ -109,7 +108,12 @@ export class SetupProcessor { switch (provingSystem) { case "groth16": - await this._generateGroth16ZKeyFile(r1csFilePath, ptauFilePath, zkeyFilePath, contributions); + await this._generateGroth16ZKeyFile( + r1csFilePath, + ptauFilePath, + zkeyFilePath, + contributionSettings.contributions, + ); break; case "plonk": await this._generatePlonkZKeyFile(r1csFilePath, ptauFilePath, zkeyFilePath); @@ -117,9 +121,14 @@ export class SetupProcessor { default: throw new HardhatZKitError(`Unsupported proving system - ${provingSystem}`); } - } - Reporter!.reportZKeyFileGenerationResult(spinnerId, setupInfo.circuitArtifact.circuitTemplateName, contributions); + Reporter!.reportZKeyFileGenerationResult( + spinnerId, + setupInfo.circuitArtifact.circuitTemplateName, + provingSystem, + contributionSettings.contributions, + ); + } } } @@ -127,11 +136,12 @@ export class SetupProcessor { Reporter!.reportVKeyFilesGenerationHeader(); for (const setupInfo of circuitSetupInfoArr) { - const spinnerId: string | null = Reporter!.reportVKeyFileGenerationStartWithSpinner( - setupInfo.circuitArtifact.circuitTemplateName, - ); - for (const provingSystem of setupInfo.provingSystems) { + const spinnerId: string | null = Reporter!.reportVKeyFileGenerationStartWithSpinner( + setupInfo.circuitArtifact.circuitTemplateName, + provingSystem, + ); + const zkeyFilePath = this._circuitArtifacts.getCircuitArtifactFileFullPath( setupInfo.circuitArtifact, "zkey", @@ -152,9 +162,13 @@ export class SetupProcessor { const vKeyData = await snarkjs.zKey.exportVerificationKey(zkeyFilePath); fsExtra.outputFileSync(vkeyFilePath, JSON.stringify(vKeyData)); - } - Reporter!.reportVKeyFileGenerationResult(spinnerId, setupInfo.circuitArtifact.circuitTemplateName); + Reporter!.reportVKeyFileGenerationResult( + spinnerId, + setupInfo.circuitArtifact.circuitTemplateName, + provingSystem, + ); + } } } diff --git a/src/index.ts b/src/index.ts index d6d2705..7ea4766 100644 --- a/src/index.ts +++ b/src/index.ts @@ -286,12 +286,13 @@ const generateVerifiers: ActionType = async ( for (const name of allFullyQualifiedNames) { const circuitArtifact: CircuitArtifact = await env.zkit.circuitArtifacts.readCircuitArtifact(name); - const spinnerId: string | null = Reporter!.reportVerifierGenerationStartWithSpinner( - circuitArtifact.circuitTemplateName, - verifiersType, - ); - for (const provingSystem of provingSystems) { + const spinnerId: string | null = Reporter!.reportVerifierGenerationStartWithSpinner( + circuitArtifact.circuitTemplateName, + verifiersType, + provingSystem, + ); + if (!protocolImplementers.has(provingSystem)) { switch (provingSystem) { case "groth16": @@ -318,12 +319,17 @@ const generateVerifiers: ActionType = async ( }, protocolImplementer, ).createVerifier(verifiersType); - } - Reporter!.reportVerifierGenerationResult(spinnerId, circuitArtifact.circuitTemplateName, verifiersType); + Reporter!.reportVerifierGenerationResult( + spinnerId, + circuitArtifact.circuitTemplateName, + verifiersType, + provingSystem, + ); + } } - Reporter!.reportVerifiersGenerationResult(verifiersType, allFullyQualifiedNames.length); + Reporter!.reportVerifiersGenerationResult(verifiersType, allFullyQualifiedNames.length * provingSystems.length); } else { Reporter!.reportNothingToGenerate(); } diff --git a/src/reporter/ReporterFacade.ts b/src/reporter/ReporterFacade.ts index 72ec80a..2e7c62a 100644 --- a/src/reporter/ReporterFacade.ts +++ b/src/reporter/ReporterFacade.ts @@ -1,7 +1,7 @@ /* eslint-disable no-console */ import debug from "debug"; -import { VerifierLanguageType } from "@solarity/zkit"; +import { ProvingSystemType, VerifierLanguageType } from "@solarity/zkit"; import { ProgressReporter, @@ -19,7 +19,7 @@ import { import { createProgressBarProcessor } from "./ProgressBarProcessor"; import { createSpinnerProcessor } from "./SpinnerProcessor"; -import { CompilationInfo, CircuitSetupInfo, SimpleParserRuleContext } from "../types/core"; +import { CompilationInfo, CircuitSetupInfo, SimpleParserRuleContext, SetupContributionSettings } from "../types/core"; /** * A facade for reporting various types of log information to the user, @@ -155,28 +155,43 @@ class ReporterFacade { this._setupReporter.reportResult(circuitSetupInfoArr); } - public reportZKeyFilesGenerationHeader(contributions: number) { - this._zKeyFilesGenerationReporter.reportHeader(contributions); + public reportZKeyFilesGenerationHeader(contributionSettings: SetupContributionSettings) { + this._zKeyFilesGenerationReporter.reportHeader(contributionSettings); } - public reportZKeyFileGenerationStartWithSpinner(circuitName: string): string | null { - return this._zKeyFilesGenerationReporter.reportStartWithSpinner(circuitName); + public reportZKeyFileGenerationStartWithSpinner( + circuitName: string, + provingSystem: ProvingSystemType, + ): string | null { + return this._zKeyFilesGenerationReporter.reportStartWithSpinner(circuitName, provingSystem); } - public reportZKeyFileGenerationResult(spinnerId: string | null, circuitName: string, contributionsNumber: number) { - this._zKeyFilesGenerationReporter.reportResult(spinnerId, circuitName, contributionsNumber); + public reportZKeyFileGenerationResult( + spinnerId: string | null, + circuitName: string, + provingSystem: ProvingSystemType, + contributionsNumber: number, + ) { + this._zKeyFilesGenerationReporter.reportResult(spinnerId, circuitName, provingSystem, contributionsNumber); } public reportVKeyFilesGenerationHeader() { this._vKeyFilesGenerationReporter.reportHeader(); } - public reportVKeyFileGenerationStartWithSpinner(circuitName: string): string | null { - return this._vKeyFilesGenerationReporter.reportStartWithSpinner(circuitName); + public reportVKeyFileGenerationStartWithSpinner( + circuitName: string, + provingSystem: ProvingSystemType, + ): string | null { + return this._vKeyFilesGenerationReporter.reportStartWithSpinner(circuitName, provingSystem); } - public reportVKeyFileGenerationResult(spinnerId: string | null, circuitName: string) { - this._vKeyFilesGenerationReporter.reportResult(spinnerId, circuitName); + public reportVKeyFileGenerationResult( + spinnerId: string | null, + circuitName: string, + provingSystem: ProvingSystemType, + ) { + this._vKeyFilesGenerationReporter.reportResult(spinnerId, circuitName, provingSystem); } public reportNothingToCompile() { @@ -198,16 +213,18 @@ class ReporterFacade { public reportVerifierGenerationStartWithSpinner( circuitName: string, verifiersType: VerifierLanguageType, + provingSystem: ProvingSystemType, ): string | null { - return this._verifiersGenerationReporter.reportStartWithSpinner(circuitName, verifiersType); + return this._verifiersGenerationReporter.reportStartWithSpinner(circuitName, verifiersType, provingSystem); } public reportVerifierGenerationResult( spinnerId: string | null, circuitName: string, verifiersType: VerifierLanguageType, + provingSystem: ProvingSystemType, ) { - this._verifiersGenerationReporter.reportResult(spinnerId, circuitName, verifiersType); + this._verifiersGenerationReporter.reportResult(spinnerId, circuitName, verifiersType, provingSystem); } public reportVerifiersGenerationResult(verifiersType: VerifierLanguageType, verifiersCount: number) { diff --git a/src/reporter/reporters/SetupReporter.ts b/src/reporter/reporters/SetupReporter.ts index a7058d5..556ff00 100644 --- a/src/reporter/reporters/SetupReporter.ts +++ b/src/reporter/reporters/SetupReporter.ts @@ -1,6 +1,7 @@ /* eslint-disable no-console */ import fs from "fs"; import chalk from "chalk"; +import { capitalize } from "lodash"; import { BaseReporter } from "./BaseReporter"; import { CircuitArtifacts } from "../../artifacts/CircuitArtifacts"; @@ -59,12 +60,17 @@ export class SetupReporter extends BaseReporter { const table = this._getCLITable(); - table.push([{ content: chalk.bold("Circuit Name") }, { content: chalk.bold(`ZKey file size (MB)`) }]); + table.push([ + { content: chalk.bold("Circuit Name") }, + { content: chalk.bold("Proving system") }, + { content: chalk.bold(`ZKey file size (MB)`) }, + ]); for (const setupInfo of circuitSetupInfoArr) { for (const provingSystem of setupInfo.provingSystems) { table.push([ - { content: `${setupInfo.circuitArtifact.circuitTemplateName} ${chalk.grey(`(${provingSystem})`)}` }, + { content: setupInfo.circuitArtifact.circuitTemplateName }, + { content: capitalize(provingSystem), hAlign: "left" }, { content: this._getFileSizeInMB( setupInfo.circuitArtifact.compilerOutputFiles[ diff --git a/src/reporter/reporters/VKeyFilesGenerationReporter.ts b/src/reporter/reporters/VKeyFilesGenerationReporter.ts index 8ea0313..ba7523d 100644 --- a/src/reporter/reporters/VKeyFilesGenerationReporter.ts +++ b/src/reporter/reporters/VKeyFilesGenerationReporter.ts @@ -1,5 +1,9 @@ /* eslint-disable no-console */ import chalk from "chalk"; +import { capitalize } from "lodash"; + +import { ProvingSystemType } from "@solarity/zkit"; + import { BaseReporter } from "./BaseReporter"; import { SpinnerProcessor } from "../SpinnerProcessor"; @@ -16,11 +20,15 @@ export class VKeyFilesGenerationReporter extends BaseReporter { console.log(output); } - public reportStartWithSpinner(circuitName: string): string | null { - return this._startSpinner(circuitName, "generate-vkey", `Generating VKey file for ${circuitName} circuit`); + public reportStartWithSpinner(circuitName: string, provingSystem: ProvingSystemType): string | null { + return this._startSpinner( + circuitName, + "generate-vkey", + `Generating ${capitalize(provingSystem)} VKey file for ${circuitName} circuit`, + ); } - public reportResult(spinnerId: string | null, circuitName: string) { + public reportResult(spinnerId: string | null, circuitName: string, provingSystem: ProvingSystemType) { if (this.isQuiet() || !spinnerId) return; const generationTimeMessage: string = this._getSpinnerWorkingTimeMessage( @@ -29,7 +37,7 @@ export class VKeyFilesGenerationReporter extends BaseReporter { SpinnerProcessor!.succeedSpinner( spinnerId, - `Generated VKey file for ${chalk.italic(circuitName)} circuit ${generationTimeMessage}`, + `Generated ${capitalize(provingSystem)} VKey file for ${chalk.italic(circuitName)} circuit ${generationTimeMessage}`, ); } } diff --git a/src/reporter/reporters/VerifiersGenerationReporter.ts b/src/reporter/reporters/VerifiersGenerationReporter.ts index b5a03b2..d280c49 100644 --- a/src/reporter/reporters/VerifiersGenerationReporter.ts +++ b/src/reporter/reporters/VerifiersGenerationReporter.ts @@ -1,9 +1,12 @@ /* eslint-disable no-console */ import chalk from "chalk"; +import { capitalize } from "lodash"; + +import { ProvingSystemType, VerifierLanguageType } from "@solarity/zkit"; + import { BaseReporter } from "./BaseReporter"; import { SpinnerProcessor } from "../SpinnerProcessor"; import { HardhatZKitError } from "../../errors"; -import { VerifierLanguageType } from "@solarity/zkit"; export class VerifiersGenerationReporter extends BaseReporter { public reportHeader(verifiersType: VerifierLanguageType) { @@ -16,15 +19,24 @@ export class VerifiersGenerationReporter extends BaseReporter { console.log(output); } - public reportStartWithSpinner(circuitName: string, verifiersType: VerifierLanguageType): string | null { + public reportStartWithSpinner( + circuitName: string, + verifiersType: VerifierLanguageType, + provingSystem: ProvingSystemType, + ): string | null { return this._startSpinner( circuitName, "verifier-generation", - `Generating ${this._getVerifierLanguageMessage(verifiersType)} verifier contract for ${circuitName} circuit`, + `Generating ${capitalize(provingSystem)} ${this._getVerifierLanguageMessage(verifiersType)} verifier contract for ${circuitName} circuit`, ); } - public reportResult(spinnerId: string | null, circuitName: string, verifiersType: VerifierLanguageType) { + public reportResult( + spinnerId: string | null, + circuitName: string, + verifiersType: VerifierLanguageType, + provingSystem: ProvingSystemType, + ) { if (this.isQuiet() || !spinnerId) return; const generationTimeMessage: string = this._getSpinnerWorkingTimeMessage( @@ -33,7 +45,7 @@ export class VerifiersGenerationReporter extends BaseReporter { SpinnerProcessor!.succeedSpinner( spinnerId, - `Generated ${this._getVerifierLanguageMessage(verifiersType)} verifier contract for ${chalk.italic(circuitName)} circuit ${generationTimeMessage}`, + `Generated ${capitalize(provingSystem)} ${this._getVerifierLanguageMessage(verifiersType)} verifier contract for ${chalk.italic(circuitName)} circuit ${generationTimeMessage}`, ); } diff --git a/src/reporter/reporters/ZKeyFilesGenerationReporter.ts b/src/reporter/reporters/ZKeyFilesGenerationReporter.ts index 1ad6043..6a56b89 100644 --- a/src/reporter/reporters/ZKeyFilesGenerationReporter.ts +++ b/src/reporter/reporters/ZKeyFilesGenerationReporter.ts @@ -1,21 +1,29 @@ /* eslint-disable no-console */ import chalk from "chalk"; +import { capitalize } from "lodash"; + import { pluralize } from "hardhat/internal/util/strings"; +import { ProvingSystemType } from "@solarity/zkit"; + import { BaseReporter } from "./BaseReporter"; import { SpinnerProcessor } from "../SpinnerProcessor"; +import { SetupContributionSettings } from "../../../src/types/core"; + export class ZKeyFilesGenerationReporter extends BaseReporter { - public reportHeader(contributions: number) { + public reportHeader(contributionSettings: SetupContributionSettings) { if (this.isQuiet()) return; let output: string = ""; output += `\n${chalk.italic.cyan("Second step - Generating ZKey files for circuits")}\n`; - if (contributions > 0) { - output += `\n> Phase-2 contributions to ZKey file ${chalk.green("enabled")}`; - output += `\n> Contributions count: ${contributions}\n`; + output += `\n> Configured proving systems: ${contributionSettings.provingSystems.map((provingSystem) => capitalize(provingSystem)).join(", ")}\n`; + + if (contributionSettings.provingSystems.includes("groth16") && contributionSettings.contributions > 0) { + output += `> Groth16 Phase-2 contributions to ZKey file ${chalk.green("enabled")}`; + output += `\n> Contributions count: ${contributionSettings.contributions}\n`; } output += `\nStarting generation of ZKey files:\n`; @@ -23,22 +31,33 @@ export class ZKeyFilesGenerationReporter extends BaseReporter { console.log(output); } - public reportStartWithSpinner(circuitName: string): string | null { - return this._startSpinner(circuitName, "generate-zkey", `Generating ZKey file for ${circuitName} circuit`); + public reportStartWithSpinner(circuitName: string, provingSystem: ProvingSystemType): string | null { + return this._startSpinner( + circuitName, + "generate-zkey", + `Generating ${capitalize(provingSystem)} ZKey file for ${circuitName} circuit`, + ); } - public reportResult(spinnerId: string | null, circuitName: string, contributionsNumber: number) { + public reportResult( + spinnerId: string | null, + circuitName: string, + provingSystem: ProvingSystemType, + contributionsNumber: number, + ) { if (this.isQuiet() || !spinnerId) return; const generationTimeMessage: string | undefined = this._getSpinnerWorkingTimeMessage( SpinnerProcessor!.getWorkingTime(spinnerId), ); const contributionMessage: string = - contributionsNumber !== 0 ? `with ${contributionsNumber} ${pluralize(contributionsNumber, "contribution")} ` : ""; + provingSystem === "groth16" && contributionsNumber !== 0 + ? `with ${contributionsNumber} ${pluralize(contributionsNumber, "contribution")} ` + : ""; SpinnerProcessor!.succeedSpinner( spinnerId, - `Generated ZKey file for ${chalk.italic(circuitName)} circuit ${contributionMessage}${generationTimeMessage}`, + `Generated ${capitalize(provingSystem)} ZKey file for ${chalk.italic(circuitName)} circuit ${contributionMessage}${generationTimeMessage}`, ); } } From 66386602c26fff578ea1bdbd790acdd4fbacaa9c Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Fri, 1 Nov 2024 17:26:50 +0200 Subject: [PATCH 04/13] Add CircuitZKitBuilder class --- src/core/index.ts | 1 + src/core/zkit/CircuitZKitBuilder.ts | 109 +++++++++++++++ src/core/zktype/TypeGenerationProcessor.ts | 7 + src/index.ts | 131 +++--------------- src/task-names.ts | 2 - src/types/core/index.ts | 1 + src/types/core/zkit/circuit-zkit-builder.ts | 11 ++ src/types/hardhat-zkit.ts | 6 +- src/types/tasks.ts | 8 +- .../hardhat.config.ts | 3 + test/integration/tasks.test.ts | 2 +- 11 files changed, 156 insertions(+), 125 deletions(-) create mode 100644 src/core/zkit/CircuitZKitBuilder.ts create mode 100644 src/types/core/zkit/circuit-zkit-builder.ts diff --git a/src/core/index.ts b/src/core/index.ts index 910050f..4b4e357 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -3,4 +3,5 @@ export * from "./compiler"; export * from "./setup"; export * from "./dependencies"; export * from "./zktype/TypeGenerationProcessor"; +export * from "./zkit/CircuitZKitBuilder"; export * from "./utils/PtauDownloader"; diff --git a/src/core/zkit/CircuitZKitBuilder.ts b/src/core/zkit/CircuitZKitBuilder.ts new file mode 100644 index 0000000..1b1bc48 --- /dev/null +++ b/src/core/zkit/CircuitZKitBuilder.ts @@ -0,0 +1,109 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { willRunWithTypescript } from "hardhat/internal/core/typescript-support"; + +import { + CircuitZKit, + CircuitZKitConfig, + Groth16Implementer, + IProtocolImplementer, + PlonkImplementer, + ProvingSystemType, +} from "@solarity/zkit"; +import { CircuitTypesGenerator } from "@solarity/zktype"; + +import { HardhatZKitError } from "../../errors"; +import { getNormalizedFullPath } from "../../utils"; + +import { ICircuitZKitBuilder } from "../../types/core"; +import { CircuitArtifact } from "../../types/artifacts/circuit-artifacts"; + +export class CircuitZKitBuilder implements ICircuitZKitBuilder { + private readonly _isTSProject: boolean; + private readonly _typesGenerator: CircuitTypesGenerator; + private _protocolImplementers = new Map>(); + + constructor(private readonly _hre: HardhatRuntimeEnvironment) { + this._typesGenerator = new CircuitTypesGenerator({ + basePath: _hre.config.zkit.circuitsDir, + projectRoot: _hre.config.paths.root, + outputTypesDir: _hre.config.zkit.typesDir, + circuitsArtifactsPaths: [], + }); + + this._isTSProject = willRunWithTypescript(_hre.hardhatArguments.config); + } + + public async getCircuitZKit( + circuitName: string, + provingSystem?: ProvingSystemType, + verifiersDir?: string, + ): Promise> { + const circuitArtifact: CircuitArtifact = await this._hre.zkit.circuitArtifacts.readCircuitArtifact(circuitName); + const circuitZKitConfig: CircuitZKitConfig = this._getCircuitZKitConfig(circuitArtifact, verifiersDir); + + if (this._isTSProject) { + if (circuitArtifact.baseCircuitInfo.protocol.length > 1 && !provingSystem) { + throw new HardhatZKitError( + "Found several proving systems. Please specify the exact proving system in getCircuit function", + ); + } else if (circuitArtifact.baseCircuitInfo.protocol.length === 1) { + const existingProvingSystem: ProvingSystemType = circuitArtifact.baseCircuitInfo.protocol[0]; + + if (provingSystem && provingSystem !== existingProvingSystem) { + throw new HardhatZKitError( + `Passed invalid proving system. Please pass ${existingProvingSystem} proving system or run make task with needed proving systems`, + ); + } + + provingSystem = undefined; + } + + const module = await this._typesGenerator.getCircuitObject(circuitName, provingSystem); + + return new module(circuitZKitConfig); + } else { + if (!provingSystem || !circuitArtifact.baseCircuitInfo.protocol.includes(provingSystem)) { + throw new HardhatZKitError( + "Passed undefined or invalid proving system. Please run make task or change proving system.", + ); + } + + return new CircuitZKit(circuitZKitConfig, this.getProtocolImplementer(provingSystem)); + } + } + + public getProtocolImplementer(provingSystem: ProvingSystemType): IProtocolImplementer { + if (!this._protocolImplementers.has(provingSystem)) { + switch (provingSystem) { + case "groth16": + this._protocolImplementers.set(provingSystem, new Groth16Implementer()); + break; + case "plonk": + this._protocolImplementers.set(provingSystem, new PlonkImplementer()); + break; + default: + throw new HardhatZKitError(`Unsupported proving system - ${provingSystem}`); + } + } + + return this._protocolImplementers.get(provingSystem)!; + } + + private _getCircuitZKitConfig(circuitArtifact: CircuitArtifact, verifiersDir: string | undefined): CircuitZKitConfig { + const verifiersDirFullPath: string = getNormalizedFullPath( + this._hre.config.paths.root, + verifiersDir ?? this._hre.config.zkit.verifiersSettings.verifiersDir, + ); + + const circuitArtifactsDirPath: string = getNormalizedFullPath( + this._hre.zkit.circuitArtifacts.getCircuitArtifactsDirFullPath(), + circuitArtifact.circuitSourceName, + ); + + return { + circuitName: circuitArtifact.circuitTemplateName, + circuitArtifactsPath: circuitArtifactsDirPath, + verifierDirPath: verifiersDirFullPath, + }; + } +} diff --git a/src/core/zktype/TypeGenerationProcessor.ts b/src/core/zktype/TypeGenerationProcessor.ts index 2c67f84..1505d00 100644 --- a/src/core/zktype/TypeGenerationProcessor.ts +++ b/src/core/zktype/TypeGenerationProcessor.ts @@ -1,5 +1,6 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { localPathToSourceName } from "hardhat/utils/source-names"; +import { willRunWithTypescript } from "hardhat/internal/core/typescript-support"; import { CircuitTypesGenerator } from "@solarity/zktype"; @@ -24,11 +25,13 @@ export class TypeGenerationProcessor { private readonly _zkitConfig: ZKitConfig; private readonly _circuitArtifacts: ICircuitArtifacts; private readonly _root: string; + private readonly _isTSProject: boolean; constructor(hre: HardhatRuntimeEnvironment) { this._circuitArtifacts = hre.zkit.circuitArtifacts; this._zkitConfig = hre.config.zkit; this._root = hre.config.paths.root; + this._isTSProject = willRunWithTypescript(hre.hardhatArguments.config); } /** @@ -42,6 +45,10 @@ export class TypeGenerationProcessor { * 4. Generate the types based on the provided circuit artifacts */ public async generateAllTypes() { + if (!this._isTSProject) { + return; + } + const circuitsArtifactsPaths: string[] = await Promise.all( (await this._circuitArtifacts.getCircuitArtifactPaths()).map(async (fullPath: string) => { return localPathToSourceName(this._root, fullPath); diff --git a/src/index.ts b/src/index.ts index 7ea4766..cec5bb6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,21 +3,11 @@ import path from "path"; import fs from "fs"; import { lazyObject } from "hardhat/plugins"; -import { extendConfig, extendEnvironment, scope, task, subtask, types } from "hardhat/config"; +import { extendConfig, extendEnvironment, scope, task, types } from "hardhat/config"; import { ActionType, HardhatRuntimeEnvironment, RunSuperFunction } from "hardhat/types"; import { TASK_CLEAN, TASK_COMPILE_SOLIDITY_READ_FILE as TASK_READ_FILE } from "hardhat/builtin-tasks/task-names"; -import { willRunWithTypescript } from "hardhat/internal/core/typescript-support"; -import { - CircuitZKit, - CircuitZKitConfig, - VerifierLanguageType, - ProvingSystemType, - IProtocolImplementer, - Groth16Implementer, - PlonkImplementer, -} from "@solarity/zkit"; -import { CircuitTypesGenerator } from "@solarity/zktype"; +import { CircuitZKit, VerifierLanguageType, ProvingSystemType } from "@solarity/zkit"; import "./type-extensions"; @@ -28,7 +18,6 @@ import { TASK_CIRCUITS_SETUP, TASK_GENERATE_VERIFIERS, TASK_ZKIT_CLEAN, - SUBTASK_ZKIT_GET_CIRCUIT_ZKIT, } from "./task-names"; import { zkitConfigExtender } from "./config/config"; @@ -45,6 +34,8 @@ import { TypeGenerationProcessor, SetupProcessor, SetupFilesResolver, + isVersionValid, + CircuitZKitBuilder, } from "./core"; import { HardhatZKitError } from "./errors"; @@ -52,15 +43,8 @@ import { Reporter, createReporter } from "./reporter"; import { CircuitArtifacts } from "./artifacts/CircuitArtifacts"; import { CIRCUITS_COMPILE_CACHE_FILENAME, CIRCUITS_SETUP_CACHE_FILENAME } from "./constants"; import { getNormalizedFullPath, getUniqueProvingSystems } from "./utils"; -import { isVersionValid } from "./core/compiler/versioning"; -import { - MakeTaskConfig, - CompileTaskConfig, - GenerateVerifiersTaskConfig, - GetCircuitZKitConfig, - SetupTaskConfig, -} from "./types/tasks"; +import { MakeTaskConfig, CompileTaskConfig, GenerateVerifiersTaskConfig, SetupTaskConfig } from "./types/tasks"; import { CircuitArtifact } from "./types/artifacts/circuit-artifacts"; import { CompileFlags, CircomResolvedFileInfo, CircuitSetupInfo, SetupContributionSettings } from "./types/core"; import { ProvingSystemData } from "./types/cache"; @@ -74,14 +58,16 @@ extendEnvironment((hre) => { const circuitArtifacts: CircuitArtifacts = new CircuitArtifacts( getNormalizedFullPath(hre.config.paths.root, hre.config.zkit.compilationSettings.artifactsDir), ); + const circuitZKitBuilder: CircuitZKitBuilder = new CircuitZKitBuilder(hre); return { circuitArtifacts, + circuitZKitBuilder, getCircuit: async ( circuitName: string, - provingSystem: ProvingSystemType = "groth16", - ): Promise> => { - return hre.run(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT, { circuitName, provingSystem }); + provingSystem?: ProvingSystemType, + ): Promise> => { + return circuitZKitBuilder.getCircuitZKit(circuitName, provingSystem); }, }; }); @@ -274,51 +260,24 @@ const generateVerifiers: ActionType = async ( Reporter!.verboseLog("index", "Verifiers generation dir - %s", [verifiersDirFullPath]); const allFullyQualifiedNames: string[] = await env.zkit.circuitArtifacts.getAllCircuitFullyQualifiedNames(); + let verifiersCount: number = 0; if (allFullyQualifiedNames.length > 0) { Reporter!.reportVerifiersGenerationHeader(verifiersType); - const provingSystems: ProvingSystemType[] = getUniqueProvingSystems( - env.config.zkit.setupSettings.contributionSettings.provingSystem, - ); - const protocolImplementers = new Map>(); - for (const name of allFullyQualifiedNames) { const circuitArtifact: CircuitArtifact = await env.zkit.circuitArtifacts.readCircuitArtifact(name); - for (const provingSystem of provingSystems) { + for (const provingSystem of circuitArtifact.baseCircuitInfo.protocol) { const spinnerId: string | null = Reporter!.reportVerifierGenerationStartWithSpinner( circuitArtifact.circuitTemplateName, verifiersType, provingSystem, ); - if (!protocolImplementers.has(provingSystem)) { - switch (provingSystem) { - case "groth16": - protocolImplementers.set(provingSystem, new Groth16Implementer()); - break; - case "plonk": - protocolImplementers.set(provingSystem, new PlonkImplementer()); - break; - default: - throw new HardhatZKitError(`Unsupported proving system - ${provingSystem}`); - } - } - - const protocolImplementer: IProtocolImplementer = - protocolImplementers.get(provingSystem)!; - - await new CircuitZKit( - { - circuitName: circuitArtifact.circuitTemplateName, - circuitArtifactsPath: path.dirname( - env.zkit.circuitArtifacts.formCircuitArtifactPathFromFullyQualifiedName(name), - ), - verifierDirPath: verifiersDirFullPath, - }, - protocolImplementer, - ).createVerifier(verifiersType); + (await env.zkit.circuitZKitBuilder.getCircuitZKit(name, provingSystem, taskArgs.verifiersDir)).createVerifier( + verifiersType, + ); Reporter!.reportVerifierGenerationResult( spinnerId, @@ -326,10 +285,12 @@ const generateVerifiers: ActionType = async ( verifiersType, provingSystem, ); + + verifiersCount++; } } - Reporter!.reportVerifiersGenerationResult(verifiersType, allFullyQualifiedNames.length * provingSystems.length); + Reporter!.reportVerifiersGenerationResult(verifiersType, verifiersCount); } else { Reporter!.reportNothingToGenerate(); } @@ -356,56 +317,6 @@ const clean: ActionType = async (_taskArgs: any, env: HardhatRuntimeEnviron fs.rmSync(circuitTypesFullPath, { recursive: true, force: true }); }; -const getCircuitZKit: ActionType = async ( - taskArgs: GetCircuitZKitConfig, - env: HardhatRuntimeEnvironment, -): Promise> => { - const circuitArtifact: CircuitArtifact = await env.zkit.circuitArtifacts.readCircuitArtifact(taskArgs.circuitName); - - const verifiersDirFullPath: string = getNormalizedFullPath( - env.config.paths.root, - taskArgs.verifiersDir ?? env.config.zkit.verifiersSettings.verifiersDir, - ); - const circuitArtifactsDirPath: string = getNormalizedFullPath( - env.zkit.circuitArtifacts.getCircuitArtifactsDirFullPath(), - circuitArtifact.circuitSourceName, - ); - - const typesGenerator: CircuitTypesGenerator = new CircuitTypesGenerator({ - basePath: env.config.zkit.circuitsDir, - projectRoot: env.config.paths.root, - outputTypesDir: env.config.zkit.typesDir, - circuitsArtifactsPaths: [], - }); - - const circuitZKitConfig: CircuitZKitConfig = { - circuitName: circuitArtifact.circuitTemplateName, - circuitArtifactsPath: circuitArtifactsDirPath, - verifierDirPath: verifiersDirFullPath, - }; - - if (willRunWithTypescript(env.hardhatArguments.config)) { - const module = await typesGenerator.getCircuitObject(taskArgs.circuitName); - - return new module(circuitZKitConfig); - } else { - let protocolImplementer: IProtocolImplementer; - - switch (taskArgs.provingSystem) { - case "groth16": - protocolImplementer = new Groth16Implementer(); - break; - case "plonk": - protocolImplementer = new PlonkImplementer(); - break; - default: - throw new HardhatZKitError(`Unsupported proving system - ${taskArgs.provingSystem}`); - } - - return new CircuitZKit(circuitZKitConfig, protocolImplementer); - } -}; - task(TASK_CLEAN).setAction(async (_taskArgs: any, env: HardhatRuntimeEnvironment, runSuper: RunSuperFunction) => { await runSuper(); @@ -459,9 +370,3 @@ zkitScope .setAction(generateVerifiers); zkitScope.task(TASK_ZKIT_CLEAN, "Clean all circuit artifacts, keys, types and etc").setAction(clean); - -subtask(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT) - .addOptionalParam("verifiersDir", undefined, undefined, types.string) - .addOptionalParam("verifierTemplateType", undefined, undefined, types.any) - .addParam("circuitName", undefined, undefined, types.string) - .setAction(getCircuitZKit); diff --git a/src/task-names.ts b/src/task-names.ts index 7110645..1d28b2d 100644 --- a/src/task-names.ts +++ b/src/task-names.ts @@ -5,5 +5,3 @@ export const TASK_CIRCUITS_COMPILE = "compile"; export const TASK_CIRCUITS_SETUP = "setup"; export const TASK_GENERATE_VERIFIERS = "verifiers"; export const TASK_ZKIT_CLEAN = "clean"; - -export const SUBTASK_ZKIT_GET_CIRCUIT_ZKIT = "zkit:get-circuit-zkit"; diff --git a/src/types/core/index.ts b/src/types/core/index.ts index 5cd2a0a..e60a642 100644 --- a/src/types/core/index.ts +++ b/src/types/core/index.ts @@ -2,3 +2,4 @@ export * from "./compile"; export * from "./compiler"; export * from "./setup"; export * from "./dependencies"; +export * from "./zkit/circuit-zkit-builder"; diff --git a/src/types/core/zkit/circuit-zkit-builder.ts b/src/types/core/zkit/circuit-zkit-builder.ts new file mode 100644 index 0000000..b4d6b4d --- /dev/null +++ b/src/types/core/zkit/circuit-zkit-builder.ts @@ -0,0 +1,11 @@ +import { CircuitZKit, IProtocolImplementer, ProvingSystemType } from "@solarity/zkit"; + +export interface ICircuitZKitBuilder { + getCircuitZKit( + circuitName: string, + provingSystem?: ProvingSystemType, + verifiersDir?: string, + ): Promise>; + + getProtocolImplementer(provingSystem: ProvingSystemType): IProtocolImplementer; +} diff --git a/src/types/hardhat-zkit.ts b/src/types/hardhat-zkit.ts index 9409dc6..5b5c3eb 100644 --- a/src/types/hardhat-zkit.ts +++ b/src/types/hardhat-zkit.ts @@ -1,14 +1,16 @@ import { CircuitZKit, ProvingSystemType } from "@solarity/zkit"; +import { ICircuitZKitBuilder } from "./core"; import { ICircuitArtifacts } from "./artifacts/circuit-artifacts"; export declare function getCircuit( circuitName: string, - provingSystem: ProvingSystemType, -): Promise>; + provingSystem?: ProvingSystemType, +): Promise>; export interface HardhatZKit { circuitArtifacts: ICircuitArtifacts; + circuitZKitBuilder: ICircuitZKitBuilder; getCircuit: typeof getCircuit; } diff --git a/src/types/tasks.ts b/src/types/tasks.ts index ba49835..3c4489f 100644 --- a/src/types/tasks.ts +++ b/src/types/tasks.ts @@ -1,4 +1,4 @@ -import { VerifierLanguageType, ProvingSystemType } from "@solarity/zkit"; +import { VerifierLanguageType } from "@solarity/zkit"; export type MakeTaskConfig = { force: boolean; @@ -27,9 +27,3 @@ export type GenerateVerifiersTaskConfig = { quiet: boolean; force: boolean; }; - -export type GetCircuitZKitConfig = { - verifiersDir?: string; - circuitName: string; - provingSystem: ProvingSystemType; -}; diff --git a/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts b/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts index b15dfa9..077e694 100644 --- a/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts +++ b/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts @@ -11,6 +11,9 @@ const defaultConfig: HardhatUserConfig = { skipFiles: ["vendor"], }, setupSettings: { + contributionSettings: { + provingSystem: ["groth16"], + }, ptauDir: "zkit/ptau", ptauDownload: true, }, diff --git a/test/integration/tasks.test.ts b/test/integration/tasks.test.ts index 589b6c5..e57174f 100644 --- a/test/integration/tasks.test.ts +++ b/test/integration/tasks.test.ts @@ -84,7 +84,7 @@ describe("ZKit tasks", async function () { const ptauFullPath: string = getNormalizedFullPath(config.paths!.root!, "zkit/ptau"); expect(fsExtra.readdirSync(ptauFullPath)).to.be.deep.eq(["powers-of-tau-8.ptau"]); - const circuit = await zkit.getCircuit("Multiplier2", "groth16"); + const circuit = await zkit.getCircuit("Multiplier2"); await expect(circuit).with.witnessInputs({ in1: "3", in2: "7" }).to.have.witnessOutputs(["21"]); const proof = await circuit.generateProof({ in1: "4", in2: "2" }); From 58c116c6d9b22d4b04c7e45e0bf5a74822774b58 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Mon, 4 Nov 2024 15:57:46 +0200 Subject: [PATCH 05/13] Small fixes --- README.md | 2 +- src/core/zkit/CircuitZKitBuilder.ts | 10 ++++++---- src/index.ts | 30 ++++++++++++++++++++++++++--- src/task-names.ts | 2 ++ src/types/tasks.ts | 8 +++++++- 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 207801d..583eeac 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ module.exports = { setupSettings: { contributionSettings: { provingSystem: "groth16", - contributions: 1, + contributions: 2, }, onlyFiles: [], skipFiles: [], diff --git a/src/core/zkit/CircuitZKitBuilder.ts b/src/core/zkit/CircuitZKitBuilder.ts index 1b1bc48..f502f8e 100644 --- a/src/core/zkit/CircuitZKitBuilder.ts +++ b/src/core/zkit/CircuitZKitBuilder.ts @@ -44,14 +44,16 @@ export class CircuitZKitBuilder implements ICircuitZKitBuilder { if (this._isTSProject) { if (circuitArtifact.baseCircuitInfo.protocol.length > 1 && !provingSystem) { throw new HardhatZKitError( - "Found several proving systems. Please specify the exact proving system in getCircuit function", + "Found several proving systems. Please specify the exact proving system in the getCircuit function.", ); - } else if (circuitArtifact.baseCircuitInfo.protocol.length === 1) { + } + + if (circuitArtifact.baseCircuitInfo.protocol.length === 1) { const existingProvingSystem: ProvingSystemType = circuitArtifact.baseCircuitInfo.protocol[0]; if (provingSystem && provingSystem !== existingProvingSystem) { throw new HardhatZKitError( - `Passed invalid proving system. Please pass ${existingProvingSystem} proving system or run make task with needed proving systems`, + `Invalid proving system is passed. Please pass ${existingProvingSystem} proving system or recompile the circuits with the needed one.`, ); } @@ -64,7 +66,7 @@ export class CircuitZKitBuilder implements ICircuitZKitBuilder { } else { if (!provingSystem || !circuitArtifact.baseCircuitInfo.protocol.includes(provingSystem)) { throw new HardhatZKitError( - "Passed undefined or invalid proving system. Please run make task or change proving system.", + "Undefined or invalid proving system is passed. Please recompile the circuits or change the proving system.", ); } diff --git a/src/index.ts b/src/index.ts index cec5bb6..0f017f3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import path from "path"; import fs from "fs"; import { lazyObject } from "hardhat/plugins"; -import { extendConfig, extendEnvironment, scope, task, types } from "hardhat/config"; +import { extendConfig, extendEnvironment, scope, subtask, task, types } from "hardhat/config"; import { ActionType, HardhatRuntimeEnvironment, RunSuperFunction } from "hardhat/types"; import { TASK_CLEAN, TASK_COMPILE_SOLIDITY_READ_FILE as TASK_READ_FILE } from "hardhat/builtin-tasks/task-names"; @@ -18,6 +18,7 @@ import { TASK_CIRCUITS_SETUP, TASK_GENERATE_VERIFIERS, TASK_ZKIT_CLEAN, + SUBTASK_ZKIT_GET_CIRCUIT_ZKIT, } from "./task-names"; import { zkitConfigExtender } from "./config/config"; @@ -44,7 +45,13 @@ import { CircuitArtifacts } from "./artifacts/CircuitArtifacts"; import { CIRCUITS_COMPILE_CACHE_FILENAME, CIRCUITS_SETUP_CACHE_FILENAME } from "./constants"; import { getNormalizedFullPath, getUniqueProvingSystems } from "./utils"; -import { MakeTaskConfig, CompileTaskConfig, GenerateVerifiersTaskConfig, SetupTaskConfig } from "./types/tasks"; +import { + MakeTaskConfig, + CompileTaskConfig, + GenerateVerifiersTaskConfig, + SetupTaskConfig, + GetCircuitZKitConfig, +} from "./types/tasks"; import { CircuitArtifact } from "./types/artifacts/circuit-artifacts"; import { CompileFlags, CircomResolvedFileInfo, CircuitSetupInfo, SetupContributionSettings } from "./types/core"; import { ProvingSystemData } from "./types/cache"; @@ -67,7 +74,7 @@ extendEnvironment((hre) => { circuitName: string, provingSystem?: ProvingSystemType, ): Promise> => { - return circuitZKitBuilder.getCircuitZKit(circuitName, provingSystem); + return hre.run(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT, { circuitName, provingSystem }); }, }; }); @@ -317,6 +324,17 @@ const clean: ActionType = async (_taskArgs: any, env: HardhatRuntimeEnviron fs.rmSync(circuitTypesFullPath, { recursive: true, force: true }); }; +const getCircuitZKit: ActionType = async ( + taskArgs: GetCircuitZKitConfig, + env: HardhatRuntimeEnvironment, +): Promise> => { + return env.zkit.circuitZKitBuilder.getCircuitZKit( + taskArgs.circuitName, + taskArgs.provingSystem, + taskArgs.verifiersDir, + ); +}; + task(TASK_CLEAN).setAction(async (_taskArgs: any, env: HardhatRuntimeEnvironment, runSuper: RunSuperFunction) => { await runSuper(); @@ -370,3 +388,9 @@ zkitScope .setAction(generateVerifiers); zkitScope.task(TASK_ZKIT_CLEAN, "Clean all circuit artifacts, keys, types and etc").setAction(clean); + +subtask(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT) + .addOptionalParam("verifiersDir", undefined, undefined, types.string) + .addOptionalParam("verifierTemplateType", undefined, undefined, types.any) + .addParam("circuitName", undefined, undefined, types.string) + .setAction(getCircuitZKit); diff --git a/src/task-names.ts b/src/task-names.ts index 1d28b2d..7110645 100644 --- a/src/task-names.ts +++ b/src/task-names.ts @@ -5,3 +5,5 @@ export const TASK_CIRCUITS_COMPILE = "compile"; export const TASK_CIRCUITS_SETUP = "setup"; export const TASK_GENERATE_VERIFIERS = "verifiers"; export const TASK_ZKIT_CLEAN = "clean"; + +export const SUBTASK_ZKIT_GET_CIRCUIT_ZKIT = "zkit:get-circuit-zkit"; diff --git a/src/types/tasks.ts b/src/types/tasks.ts index 3c4489f..944e66c 100644 --- a/src/types/tasks.ts +++ b/src/types/tasks.ts @@ -1,4 +1,4 @@ -import { VerifierLanguageType } from "@solarity/zkit"; +import { ProvingSystemType, VerifierLanguageType } from "@solarity/zkit"; export type MakeTaskConfig = { force: boolean; @@ -27,3 +27,9 @@ export type GenerateVerifiersTaskConfig = { quiet: boolean; force: boolean; }; + +export type GetCircuitZKitConfig = { + circuitName: string; + verifiersDir?: string; + provingSystem?: ProvingSystemType; +}; From fab52acb1a83662c906c86c18ef40848c4029861 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Tue, 5 Nov 2024 18:27:44 +0200 Subject: [PATCH 06/13] Fix multiple ploring systems user flow --- package-lock.json | 7 ++-- package.json | 2 +- src/artifacts/CircuitArtifacts.ts | 38 +++++++++++++--------- src/cache/schemas/compile-schemas.ts | 6 ++-- src/core/compile/CompilationProcessor.ts | 16 +++------ src/core/zkit/CircuitZKitBuilder.ts | 24 ++++++-------- src/core/zktype/TypeGenerationProcessor.ts | 11 ++++++- src/index.ts | 34 ++++++++++--------- src/types/artifacts/circuit-artifacts.ts | 3 +- 9 files changed, 74 insertions(+), 67 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74a5895..c306118 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "dependencies": { "@distributedlab/circom-parser": "0.2.0", "@solarity/zkit": "0.3.0", - "@solarity/zktype": "0.4.0-rc.0", + "@solarity/zktype": "0.4.1", "@wasmer/wasi": "0.12.0", "chalk": "4.1.2", "cli-progress": "3.12.0", @@ -2077,8 +2077,9 @@ } }, "node_modules/@solarity/zktype": { - "version": "0.4.0-rc.0", - "license": "MIT", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@solarity/zktype/-/zktype-0.4.1.tgz", + "integrity": "sha512-tR2iZRrvtGZtdQCNunkaf+ODX3lqFZClhmIhOh3B3XYrPd0Dnfv6mafVfV4HN8nciRVYNDGCIiRFN9Wa6r90oA==", "dependencies": { "ejs": "3.1.10", "prettier": "3.3.3", diff --git a/package.json b/package.json index ca04dcc..7be7e1c 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "dependencies": { "@distributedlab/circom-parser": "0.2.0", "@solarity/zkit": "0.3.0", - "@solarity/zktype": "0.4.0-rc.0", + "@solarity/zktype": "0.4.1", "@wasmer/wasi": "0.12.0", "chalk": "4.1.2", "cli-progress": "3.12.0", diff --git a/src/artifacts/CircuitArtifacts.ts b/src/artifacts/CircuitArtifacts.ts index d5da47a..2d5b79a 100644 --- a/src/artifacts/CircuitArtifacts.ts +++ b/src/artifacts/CircuitArtifacts.ts @@ -1,6 +1,7 @@ import path from "path"; import fsExtra from "fs-extra"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; import { FileNotFoundError, getAllFilesMatching, getFileTrueCase } from "hardhat/internal/util/fs-utils"; import { isFullyQualifiedName } from "hardhat/utils/contract-names"; import { replaceBackslashes } from "hardhat/utils/source-names"; @@ -12,13 +13,13 @@ import { ProvingSystemType } from "@solarity/zkit"; import { HardhatZKitError } from "../errors"; import { CIRCUIT_ARTIFACTS_SUFFIX } from "../constants"; import { Reporter } from "../reporter"; -import { getFileHash } from "../utils/utils"; +import { getFileHash, getNormalizedFullPath } from "../utils"; import { - ArtifactsFileType, - ArtifactsCache, CircuitArtifact, ICircuitArtifacts, + ArtifactsCache, + ArtifactsFileType, } from "../types/artifacts/circuit-artifacts"; /** @@ -29,12 +30,19 @@ import { * methods for fetching, generating, and cleaning up artifacts that are no longer needed. */ export class CircuitArtifacts implements ICircuitArtifacts { + private readonly _artifactsPath: string; + // Undefined means that the cache is disabled. private _cache?: ArtifactsCache = { artifactNameToArtifactPathCache: new Map(), }; - constructor(private readonly _artifactsPath: string) {} + constructor(hre: HardhatRuntimeEnvironment) { + this._artifactsPath = getNormalizedFullPath( + hre.config.paths.root, + hre.config.zkit.compilationSettings.artifactsDir, + ); + } /** * Generates a unique artifact file key using the specified {@link ArtifactsFileType | fileType} @@ -44,8 +52,12 @@ export class CircuitArtifacts implements ICircuitArtifacts { * @param provingSystem The type of the proving system * @returns A generated key for the artifact file */ - public static getArtifactOutputFileKey(fileType: ArtifactsFileType, provingSystem: ProvingSystemType): string { + public static getArtifactOutputFileKey(fileType: ArtifactsFileType, provingSystem?: ProvingSystemType): string { if (fileType === "zkey" || fileType === "vkey") { + if (!provingSystem) { + throw new HardhatZKitError("Undefined proving system is passed. Please provide valid proving system."); + } + return `${provingSystem}.${fileType}`; } @@ -187,14 +199,14 @@ export class CircuitArtifacts implements ICircuitArtifacts { * @param circuitArtifact The {@link CircuitArtifact} object to be saved * @param updatedFileTypes An array of {@link ArtifactsFileType | file types} that have been modified * during the most recent session, such as during compilation - * @param provingSystems An array of {@link ProvingSystemType | proving systems} that have been added + * @param updatedProvingSystems An array of {@link ProvingSystemType | proving systems} that have been added * during the most recent session * @returns A promise that resolves once the save operation is complete */ public async saveCircuitArtifact( circuitArtifact: CircuitArtifact, updatedFileTypes: ArtifactsFileType[], - provingSystems: ProvingSystemType[], + updatedProvingSystems: ProvingSystemType[], ) { const fullyQualifiedName = this.getCircuitFullyQualifiedName( circuitArtifact.circuitSourceName, @@ -203,16 +215,12 @@ export class CircuitArtifacts implements ICircuitArtifacts { const artifactPath = this.formCircuitArtifactPathFromFullyQualifiedName(fullyQualifiedName); - const allArtifactProvingSystems = new Set([ - ...circuitArtifact.baseCircuitInfo.protocol, - ...provingSystems, - ]); - - circuitArtifact.baseCircuitInfo.protocol = [...allArtifactProvingSystems]; + // Create array with one element for the compilation case + const provingSystems = updatedProvingSystems.length > 0 ? updatedProvingSystems : [undefined]; // Updates the data for files that have been recently modified - for (const provingSystem of provingSystems) { - for (const fileType of updatedFileTypes) { + for (const fileType of updatedFileTypes) { + for (const provingSystem of provingSystems) { const fileSourcePath: string = this.getCircuitArtifactFileFullPath(circuitArtifact, fileType, provingSystem); circuitArtifact.compilerOutputFiles[CircuitArtifacts.getArtifactOutputFileKey(fileType, provingSystem)] = { diff --git a/src/cache/schemas/compile-schemas.ts b/src/cache/schemas/compile-schemas.ts index 43e2dcc..a14e4cf 100644 --- a/src/cache/schemas/compile-schemas.ts +++ b/src/cache/schemas/compile-schemas.ts @@ -20,14 +20,14 @@ export const PragmaComponentSchema = z.object({ }); export const InputDataSchema = z.object({ - dimension: z.string().array(), + dimension: z.number().array(), type: z.string(), }); export const TemplateSchema = z.object({ - inputs: z.record(z.string(), InputDataSchema), parameters: z.string().array(), isCustom: z.boolean(), + parallel: z.boolean(), }); export const TemplatesSchema = z.record(z.string(), TemplateSchema); @@ -47,7 +47,7 @@ export const ParsedCircomFileDataSchema = z.object({ export const SignalInfoSchema = z.object({ name: z.string(), - dimension: z.string().array(), + dimension: z.number().array(), type: SignalTypeSchema, visibility: VisibilityTypeSchema, }); diff --git a/src/core/compile/CompilationProcessor.ts b/src/core/compile/CompilationProcessor.ts index b5e2a1e..af12a22 100644 --- a/src/core/compile/CompilationProcessor.ts +++ b/src/core/compile/CompilationProcessor.ts @@ -7,8 +7,6 @@ import { v4 as uuid } from "uuid"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { ProvingSystemType } from "@solarity/zkit"; - import { CircomCompilerFactory, createCircomCompilerFactory, getHighestVersion, isVersionValid } from "../compiler"; import { HardhatZKitError } from "../../errors"; import { CIRCUIT_ARTIFACT_VERSION, NODE_MODULES } from "../../constants"; @@ -67,9 +65,8 @@ export class CompilationProcessor { * 6. Saves the artifact information using {@link ICircuitArtifacts | CircuitArtifacts} * * @param filesInfoToCompile Information about circuit files needed for compilation - * @param provingSystems An array of {@link ProvingSystemType | proving systems} from the plugin config */ - public async compile(filesInfoToCompile: CircomResolvedFileInfo[], provingSystems: ProvingSystemType[]) { + public async compile(filesInfoToCompile: CircomResolvedFileInfo[]) { const tempDir: string = path.join(os.tmpdir(), ".zkit", uuid()); try { @@ -110,7 +107,7 @@ export class CompilationProcessor { await this._moveFromTempDirToArtifacts(compilationInfoArr); - await this._emitArtifacts(compilationInfoArr, provingSystems); + await this._emitArtifacts(compilationInfoArr); Reporter!.reportCompilationResult(compilationInfoArr); } finally { @@ -168,7 +165,7 @@ export class CompilationProcessor { } } - private async _emitArtifacts(compilationInfoArr: CompilationInfo[], provingSystems: ProvingSystemType[]) { + private async _emitArtifacts(compilationInfoArr: CompilationInfo[]) { for (const info of compilationInfoArr) { const fullyQualifiedName: string = this._circuitArtifacts.getCircuitFullyQualifiedName( info.resolvedFile.sourceName, @@ -186,7 +183,6 @@ export class CompilationProcessor { circuitFileName: info.circuitFileName, circuitSourceName: info.resolvedFile.sourceName, baseCircuitInfo: { - protocol: [], constraintsNumber: 0, signals: [], }, @@ -201,11 +197,7 @@ export class CompilationProcessor { circuitArtifact.baseCircuitInfo.constraintsNumber = info.constraintsNumber; circuitArtifact.baseCircuitInfo.signals = info.resolvedFile.fileData.mainComponentData.signals; - await this._circuitArtifacts.saveCircuitArtifact( - circuitArtifact, - this._getUpdatedArtifactFileTypes(), - provingSystems, - ); + await this._circuitArtifacts.saveCircuitArtifact(circuitArtifact, this._getUpdatedArtifactFileTypes(), []); } } diff --git a/src/core/zkit/CircuitZKitBuilder.ts b/src/core/zkit/CircuitZKitBuilder.ts index f502f8e..2c91508 100644 --- a/src/core/zkit/CircuitZKitBuilder.ts +++ b/src/core/zkit/CircuitZKitBuilder.ts @@ -12,7 +12,7 @@ import { import { CircuitTypesGenerator } from "@solarity/zktype"; import { HardhatZKitError } from "../../errors"; -import { getNormalizedFullPath } from "../../utils"; +import { getNormalizedFullPath, getUniqueProvingSystems } from "../../utils"; import { ICircuitZKitBuilder } from "../../types/core"; import { CircuitArtifact } from "../../types/artifacts/circuit-artifacts"; @@ -20,6 +20,7 @@ import { CircuitArtifact } from "../../types/artifacts/circuit-artifacts"; export class CircuitZKitBuilder implements ICircuitZKitBuilder { private readonly _isTSProject: boolean; private readonly _typesGenerator: CircuitTypesGenerator; + private readonly _provingSystems: ProvingSystemType[]; private _protocolImplementers = new Map>(); constructor(private readonly _hre: HardhatRuntimeEnvironment) { @@ -27,10 +28,11 @@ export class CircuitZKitBuilder implements ICircuitZKitBuilder { basePath: _hre.config.zkit.circuitsDir, projectRoot: _hre.config.paths.root, outputTypesDir: _hre.config.zkit.typesDir, - circuitsArtifactsPaths: [], + circuitsArtifacts: [], }); this._isTSProject = willRunWithTypescript(_hre.hardhatArguments.config); + this._provingSystems = getUniqueProvingSystems(_hre.config.zkit.setupSettings.contributionSettings.provingSystem); } public async getCircuitZKit( @@ -42,29 +44,23 @@ export class CircuitZKitBuilder implements ICircuitZKitBuilder { const circuitZKitConfig: CircuitZKitConfig = this._getCircuitZKitConfig(circuitArtifact, verifiersDir); if (this._isTSProject) { - if (circuitArtifact.baseCircuitInfo.protocol.length > 1 && !provingSystem) { + if (this._provingSystems.length > 1 && !provingSystem) { throw new HardhatZKitError( "Found several proving systems. Please specify the exact proving system in the getCircuit function.", ); } - if (circuitArtifact.baseCircuitInfo.protocol.length === 1) { - const existingProvingSystem: ProvingSystemType = circuitArtifact.baseCircuitInfo.protocol[0]; - - if (provingSystem && provingSystem !== existingProvingSystem) { - throw new HardhatZKitError( - `Invalid proving system is passed. Please pass ${existingProvingSystem} proving system or recompile the circuits with the needed one.`, - ); - } - - provingSystem = undefined; + if (this._provingSystems.length === 1 && provingSystem) { + throw new HardhatZKitError( + `Found single proving system. No need to specify the exact proving system in the getCircuit function.`, + ); } const module = await this._typesGenerator.getCircuitObject(circuitName, provingSystem); return new module(circuitZKitConfig); } else { - if (!provingSystem || !circuitArtifact.baseCircuitInfo.protocol.includes(provingSystem)) { + if (!provingSystem || !this._provingSystems.includes(provingSystem)) { throw new HardhatZKitError( "Undefined or invalid proving system is passed. Please recompile the circuits or change the proving system.", ); diff --git a/src/core/zktype/TypeGenerationProcessor.ts b/src/core/zktype/TypeGenerationProcessor.ts index 1505d00..212a2cf 100644 --- a/src/core/zktype/TypeGenerationProcessor.ts +++ b/src/core/zktype/TypeGenerationProcessor.ts @@ -2,9 +2,11 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { localPathToSourceName } from "hardhat/utils/source-names"; import { willRunWithTypescript } from "hardhat/internal/core/typescript-support"; +import { ProvingSystemType } from "@solarity/zkit"; import { CircuitTypesGenerator } from "@solarity/zktype"; import { Reporter } from "../../reporter"; +import { getUniqueProvingSystems } from "../../utils"; import { ZKitConfig } from "../../types/zkit-config"; import { ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; @@ -26,12 +28,14 @@ export class TypeGenerationProcessor { private readonly _circuitArtifacts: ICircuitArtifacts; private readonly _root: string; private readonly _isTSProject: boolean; + private readonly _provingSystems: ProvingSystemType[]; constructor(hre: HardhatRuntimeEnvironment) { this._circuitArtifacts = hre.zkit.circuitArtifacts; this._zkitConfig = hre.config.zkit; this._root = hre.config.paths.root; this._isTSProject = willRunWithTypescript(hre.hardhatArguments.config); + this._provingSystems = getUniqueProvingSystems(hre.config.zkit.setupSettings.contributionSettings.provingSystem); } /** @@ -59,7 +63,12 @@ export class TypeGenerationProcessor { basePath: this._zkitConfig.circuitsDir, projectRoot: this._root, outputTypesDir: this._zkitConfig.typesDir, - circuitsArtifactsPaths, + circuitsArtifacts: circuitsArtifactsPaths.map((path: string) => { + return { + artifactPath: path, + circuitProtocolType: this._provingSystems, + }; + }), }); await typesGenerator.generateTypes(); diff --git a/src/index.ts b/src/index.ts index 0f017f3..2f37d8e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -62,9 +62,7 @@ extendConfig(zkitConfigExtender); extendEnvironment((hre) => { hre.zkit = lazyObject(() => { - const circuitArtifacts: CircuitArtifacts = new CircuitArtifacts( - getNormalizedFullPath(hre.config.paths.root, hre.config.zkit.compilationSettings.artifactsDir), - ); + const circuitArtifacts: CircuitArtifacts = new CircuitArtifacts(hre); const circuitZKitBuilder: CircuitZKitBuilder = new CircuitZKitBuilder(hre); return { @@ -134,13 +132,7 @@ const compile: ActionType = async (taskArgs: CompileTaskConfi env, ); - const provingSystems: ProvingSystemType[] = getUniqueProvingSystems( - env.config.zkit.setupSettings.contributionSettings.provingSystem, - ); - - await compilationProcessor.compile(resolvedFilesInfo, provingSystems); - - await new TypeGenerationProcessor(env).generateAllTypes(); + await compilationProcessor.compile(resolvedFilesInfo); for (const fileInfo of resolvedFilesInfo) { for (const file of [fileInfo.resolvedFile, ...fileInfo.dependencies]) { @@ -157,6 +149,8 @@ const compile: ActionType = async (taskArgs: CompileTaskConfi Reporter!.reportNothingToCompile(); } + await new TypeGenerationProcessor(env).generateAllTypes(); + await CircuitsCompileCache!.writeToFile(circuitsCompileCacheFullPath); }; @@ -196,14 +190,13 @@ const setup: ActionType = async (taskArgs: SetupTaskConfig, env await setupProcessor.setup(circuitSetupInfoArr, setupContributionSettings); - await new TypeGenerationProcessor(env).generateAllTypes(); - for (const setupInfo of circuitSetupInfoArr) { const currentSetupCacheEntry = CircuitsSetupCache!.getEntry(setupInfo.circuitArtifactFullPath); let currentProvingSystemsData: ProvingSystemData[] = []; if (currentSetupCacheEntry) { + // Getting untouched proving systems data currentProvingSystemsData = currentSetupCacheEntry.provingSystemsData.filter((data: ProvingSystemData) => { return !setupInfo.provingSystems.includes(data.provingSystem); }); @@ -228,6 +221,8 @@ const setup: ActionType = async (taskArgs: SetupTaskConfig, env Reporter!.reportNothingToSetup(); } + await new TypeGenerationProcessor(env).generateAllTypes(); + await CircuitsSetupCache!.writeToFile(circuitsSetupCacheFullPath); }; @@ -263,6 +258,9 @@ const generateVerifiers: ActionType = async ( taskArgs.verifiersDir ?? env.config.zkit.verifiersSettings.verifiersDir, ); const verifiersType: VerifierLanguageType = taskArgs.verifiersType ?? env.config.zkit.verifiersSettings.verifiersType; + const provingSystems: ProvingSystemType[] = getUniqueProvingSystems( + env.config.zkit.setupSettings.contributionSettings.provingSystem, + ); Reporter!.verboseLog("index", "Verifiers generation dir - %s", [verifiersDirFullPath]); @@ -275,16 +273,20 @@ const generateVerifiers: ActionType = async ( for (const name of allFullyQualifiedNames) { const circuitArtifact: CircuitArtifact = await env.zkit.circuitArtifacts.readCircuitArtifact(name); - for (const provingSystem of circuitArtifact.baseCircuitInfo.protocol) { + for (const provingSystem of provingSystems) { const spinnerId: string | null = Reporter!.reportVerifierGenerationStartWithSpinner( circuitArtifact.circuitTemplateName, verifiersType, provingSystem, ); - (await env.zkit.circuitZKitBuilder.getCircuitZKit(name, provingSystem, taskArgs.verifiersDir)).createVerifier( - verifiersType, - ); + ( + await env.zkit.circuitZKitBuilder.getCircuitZKit( + name, + provingSystems.length > 1 ? provingSystem : undefined, + taskArgs.verifiersDir, + ) + ).createVerifier(verifiersType); Reporter!.reportVerifierGenerationResult( spinnerId, diff --git a/src/types/artifacts/circuit-artifacts.ts b/src/types/artifacts/circuit-artifacts.ts index ddf9166..87fdb4c 100644 --- a/src/types/artifacts/circuit-artifacts.ts +++ b/src/types/artifacts/circuit-artifacts.ts @@ -25,7 +25,7 @@ export interface ICircuitArtifacts { saveCircuitArtifact( circuitArtifact: CircuitArtifact, updatedFileTypes: ArtifactsFileType[], - provingSystems: ProvingSystemType[], + updatedProvingSystems: ProvingSystemType[], ): Promise; clearCache(): void; @@ -45,7 +45,6 @@ export type CircuitArtifact = { export type BaseCircuitInfo = { constraintsNumber: number; signals: SignalInfo[]; - protocol: ProvingSystemType[]; }; export type CompilerOutputFileInfo = { From 970a76102a225fe973d6c4c7ed5db93bdacd81da Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Tue, 5 Nov 2024 19:01:26 +0200 Subject: [PATCH 07/13] Fix outdated subtask params --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 2f37d8e..cbf7e90 100644 --- a/src/index.ts +++ b/src/index.ts @@ -393,6 +393,6 @@ zkitScope.task(TASK_ZKIT_CLEAN, "Clean all circuit artifacts, keys, types and et subtask(SUBTASK_ZKIT_GET_CIRCUIT_ZKIT) .addOptionalParam("verifiersDir", undefined, undefined, types.string) - .addOptionalParam("verifierTemplateType", undefined, undefined, types.any) + .addOptionalParam("provingSystem", undefined, undefined, types.any) .addParam("circuitName", undefined, undefined, types.string) .setAction(getCircuitZKit); From eb998446a34c22935ee34c9dacd3864f0e059764 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 6 Nov 2024 16:00:21 +0200 Subject: [PATCH 08/13] added getPlonkConstraintsNumber function --- src/constants.ts | 5 -- src/core/compile/CompilationProcessor.ts | 44 ++--------- src/core/setup/SetupProcessor.ts | 24 +++--- src/types/utils.ts | 4 + src/utils/constraints-utils.ts | 93 ++++++++++++++++++++++++ src/utils/index.ts | 3 +- 6 files changed, 117 insertions(+), 56 deletions(-) create mode 100644 src/utils/constraints-utils.ts diff --git a/src/constants.ts b/src/constants.ts index daea658..1b4e17f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -18,11 +18,6 @@ export const BYTES_IN_MB = 1048576; export const MAX_PTAU_ID = 27; export const PTAU_FILE_REG_EXP = /^(?:.+-|)(\d{1,2}).ptau$/; -export const PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS: { [key: string]: number } = { - groth16: 1, - plonk: 11, -}; - export const CIRCOM_FILE_REG_EXP = /\w+\.circom/; export const NODE_MODULES_REG_EXP = /^node_modules\//; diff --git a/src/core/compile/CompilationProcessor.ts b/src/core/compile/CompilationProcessor.ts index af12a22..45f4729 100644 --- a/src/core/compile/CompilationProcessor.ts +++ b/src/core/compile/CompilationProcessor.ts @@ -1,6 +1,5 @@ import path from "path"; import os from "os"; -import fs from "fs"; import semver from "semver"; import fsExtra from "fs-extra"; import { v4 as uuid } from "uuid"; @@ -11,6 +10,8 @@ import { CircomCompilerFactory, createCircomCompilerFactory, getHighestVersion, import { HardhatZKitError } from "../../errors"; import { CIRCUIT_ARTIFACT_VERSION, NODE_MODULES } from "../../constants"; import { Reporter } from "../../reporter"; + +import { getGroth16ConstraintsNumber } from "../../utils/constraints-utils"; import { getNormalizedFullPath, renameFilesRecursively, readDirRecursively } from "../../utils/path-utils"; import { ZKitConfig } from "../../types/zkit-config"; @@ -101,9 +102,10 @@ export class CompilationProcessor { await this._compileCircuits(compiler, compilationInfoArr); - compilationInfoArr.forEach((info: CompilationInfo) => { - info.constraintsNumber = this._getConstraintsNumber(info); - }); + for (const info of compilationInfoArr) { + const r1csFilePath = getNormalizedFullPath(info.tempArtifactsPath, `${info.circuitName}.r1cs`); + info.constraintsNumber = await getGroth16ConstraintsNumber(r1csFilePath); + } await this._moveFromTempDirToArtifacts(compilationInfoArr); @@ -258,40 +260,6 @@ export class CompilationProcessor { return fileTypes; } - private _getConstraintsNumber(compilationInfo: CompilationInfo): number { - const r1csFileName = `${compilationInfo.circuitName}.r1cs`; - const r1csFile = getNormalizedFullPath(compilationInfo.tempArtifactsPath, r1csFileName); - const r1csDescriptor = fs.openSync(r1csFile, "r"); - - const readBytes = (position: number, length: number): bigint => { - const buffer = Buffer.alloc(length); - - fs.readSync(r1csDescriptor, buffer, { length, position }); - - return BigInt(`0x${buffer.reverse().toString("hex")}`); - }; - - // https://github.com/iden3/r1csfile/blob/d82959da1f88fbd06db0407051fde94afbf8824a/doc/r1cs_bin_format.md#format-of-the-file - const numberOfSections = readBytes(8, 4); - let sectionStart = 12; - - for (let i = 0; i < numberOfSections; ++i) { - const sectionType = Number(readBytes(sectionStart, 4)); - const sectionSize = Number(readBytes(sectionStart + 4, 8)); - - // Reading header section - if (sectionType == 1) { - const totalConstraintsOffset = 4 + 8 + 4 + 32 + 4 + 4 + 4 + 4 + 8; - - return Number(readBytes(sectionStart + totalConstraintsOffset, 4)); - } - - sectionStart += 4 + 8 + sectionSize; - } - - throw new HardhatZKitError(`Header section in ${r1csFileName} file is not found.`); - } - private _getLinkLibraries(): string[] { return [this._nodeModulesPath]; } diff --git a/src/core/setup/SetupProcessor.ts b/src/core/setup/SetupProcessor.ts index a4193d5..c4da17d 100644 --- a/src/core/setup/SetupProcessor.ts +++ b/src/core/setup/SetupProcessor.ts @@ -8,11 +8,12 @@ import * as snarkjs from "snarkjs"; import { ProvingSystemType } from "@solarity/zkit"; import { HardhatZKitError } from "../../errors"; -import { PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS, PTAU_FILE_REG_EXP } from "../../constants"; +import { BN128_CURVE_NAME, PTAU_FILE_REG_EXP } from "../../constants"; import { Reporter } from "../../reporter"; import { PtauDownloader } from "../utils/PtauDownloader"; import { terminateCurve } from "../../utils/utils"; import { getNormalizedFullPath } from "../../utils/path-utils"; +import { getPlonkConstraintsNumber } from "../../utils/constraints-utils"; import { ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; import { CircuitSetupInfo, SetupContributionSettings } from "../../types/core"; @@ -212,24 +213,23 @@ export class SetupProcessor { circuitSetupInfoArr: CircuitSetupInfo[], provingSystems: ProvingSystemType[], ): Promise { + const usePlonk = provingSystems.includes("plonk"); + + const curve = await (snarkjs as any).curves.getCurveFromName(BN128_CURVE_NAME); + const circuitsConstraintsNumber: number[] = await Promise.all( circuitSetupInfoArr.map(async (setupInfo: CircuitSetupInfo) => { - return setupInfo.circuitArtifact.baseCircuitInfo.constraintsNumber; + return usePlonk + ? getPlonkConstraintsNumber(setupInfo.r1csSourcePath, curve.Fr) + : setupInfo.circuitArtifact.baseCircuitInfo.constraintsNumber; }), ); - const maxConstraintsNumber = Math.max(...circuitsConstraintsNumber); - let provingSystemMultiplier = 1; - - for (const provingSystem of provingSystems) { - const currentMultiplier = PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS[provingSystem]; + await curve.terminate(); - if (currentMultiplier && currentMultiplier > provingSystemMultiplier) { - provingSystemMultiplier = currentMultiplier; - } - } + const maxConstraintsNumber = Math.max(...circuitsConstraintsNumber); - const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber * provingSystemMultiplier)), 8); + const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber)), 8); let entries: fsExtra.Dirent[] = []; diff --git a/src/types/utils.ts b/src/types/utils.ts index 3cdb6a7..5dfc941 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -6,3 +6,7 @@ export type ExecCallResult = { stdout: string; stderr: string; }; + +export type LinearCombination = { [key: string]: bigint }; + +export type R1CSConstraint = [LinearCombination, LinearCombination, LinearCombination]; diff --git a/src/utils/constraints-utils.ts b/src/utils/constraints-utils.ts new file mode 100644 index 0000000..57906cc --- /dev/null +++ b/src/utils/constraints-utils.ts @@ -0,0 +1,93 @@ +import * as snarkjs from "snarkjs"; +// @ts-expect-error: No type definitions available for the "r1csfile" package +import * as r1csfile from "r1csfile"; +// @ts-expect-error: No type definitions available for the "@iden3/binfileutils" package +import * as binfileutils from "@iden3/binfileutils"; + +import { LinearCombination, R1CSConstraint } from "../../src/types/utils"; + +export async function getGroth16ConstraintsNumber(r1csFilePath: string): Promise { + return (await snarkjs.r1cs.info(r1csFilePath)).nConstraints; +} + +export async function getPlonkConstraintsNumber(r1csFilePath: string, Fr: any): Promise { + const normalize = (lc: LinearCombination) => { + Object.keys(lc).forEach((key) => { + if (lc[key] == 0n) delete lc[key]; + }); + }; + + const join = (lc1: LinearCombination, k: bigint, lc2: LinearCombination) => { + const res = { ...lc1 }; + Object.keys(lc2).forEach((s) => { + res[s] = res[s] ? Fr.add(res[s], Fr.mul(k, lc2[s])) : lc2[s]; + }); + normalize(res); + return res; + }; + + const reduceCoefs = (linearComb: LinearCombination, maxC: number) => { + let n = Object.keys(linearComb).filter((s) => s !== "0" && linearComb[s] != 0n).length; + + while (n > maxC) { + plonkConstraintsCount++; + n--; + } + }; + + const addConstraintSum = (lc: LinearCombination) => { + reduceCoefs(lc, 3); + plonkConstraintsCount++; + }; + + const getLinearCombinationType = (lc: LinearCombination) => { + let k = Fr.zero; + let n = 0; + + Object.keys(lc).forEach((key) => { + if (lc[key] !== 0n) { + if (key === "0") { + k = Fr.add(k, lc[key]); + } else { + n++; + } + } + }); + + return n > 0 ? n.toString() : k != Fr.zero ? "k" : "0"; + }; + + const process = (lcA: LinearCombination, lcB: LinearCombination, lcC: LinearCombination) => { + const lctA = getLinearCombinationType(lcA); + const lctB = getLinearCombinationType(lcB); + + if (lctA === "0" || lctB === "0") { + normalize(lcC); + addConstraintSum(lcC); + } else if (lctA === "k") { + addConstraintSum(join(lcB, lcA[0], lcC)); + } else if (lctB === "k") { + addConstraintSum(join(lcA, lcB[0], lcC)); + } else { + [lcA, lcB, lcC].forEach((lc) => reduceCoefs(lc, 1)); + plonkConstraintsCount++; + } + }; + + const { fd: fdR1cs, sections: sectionsR1cs } = await binfileutils.readBinFile( + r1csFilePath, + "r1cs", + 1, + 1 << 22, + 1 << 24, + ); + const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, { loadConstraints: true, loadCustomGates: true }); + + let plonkConstraintsCount = r1cs.nOutputs + r1cs.nPubInputs; + + r1cs.constraints.forEach((constraint: R1CSConstraint) => process(...constraint)); + + await fdR1cs.fd.close(); + + return plonkConstraintsCount; +} diff --git a/src/utils/index.ts b/src/utils/index.ts index ac50f87..7093814 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,2 +1,3 @@ -export * from "./path-utils"; export * from "./utils"; +export * from "./path-utils"; +export * from "./constraints-utils"; From 0af750791fc2477f1d0582c8742459d782001998 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Wed, 6 Nov 2024 17:24:04 +0200 Subject: [PATCH 09/13] Add unit tests --- src/core/zkit/CircuitZKitBuilder.ts | 2 +- src/utils/path-utils.ts | 39 ---- .../hardhat.config.ts | 1 + test/helpers.ts | 16 +- test/integration/tasks.test.ts | 168 +++++++++++++++--- test/unit/cache/circuits-setup-cache.test.ts | 22 ++- .../core/zkit/circuit-zkit-builder.test.ts | 85 +++++++++ test/utils.ts | 36 ++++ 8 files changed, 299 insertions(+), 70 deletions(-) create mode 100644 test/unit/core/zkit/circuit-zkit-builder.test.ts diff --git a/src/core/zkit/CircuitZKitBuilder.ts b/src/core/zkit/CircuitZKitBuilder.ts index 2c91508..9a88e20 100644 --- a/src/core/zkit/CircuitZKitBuilder.ts +++ b/src/core/zkit/CircuitZKitBuilder.ts @@ -52,7 +52,7 @@ export class CircuitZKitBuilder implements ICircuitZKitBuilder { if (this._provingSystems.length === 1 && provingSystem) { throw new HardhatZKitError( - `Found single proving system. No need to specify the exact proving system in the getCircuit function.`, + "Found single proving system. No need to specify the exact proving system in the getCircuit function.", ); } diff --git a/src/utils/path-utils.ts b/src/utils/path-utils.ts index e47979e..fc54c4d 100644 --- a/src/utils/path-utils.ts +++ b/src/utils/path-utils.ts @@ -2,7 +2,6 @@ import fs from "fs"; import path from "path"; import { normalizeSourceName, localSourceNameToPath } from "hardhat/utils/source-names"; -import { FileSystemAccessError, InvalidDirectoryError } from "hardhat/internal/util/fs-utils"; import { FileFilterSettings } from "../types/zkit-config"; @@ -10,28 +9,6 @@ export function getNormalizedFullPath(projectRoot: string, dirPath: string): str return localSourceNameToPath(projectRoot, normalizeSourceName(dirPath)); } -export function getAllDirsMatchingSync( - absolutePathToDir: string, - matches?: (absolutePath: string) => boolean, -): string[] { - const dir = readdirSync(absolutePathToDir); - - const results = dir.map((file) => { - const absolutePath = path.join(absolutePathToDir, file); - const stats = fs.statSync(absolutePath); - - if (stats.isDirectory() && (matches === undefined || matches(absolutePath))) { - return absolutePath; - } else if (stats.isDirectory()) { - return getAllDirsMatchingSync(absolutePath, matches).flat(); - } else { - return []; - } - }); - - return results.flat(); -} - /** * Reads a directory recursively and calls the callback for each file. * @@ -79,22 +56,6 @@ export function renameFilesRecursively(dir: string, searchValue: string, replace } } -function readdirSync(absolutePathToDir: string) { - try { - return fs.readdirSync(absolutePathToDir); - } catch (e: any) { - if (e.code === "ENOENT") { - return []; - } - - if (e.code === "ENOTDIR") { - throw new InvalidDirectoryError(absolutePathToDir, e); - } - - throw new FileSystemAccessError(e.message, e); - } -} - export function filterCircuitFiles( circuitsInfo: T[], circuitsRoot: string, diff --git a/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts b/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts index 077e694..f94665d 100644 --- a/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts +++ b/test/fixture-projects/hardhat-project-with-circuits/hardhat.config.ts @@ -21,6 +21,7 @@ const defaultConfig: HardhatUserConfig = { verifiersSettings: { verifiersDir: "contracts/verifiers", }, + typesDir: "generated-types/zkit", }, }; diff --git a/test/helpers.ts b/test/helpers.ts index a8f17e6..070d0c5 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -4,10 +4,16 @@ import fsExtra from "fs-extra"; import { resetHardhatContext } from "hardhat/plugins-testing"; import { TASK_COMPILE } from "hardhat/builtin-tasks/task-names"; -import { getNormalizedFullPath } from "../src/utils/path-utils"; +import { createReporter, Reporter } from "../src/reporter"; import { resetCircuitsCompileCache, resetCircuitsSetupCache } from "../src/cache"; +import { getNormalizedFullPath } from "../src/utils/path-utils"; -export function useEnvironment(fixtureProjectName: string, withCleanUp: boolean = false, networkName = "hardhat") { +export function useEnvironment( + fixtureProjectName: string, + withCleanUp: boolean = false, + withLogging: boolean = true, + networkName = "hardhat", +) { beforeEach("Loading hardhat environment", async function () { const prefix = "hardhat-project-"; process.chdir(join(__dirname, "fixture-projects", prefix + fixtureProjectName)); @@ -21,6 +27,12 @@ export function useEnvironment(fixtureProjectName: string, withCleanUp: boolean return; } + if (!Reporter) { + createReporter(!withLogging); + } else { + Reporter!.setQuiet(!withLogging); + } + await this.hre.run(TASK_COMPILE, { quiet: true }); }); diff --git a/test/integration/tasks.test.ts b/test/integration/tasks.test.ts index e57174f..ed2c3e1 100644 --- a/test/integration/tasks.test.ts +++ b/test/integration/tasks.test.ts @@ -1,6 +1,7 @@ import os from "os"; import path from "path"; import fsExtra from "fs-extra"; +import { capitalize } from "lodash"; import { execSync } from "child_process"; import "@solarity/chai-zkit"; @@ -10,6 +11,8 @@ import { stub, SinonStub } from "sinon"; import { HardhatUserConfig } from "hardhat/config"; +import { ProvingSystemType } from "@solarity/zkit"; + import { TASK_CIRCUITS_COMPILE, TASK_CIRCUITS_MAKE, @@ -23,7 +26,13 @@ import { CompileCacheEntry, SetupCacheEntry } from "@src/types/cache"; import { cleanUp, useEnvironment } from "@test-helpers"; import { getNormalizedFullPath } from "@src/utils/path-utils"; -import { getCompileCacheEntry, getSetupCacheEntry } from "../utils"; +import { + getCompileCacheEntry, + getSetupCacheEntry, + updateInclude, + updateProvingSystems, + updateTypesDir, +} from "../utils"; import { HardhatZKit } from "@src/types/hardhat-zkit"; import { BaseCircomCompilerFactory } from "@src/core"; @@ -32,6 +41,7 @@ import { CircomCompilerDownloader } from "@src/core/compiler/CircomCompilerDownl describe("ZKit tasks", async function () { const circuitNames = ["Multiplier2", "Multiplier3Arr"]; const sourceNames = ["circuits/main/mul2.circom", "circuits/main/Multiplier3Arr.circom"]; + const defaultTypesDir = "generated-types/zkit"; let nativeCompilerStub: SinonStub; @@ -58,7 +68,7 @@ describe("ZKit tasks", async function () { return circuitFullPaths; } - async function checkMake(config: HardhatUserConfig, zkit: HardhatZKit) { + async function checkMake(config: HardhatUserConfig, zkit: HardhatZKit, provingSystems: ProvingSystemType[]) { const cacheFullPath: string = getNormalizedFullPath(config.paths!.root!, "cache"); expect(fsExtra.readdirSync(cacheFullPath)).to.be.deep.eq([ @@ -71,9 +81,17 @@ describe("ZKit tasks", async function () { }); getZkitCircuitFullPaths(config).forEach((path, index) => { + const provingSystemsFiles: string[] = []; + + provingSystems.forEach((provingSystem) => { + provingSystemsFiles.push( + `${circuitNames[index]}.${provingSystem}.vkey.json`, + `${circuitNames[index]}.${provingSystem}.zkey`, + ); + }); + expect(fsExtra.readdirSync(path)).to.be.deep.eq([ - `${circuitNames[index]}.groth16.vkey.json`, - `${circuitNames[index]}.groth16.zkey`, + ...provingSystemsFiles, `${circuitNames[index]}.r1cs`, `${circuitNames[index]}.sym`, `${circuitNames[index]}_artifacts.json`, @@ -84,20 +102,14 @@ describe("ZKit tasks", async function () { const ptauFullPath: string = getNormalizedFullPath(config.paths!.root!, "zkit/ptau"); expect(fsExtra.readdirSync(ptauFullPath)).to.be.deep.eq(["powers-of-tau-8.ptau"]); - const circuit = await zkit.getCircuit("Multiplier2"); - await expect(circuit).with.witnessInputs({ in1: "3", in2: "7" }).to.have.witnessOutputs(["21"]); - - const proof = await circuit.generateProof({ in1: "4", in2: "2" }); - - await expect(circuit).to.verifyProof(proof); - } - - function updateInclude(filePath: string, newIncludePath: string) { - const fileContent = fsExtra.readFileSync(filePath, "utf-8"); + for (const provingSystem of provingSystems) { + const circuit = await zkit.getCircuit("Multiplier2", provingSystems.length > 1 ? provingSystem : undefined); + await expect(circuit).with.witnessInputs({ in1: "3", in2: "7" }).to.have.witnessOutputs(["21"]); - const updatedContent = fileContent.replace(/include\s*".*";/, `include "${newIncludePath}";`); + const proof = await circuit.generateProof({ in1: "4", in2: "2" }); - fsExtra.writeFileSync(filePath, updatedContent, "utf-8"); + await expect(circuit).to.verifyProof(proof); + } } describe("compile", async function () { @@ -322,9 +334,56 @@ describe("ZKit tasks", async function () { expect(constraintsSize).to.be.lt(fileSizes.constraints); }); }); + + describe("with different proving systems", async function () { + const plonkTypesDir = "zkit/types-plonk"; + const groth16PlonkTypesDir = "zkit/types-groth16-plonk"; + + useEnvironment("with-circuits", true); + + it("should correctly compile circuits with 'groth16' proving system", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + const circuit = await this.hre.zkit.getCircuit("Multiplier2"); + + expect(circuit.getProvingSystemType()).to.be.eq("groth16"); + + updateProvingSystems(this.hre.config.paths.configFile, ["plonk"]); + updateTypesDir(this.hre.config.paths.configFile, defaultTypesDir, plonkTypesDir); + }); + + it("should correctly compile circuits with 'plonk' proving system", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + const circuit = await this.hre.zkit.getCircuit("Multiplier2"); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16", "plonk"]); + updateTypesDir(this.hre.config.paths.configFile, plonkTypesDir, groth16PlonkTypesDir); + + expect(circuit.getProvingSystemType()).to.be.eq("plonk"); + }); + + it("should correctly compile circuits with several proving systems", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + let circuit = await this.hre.zkit.getCircuit("Multiplier2", "groth16"); + + expect(circuit.getProvingSystemType()).to.be.eq("groth16"); + + circuit = await this.hre.zkit.getCircuit("Multiplier2", "plonk"); + + expect(circuit.getProvingSystemType()).to.be.eq("plonk"); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16"]); + updateTypesDir(this.hre.config.paths.configFile, groth16PlonkTypesDir, defaultTypesDir); + }); + }); }); describe("setup", async function () { + const plonkTypesDir = "zkit/types-plonk"; + const groth16PlonkTypesDir = "zkit/types-groth16-plonk"; + useEnvironment("with-circuits", true); it("should not generate vkey, zkey files without compiled circuits", async function () { @@ -338,11 +397,34 @@ describe("ZKit tasks", async function () { expect(CircuitsSetupCache!.getEntries()).to.be.deep.eq([]); }); - it("should generate correct vkey, zkey files for compiled circuits", async function () { + it("should generate correct vkey, zkey files for compiled circuits with 'groth16' proving system", async function () { await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_SETUP }); - await checkMake(this.hre.config, this.hre.zkit); + await checkMake(this.hre.config, this.hre.zkit, ["groth16"]); + + updateProvingSystems(this.hre.config.paths.configFile, ["plonk"]); + updateTypesDir(this.hre.config.paths.configFile, defaultTypesDir, plonkTypesDir); + }); + + it("should generate correct vkey, zkey files for compiled circuits with 'plonk' proving system", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_SETUP }); + + await checkMake(this.hre.config, this.hre.zkit, ["plonk"]); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16", "plonk"]); + updateTypesDir(this.hre.config.paths.configFile, plonkTypesDir, groth16PlonkTypesDir); + }); + + it("should generate correct vkey, zkey files with 'plonk' and 'groth16' proving systems", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_SETUP }); + + await checkMake(this.hre.config, this.hre.zkit, ["groth16", "plonk"]); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16"]); + updateTypesDir(this.hre.config.paths.configFile, groth16PlonkTypesDir, defaultTypesDir); }); }); @@ -352,22 +434,64 @@ describe("ZKit tasks", async function () { it("should correctly compile circuits and generate vkey, zkey files", async function () { await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE }); - await checkMake(this.hre.config, this.hre.zkit); + await checkMake(this.hre.config, this.hre.zkit, ["groth16"]); }); }); describe("verifiers", async function () { + const plonkTypesDir = "zkit/types-plonk"; + const groth16PlonkTypesDir = "zkit/types-groth16-plonk"; + useEnvironment("with-circuits", true); - it("should correctly generate verifiers after running the verifiers task", async function () { + it("should correctly generate 'groth16' verifiers after running the verifiers task", async function () { await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_GENERATE_VERIFIERS }); - await checkMake(this.hre.config, this.hre.zkit); + await checkMake(this.hre.config, this.hre.zkit, ["groth16"]); const verifiersFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "contracts/verifiers"); expect(fsExtra.readdirSync(verifiersFullPath)).to.be.deep.eq( circuitNames.map((name) => `${name}Groth16Verifier.sol`), ); + + updateProvingSystems(this.hre.config.paths.configFile, ["plonk"]); + updateTypesDir(this.hre.config.paths.configFile, defaultTypesDir, plonkTypesDir); + }); + + it("should correctly generate 'plonk' verifiers after running the verifiers task", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_GENERATE_VERIFIERS }); + + await checkMake(this.hre.config, this.hre.zkit, ["plonk"]); + + const verifiersFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "contracts/verifiers"); + expect(fsExtra.readdirSync(verifiersFullPath)).to.be.deep.eq( + circuitNames.map((name) => `${name}PlonkVerifier.sol`), + ); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16", "plonk"]); + updateTypesDir(this.hre.config.paths.configFile, plonkTypesDir, groth16PlonkTypesDir); + }); + + it("should correctly generate 'groth16' and 'plonk' verifiers after running the verifiers task", async function () { + const provingSystemsArr: ProvingSystemType[] = ["groth16", "plonk"]; + + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_GENERATE_VERIFIERS }); + + await checkMake(this.hre.config, this.hre.zkit, provingSystemsArr); + + const verifiersFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "contracts/verifiers"); + const verifiersNameArr: string[] = []; + + for (const circuitName of circuitNames) { + verifiersNameArr.push( + ...provingSystemsArr.map((provingSystem) => `${circuitName}${capitalize(provingSystem)}Verifier.sol`), + ); + } + + expect(fsExtra.readdirSync(verifiersFullPath)).to.be.deep.eq(verifiersNameArr); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16"]); + updateTypesDir(this.hre.config.paths.configFile, groth16PlonkTypesDir, defaultTypesDir); }); }); @@ -394,7 +518,7 @@ describe("ZKit tasks", async function () { const cacheDir: string = getNormalizedFullPath(this.hre.config.paths.root, "cache"); const zkitDir: string = getNormalizedFullPath(this.hre.config.paths.root, "zkit"); - await checkMake(this.hre.config, this.hre.zkit); + await checkMake(this.hre.config, this.hre.zkit, ["groth16"]); await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_ZKIT_CLEAN }); diff --git a/test/unit/cache/circuits-setup-cache.test.ts b/test/unit/cache/circuits-setup-cache.test.ts index 561ddf5..8177e41 100644 --- a/test/unit/cache/circuits-setup-cache.test.ts +++ b/test/unit/cache/circuits-setup-cache.test.ts @@ -2,18 +2,19 @@ import fsExtra from "fs-extra"; import { expect } from "chai"; -import { useEnvironment } from "@test-helpers"; -import { getSetupCacheEntry } from "../../utils"; import { getFileHash } from "@src/utils/utils"; import { getNormalizedFullPath } from "@src/utils/path-utils"; +import { CircuitsSetupCache, createCircuitsSetupCache, resetCircuitsSetupCache } from "@src/cache"; +import { TASK_CIRCUITS_MAKE, ZKIT_SCOPE_NAME } from "@src/task-names"; +import { CIRCUITS_SETUP_CACHE_FILENAME, CIRCUIT_SETUP_CACHE_VERSION } from "@src/constants"; -import { defaultContributionSettings } from "../../constants"; +import { SetupContributionSettings } from "@src/types/core"; import { SetupCacheEntry } from "@src/types/cache"; import { CircuitArtifact } from "@src/types/artifacts/circuit-artifacts"; -import { TASK_CIRCUITS_MAKE, ZKIT_SCOPE_NAME } from "@src/task-names"; -import { CIRCUITS_SETUP_CACHE_FILENAME, CIRCUIT_SETUP_CACHE_VERSION } from "@src/constants"; -import { CircuitsSetupCache, createCircuitsSetupCache, resetCircuitsSetupCache } from "@src/cache"; +import { useEnvironment } from "@test-helpers"; +import { getSetupCacheEntry } from "../../utils"; +import { defaultContributionSettings } from "../../constants"; describe("CircuitsSetupCache", () => { describe("createEmpty", () => { @@ -116,6 +117,15 @@ describe("CircuitsSetupCache", () => { }), ).to.be.deep.eq(defaultContributionSettings.provingSystems); + const newContributionSettings: SetupContributionSettings = { + provingSystems: ["plonk"], + contributions: 2, + }; + + expect( + CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash, newContributionSettings), + ).to.be.deep.eq(newContributionSettings.provingSystems); + expect( CircuitsSetupCache!.hasFileChanged(mul2ArtifactFullPath, contentHash, defaultContributionSettings), ).to.be.deep.eq([]); diff --git a/test/unit/core/zkit/circuit-zkit-builder.test.ts b/test/unit/core/zkit/circuit-zkit-builder.test.ts new file mode 100644 index 0000000..e032b0c --- /dev/null +++ b/test/unit/core/zkit/circuit-zkit-builder.test.ts @@ -0,0 +1,85 @@ +import { expect } from "chai"; + +import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "@src/task-names"; + +import { useEnvironment } from "@test-helpers"; +import { updateProvingSystems, updateTypesDir } from "../../../utils"; + +describe("CircuitZKitBuilder", () => { + const defaultTypesDir = "generated-types/zkit"; + + describe("getCircuitZKit", async function () { + const groth16PlonkTypesDir = "zkit/types-groth16-plonk"; + + useEnvironment("with-circuits", true); + + it("should return correct CircuitZKit object for the 'groth16' proving system", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + const circuit = await this.hre.zkit.circuitZKitBuilder.getCircuitZKit("Multiplier2"); + + expect(circuit.getProvingSystemType()).to.be.eq("groth16"); + }); + + it("should throw an error if pass proving system instead of undefined", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + await expect(this.hre.zkit.circuitZKitBuilder.getCircuitZKit("Multiplier2", "groth16")).to.be.rejectedWith( + "Found single proving system. No need to specify the exact proving system in the getCircuit function.", + ); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16", "plonk"]); + updateTypesDir(this.hre.config.paths.configFile, defaultTypesDir, groth16PlonkTypesDir); + }); + + it("should return correct CircuitZKit object for the 'groth16' and 'plonk' proving systems", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + let circuit = await this.hre.zkit.circuitZKitBuilder.getCircuitZKit("Multiplier2", "groth16"); + + expect(circuit.getProvingSystemType()).to.be.eq("groth16"); + + circuit = await this.hre.zkit.circuitZKitBuilder.getCircuitZKit("Multiplier2", "plonk"); + + expect(circuit.getProvingSystemType()).to.be.eq("plonk"); + }); + + it("should throw an error if pass undefined proving system with several proving systems", async function () { + await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }); + + await expect(this.hre.zkit.circuitZKitBuilder.getCircuitZKit("Multiplier2")).to.be.rejectedWith( + "Found several proving systems. Please specify the exact proving system in the getCircuit function.", + ); + + updateProvingSystems(this.hre.config.paths.configFile, ["groth16"]); + updateTypesDir(this.hre.config.paths.configFile, groth16PlonkTypesDir, defaultTypesDir); + }); + }); + + describe("getProtocolImplementer", async function () { + useEnvironment("with-circuits", true); + + it("should return correct protocol implementers", async function () { + let protocolImplementer = this.hre.zkit.circuitZKitBuilder.getProtocolImplementer("groth16"); + + expect(protocolImplementer.getProvingSystemType()).to.be.eq("groth16"); + + protocolImplementer = this.hre.zkit.circuitZKitBuilder.getProtocolImplementer("plonk"); + + expect(protocolImplementer.getProvingSystemType()).to.be.eq("plonk"); + + protocolImplementer = this.hre.zkit.circuitZKitBuilder.getProtocolImplementer("groth16"); + + expect(protocolImplementer.getProvingSystemType()).to.be.eq("groth16"); + }); + + it("should get exception if pass invalid proving system", async function () { + const invalidProvingSystem = "some"; + const circuitZKitBuilder = this.hre.zkit.circuitZKitBuilder; + + expect(function () { + circuitZKitBuilder.getProtocolImplementer(invalidProvingSystem); + }).to.throw(`Unsupported proving system - ${invalidProvingSystem}`); + }); + }); +}); diff --git a/test/utils.ts b/test/utils.ts index 6bd4fe6..94f3fa0 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,5 +1,7 @@ import fsExtra from "fs-extra"; +import { ProvingSystemType } from "@solarity/zkit"; + import { CircomFilesParser } from "../src/core"; import { getFileHash } from "../src/utils/utils"; import { getNormalizedFullPath } from "../src/utils/path-utils"; @@ -56,3 +58,37 @@ export async function getSetupCacheEntry( contributionsNumber: defaultContributionSettings.contributions, }; } + +export function updateInclude(filePath: string, newIncludePath: string) { + const fileContent = fsExtra.readFileSync(filePath, "utf-8"); + + const updatedContent = fileContent.replace(/include\s*".*";/, `include "${newIncludePath}";`); + + fsExtra.writeFileSync(filePath, updatedContent, "utf-8"); +} + +export function updateProvingSystems(filePath: string, newProvingSystems: ProvingSystemType[]) { + const fileContent = fsExtra.readFileSync(filePath, "utf-8"); + + const provingSystemsStr: string = newProvingSystems + .map((provingSystem: ProvingSystemType) => { + return `"${provingSystem}"`; + }) + .join(","); + + const updatedContent = fileContent.replace( + /provingSystem: \[("\w+"|, *)+\],/, + `provingSystem: [${provingSystemsStr}],`, + ); + + fsExtra.writeFileSync(filePath, updatedContent, "utf-8"); +} + +export function updateTypesDir(filePath: string, prevTypesDir: string, newTypesDir: string) { + const fileContent = fsExtra.readFileSync(filePath, "utf-8"); + + const updatedContent = fileContent.replace(/typesDir: "[\w\-/]+",/, `typesDir: "${newTypesDir}",`); + + fsExtra.writeFileSync(filePath, updatedContent, "utf-8"); + fsExtra.rmSync(prevTypesDir, { force: true, recursive: true }); +} From 8ad4219a54d09a3c406e69c77f92e4b41e691e1b Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Wed, 6 Nov 2024 17:39:05 +0200 Subject: [PATCH 10/13] Update README file --- README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 583eeac..52bbe0f 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This hardhat plugin is a zero-config, one-stop Circom development environment that streamlines circuits management and lets you focus on the important - code. - Developer-oriented abstractions that simplify `r1cs`, `zkey`, `vkey`, and `witness` generation processes. +- Supporting of the `groth16` and `plonk` proving systems. - Recompilation of only the modified circuits. - Full TypeScript typization of signals and ZK proofs. - Automatic downloads of phase-1 `ptau` files. @@ -61,7 +62,7 @@ module.exports = { }, setupSettings: { contributionSettings: { - provingSystem: "groth16", + provingSystem: "groth16", // Or ["groth16", "plonk"] contributions: 2, }, onlyFiles: [], @@ -92,7 +93,7 @@ Where: - `optimization` - The flag to set the level of constraint simplification during compilation (`O0`, `O1` or `O2`). - `setupSettings` - `contributionSettings` - - `provingSystem` - The option to indicate which proving system to use. + - `provingSystem` - The option to indicate which proving system to use (`groth16`, `plonk` or `["groth16", "plonk"]`). - `contributions` - The number of phase-2 `zkey` contributions to make if `groth16` is chosen. - `onlyFiles` - The list of directories (or files) to be considered for the setup phase. - `skipFiles` - The list of directories (or files) to be excluded from the setup phase. @@ -201,6 +202,11 @@ describe("Multiplier", () => { it("should test the circuit", async () => { const circuit: Multiplier = await zkit.getCircuit("Multiplier"); // or await zkit.getCircuit("circuits/multiplier.circom:Multiplier"); + + /* + * If you set up both proving systems you will need to specify exact proving system in getCircuit function: + * const circuit: Multiplier = await zkit.getCircuit("Multiplier", "plonk"); + */ // witness testing await expect(circuit) @@ -235,25 +241,27 @@ Afterward, copy the provided script to the `test` directory and run the tests vi --- -- **`async getCircuit() -> zkit`** +- **`async getCircuit(, ) -> zkit`** -The method accepts the name of the `main` component of the circuit and returns the instantiated zkit object pointing to that circuit. +The method accepts the name of the `main` component of the circuit, optional proving system and returns the instantiated zkit object pointing to that circuit. The method works regardless of how the circuit was compiled, however, if `zkit compile` task was used, the zkit methods that utilize proof generation or proof verification would throw an error by design. In case there are conflicts between circuit file names and `main` component names, you should use the `fullCircuitName`, which has the following form: `circuitSourceName:circuitName`. +`provingSystem` parameter should be specified only if several proving systems have been specified in the config. + Where: - `circuitSourceName` - Path to the circuit file from the project root. - `circuitName` - Circuit `main` component name. +- `provingSystem` - Optional parameter that can be `groth16` or `plonk` > [!IMPORTANT] > Please note that the method actually returns the [`zktype`](https://github.com/dl-solarity/zktype) typed zkit wrapper objects which enable full TypeScript typization of signals and proofs. Also, check out the [`zkit`](https://github.com/dl-solarity/zkit) documentation to understand zkit object capabilities and how to interact with circuits. ## Known limitations -- Temporarily, the only available proving system is `groth16`. Support for `plonk` is just behind the corner. - Sometimes `hardhat` scripts that generate ZK proofs may run indefinitely. This will be fixed in the next major release. - Currently there is minimal support for `var` Circom variables. Some circuits may not work if you are using complex `var`-dependent expressions. - Due to current `wasm` memory limitations (address space is 32-bit), the plugin may fail to compile especially large circuits on some platforms. From 6231b415a1b796ea54be9f3e17f0eb8cf53a70a1 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 6 Nov 2024 20:14:18 +0200 Subject: [PATCH 11/13] ptauId calculation fix --- src/core/compile/CompilationProcessor.ts | 13 ++++++++++--- src/core/setup/SetupProcessor.ts | 2 +- src/utils/constraints-utils.ts | 19 ++++++++++++------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/core/compile/CompilationProcessor.ts b/src/core/compile/CompilationProcessor.ts index 45f4729..f596053 100644 --- a/src/core/compile/CompilationProcessor.ts +++ b/src/core/compile/CompilationProcessor.ts @@ -11,8 +11,13 @@ import { HardhatZKitError } from "../../errors"; import { CIRCUIT_ARTIFACT_VERSION, NODE_MODULES } from "../../constants"; import { Reporter } from "../../reporter"; -import { getGroth16ConstraintsNumber } from "../../utils/constraints-utils"; -import { getNormalizedFullPath, renameFilesRecursively, readDirRecursively } from "../../utils/path-utils"; +import { + getNormalizedFullPath, + renameFilesRecursively, + readDirRecursively, + getR1CSConstraintsNumber, + terminateCurve, +} from "../../utils"; import { ZKitConfig } from "../../types/zkit-config"; import { ArtifactsFileType, CircuitArtifact, ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; @@ -104,9 +109,11 @@ export class CompilationProcessor { for (const info of compilationInfoArr) { const r1csFilePath = getNormalizedFullPath(info.tempArtifactsPath, `${info.circuitName}.r1cs`); - info.constraintsNumber = await getGroth16ConstraintsNumber(r1csFilePath); + info.constraintsNumber = await getR1CSConstraintsNumber(r1csFilePath); } + await terminateCurve(); + await this._moveFromTempDirToArtifacts(compilationInfoArr); await this._emitArtifacts(compilationInfoArr); diff --git a/src/core/setup/SetupProcessor.ts b/src/core/setup/SetupProcessor.ts index c4da17d..f8a3358 100644 --- a/src/core/setup/SetupProcessor.ts +++ b/src/core/setup/SetupProcessor.ts @@ -229,7 +229,7 @@ export class SetupProcessor { const maxConstraintsNumber = Math.max(...circuitsConstraintsNumber); - const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber)), 8); + const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber - 1)) + 1, 8); let entries: fsExtra.Dirent[] = []; diff --git a/src/utils/constraints-utils.ts b/src/utils/constraints-utils.ts index 57906cc..fecf8af 100644 --- a/src/utils/constraints-utils.ts +++ b/src/utils/constraints-utils.ts @@ -6,7 +6,7 @@ import * as binfileutils from "@iden3/binfileutils"; import { LinearCombination, R1CSConstraint } from "../../src/types/utils"; -export async function getGroth16ConstraintsNumber(r1csFilePath: string): Promise { +export async function getR1CSConstraintsNumber(r1csFilePath: string): Promise { return (await snarkjs.r1cs.info(r1csFilePath)).nConstraints; } @@ -19,10 +19,13 @@ export async function getPlonkConstraintsNumber(r1csFilePath: string, Fr: any): const join = (lc1: LinearCombination, k: bigint, lc2: LinearCombination) => { const res = { ...lc1 }; + Object.keys(lc2).forEach((s) => { res[s] = res[s] ? Fr.add(res[s], Fr.mul(k, lc2[s])) : lc2[s]; }); + normalize(res); + return res; }; @@ -45,12 +48,14 @@ export async function getPlonkConstraintsNumber(r1csFilePath: string, Fr: any): let n = 0; Object.keys(lc).forEach((key) => { - if (lc[key] !== 0n) { - if (key === "0") { - k = Fr.add(k, lc[key]); - } else { - n++; - } + if (lc[key] === 0n) { + return; + } + + if (key === "0") { + k = Fr.add(k, lc[key]); + } else { + n++; } }); From 1b98eefd93bc3e6e1ca95fa7a8f7c9227750c92b Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 6 Nov 2024 20:23:37 +0200 Subject: [PATCH 12/13] fixed ptauId calculation for different proving systems --- src/core/setup/SetupProcessor.ts | 14 +++++++++----- src/utils/constraints-utils.ts | 21 +++++++-------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/core/setup/SetupProcessor.ts b/src/core/setup/SetupProcessor.ts index f8a3358..3fd9b04 100644 --- a/src/core/setup/SetupProcessor.ts +++ b/src/core/setup/SetupProcessor.ts @@ -11,9 +11,13 @@ import { HardhatZKitError } from "../../errors"; import { BN128_CURVE_NAME, PTAU_FILE_REG_EXP } from "../../constants"; import { Reporter } from "../../reporter"; import { PtauDownloader } from "../utils/PtauDownloader"; -import { terminateCurve } from "../../utils/utils"; -import { getNormalizedFullPath } from "../../utils/path-utils"; -import { getPlonkConstraintsNumber } from "../../utils/constraints-utils"; + +import { + terminateCurve, + getNormalizedFullPath, + getGroth16ConstraintsNumber, + getPlonkConstraintsNumber, +} from "../../utils"; import { ICircuitArtifacts } from "../../types/artifacts/circuit-artifacts"; import { CircuitSetupInfo, SetupContributionSettings } from "../../types/core"; @@ -221,7 +225,7 @@ export class SetupProcessor { circuitSetupInfoArr.map(async (setupInfo: CircuitSetupInfo) => { return usePlonk ? getPlonkConstraintsNumber(setupInfo.r1csSourcePath, curve.Fr) - : setupInfo.circuitArtifact.baseCircuitInfo.constraintsNumber; + : getGroth16ConstraintsNumber(setupInfo.r1csSourcePath); }), ); @@ -229,7 +233,7 @@ export class SetupProcessor { const maxConstraintsNumber = Math.max(...circuitsConstraintsNumber); - const ptauId = Math.max(Math.ceil(Math.log2(maxConstraintsNumber - 1)) + 1, 8); + const ptauId = Math.max(Math.floor(Math.log2(maxConstraintsNumber - (usePlonk ? 1 : 0))) + 1, 8); let entries: fsExtra.Dirent[] = []; diff --git a/src/utils/constraints-utils.ts b/src/utils/constraints-utils.ts index fecf8af..7e643e9 100644 --- a/src/utils/constraints-utils.ts +++ b/src/utils/constraints-utils.ts @@ -1,8 +1,4 @@ import * as snarkjs from "snarkjs"; -// @ts-expect-error: No type definitions available for the "r1csfile" package -import * as r1csfile from "r1csfile"; -// @ts-expect-error: No type definitions available for the "@iden3/binfileutils" package -import * as binfileutils from "@iden3/binfileutils"; import { LinearCombination, R1CSConstraint } from "../../src/types/utils"; @@ -10,6 +6,12 @@ export async function getR1CSConstraintsNumber(r1csFilePath: string): Promise { + const r1cs = await snarkjs.r1cs.info(r1csFilePath); + + return r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs; +} + export async function getPlonkConstraintsNumber(r1csFilePath: string, Fr: any): Promise { const normalize = (lc: LinearCombination) => { Object.keys(lc).forEach((key) => { @@ -79,20 +81,11 @@ export async function getPlonkConstraintsNumber(r1csFilePath: string, Fr: any): } }; - const { fd: fdR1cs, sections: sectionsR1cs } = await binfileutils.readBinFile( - r1csFilePath, - "r1cs", - 1, - 1 << 22, - 1 << 24, - ); - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, { loadConstraints: true, loadCustomGates: true }); + const r1cs = await snarkjs.r1cs.info(r1csFilePath); let plonkConstraintsCount = r1cs.nOutputs + r1cs.nPubInputs; r1cs.constraints.forEach((constraint: R1CSConstraint) => process(...constraint)); - await fdR1cs.fd.close(); - return plonkConstraintsCount; } From 689d10242e8d309fa9a93bb516adeefdf506361c Mon Sep 17 00:00:00 2001 From: Artem Chystiakov Date: Thu, 7 Nov 2024 13:52:08 +0200 Subject: [PATCH 13/13] quick readme fix --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 52bbe0f..c1737bb 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This hardhat plugin is a zero-config, one-stop Circom development environment that streamlines circuits management and lets you focus on the important - code. - Developer-oriented abstractions that simplify `r1cs`, `zkey`, `vkey`, and `witness` generation processes. -- Supporting of the `groth16` and `plonk` proving systems. +- Support of `groth16` and `plonk` proving systems. - Recompilation of only the modified circuits. - Full TypeScript typization of signals and ZK proofs. - Automatic downloads of phase-1 `ptau` files. @@ -62,7 +62,7 @@ module.exports = { }, setupSettings: { contributionSettings: { - provingSystem: "groth16", // Or ["groth16", "plonk"] + provingSystem: "groth16", // or ["groth16", "plonk"] contributions: 2, }, onlyFiles: [], @@ -202,11 +202,6 @@ describe("Multiplier", () => { it("should test the circuit", async () => { const circuit: Multiplier = await zkit.getCircuit("Multiplier"); // or await zkit.getCircuit("circuits/multiplier.circom:Multiplier"); - - /* - * If you set up both proving systems you will need to specify exact proving system in getCircuit function: - * const circuit: Multiplier = await zkit.getCircuit("Multiplier", "plonk"); - */ // witness testing await expect(circuit) @@ -249,19 +244,18 @@ The method works regardless of how the circuit was compiled, however, if `zkit c In case there are conflicts between circuit file names and `main` component names, you should use the `fullCircuitName`, which has the following form: `circuitSourceName:circuitName`. -`provingSystem` parameter should be specified only if several proving systems have been specified in the config. +The optional `provingSystem` parameter should be specified only if multiple proving systems were set in the config. Where: - `circuitSourceName` - Path to the circuit file from the project root. - `circuitName` - Circuit `main` component name. -- `provingSystem` - Optional parameter that can be `groth16` or `plonk` +- `provingSystem` - Optional parameter that can either be `groth16` or `plonk`. > [!IMPORTANT] > Please note that the method actually returns the [`zktype`](https://github.com/dl-solarity/zktype) typed zkit wrapper objects which enable full TypeScript typization of signals and proofs. Also, check out the [`zkit`](https://github.com/dl-solarity/zkit) documentation to understand zkit object capabilities and how to interact with circuits. ## Known limitations -- Sometimes `hardhat` scripts that generate ZK proofs may run indefinitely. This will be fixed in the next major release. - Currently there is minimal support for `var` Circom variables. Some circuits may not work if you are using complex `var`-dependent expressions. - Due to current `wasm` memory limitations (address space is 32-bit), the plugin may fail to compile especially large circuits on some platforms.