mirror of
https://github.com/dl-solarity/hardhat-zkit.git
synced 2026-01-09 15:58:02 -05:00
Test coverage (#30)
* added task tests * added circom-compiler-downloader.test.ts, made some fixes * fix timeout issue * debug ci * fixed ETXTBSY error * fixed ETXTBSY error without setTimeout * created tests with os mock, added verifyCompiler flag * added keys verification and circuits with libs compilation inside tasks tests * multiple workspaces with the same name fix * added ptau downloader tests * prevented native compiler usage inside tests, modified mocha timeout * added semver and tsconfig paths * moved semver to dependencies, modified eslint settings * restricted semver version, updated package version
This commit is contained in:
@@ -47,7 +47,15 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
"no-multiple-empty-lines": [2, { max: 1, maxEOF: 0, maxBOF: 0 }],
|
||||
"import/no-named-as-default-member": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
},
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
"typescript": {
|
||||
"project": "./tsconfig.json",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
"file": ["test/setup.ts"],
|
||||
"require": "ts-node/register/files",
|
||||
"ignore": ["test/fixture-projects/**/*"],
|
||||
"timeout": 10000
|
||||
"timeout": 60000
|
||||
}
|
||||
|
||||
357
package-lock.json
generated
357
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@solarity/hardhat-zkit",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@solarity/hardhat-zkit",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.2",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"test/fixture-projects/*"
|
||||
@@ -23,12 +23,14 @@
|
||||
"lodash": "4.17.21",
|
||||
"ora": "5.4.1",
|
||||
"resolve": "1.22.8",
|
||||
"semver": "7.6.3",
|
||||
"snarkjs": "0.7.3",
|
||||
"uuid": "9.0.1",
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-ethers": "3.0.5",
|
||||
"@solarity/chai-zkit": "^0.2.5",
|
||||
"@typechain/ethers-v6": "^0.5.1",
|
||||
"@typechain/hardhat": "^9.1.0",
|
||||
"@types/chai": "^4.3.12",
|
||||
@@ -40,6 +42,7 @@
|
||||
"@types/lodash": "4.17.5",
|
||||
"@types/mocha": "^10.0.6",
|
||||
"@types/resolve": "^1.20.6",
|
||||
"@types/sinon": "^17.0.3",
|
||||
"@types/snarkjs": "^0.7.8",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||
@@ -47,7 +50,8 @@
|
||||
"chai": "^4.4.1",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-import-resolver-typescript": "^3.6.3",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"ethers": "6.11.1",
|
||||
@@ -56,7 +60,9 @@
|
||||
"mocha": "^10.3.0",
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^3.2.5",
|
||||
"sinon": "^19.0.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typechain": "^8.3.2",
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
@@ -1319,6 +1325,15 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@nolyfill/is-core-module": {
|
||||
"version": "1.0.39",
|
||||
"resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
|
||||
"integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nomicfoundation/ethereumjs-block": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.4.tgz",
|
||||
@@ -2066,6 +2081,102 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@sinonjs/commons": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
|
||||
"integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"type-detect": "4.0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/commons/node_modules/type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/samsam": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz",
|
||||
"integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^3.0.1",
|
||||
"lodash.get": "^4.4.2",
|
||||
"type-detect": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/text-encoding": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz",
|
||||
"integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@solarity/chai-zkit": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@solarity/chai-zkit/-/chai-zkit-0.2.5.tgz",
|
||||
"integrity": "sha512-VRl6YXd/uQruz0U48B85hmeA7sMn1WUjUcGtMMKovFJjFY4xKjUrtGAuXfUCM8ZB9nt6iuTulsPEijLWgayIHg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chai-as-promised": "7.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@solarity/hardhat-zkit": ">=0.3.1 <0.5.0",
|
||||
"@solarity/zkit": ">=0.2.4 <0.4.0",
|
||||
"chai": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@solarity/chai-zkit/node_modules/chai-as-promised": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
|
||||
"integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"check-error": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chai": ">= 2.1.2 < 5"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@distributedlab/circom-parser": "0.1.2",
|
||||
"@distributedlab/circom2": "0.2.18-rc.4",
|
||||
"@solarity/zkit": "0.2.6",
|
||||
"@solarity/zktype": "0.3.1",
|
||||
"chalk": "4.1.2",
|
||||
"cli-progress": "3.12.0",
|
||||
"cli-table3": "0.6.5",
|
||||
"debug": "4.3.5",
|
||||
"lodash": "4.17.21",
|
||||
"ora": "5.4.1",
|
||||
"resolve": "1.22.8",
|
||||
"snarkjs": "0.7.3",
|
||||
"uuid": "9.0.1",
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hardhat": "^2.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@solarity/zkit": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@solarity/zkit/-/zkit-0.2.6.tgz",
|
||||
@@ -2315,6 +2426,21 @@
|
||||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/sinon": {
|
||||
"version": "17.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz",
|
||||
"integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/sinonjs__fake-timers": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/sinonjs__fake-timers": {
|
||||
"version": "8.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz",
|
||||
"integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/snarkjs": {
|
||||
"version": "0.7.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/snarkjs/-/snarkjs-0.7.8.tgz",
|
||||
@@ -3994,6 +4120,19 @@
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.17.1",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
|
||||
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/enquirer": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
|
||||
@@ -4337,6 +4476,41 @@
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-typescript": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz",
|
||||
"integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nolyfill/is-core-module": "1.0.39",
|
||||
"debug": "^4.3.5",
|
||||
"enhanced-resolve": "^5.15.0",
|
||||
"eslint-module-utils": "^2.8.1",
|
||||
"fast-glob": "^3.3.2",
|
||||
"get-tsconfig": "^4.7.5",
|
||||
"is-bun-module": "^1.0.2",
|
||||
"is-glob": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "*",
|
||||
"eslint-plugin-import": "*",
|
||||
"eslint-plugin-import-x": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"eslint-plugin-import": {
|
||||
"optional": true
|
||||
},
|
||||
"eslint-plugin-import-x": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-module-utils": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz",
|
||||
@@ -4426,6 +4600,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/json5": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@@ -4447,6 +4633,27 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/tsconfig-paths": {
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
|
||||
"integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json5": "^0.0.29",
|
||||
"json5": "^1.0.2",
|
||||
"minimist": "^1.2.6",
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
|
||||
@@ -5182,6 +5389,18 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
|
||||
"integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
@@ -5388,10 +5607,22 @@
|
||||
"resolved": "test/fixture-projects/hardhat-project-circuits-with-libraries",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/hardhat-project-compiler-config": {
|
||||
"resolved": "test/fixture-projects/hardhat-project-compiler-config",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/hardhat-project-compiler-incorrect-config": {
|
||||
"resolved": "test/fixture-projects/hardhat-project-compiler-incorrect-config",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/hardhat-project-defined-config": {
|
||||
"resolved": "test/fixture-projects/hardhat-project-defined-config",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/hardhat-project-invalid-circuits": {
|
||||
"resolved": "test/fixture-projects/hardhat-project-invalid-circuits",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/hardhat-project-undefined-config": {
|
||||
"resolved": "test/fixture-projects/hardhat-project-undefined-config",
|
||||
"link": true
|
||||
@@ -6031,6 +6262,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-bun-module": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz",
|
||||
"integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^7.6.3"
|
||||
}
|
||||
},
|
||||
"node_modules/is-callable": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
|
||||
@@ -6597,6 +6837,12 @@
|
||||
"underscore": "1.12.1"
|
||||
}
|
||||
},
|
||||
"node_modules/just-extend": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz",
|
||||
"integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/keccak": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz",
|
||||
@@ -6675,6 +6921,12 @@
|
||||
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.get": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
@@ -7000,6 +7252,19 @@
|
||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nise": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz",
|
||||
"integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^3.0.1",
|
||||
"@sinonjs/fake-timers": "^13.0.1",
|
||||
"@sinonjs/text-encoding": "^0.7.3",
|
||||
"just-extend": "^6.2.0",
|
||||
"path-to-regexp": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||
@@ -7516,6 +7781,15 @@
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"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==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
@@ -7882,6 +8156,15 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||
@@ -8064,7 +8347,6 @@
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
@@ -8187,6 +8469,33 @@
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"node_modules/sinon": {
|
||||
"version": "19.0.2",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz",
|
||||
"integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^3.0.1",
|
||||
"@sinonjs/fake-timers": "^13.0.2",
|
||||
"@sinonjs/samsam": "^8.0.1",
|
||||
"diff": "^7.0.0",
|
||||
"nise": "^6.1.1",
|
||||
"supports-color": "^7.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/sinon"
|
||||
}
|
||||
},
|
||||
"node_modules/sinon/node_modules/diff": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
|
||||
"integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
@@ -8600,6 +8909,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "5.0.11",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-5.0.11.tgz",
|
||||
@@ -8804,27 +9122,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
|
||||
"integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
|
||||
"integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json5": "^0.0.29",
|
||||
"json5": "^1.0.2",
|
||||
"json5": "^2.2.2",
|
||||
"minimist": "^1.2.6",
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths/node_modules/json5": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths/node_modules/strip-bom": {
|
||||
@@ -9560,9 +9868,18 @@
|
||||
"circomlib": "^2.0.5"
|
||||
}
|
||||
},
|
||||
"test/fixture-projects/hardhat-project-compiler-config": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"test/fixture-projects/hardhat-project-compiler-incorrect-config": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"test/fixture-projects/hardhat-project-defined-config": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"test/fixture-projects/hardhat-project-invalid-circuits": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"test/fixture-projects/hardhat-project-undefined-config": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
|
||||
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@solarity/hardhat-zkit",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.2",
|
||||
"description": "The ultimate TypeScript environment for Circom development",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
@@ -61,6 +61,7 @@
|
||||
"lodash": "4.17.21",
|
||||
"ora": "5.4.1",
|
||||
"resolve": "1.22.8",
|
||||
"semver": "7.6.3",
|
||||
"snarkjs": "0.7.3",
|
||||
"uuid": "9.0.1",
|
||||
"zod": "3.23.8"
|
||||
@@ -70,6 +71,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-ethers": "3.0.5",
|
||||
"@solarity/chai-zkit": "^0.2.5",
|
||||
"@typechain/ethers-v6": "^0.5.1",
|
||||
"@typechain/hardhat": "^9.1.0",
|
||||
"@types/chai": "^4.3.12",
|
||||
@@ -81,6 +83,7 @@
|
||||
"@types/lodash": "4.17.5",
|
||||
"@types/mocha": "^10.0.6",
|
||||
"@types/resolve": "^1.20.6",
|
||||
"@types/sinon": "^17.0.3",
|
||||
"@types/snarkjs": "^0.7.8",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||
@@ -88,7 +91,8 @@
|
||||
"chai": "^4.4.1",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-import-resolver-typescript": "^3.6.3",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"ethers": "6.11.1",
|
||||
@@ -97,7 +101,9 @@
|
||||
"mocha": "^10.3.0",
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^3.2.5",
|
||||
"sinon": "^19.0.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typechain": "^8.3.2",
|
||||
"typescript": "5.3.3"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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,7 +12,7 @@ import { HardhatZKitError } from "../../errors";
|
||||
import { CIRCUIT_ARTIFACT_VERSION, NODE_MODULES } from "../../constants";
|
||||
import { Reporter } from "../../reporter";
|
||||
|
||||
import { getHighestVersion, isVersionValid, isVersionHigherOrEqual } from "../compiler/versioning";
|
||||
import { getHighestVersion, isVersionValid } from "../compiler/versioning";
|
||||
import { getNormalizedFullPath, renameFilesRecursively, readDirRecursively } from "../../utils/path-utils";
|
||||
|
||||
import { ZKitConfig } from "../../types/zkit-config";
|
||||
@@ -59,7 +60,7 @@ export class CompilationProcessor {
|
||||
let version = highestCircomVersion;
|
||||
|
||||
if (this._zkitConfig.compilerVersion && isVersionValid(this._zkitConfig.compilerVersion)) {
|
||||
if (!isVersionHigherOrEqual(this._zkitConfig.compilerVersion, highestCircomVersion)) {
|
||||
if (!semver.gte(this._zkitConfig.compilerVersion, highestCircomVersion)) {
|
||||
throw new HardhatZKitError(
|
||||
`Unable to compile a circuit with Circom version ${highestCircomVersion} using compiler version ${this._zkitConfig.compilerVersion} specified in the config`,
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import os from "os";
|
||||
import path from "path";
|
||||
import fs from "fs-extra";
|
||||
import https from "https";
|
||||
import semver from "semver";
|
||||
import { promisify } from "util";
|
||||
import { execFile } from "child_process";
|
||||
|
||||
@@ -18,7 +19,7 @@ import { HardhatZKitError } from "../../errors";
|
||||
import { CompilerInfo, CompilerPlatformBinary } from "../../types/core";
|
||||
|
||||
import { downloadFile } from "../../utils/utils";
|
||||
import { getHighestVersion, isVersionHigherOrEqual } from "./versioning";
|
||||
import { getHighestVersion } from "./versioning";
|
||||
|
||||
import { MultiProcessMutex } from "hardhat/internal/util/multi-process-mutex";
|
||||
|
||||
@@ -67,14 +68,14 @@ export class CircomCompilerDownloader {
|
||||
return (await fs.pathExists(downloadPath)) || fs.pathExists(downloadPathWasm);
|
||||
}
|
||||
|
||||
const latestDownloadedVersion = await this._getLatestDownloadedCircomVersion();
|
||||
const latestDownloadedVersion = this._getLatestDownloadedCircomVersion();
|
||||
|
||||
return isVersionHigherOrEqual(latestDownloadedVersion, version);
|
||||
return semver.gte(latestDownloadedVersion, version);
|
||||
}
|
||||
|
||||
public async getCompilerBinary(version: string, isVersionStrict: boolean): Promise<CompilerInfo> {
|
||||
if (!isVersionStrict) {
|
||||
version = await this._getLatestDownloadedCircomVersion();
|
||||
version = this._getLatestDownloadedCircomVersion();
|
||||
|
||||
if (!version || version === "0.0.0") {
|
||||
throw new HardhatZKitError("No latest compiler found");
|
||||
@@ -84,18 +85,18 @@ export class CircomCompilerDownloader {
|
||||
const compilerBinaryPath = this._getCompilerDownloadPath(version);
|
||||
const wasmCompilerBinaryPath = this._getWasmCompilerDownloadPath(version);
|
||||
|
||||
if (await fs.pathExists(compilerBinaryPath)) {
|
||||
return { binaryPath: compilerBinaryPath, version: version, isWasm: false };
|
||||
}
|
||||
|
||||
if (await fs.pathExists(wasmCompilerBinaryPath)) {
|
||||
return { binaryPath: wasmCompilerBinaryPath, version: version, isWasm: true };
|
||||
}
|
||||
|
||||
if (await fs.pathExists(compilerBinaryPath)) {
|
||||
return { binaryPath: compilerBinaryPath, version: version, isWasm: false };
|
||||
}
|
||||
|
||||
throw new HardhatZKitError(`Trying to get a Circom compiler v${version} before it was downloaded`);
|
||||
}
|
||||
|
||||
public async downloadCompiler(version: string, isVersionStrict: boolean): Promise<void> {
|
||||
public async downloadCompiler(version: string, isVersionStrict: boolean, verifyCompiler: boolean): Promise<void> {
|
||||
await this._mutex.use(async () => {
|
||||
const versionToDownload = isVersionStrict ? version : await this._getLatestCircomVersion();
|
||||
|
||||
@@ -110,25 +111,27 @@ export class CircomCompilerDownloader {
|
||||
try {
|
||||
downloadPath = await this._downloadCompiler(versionToDownload);
|
||||
} catch (error: any) {
|
||||
throw new HardhatZKitError(error);
|
||||
throw new HardhatZKitError(error.message);
|
||||
}
|
||||
|
||||
await this._postProcessCompilerDownload(downloadPath);
|
||||
if (verifyCompiler) {
|
||||
await this._postProcessCompilerDownload(downloadPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _getLatestDownloadedCircomVersion(): Promise<string> {
|
||||
private _getLatestDownloadedCircomVersion(): string {
|
||||
try {
|
||||
const entries = await fs.promises.readdir(this._compilersDir, { withFileTypes: true });
|
||||
const entries = fs.readdirSync(this._compilersDir, { withFileTypes: true });
|
||||
|
||||
const versions = entries
|
||||
.filter(async (entry) => {
|
||||
.filter((entry) => {
|
||||
if (!entry.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dirPath = path.join(this._compilersDir, entry.name);
|
||||
const files = await fs.promises.readdir(dirPath);
|
||||
const files = fs.readdirSync(dirPath);
|
||||
|
||||
return files.includes(this._platform) || files.includes("circom.wasm");
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import fs from "fs-extra";
|
||||
import semver from "semver";
|
||||
import { promisify } from "util";
|
||||
import { exec } from "child_process";
|
||||
|
||||
@@ -11,16 +12,18 @@ import { LATEST_SUPPORTED_CIRCOM_VERSION, OLDEST_SUPPORTED_ARM_CIRCOM_VERSION }
|
||||
import { BinaryCircomCompiler, WASMCircomCompiler } from "./CircomCompiler";
|
||||
import { CircomCompilerDownloader } from "./CircomCompilerDownloader";
|
||||
|
||||
import { isVersionHigherOrEqual } from "./versioning";
|
||||
|
||||
import { CompilerInfo, CompilerPlatformBinary, ICircomCompiler, NativeCompiler } from "../../types/core";
|
||||
|
||||
// eslint-disable-next-line
|
||||
const { Context } = require("@distributedlab/circom2");
|
||||
|
||||
export class BaseCircomCompilerFactory {
|
||||
public async createCircomCompiler(version: string, isVersionStrict: boolean): Promise<ICircomCompiler> {
|
||||
if (!isVersionHigherOrEqual(LATEST_SUPPORTED_CIRCOM_VERSION, version)) {
|
||||
public async createCircomCompiler(
|
||||
version: string,
|
||||
isVersionStrict: boolean,
|
||||
verifyCompiler: boolean = true,
|
||||
): Promise<ICircomCompiler> {
|
||||
if (!semver.gte(LATEST_SUPPORTED_CIRCOM_VERSION, version)) {
|
||||
throw new HardhatZKitError(`Unsupported Circom compiler version - ${version}. Please provide another version.`);
|
||||
}
|
||||
|
||||
@@ -34,23 +37,19 @@ export class BaseCircomCompilerFactory {
|
||||
|
||||
// Utilize binary translators like Rosetta (macOS) or Prism (Windows)
|
||||
// to run x64 binaries on arm64 systems when no arm64 versions are available.
|
||||
if (
|
||||
isVersionStrict &&
|
||||
os.arch() === "arm64" &&
|
||||
!isVersionHigherOrEqual(version, OLDEST_SUPPORTED_ARM_CIRCOM_VERSION)
|
||||
) {
|
||||
if (isVersionStrict && os.arch() === "arm64" && !semver.gte(version, OLDEST_SUPPORTED_ARM_CIRCOM_VERSION)) {
|
||||
compilerPlatformBinary = CircomCompilerDownloader.getCompilerPlatformBinary("x64");
|
||||
}
|
||||
|
||||
if (compilerPlatformBinary !== CompilerPlatformBinary.WASM) {
|
||||
compiler = await this._tryCreateBinaryCompiler(compilerPlatformBinary, version, isVersionStrict);
|
||||
compiler = await this._tryCreateBinaryCompiler(compilerPlatformBinary, version, isVersionStrict, verifyCompiler);
|
||||
|
||||
if (compiler) {
|
||||
return compiler;
|
||||
}
|
||||
}
|
||||
|
||||
return this._createWasmCompiler(version, isVersionStrict);
|
||||
return this._createWasmCompiler(version, isVersionStrict, verifyCompiler);
|
||||
}
|
||||
|
||||
private async _tryCreateNativeCompiler(
|
||||
@@ -65,7 +64,7 @@ export class BaseCircomCompilerFactory {
|
||||
|
||||
const isValidVersion = isVersionStrict
|
||||
? nativeCompiler.version === version
|
||||
: isVersionHigherOrEqual(nativeCompiler.version, version);
|
||||
: semver.gte(nativeCompiler.version, version);
|
||||
|
||||
if (isValidVersion) {
|
||||
Reporter!.reportCompilerVersion(nativeCompiler.version);
|
||||
@@ -78,9 +77,10 @@ export class BaseCircomCompilerFactory {
|
||||
platform: CompilerPlatformBinary,
|
||||
version: string,
|
||||
isVersionStrict: boolean,
|
||||
verifyCompiler: boolean,
|
||||
): Promise<ICircomCompiler | undefined> {
|
||||
try {
|
||||
const compilerInfo = await this._getBinaryCompiler(platform, version, isVersionStrict);
|
||||
const compilerInfo = await this._getBinaryCompiler(platform, version, isVersionStrict, verifyCompiler);
|
||||
|
||||
if (compilerInfo.isWasm) {
|
||||
return new WASMCircomCompiler(this._getWasmCompiler(compilerInfo.binaryPath));
|
||||
@@ -92,8 +92,17 @@ export class BaseCircomCompilerFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private async _createWasmCompiler(version: string, isVersionStrict: boolean): Promise<ICircomCompiler> {
|
||||
const compilerInfo = await this._getBinaryCompiler(CompilerPlatformBinary.WASM, version, isVersionStrict);
|
||||
private async _createWasmCompiler(
|
||||
version: string,
|
||||
isVersionStrict: boolean,
|
||||
verifyCompiler: boolean,
|
||||
): Promise<ICircomCompiler> {
|
||||
const compilerInfo = await this._getBinaryCompiler(
|
||||
CompilerPlatformBinary.WASM,
|
||||
version,
|
||||
isVersionStrict,
|
||||
verifyCompiler,
|
||||
);
|
||||
|
||||
return new WASMCircomCompiler(this._getWasmCompiler(compilerInfo.binaryPath));
|
||||
}
|
||||
@@ -130,12 +139,13 @@ export class BaseCircomCompilerFactory {
|
||||
platform: CompilerPlatformBinary,
|
||||
version: string,
|
||||
isVersionStrict: boolean,
|
||||
verifyCompiler: boolean,
|
||||
): Promise<CompilerInfo> {
|
||||
const compilersDir = await this._getCompilersDir();
|
||||
const downloader = CircomCompilerDownloader.getCircomCompilerDownloader(platform, compilersDir);
|
||||
|
||||
if (!(await downloader.isCompilerDownloaded(version, isVersionStrict))) {
|
||||
await downloader.downloadCompiler(version, isVersionStrict);
|
||||
await downloader.downloadCompiler(version, isVersionStrict, verifyCompiler);
|
||||
}
|
||||
|
||||
const compilerBinaryInfo = await downloader.getCompilerBinary(version, isVersionStrict);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import semver from "semver";
|
||||
|
||||
import { CircomResolvedFileInfo } from "../../types/core";
|
||||
|
||||
export function getHighestVersion(circomVersions: CircomResolvedFileInfo[] | string[]) {
|
||||
let highestVersion = "";
|
||||
let highestVersion = "0.0.0";
|
||||
|
||||
for (const info of circomVersions) {
|
||||
const circomVersion =
|
||||
typeof info == "string" ? info : info.resolvedFile.fileData.parsedFileData.pragmaInfo.compilerVersion;
|
||||
|
||||
if (isVersionHigherOrEqual(circomVersion, highestVersion)) {
|
||||
if (semver.gte(circomVersion, highestVersion)) {
|
||||
highestVersion = circomVersion;
|
||||
}
|
||||
}
|
||||
@@ -15,35 +17,6 @@ export function getHighestVersion(circomVersions: CircomResolvedFileInfo[] | str
|
||||
return highestVersion;
|
||||
}
|
||||
|
||||
export function isVersionHigherOrEqual(version1: string, version2: string): boolean {
|
||||
if (!version1 && version2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!version2 || (!version1 && !version2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const [v1Major, v1Minor, v1Patch] = version1.split(".").map(Number);
|
||||
const [v2Major, v2Minor, v2Patch] = version2.split(".").map(Number);
|
||||
|
||||
if (v1Major !== v2Major) {
|
||||
return v1Major > v2Major;
|
||||
}
|
||||
|
||||
if (v1Minor !== v2Minor) {
|
||||
return v1Minor > v2Minor;
|
||||
}
|
||||
|
||||
return v1Patch >= v2Patch;
|
||||
}
|
||||
|
||||
export function isVersionValid(version: string) {
|
||||
const versionParts = version.trim().split(".");
|
||||
|
||||
if (versionParts.length !== 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !isNaN(Number(versionParts[0])) && !isNaN(Number(versionParts[1])) && !isNaN(Number(versionParts[2]));
|
||||
export function isVersionValid(version: string): boolean {
|
||||
return semver.valid(version) === version;
|
||||
}
|
||||
|
||||
@@ -23,60 +23,67 @@ export async function downloadFile(
|
||||
onFinishReporter: () => void,
|
||||
onErrorReporter: () => void,
|
||||
): Promise<boolean> {
|
||||
await fs.ensureFile(file);
|
||||
try {
|
||||
await fs.ensureFile(file);
|
||||
const fileStream = fs.createWriteStream(file);
|
||||
|
||||
const fileStream = fs.createWriteStream(file);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const handleRequest = (currentUrl: string) => {
|
||||
const request = https.get(currentUrl, (response) => {
|
||||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||||
const redirectUrl = response.headers.location;
|
||||
|
||||
if (redirectUrl) {
|
||||
handleRequest(redirectUrl);
|
||||
} else {
|
||||
onErrorReporter();
|
||||
fs.unlink(file, () => reject(new Error("Invalid redirect response")));
|
||||
return new Promise((resolve) => {
|
||||
const handleRequest = (currentUrl: string) => {
|
||||
const request = https.get(currentUrl, (response) => {
|
||||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||||
const redirectUrl = response.headers.location;
|
||||
if (redirectUrl) {
|
||||
handleRequest(redirectUrl);
|
||||
} else {
|
||||
onErrorReporter();
|
||||
fs.unlink(file, () => resolve(false));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
onErrorReporter();
|
||||
fs.unlink(file, () => reject(new Error(`Failed to download file with status code: ${response.statusCode}`)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const totalSize = parseInt(response.headers["content-length"] || "0", 10);
|
||||
|
||||
Reporter!.reportStartFileDownloadingWithProgressBar(totalSize, 0);
|
||||
|
||||
response.pipe(fileStream);
|
||||
|
||||
response
|
||||
.on("data", (chunk) => {
|
||||
Reporter!.updateProgressBarValue(chunk.length);
|
||||
})
|
||||
.on("error", (err) => {
|
||||
if (response.statusCode !== 200) {
|
||||
onErrorReporter();
|
||||
fs.unlink(file, () => reject(err));
|
||||
})
|
||||
.on("end", () => {
|
||||
onFinishReporter();
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
fs.unlink(file, () => resolve(false));
|
||||
return;
|
||||
}
|
||||
|
||||
request.on("error", (err) => {
|
||||
fs.unlink(file, () => reject(err));
|
||||
});
|
||||
};
|
||||
const totalSize = parseInt(response.headers["content-length"] || "0", 10);
|
||||
Reporter!.reportStartFileDownloadingWithProgressBar(totalSize, 0);
|
||||
|
||||
handleRequest(url);
|
||||
});
|
||||
response.pipe(fileStream);
|
||||
|
||||
response
|
||||
.on("data", (chunk) => {
|
||||
Reporter!.updateProgressBarValue(chunk.length);
|
||||
})
|
||||
.on("error", () => {
|
||||
onErrorReporter();
|
||||
fs.unlink(file, () => resolve(false));
|
||||
});
|
||||
|
||||
fileStream
|
||||
.on("finish", () => {
|
||||
fileStream.close(() => {
|
||||
onFinishReporter();
|
||||
resolve(true);
|
||||
});
|
||||
})
|
||||
.on("error", () => {
|
||||
onErrorReporter();
|
||||
fs.unlink(file, () => resolve(false));
|
||||
});
|
||||
});
|
||||
|
||||
request.on("error", () => {
|
||||
fs.unlink(file, () => resolve(false));
|
||||
});
|
||||
};
|
||||
|
||||
handleRequest(url);
|
||||
});
|
||||
} catch (error: any) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function execCall(execFile: string, callArgs: string[]): Promise<ExecCallResult> {
|
||||
|
||||
14
test/constants.ts
Normal file
14
test/constants.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { CompileFlags, ContributionSettings } from "../src/types/core";
|
||||
|
||||
export const defaultCompileFlags: CompileFlags = {
|
||||
r1cs: true,
|
||||
wasm: true,
|
||||
sym: true,
|
||||
c: false,
|
||||
json: false,
|
||||
};
|
||||
|
||||
export const defaultContributionSettings: ContributionSettings = {
|
||||
provingSystem: "groth16",
|
||||
contributions: 1,
|
||||
};
|
||||
@@ -14,4 +14,4 @@ template Hash2(){
|
||||
out <== h.out;
|
||||
}
|
||||
|
||||
component main = Hash2();
|
||||
component main = Hash2();
|
||||
|
||||
7
test/fixture-projects/hardhat-project-compiler-config/.gitignore
vendored
Normal file
7
test/fixture-projects/hardhat-project-compiler-config/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/cache
|
||||
/artifacts
|
||||
|
||||
generated-types
|
||||
compilers
|
||||
contracts/verifiers
|
||||
zkit
|
||||
@@ -0,0 +1,9 @@
|
||||
pragma circom 2.0.0;
|
||||
|
||||
template Multiplier2(){
|
||||
signal input in1;
|
||||
signal input in2;
|
||||
signal output out;
|
||||
|
||||
out <== in1 * in2;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
pragma circom 2.0.0;
|
||||
|
||||
template SumMul(){
|
||||
signal input in1;
|
||||
signal input in2;
|
||||
signal input in3;
|
||||
signal output out;
|
||||
|
||||
out <== in1 + in2 * in3;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "../base/mul2Base.circom";
|
||||
include "../base/sumMul.circom";
|
||||
|
||||
component main = Multiplier2();
|
||||
@@ -0,0 +1,25 @@
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
|
||||
import config from "../hardhat.config";
|
||||
|
||||
const defaultConfig: HardhatUserConfig = {
|
||||
...config,
|
||||
zkit: {
|
||||
compilerVersion: "2.1.9",
|
||||
circuitsDir: "circuits",
|
||||
compilationSettings: {
|
||||
artifactsDir: "zkit/artifacts",
|
||||
skipFiles: ["vendor"],
|
||||
},
|
||||
setupSettings: {
|
||||
ptauDir: "zkit/ptau",
|
||||
ptauDownload: true,
|
||||
},
|
||||
quiet: true,
|
||||
verifiersSettings: {
|
||||
verifiersDir: "contracts/verifiers",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default defaultConfig;
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "hardhat-project-compiler-config",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"compile": "hardhat compile --force",
|
||||
"clean": "hardhat clean && rm -rf artifacts && rm -rf cache"
|
||||
}
|
||||
}
|
||||
7
test/fixture-projects/hardhat-project-compiler-incorrect-config/.gitignore
vendored
Normal file
7
test/fixture-projects/hardhat-project-compiler-incorrect-config/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/cache
|
||||
/artifacts
|
||||
|
||||
generated-types
|
||||
compilers
|
||||
contracts/verifiers
|
||||
zkit
|
||||
@@ -0,0 +1,9 @@
|
||||
pragma circom 2.1.9;
|
||||
|
||||
template Multiplier2(){
|
||||
signal input in1;
|
||||
signal input in2;
|
||||
signal output out;
|
||||
|
||||
out <== in1 * in2;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
pragma circom 2.1.9;
|
||||
|
||||
template SumMul(){
|
||||
signal input in1;
|
||||
signal input in2;
|
||||
signal input in3;
|
||||
signal output out;
|
||||
|
||||
out <== in1 + in2 * in3;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
pragma circom 2.1.9;
|
||||
|
||||
include "../base/mul2Base.circom";
|
||||
include "../base/sumMul.circom";
|
||||
|
||||
component main = Multiplier2();
|
||||
@@ -0,0 +1,25 @@
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
|
||||
import config from "../hardhat.config";
|
||||
|
||||
const defaultConfig: HardhatUserConfig = {
|
||||
...config,
|
||||
zkit: {
|
||||
compilerVersion: "2.1.8",
|
||||
circuitsDir: "circuits",
|
||||
compilationSettings: {
|
||||
artifactsDir: "zkit/artifacts",
|
||||
skipFiles: ["vendor"],
|
||||
},
|
||||
setupSettings: {
|
||||
ptauDir: "zkit/ptau",
|
||||
ptauDownload: true,
|
||||
},
|
||||
quiet: true,
|
||||
verifiersSettings: {
|
||||
verifiersDir: "contracts/verifiers",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default defaultConfig;
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "hardhat-project-compiler-incorrect-config",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"compile": "hardhat compile --force",
|
||||
"clean": "hardhat clean && rm -rf artifacts && rm -rf cache"
|
||||
}
|
||||
}
|
||||
5
test/fixture-projects/hardhat-project-invalid-circuits/.gitignore
vendored
Normal file
5
test/fixture-projects/hardhat-project-invalid-circuits/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/cache
|
||||
/artifacts
|
||||
|
||||
contracts/verifiers
|
||||
zkit
|
||||
@@ -0,0 +1,17 @@
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "/absolute/path/to/circuit.circom";
|
||||
|
||||
template Hash2(){
|
||||
signal input in1;
|
||||
signal input in2;
|
||||
signal output out;
|
||||
|
||||
component h = Poseidon(2);
|
||||
h.inputs[0] <== in1;
|
||||
h.inputs[1] <== in2;
|
||||
|
||||
out <== h.out;
|
||||
}
|
||||
|
||||
component main = Hash2();
|
||||
@@ -0,0 +1,23 @@
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
|
||||
import config from "../hardhat.config";
|
||||
|
||||
const defaultConfig: HardhatUserConfig = {
|
||||
...config,
|
||||
zkit: {
|
||||
circuitsDir: "circuits",
|
||||
compilationSettings: {
|
||||
artifactsDir: "zkit/artifacts",
|
||||
},
|
||||
setupSettings: {
|
||||
ptauDir: "zkit/ptau",
|
||||
ptauDownload: true,
|
||||
},
|
||||
quiet: true,
|
||||
verifiersSettings: {
|
||||
verifiersDir: "contracts/verifiers",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default defaultConfig;
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "hardhat-project-invalid-circuits",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"compile": "hardhat compile --force",
|
||||
"clean": "hardhat clean && rm -rf artifacts && rm -rf cache"
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,6 @@
|
||||
/artifacts
|
||||
|
||||
generated-types
|
||||
compilers
|
||||
contracts/verifiers
|
||||
zkit
|
||||
zkit
|
||||
|
||||
@@ -4,5 +4,6 @@ template Multiplier2(){
|
||||
signal input in1;
|
||||
signal input in2;
|
||||
signal output out;
|
||||
|
||||
out <== in1 * in2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pragma circom 2.0.0;
|
||||
pragma circom 2.1.8;
|
||||
|
||||
template Multiplier3Arr(){
|
||||
signal input in[3];
|
||||
@@ -9,4 +9,4 @@ template Multiplier3Arr(){
|
||||
out <== tmp * in[2];
|
||||
}
|
||||
|
||||
component main = Multiplier3Arr();
|
||||
component main = Multiplier3Arr();
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.20;
|
||||
|
||||
interface IMul2Verifier {
|
||||
function verifyProof(
|
||||
uint256[2] calldata pA_,
|
||||
uint256[2][2] calldata pB_,
|
||||
uint256[2] calldata pC_,
|
||||
uint256[1] calldata pubSignals_
|
||||
) external view;
|
||||
}
|
||||
|
||||
contract Mul2ProofVerifier {
|
||||
IMul2Verifier public verifier;
|
||||
|
||||
mapping (address => bool) public isVerified;
|
||||
|
||||
constructor (address verifierAddr_) {
|
||||
verifier = IMul2Verifier(verifierAddr_);
|
||||
}
|
||||
|
||||
function verifyProof(
|
||||
uint256[2] calldata pA_,
|
||||
uint256[2][2] calldata pB_,
|
||||
uint256[2] calldata pC_,
|
||||
uint256[1] calldata pubSignals_
|
||||
) external {
|
||||
verifier.verifyProof(pA_, pB_, pC_, pubSignals_);
|
||||
|
||||
isVerified[msg.sender] = true;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.20;
|
||||
|
||||
interface IMul3ArrVerifier {
|
||||
function verifyProof(
|
||||
uint256[2] calldata pA_,
|
||||
uint256[2][2] calldata pB_,
|
||||
uint256[2] calldata pC_,
|
||||
uint256[1] calldata pubSignals_
|
||||
) external view;
|
||||
}
|
||||
|
||||
contract Mul3ArrProofVerifier {
|
||||
IMul3ArrVerifier public verifier;
|
||||
|
||||
mapping (address => bool) public isVerified;
|
||||
|
||||
constructor (address verifierAddr_) {
|
||||
verifier = IMul3ArrVerifier(verifierAddr_);
|
||||
}
|
||||
|
||||
function verifyProof(
|
||||
uint256[2] calldata pA_,
|
||||
uint256[2][2] calldata pB_,
|
||||
uint256[2] calldata pC_,
|
||||
uint256[1] calldata pubSignals_
|
||||
) external {
|
||||
verifier.verifyProof(pA_, pB_, pC_, pubSignals_);
|
||||
|
||||
isVerified[msg.sender] = true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/cache
|
||||
/artifacts
|
||||
|
||||
compilers
|
||||
contracts/verifiers
|
||||
zkit
|
||||
zkit
|
||||
|
||||
@@ -5,8 +5,9 @@ import { resetHardhatContext } from "hardhat/plugins-testing";
|
||||
import { TASK_COMPILE } from "hardhat/builtin-tasks/task-names";
|
||||
|
||||
import { getNormalizedFullPath } from "../src/utils/path-utils";
|
||||
import { resetCircuitsCompileCache, resetCircuitsSetupCache } from "../src/cache";
|
||||
|
||||
export function useEnvironment(fixtureProjectName: string, networkName = "hardhat") {
|
||||
export function useEnvironment(fixtureProjectName: string, withCleanUp: boolean = false, networkName = "hardhat") {
|
||||
beforeEach("Loading hardhat environment", async function () {
|
||||
const prefix = "hardhat-project-";
|
||||
process.chdir(join(__dirname, "fixture-projects", prefix + fixtureProjectName));
|
||||
@@ -14,6 +15,12 @@ export function useEnvironment(fixtureProjectName: string, networkName = "hardha
|
||||
|
||||
this.hre = require("hardhat");
|
||||
|
||||
if (withCleanUp) {
|
||||
cleanUp(this.hre.config.paths.root);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.hre.run(TASK_COMPILE, { quiet: true });
|
||||
});
|
||||
|
||||
@@ -28,3 +35,21 @@ export function useEnvironment(fixtureProjectName: string, networkName = "hardha
|
||||
export function getProjectRootPath(): string {
|
||||
return dirname(__dirname);
|
||||
}
|
||||
|
||||
export function cleanUp(rootPath: string) {
|
||||
resetCircuitsCompileCache();
|
||||
resetCircuitsSetupCache();
|
||||
|
||||
const directoriesToRemove = [
|
||||
"generated-types/zkit",
|
||||
"cache",
|
||||
"zkit",
|
||||
"artifacts",
|
||||
"contracts/verifiers",
|
||||
"compilers",
|
||||
].map((dir) => getNormalizedFullPath(rootPath, dir));
|
||||
|
||||
directoriesToRemove.forEach((dir) => {
|
||||
fsExtra.rmSync(dir, { recursive: true, force: true });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { extendConfig } from "hardhat/config";
|
||||
|
||||
import { useEnvironment } from "../../helpers";
|
||||
|
||||
import { zkitConfigExtender } from "../../../src/config/config";
|
||||
import { zkitConfigExtender } from "@src/config/config";
|
||||
|
||||
import { ZKitConfig } from "../../../src/types/zkit-config";
|
||||
import { ZKitConfig } from "@src/types/zkit-config";
|
||||
|
||||
describe("config", () => {
|
||||
describe("loading", () => {
|
||||
|
||||
341
test/integration/tasks.test.ts
Normal file
341
test/integration/tasks.test.ts
Normal file
@@ -0,0 +1,341 @@
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import fsExtra from "fs-extra";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
import "@solarity/chai-zkit";
|
||||
import { expect } from "chai";
|
||||
import { before } from "mocha";
|
||||
import { stub, SinonStub } from "sinon";
|
||||
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
|
||||
import {
|
||||
TASK_CIRCUITS_COMPILE,
|
||||
TASK_CIRCUITS_MAKE,
|
||||
TASK_CIRCUITS_SETUP,
|
||||
TASK_GENERATE_VERIFIERS,
|
||||
TASK_ZKIT_CLEAN,
|
||||
ZKIT_SCOPE_NAME,
|
||||
} from "@src/task-names";
|
||||
import { CircuitsCompileCache, CircuitsSetupCache } from "@src/cache";
|
||||
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 { HardhatZKit } from "@src/types/hardhat-zkit";
|
||||
import { BaseCircomCompilerFactory } from "@src/core";
|
||||
import { CircomCompilerDownloader } from "@src/core/compiler/CircomCompilerDownloader";
|
||||
|
||||
describe("ZKit tasks", async function () {
|
||||
const circuitNames = ["Multiplier2", "Multiplier3Arr"];
|
||||
const sourceNames = ["circuits/main/mul2.circom", "circuits/main/Multiplier3Arr.circom"];
|
||||
|
||||
let nativeCompilerStub: SinonStub;
|
||||
|
||||
before(() => {
|
||||
nativeCompilerStub = stub(BaseCircomCompilerFactory.prototype, "_tryCreateNativeCompiler" as any).callsFake(
|
||||
async () => {
|
||||
return undefined;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
nativeCompilerStub.restore();
|
||||
});
|
||||
|
||||
function getZkitCircuitFullPaths(config: HardhatUserConfig): string[] {
|
||||
const circuitFullPaths: string[] = [];
|
||||
sourceNames.forEach((sourceName) => {
|
||||
circuitFullPaths.push(
|
||||
getNormalizedFullPath(config.paths!.root!, `${config.zkit!.compilationSettings!.artifactsDir}/${sourceName}`),
|
||||
);
|
||||
});
|
||||
|
||||
return circuitFullPaths;
|
||||
}
|
||||
|
||||
async function checkMake(config: HardhatUserConfig, zkit: HardhatZKit) {
|
||||
const cacheFullPath: string = getNormalizedFullPath(config.paths!.root!, "cache");
|
||||
|
||||
expect(fsExtra.readdirSync(cacheFullPath)).to.be.deep.eq([
|
||||
"circuits-compile-cache.json",
|
||||
"circuits-setup-cache.json",
|
||||
]);
|
||||
|
||||
CircuitsSetupCache!.getEntries().forEach(async (entry: SetupCacheEntry) => {
|
||||
expect(entry).to.be.deep.eq(await getSetupCacheEntry(entry.circuitSourceName, entry.r1csSourcePath));
|
||||
});
|
||||
|
||||
getZkitCircuitFullPaths(config).forEach((path, index) => {
|
||||
expect(fsExtra.readdirSync(path)).to.be.deep.eq([
|
||||
`${circuitNames[index]}.r1cs`,
|
||||
`${circuitNames[index]}.sym`,
|
||||
`${circuitNames[index]}.vkey.json`,
|
||||
`${circuitNames[index]}.zkey`,
|
||||
`${circuitNames[index]}_artifacts.json`,
|
||||
`${circuitNames[index]}_js`,
|
||||
]);
|
||||
});
|
||||
|
||||
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");
|
||||
|
||||
const updatedContent = fileContent.replace(/include\s*".*";/, `include "${newIncludePath}";`);
|
||||
|
||||
fsExtra.writeFileSync(filePath, updatedContent, "utf-8");
|
||||
}
|
||||
|
||||
describe("compile", async function () {
|
||||
describe("no config compiler version", async function () {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
it("should correctly compile circuits", async function () {
|
||||
await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE });
|
||||
|
||||
const cacheFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "cache");
|
||||
|
||||
expect(fsExtra.readdirSync(cacheFullPath)).to.be.deep.eq(["circuits-compile-cache.json"]);
|
||||
|
||||
CircuitsCompileCache!.getEntries().forEach(async (entry: CompileCacheEntry) => {
|
||||
expect(entry).to.be.deep.eq(await getCompileCacheEntry(this.hre.config.paths.root, entry.sourceName));
|
||||
});
|
||||
|
||||
getZkitCircuitFullPaths(this.hre.config).forEach((path, index) => {
|
||||
expect(fsExtra.readdirSync(path)).to.be.deep.eq([
|
||||
`${circuitNames[index]}.r1cs`,
|
||||
`${circuitNames[index]}.sym`,
|
||||
`${circuitNames[index]}_artifacts.json`,
|
||||
`${circuitNames[index]}_js`,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should correctly compile circuits with task arguments", async function () {
|
||||
await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE }, { json: true, c: true });
|
||||
|
||||
const cacheFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "cache");
|
||||
|
||||
expect(fsExtra.readdirSync(cacheFullPath)).to.be.deep.eq(["circuits-compile-cache.json"]);
|
||||
|
||||
CircuitsCompileCache!.getEntries().forEach(async (entry: CompileCacheEntry) => {
|
||||
expect(entry).to.be.deep.eq(await getCompileCacheEntry(this.hre.config.paths.root, entry.sourceName));
|
||||
});
|
||||
|
||||
getZkitCircuitFullPaths(this.hre.config).forEach((path, index) => {
|
||||
expect(fsExtra.readdirSync(path)).to.be.deep.eq([
|
||||
`${circuitNames[index]}.r1cs`,
|
||||
`${circuitNames[index]}.sym`,
|
||||
`${circuitNames[index]}_artifacts.json`,
|
||||
`${circuitNames[index]}_constraints.json`,
|
||||
`${circuitNames[index]}_cpp`,
|
||||
`${circuitNames[index]}_js`,
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("config compiler version", async function () {
|
||||
useEnvironment("compiler-config", true);
|
||||
|
||||
it("should correctly compile circuits with the specified version of the compiler", async function () {
|
||||
await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE });
|
||||
|
||||
const artifactsPath = getNormalizedFullPath(
|
||||
this.hre.config.paths.root,
|
||||
`${this.hre.config.zkit!.compilationSettings!.artifactsDir}/circuits/main/mul2.circom`,
|
||||
);
|
||||
|
||||
expect(fsExtra.readdirSync(artifactsPath)).to.be.deep.eq([
|
||||
"Multiplier2.r1cs",
|
||||
"Multiplier2.sym",
|
||||
"Multiplier2_artifacts.json",
|
||||
"Multiplier2_js",
|
||||
]);
|
||||
|
||||
const compilerPath = path.join(os.homedir(), ".zkit", "compilers", this.hre.config.zkit.compilerVersion);
|
||||
expect(fsExtra.readdirSync(compilerPath)).to.be.deep.equal([
|
||||
CircomCompilerDownloader.getCompilerPlatformBinary(),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("incorrect config compiler version", async function () {
|
||||
useEnvironment("compiler-incorrect-config", true);
|
||||
|
||||
it("should throw an error when the specified config compiler version is lower that the circuit one", async function () {
|
||||
await expect(this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE })).to.be.rejectedWith(
|
||||
"Unable to compile a circuit with Circom version 2.1.9 using compiler version 2.1.8 specified in the config",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with libraries", async function () {
|
||||
describe("valid circuits", function () {
|
||||
useEnvironment("circuits-with-libraries", true);
|
||||
|
||||
it("should correctly compile circuits that include libraries", async function () {
|
||||
const root = this.hre.config.paths.root;
|
||||
|
||||
execSync("npm install --no-workspaces", { cwd: root });
|
||||
await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE });
|
||||
|
||||
const cacheFullPath: string = getNormalizedFullPath(root, "cache");
|
||||
|
||||
expect(fsExtra.readdirSync(cacheFullPath)).to.be.deep.eq(["circuits-compile-cache.json"]);
|
||||
|
||||
CircuitsCompileCache!.getEntries().forEach(async (entry: CompileCacheEntry) => {
|
||||
expect(entry).to.be.deep.eq(await getCompileCacheEntry(root, entry.sourceName));
|
||||
});
|
||||
|
||||
const circuitPath = getNormalizedFullPath(
|
||||
root,
|
||||
`${this.hre.config.zkit.compilationSettings.artifactsDir}/circuits/hash2.circom`,
|
||||
);
|
||||
|
||||
expect(fsExtra.readdirSync(circuitPath)).to.be.deep.eq([
|
||||
`Hash2.r1cs`,
|
||||
`Hash2.sym`,
|
||||
`Hash2_artifacts.json`,
|
||||
`Hash2_js`,
|
||||
]);
|
||||
|
||||
fsExtra.rmSync(`${root}/node_modules`, { recursive: true, force: true });
|
||||
fsExtra.rmSync(`${root}/package-lock.json`, { recursive: true, force: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("invalid circuits", function () {
|
||||
useEnvironment("invalid-circuits", true);
|
||||
|
||||
it("should throw an error if circuit include statement is URI", async function () {
|
||||
const circuitPath = "circuits/invalidImportCircuit.circom";
|
||||
const circuitFullPath = path.join(this.hre.config.paths.root, circuitPath);
|
||||
const invalidImportPath = "http://example.com/circuit.circom";
|
||||
|
||||
updateInclude(circuitFullPath, invalidImportPath);
|
||||
|
||||
await expect(this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE })).to.be.rejectedWith(
|
||||
`Invalid import ${invalidImportPath} from ${circuitPath}. Hardhat doesn't support imports via http`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw an error if circuit include statement includes backslashes", async function () {
|
||||
const circuitPath = "circuits/invalidImportCircuit.circom";
|
||||
const circuitFullPath = path.join(this.hre.config.paths.root, circuitPath);
|
||||
const invalidImportPath = "circomlib/circuits\\poseidon.circom";
|
||||
|
||||
updateInclude(circuitFullPath, invalidImportPath);
|
||||
|
||||
await expect(this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE })).to.be.rejectedWith(
|
||||
`Invalid import ${invalidImportPath} from ${circuitPath}. Imports must use / instead of \\, even in Windows`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw an error if circuit include statement is absolute path", async function () {
|
||||
const circuitPath = "circuits/invalidImportCircuit.circom";
|
||||
const circuitFullPath = path.join(this.hre.config.paths.root, circuitPath);
|
||||
const invalidImportPath = "/absolute/path/to/circuit.circom";
|
||||
|
||||
updateInclude(circuitFullPath, invalidImportPath);
|
||||
|
||||
await expect(this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_COMPILE })).to.be.rejectedWith(
|
||||
` Invalid import ${invalidImportPath} from ${circuitPath}. Hardhat doesn't support imports with absolute paths.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setup", async function () {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
it("should not generate vkey, zkey files without compiled circuits", async function () {
|
||||
cleanUp(this.hre.config.paths.root);
|
||||
|
||||
await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_SETUP });
|
||||
|
||||
const cacheFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "cache");
|
||||
expect(fsExtra.readdirSync(cacheFullPath)).to.be.deep.eq(["circuits-setup-cache.json"]);
|
||||
|
||||
expect(CircuitsSetupCache!.getEntries()).to.be.deep.eq([]);
|
||||
});
|
||||
|
||||
it("should generate correct vkey, zkey files for compiled circuits", 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);
|
||||
});
|
||||
});
|
||||
|
||||
describe("make", async function () {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
describe("verifiers", async function () {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
it("should correctly generate 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);
|
||||
|
||||
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`));
|
||||
});
|
||||
});
|
||||
|
||||
describe("clean", async function () {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
it("should correctly clean up the generated artifacts, types, etc", async function () {
|
||||
expect(fsExtra.readdirSync(this.hre.config.paths.root)).to.be.deep.eq([
|
||||
".gitignore",
|
||||
"circuits",
|
||||
"contracts",
|
||||
"generated-types",
|
||||
"hardhat.config.ts",
|
||||
"package.json",
|
||||
]);
|
||||
|
||||
expect(fsExtra.readdirSync(getNormalizedFullPath(this.hre.config.paths.root, "generated-types"))).to.be.deep.eq(
|
||||
[],
|
||||
);
|
||||
|
||||
await this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_CIRCUITS_MAKE });
|
||||
|
||||
const typesDir: string = getNormalizedFullPath(this.hre.config.paths.root, "generated-types");
|
||||
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 this.hre.run({ scope: ZKIT_SCOPE_NAME, task: TASK_ZKIT_CLEAN });
|
||||
|
||||
expect(fsExtra.readdirSync(cacheDir)).to.be.deep.eq([]);
|
||||
expect(fsExtra.readdirSync(typesDir)).to.be.deep.eq([]);
|
||||
expect(fsExtra.readdirSync(zkitDir)).to.be.deep.eq(["ptau"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
60
test/unit/cache/circuits-compile-cache.test.ts
vendored
60
test/unit/cache/circuits-compile-cache.test.ts
vendored
@@ -2,57 +2,19 @@ import fsExtra from "fs-extra";
|
||||
|
||||
import { expect } from "chai";
|
||||
|
||||
import { useEnvironment } from "../../helpers";
|
||||
import { CircuitsCompileCache, createCircuitsCompileCache, resetCircuitsCompileCache } from "../../../src/cache";
|
||||
import { getNormalizedFullPath } from "../../../src/utils/path-utils";
|
||||
import { CIRCUITS_COMPILE_CACHE_FILENAME, CIRCUIT_COMPILE_CACHE_VERSION } from "../../../src/constants";
|
||||
import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "../../../src/task-names";
|
||||
import { getFileHash } from "../../../src/utils/utils";
|
||||
import { useEnvironment } from "@test-helpers";
|
||||
import { getCompileCacheEntry } from "../../utils";
|
||||
import { getFileHash } from "@src/utils/utils";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
|
||||
import { CompileFlags, ResolvedFileData } from "../../../src/types/core";
|
||||
import { CompileCacheEntry } from "../../../src/types/cache";
|
||||
import { CircomFilesParser } from "../../../src/core";
|
||||
import { defaultCompileFlags } from "../../constants";
|
||||
import { CompileCacheEntry } from "@src/types/cache";
|
||||
import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "@src/task-names";
|
||||
import { CIRCUITS_COMPILE_CACHE_FILENAME, CIRCUIT_COMPILE_CACHE_VERSION } from "@src/constants";
|
||||
|
||||
import { CircuitsCompileCache, createCircuitsCompileCache, resetCircuitsCompileCache } from "@src/cache";
|
||||
|
||||
describe("CircuitsCompileCache", () => {
|
||||
const defaultCompileFlags: CompileFlags = {
|
||||
r1cs: true,
|
||||
wasm: true,
|
||||
sym: true,
|
||||
c: false,
|
||||
json: false,
|
||||
};
|
||||
|
||||
async function getCacheEntry(
|
||||
projectRoot: string,
|
||||
sourceName: string,
|
||||
compileFlags: CompileFlags = defaultCompileFlags,
|
||||
contentHash?: string,
|
||||
): Promise<CompileCacheEntry> {
|
||||
const circuitPath = getNormalizedFullPath(projectRoot, sourceName);
|
||||
|
||||
if (!contentHash) {
|
||||
contentHash = getFileHash(circuitPath);
|
||||
}
|
||||
|
||||
const parser: CircomFilesParser = new CircomFilesParser();
|
||||
const fileData: ResolvedFileData = parser.parse(
|
||||
fsExtra.readFileSync(circuitPath, "utf-8"),
|
||||
circuitPath,
|
||||
contentHash,
|
||||
);
|
||||
|
||||
const stats = await fsExtra.stat(circuitPath);
|
||||
const lastModificationDate: Date = new Date(stats.ctime);
|
||||
|
||||
return {
|
||||
sourceName,
|
||||
contentHash,
|
||||
lastModificationDate: lastModificationDate.valueOf(),
|
||||
compileFlags,
|
||||
fileData,
|
||||
};
|
||||
}
|
||||
|
||||
describe("createEmpty", () => {
|
||||
it("should correctly create empty CircuitsCompileCache instance", async () => {
|
||||
resetCircuitsCompileCache();
|
||||
@@ -69,7 +31,7 @@ describe("CircuitsCompileCache", () => {
|
||||
|
||||
it("should correctly create CircuitsCompileCache instance from file", async function () {
|
||||
CircuitsCompileCache!.getEntries().forEach(async (entry: CompileCacheEntry) => {
|
||||
expect(entry).to.be.deep.eq(await getCacheEntry(this.hre.config.paths.root, entry.sourceName));
|
||||
expect(entry).to.be.deep.eq(await getCompileCacheEntry(this.hre.config.paths.root, entry.sourceName));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
45
test/unit/cache/circuits-setup-cache.test.ts
vendored
45
test/unit/cache/circuits-setup-cache.test.ts
vendored
@@ -2,41 +2,20 @@ import fsExtra from "fs-extra";
|
||||
|
||||
import { expect } from "chai";
|
||||
|
||||
import { TASK_CIRCUITS_MAKE, ZKIT_SCOPE_NAME } from "../../../src/task-names";
|
||||
import { useEnvironment } from "../../helpers";
|
||||
import { CircuitsSetupCache, createCircuitsSetupCache, resetCircuitsSetupCache } from "../../../src/cache";
|
||||
import { getNormalizedFullPath } from "../../../src/utils/path-utils";
|
||||
import { CIRCUITS_SETUP_CACHE_FILENAME, CIRCUIT_SETUP_CACHE_VERSION } from "../../../src/constants";
|
||||
import { getFileHash } from "../../../src/utils/utils";
|
||||
import { useEnvironment } from "@test-helpers";
|
||||
import { getSetupCacheEntry } from "../../utils";
|
||||
import { getFileHash } from "@src/utils/utils";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
|
||||
import { ContributionSettings } from "../../../src/types/core";
|
||||
import { SetupCacheEntry } from "../../../src/types/cache";
|
||||
import { CircuitArtifact } from "../../../src/types/artifacts/circuit-artifacts";
|
||||
import { defaultContributionSettings } from "../../constants";
|
||||
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";
|
||||
|
||||
describe("CircuitsSetupCache", () => {
|
||||
const defaultContributionSettings: ContributionSettings = {
|
||||
provingSystem: "groth16",
|
||||
contributions: 1,
|
||||
};
|
||||
|
||||
async function getCacheEntry(
|
||||
sourceName: string,
|
||||
r1csSourcePath: string,
|
||||
contributionSettings: ContributionSettings = defaultContributionSettings,
|
||||
r1csContentHash?: string,
|
||||
): Promise<SetupCacheEntry> {
|
||||
if (!r1csContentHash) {
|
||||
r1csContentHash = getFileHash(r1csSourcePath);
|
||||
}
|
||||
|
||||
return {
|
||||
circuitSourceName: sourceName,
|
||||
r1csSourcePath,
|
||||
r1csContentHash,
|
||||
contributionSettings,
|
||||
};
|
||||
}
|
||||
|
||||
describe("createEmpty", () => {
|
||||
it("should correctly create empty CircuitsSetupCache instance", async () => {
|
||||
resetCircuitsSetupCache();
|
||||
@@ -53,7 +32,7 @@ describe("CircuitsSetupCache", () => {
|
||||
|
||||
it("should correctly create CircuitsSetupCache instance from file", async function () {
|
||||
CircuitsSetupCache!.getEntries().forEach(async (entry: SetupCacheEntry) => {
|
||||
expect(entry).to.be.deep.eq(await getCacheEntry(entry.circuitSourceName, entry.r1csSourcePath));
|
||||
expect(entry).to.be.deep.eq(await getSetupCacheEntry(entry.circuitSourceName, entry.r1csSourcePath));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import fsExtra from "fs-extra";
|
||||
|
||||
import { expect } from "chai";
|
||||
|
||||
import { useEnvironment } from "../../../helpers";
|
||||
import { CircomCompilerFactory, createCircomCompilerFactory } from "../../../../src/core";
|
||||
import { getNormalizedFullPath } from "../../../../src/utils/path-utils";
|
||||
|
||||
import { CompileFlags, ICircomCompiler } from "../../../../src/types/core";
|
||||
|
||||
describe("CircomCompilerFactory", () => {
|
||||
const defaultCompileFlags: CompileFlags = {
|
||||
r1cs: true,
|
||||
wasm: true,
|
||||
c: false,
|
||||
json: false,
|
||||
sym: false,
|
||||
};
|
||||
|
||||
describe("createCircomCompiler", () => {
|
||||
useEnvironment("with-circuits");
|
||||
|
||||
it("should correctly create circom compiler instance", async function () {
|
||||
createCircomCompilerFactory();
|
||||
const compiler: ICircomCompiler = await CircomCompilerFactory!.createCircomCompiler("0.2.18", false);
|
||||
|
||||
const circuitFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "circuits/main/mul2.circom");
|
||||
const artifactsFullPath: string = getNormalizedFullPath(
|
||||
this.hre.config.paths.root,
|
||||
"zkit/artifacts/test/mul2.circom",
|
||||
);
|
||||
const errorFileFullPath: string = getNormalizedFullPath(artifactsFullPath, "errors.log");
|
||||
const typesDir: string = getNormalizedFullPath(this.hre.config.paths.root, "generated-types/zkit");
|
||||
|
||||
fsExtra.rmSync(artifactsFullPath, { recursive: true, force: true });
|
||||
fsExtra.mkdirSync(artifactsFullPath, { recursive: true });
|
||||
|
||||
await compiler.compile({
|
||||
circuitFullPath,
|
||||
artifactsFullPath,
|
||||
errorFileFullPath,
|
||||
linkLibraries: [],
|
||||
compileFlags: { ...defaultCompileFlags, sym: true },
|
||||
quiet: true,
|
||||
});
|
||||
|
||||
fsExtra.rmSync(errorFileFullPath, { force: true });
|
||||
|
||||
expect(fsExtra.readdirSync(artifactsFullPath)).to.be.deep.eq(["mul2.r1cs", "mul2.sym", "mul2_js"]);
|
||||
|
||||
fsExtra.rmSync(typesDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("should correctly throw error if pass invalid version", async function () {
|
||||
const invalidVersion = "2.1.10";
|
||||
|
||||
const reason = `Unsupported Circom compiler version - ${invalidVersion}. Please provide another version.`;
|
||||
|
||||
createCircomCompilerFactory();
|
||||
await expect(CircomCompilerFactory!.createCircomCompiler(invalidVersion, false)).to.be.rejectedWith(reason);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CircomFilesResolver, CompilationFilesResolver, DependencyGraph } from "../../../../src/core";
|
||||
import { CompileFlags, CircomResolvedFileInfo, CircomResolvedFile } from "../../../../src/types/core";
|
||||
import { CircomFilesResolver, CompilationFilesResolver, DependencyGraph } from "@src/core";
|
||||
import { CompileFlags, CircomResolvedFileInfo, CircomResolvedFile } from "@src/types/core";
|
||||
|
||||
export class CompilationFilesResolverMock extends CompilationFilesResolver {
|
||||
public filterResolvedFiles(
|
||||
199
test/unit/core/compile/core/circom-compiler-downloader.test.ts
Normal file
199
test/unit/core/compile/core/circom-compiler-downloader.test.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
import os from "os";
|
||||
import fsExtra from "fs-extra";
|
||||
|
||||
import { spy } from "sinon";
|
||||
import { expect } from "chai";
|
||||
|
||||
import { cleanUp, useEnvironment } from "@test-helpers";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
|
||||
import { CompilerPlatformBinary } from "@src/types/core";
|
||||
import { createReporter, Reporter } from "@src/reporter";
|
||||
import { LATEST_SUPPORTED_CIRCOM_VERSION } from "@src/constants";
|
||||
import { CircomCompilerDownloader } from "@src/core/compiler/CircomCompilerDownloader";
|
||||
|
||||
describe("CircomCompilerDownloader", () => {
|
||||
createReporter(true);
|
||||
|
||||
describe("isCompilerDownloaded", () => {
|
||||
useEnvironment("with-circuits");
|
||||
|
||||
it("should correctly identify whether the latest compatible compiler is downloaded", async function () {
|
||||
cleanUp(this.hre.config.paths.root);
|
||||
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CircomCompilerDownloader.getCompilerPlatformBinary(),
|
||||
compilersDir,
|
||||
);
|
||||
|
||||
expect(await circomCompilerDownloader.isCompilerDownloaded("2.1.1", false)).to.be.false;
|
||||
|
||||
await circomCompilerDownloader.downloadCompiler("2.1.1", false, true);
|
||||
|
||||
expect(await circomCompilerDownloader.isCompilerDownloaded("2.1.1", false)).to.be.true;
|
||||
});
|
||||
|
||||
it("should correctly identify whether the specific compiler version is downloaded", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CompilerPlatformBinary.WASM,
|
||||
compilersDir,
|
||||
);
|
||||
|
||||
expect(await circomCompilerDownloader.isCompilerDownloaded("2.1.8", true)).to.be.false;
|
||||
|
||||
await circomCompilerDownloader.downloadCompiler("2.1.8", true, true);
|
||||
|
||||
expect(await circomCompilerDownloader.isCompilerDownloaded("2.1.8", true)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe("getCompilerBinary", () => {
|
||||
useEnvironment("with-circuits");
|
||||
|
||||
it("should return a correct compiler binary path", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const platform = CircomCompilerDownloader.getCompilerPlatformBinary();
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(platform, compilersDir);
|
||||
|
||||
expect(await circomCompilerDownloader.getCompilerBinary("2.0.0", false)).to.be.deep.equal({
|
||||
binaryPath: `${compilersDir}/${LATEST_SUPPORTED_CIRCOM_VERSION}/${platform}`,
|
||||
version: LATEST_SUPPORTED_CIRCOM_VERSION,
|
||||
isWasm: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a correct specific version compiler binary path", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const platform = CompilerPlatformBinary.WASM;
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(platform, compilersDir);
|
||||
|
||||
expect(await circomCompilerDownloader.getCompilerBinary("2.1.8", true)).to.be.deep.equal({
|
||||
binaryPath: `${compilersDir}/2.1.8/${platform}`,
|
||||
version: "2.1.8",
|
||||
isWasm: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw an error if the correct compiler is not downloaded", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CircomCompilerDownloader.getCompilerPlatformBinary(),
|
||||
compilersDir,
|
||||
);
|
||||
|
||||
await expect(circomCompilerDownloader.getCompilerBinary("2.1.7", true)).to.be.rejectedWith(
|
||||
"Trying to get a Circom compiler v2.1.7 before it was downloaded",
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw an error if no latest compiler is found", async function () {
|
||||
cleanUp(this.hre.config.paths.root);
|
||||
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CircomCompilerDownloader.getCompilerPlatformBinary(),
|
||||
compilersDir,
|
||||
);
|
||||
|
||||
await expect(circomCompilerDownloader.getCompilerBinary("2.1.6", false)).to.be.rejectedWith(
|
||||
"No latest compiler found",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("downloadCompiler", () => {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
it("should download the latest available compiler properly", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const platform = CircomCompilerDownloader.getCompilerPlatformBinary();
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(platform, compilersDir);
|
||||
|
||||
await circomCompilerDownloader.downloadCompiler("2.0.0", false, true);
|
||||
|
||||
expect(fsExtra.readdirSync(`${compilersDir}/${LATEST_SUPPORTED_CIRCOM_VERSION}`)).to.be.deep.equal([platform]);
|
||||
expect(await circomCompilerDownloader.isCompilerDownloaded(LATEST_SUPPORTED_CIRCOM_VERSION, true)).to.be.true;
|
||||
});
|
||||
|
||||
it("should download the specific compiler version properly", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const platform = CompilerPlatformBinary.WASM;
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(platform, compilersDir);
|
||||
|
||||
await circomCompilerDownloader.downloadCompiler("2.1.8", true, true);
|
||||
|
||||
expect(fsExtra.readdirSync(`${compilersDir}/2.1.8`)).to.be.deep.equal([platform]);
|
||||
expect(await circomCompilerDownloader.isCompilerDownloaded("2.1.8", true)).to.be.true;
|
||||
});
|
||||
|
||||
it("should return without downloading if the needed compiler is downloaded", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CircomCompilerDownloader.getCompilerPlatformBinary(),
|
||||
compilersDir,
|
||||
);
|
||||
await circomCompilerDownloader.downloadCompiler("2.1.9", true, true);
|
||||
|
||||
const reporterSpy = spy(Reporter!, "reportCircomCompilerDownloadingInfo");
|
||||
|
||||
await circomCompilerDownloader.downloadCompiler("2.1.9", true, true);
|
||||
|
||||
expect(reporterSpy.called).to.be.false;
|
||||
});
|
||||
|
||||
it("should throw an error if the downloaded compiler is not working", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const targetPlatform =
|
||||
os.platform() === "win32" ? CompilerPlatformBinary.MACOS_ARM : CompilerPlatformBinary.WINDOWS_ARM;
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
targetPlatform,
|
||||
compilersDir,
|
||||
);
|
||||
|
||||
await expect(circomCompilerDownloader.downloadCompiler("2.0.0", false, true)).to.be.rejectedWith(
|
||||
"Downloaded compiler is not working",
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw an error if compiler downloading was not successful", async function () {
|
||||
const compilersDir = getNormalizedFullPath(this.hre.config.paths.root, "compilers");
|
||||
await fsExtra.ensureDir(compilersDir);
|
||||
|
||||
const circomCompilerDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CompilerPlatformBinary.MACOS_ARM,
|
||||
compilersDir,
|
||||
);
|
||||
|
||||
await expect(circomCompilerDownloader.downloadCompiler("2.1.8", true, true)).to.be.rejectedWith(
|
||||
"Failed to download Circom compiler v2.1.8. Please try again or download manually.",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
209
test/unit/core/compile/core/circom-compiler-factory.test.ts
Normal file
209
test/unit/core/compile/core/circom-compiler-factory.test.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import fsExtra from "fs-extra";
|
||||
|
||||
import { expect } from "chai";
|
||||
import { before } from "mocha";
|
||||
import { stub, SinonStub } from "sinon";
|
||||
|
||||
import { useEnvironment } from "@test-helpers";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
import { CompilerPlatformBinary, ICircomCompiler } from "@src/types/core";
|
||||
import {
|
||||
BaseCircomCompilerFactory,
|
||||
BinaryCircomCompiler,
|
||||
CircomCompilerFactory,
|
||||
createCircomCompilerFactory,
|
||||
WASMCircomCompiler,
|
||||
} from "@src/core";
|
||||
|
||||
import { CircomCompilerDownloader } from "@src/core/compiler/CircomCompilerDownloader";
|
||||
|
||||
import { defaultCompileFlags } from "../../../../constants";
|
||||
import { LATEST_SUPPORTED_CIRCOM_VERSION } from "@src/constants";
|
||||
|
||||
describe("CircomCompilerFactory", () => {
|
||||
let nativeCompilerStub: SinonStub;
|
||||
|
||||
before(() => {
|
||||
nativeCompilerStub = stub(BaseCircomCompilerFactory.prototype, "_tryCreateNativeCompiler" as any).callsFake(
|
||||
async () => {
|
||||
return undefined;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
nativeCompilerStub.restore();
|
||||
});
|
||||
|
||||
async function checkPlatformSpecificCompiler(osType: NodeJS.Platform) {
|
||||
const compilerDir = path.join(os.homedir(), ".zkit", "compilers", LATEST_SUPPORTED_CIRCOM_VERSION);
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
|
||||
const platformStub = stub(os, "platform").callsFake(() => {
|
||||
return osType;
|
||||
});
|
||||
|
||||
const compiler = await CircomCompilerFactory!.createCircomCompiler("2.0.0", false, false);
|
||||
|
||||
const platform = CircomCompilerDownloader.getCompilerPlatformBinary();
|
||||
|
||||
if (platform === CompilerPlatformBinary.WASM) {
|
||||
expect(compiler).to.be.instanceof(WASMCircomCompiler);
|
||||
} else {
|
||||
expect(compiler).to.be.instanceof(BinaryCircomCompiler);
|
||||
}
|
||||
|
||||
expect(fsExtra.readdirSync(compilerDir)).to.be.deep.equal([platform]);
|
||||
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
platformStub.restore();
|
||||
}
|
||||
|
||||
describe("createCircomCompiler", () => {
|
||||
useEnvironment("with-circuits");
|
||||
|
||||
it("should correctly create circom compiler instance", async function () {
|
||||
createCircomCompilerFactory();
|
||||
const compiler: ICircomCompiler = await CircomCompilerFactory!.createCircomCompiler("0.2.18", false);
|
||||
|
||||
const circuitFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "circuits/main/mul2.circom");
|
||||
const artifactsFullPath: string = getNormalizedFullPath(
|
||||
this.hre.config.paths.root,
|
||||
"zkit/artifacts/test/mul2.circom",
|
||||
);
|
||||
const errorFileFullPath: string = getNormalizedFullPath(artifactsFullPath, "errors.log");
|
||||
const typesDir: string = getNormalizedFullPath(this.hre.config.paths.root, "generated-types/zkit");
|
||||
|
||||
fsExtra.rmSync(artifactsFullPath, { recursive: true, force: true });
|
||||
fsExtra.mkdirSync(artifactsFullPath, { recursive: true });
|
||||
|
||||
await compiler.compile({
|
||||
circuitFullPath,
|
||||
artifactsFullPath,
|
||||
errorFileFullPath,
|
||||
linkLibraries: [],
|
||||
compileFlags: { ...defaultCompileFlags, sym: true },
|
||||
quiet: true,
|
||||
});
|
||||
|
||||
fsExtra.rmSync(errorFileFullPath, { force: true });
|
||||
|
||||
expect(fsExtra.readdirSync(artifactsFullPath)).to.be.deep.eq(["mul2.r1cs", "mul2.sym", "mul2_js"]);
|
||||
|
||||
fsExtra.rmSync(typesDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("should correctly throw error if pass invalid version", async function () {
|
||||
const invalidVersion = "2.1.10";
|
||||
|
||||
const reason = `Unsupported Circom compiler version - ${invalidVersion}. Please provide another version.`;
|
||||
|
||||
createCircomCompilerFactory();
|
||||
await expect(CircomCompilerFactory!.createCircomCompiler(invalidVersion, false)).to.be.rejectedWith(reason);
|
||||
});
|
||||
|
||||
it("should create compiler for each platform properly", async function () {
|
||||
let archStub = stub(os, "arch").callsFake(() => {
|
||||
return "x64";
|
||||
});
|
||||
|
||||
await checkPlatformSpecificCompiler("linux");
|
||||
await checkPlatformSpecificCompiler("darwin");
|
||||
await checkPlatformSpecificCompiler("win32");
|
||||
await checkPlatformSpecificCompiler("freebsd");
|
||||
|
||||
archStub.restore();
|
||||
|
||||
archStub = stub(os, "arch").callsFake(() => {
|
||||
return "arm64";
|
||||
});
|
||||
|
||||
await checkPlatformSpecificCompiler("linux");
|
||||
await checkPlatformSpecificCompiler("darwin");
|
||||
await checkPlatformSpecificCompiler("win32");
|
||||
|
||||
archStub.restore();
|
||||
|
||||
archStub = stub(os, "arch").callsFake(() => {
|
||||
return "mips";
|
||||
});
|
||||
|
||||
await checkPlatformSpecificCompiler("linux");
|
||||
|
||||
archStub.restore();
|
||||
});
|
||||
|
||||
it("should create amd compiler if arm compiler with specific version is unavailable", async function () {
|
||||
const archStub = stub(os, "arch").callsFake(() => {
|
||||
return "arm64";
|
||||
});
|
||||
|
||||
const platformStub = stub(os, "platform").callsFake(() => {
|
||||
return "darwin";
|
||||
});
|
||||
|
||||
const compilerDir = path.join(os.homedir(), ".zkit", "compilers", "2.1.7");
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
|
||||
const compiler = await CircomCompilerFactory!.createCircomCompiler("2.1.7", true, false);
|
||||
const platform = CompilerPlatformBinary.MACOS_AMD;
|
||||
|
||||
expect(compiler).to.be.instanceof(BinaryCircomCompiler);
|
||||
expect(fsExtra.readdirSync(compilerDir)).to.be.deep.equal([platform]);
|
||||
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
platformStub.restore();
|
||||
archStub.restore();
|
||||
});
|
||||
|
||||
it("should create wasm compiler if the downloaded platform compiler is not working", async function () {
|
||||
const archStub = stub(os, "arch").callsFake(() => {
|
||||
return "arm64";
|
||||
});
|
||||
|
||||
const mockPlatform = os.platform() === "win32" ? "darwin" : "win32";
|
||||
const platformStub = stub(os, "platform").callsFake(() => mockPlatform);
|
||||
|
||||
const compilerDir = path.join(os.homedir(), ".zkit", "compilers", LATEST_SUPPORTED_CIRCOM_VERSION);
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
|
||||
const compiler = await CircomCompilerFactory!.createCircomCompiler("2.0.0", false, true);
|
||||
const platform = CompilerPlatformBinary.WASM;
|
||||
|
||||
expect(compiler).to.be.instanceof(WASMCircomCompiler);
|
||||
expect(fsExtra.readdirSync(compilerDir)).to.be.deep.equal([platform]);
|
||||
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
platformStub.restore();
|
||||
archStub.restore();
|
||||
});
|
||||
|
||||
it("should not download a platform compiler if there already is a wasm one", async function () {
|
||||
createCircomCompilerFactory();
|
||||
|
||||
const compilerDir = path.join(os.homedir(), ".zkit", "compilers");
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
|
||||
const wasmDownloader = CircomCompilerDownloader.getCircomCompilerDownloader(
|
||||
CompilerPlatformBinary.WASM,
|
||||
compilerDir,
|
||||
);
|
||||
await wasmDownloader.downloadCompiler(LATEST_SUPPORTED_CIRCOM_VERSION, true, true);
|
||||
|
||||
const platformStub = stub(os, "platform").callsFake(() => {
|
||||
return "darwin";
|
||||
});
|
||||
|
||||
const compiler = await CircomCompilerFactory!.createCircomCompiler(LATEST_SUPPORTED_CIRCOM_VERSION, true, false);
|
||||
const platform = CompilerPlatformBinary.WASM;
|
||||
|
||||
expect(compiler).to.be.instanceof(WASMCircomCompiler);
|
||||
expect(fsExtra.readdirSync(`${compilerDir}/${LATEST_SUPPORTED_CIRCOM_VERSION}`)).to.be.deep.equal([platform]);
|
||||
|
||||
fsExtra.rmSync(compilerDir, { recursive: true, force: true });
|
||||
platformStub.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,12 +2,12 @@ import fsExtra from "fs-extra";
|
||||
|
||||
import { expect } from "chai";
|
||||
|
||||
import { getProjectRootPath, useEnvironment } from "../../../helpers";
|
||||
import { getNormalizedFullPath } from "../../../../src/utils/path-utils";
|
||||
import { WASMCircomCompiler } from "../../../../src/core";
|
||||
import { NODE_MODULES } from "../../../../src/constants";
|
||||
import { getProjectRootPath, useEnvironment } from "@test-helpers";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
import { CircomCompilerFactory, createCircomCompilerFactory, WASMCircomCompiler } from "@src/core";
|
||||
|
||||
import { CompileFlags } from "../../../../src/types/core";
|
||||
import { NODE_MODULES } from "@src/constants";
|
||||
import { CompileFlags } from "@src/types/core";
|
||||
|
||||
describe("WASMCircomCompiler", () => {
|
||||
const defaultCompileFlags: CompileFlags = {
|
||||
@@ -68,18 +68,33 @@ describe("WASMCircomCompiler", () => {
|
||||
);
|
||||
const errorFileFullPath: string = getNormalizedFullPath(artifactsFullPath, "errors.log");
|
||||
|
||||
const compilationArgs = {
|
||||
circuitFullPath,
|
||||
artifactsFullPath,
|
||||
errorFileFullPath,
|
||||
linkLibraries: [],
|
||||
compileFlags: defaultCompileFlags,
|
||||
quiet: true,
|
||||
};
|
||||
|
||||
const reason: string = "Compilation failed.\nHardhatZKitError: Error during compiler execution. Exit code: 1.";
|
||||
|
||||
await expect(
|
||||
circomCompiler.compile({
|
||||
circuitFullPath,
|
||||
artifactsFullPath,
|
||||
errorFileFullPath,
|
||||
linkLibraries: [],
|
||||
compileFlags: defaultCompileFlags,
|
||||
quiet: true,
|
||||
}),
|
||||
).to.be.rejectedWith(reason);
|
||||
await expect(circomCompiler.compile(compilationArgs)).to.be.rejectedWith(reason);
|
||||
|
||||
createCircomCompilerFactory();
|
||||
const platformCompiler = await CircomCompilerFactory!.createCircomCompiler("2.0.0", false);
|
||||
|
||||
await expect(platformCompiler.compile(compilationArgs)).to.be.rejected;
|
||||
|
||||
try {
|
||||
await platformCompiler.compile(compilationArgs);
|
||||
} catch (error: any) {
|
||||
const message = error.message;
|
||||
|
||||
expect(message).to.include("Compilation failed.");
|
||||
expect(message).to.include("Command failed");
|
||||
expect(message).to.include("No main specified in the project structure");
|
||||
}
|
||||
});
|
||||
|
||||
it("should correctly throw error with quiet=false", async function () {
|
||||
@@ -123,7 +138,7 @@ describe("WASMCircomCompiler", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("should correctly compile circuit with library inclue", async function () {
|
||||
it("should correctly compile circuit with library include", async function () {
|
||||
const circuitFullPath: string = getNormalizedFullPath(this.hre.config.paths.root, "circuits/hash2.circom");
|
||||
const artifactsFullPath: string = getNormalizedFullPath(
|
||||
this.hre.config.paths.root,
|
||||
@@ -7,14 +7,14 @@ import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { getAllFilesMatching } from "hardhat/internal/util/fs-utils";
|
||||
|
||||
import { CompilationFilesResolverMock } from "./CompilationFilesResolverMock";
|
||||
import { useEnvironment } from "../../../helpers";
|
||||
import { CircuitsCompileCache } from "../../../../src/cache";
|
||||
import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "../../../../src/task-names";
|
||||
import { DependencyGraph, CircomFilesResolver, CircomFilesParser } from "../../../../src/core";
|
||||
import { getNormalizedFullPath } from "../../../../src/utils/path-utils";
|
||||
import { CIRCUITS_COMPILE_CACHE_FILENAME } from "../../../../src/constants";
|
||||
import { useEnvironment } from "@test-helpers";
|
||||
import { CircuitsCompileCache } from "@src/cache";
|
||||
import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "@src/task-names";
|
||||
import { DependencyGraph, CircomFilesResolver, CircomFilesParser } from "@src/core";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
import { CIRCUITS_COMPILE_CACHE_FILENAME } from "@src/constants";
|
||||
|
||||
import { CircomResolvedFileInfo, CircomResolvedFile } from "../../../../src/types/core";
|
||||
import { CircomResolvedFileInfo, CircomResolvedFile } from "@src/types/core";
|
||||
|
||||
describe("CompilationFilesResolver", () => {
|
||||
function getCompilationFilesManagerMock(hre: HardhatRuntimeEnvironment): CompilationFilesResolverMock {
|
||||
@@ -3,15 +3,15 @@ import { expect } from "chai";
|
||||
|
||||
import { createNonCryptographicHashBasedIdentifier } from "hardhat/internal/util/hash";
|
||||
|
||||
import { useEnvironment } from "../../../helpers";
|
||||
import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "../../../../src/task-names";
|
||||
import { CircomFilesParser } from "../../../../src/core/dependencies";
|
||||
import { getNormalizedFullPath } from "../../../../src/utils/path-utils";
|
||||
import { CIRCUITS_COMPILE_CACHE_FILENAME } from "../../../../src/constants";
|
||||
import { createCircuitsCompileCache } from "../../../../src/cache";
|
||||
import { createReporter } from "../../../../src/reporter";
|
||||
import { useEnvironment } from "@test-helpers";
|
||||
import { CircomFilesParser } from "@src/core";
|
||||
import { TASK_CIRCUITS_COMPILE, ZKIT_SCOPE_NAME } from "@src/task-names";
|
||||
import { getNormalizedFullPath } from "@src/utils/path-utils";
|
||||
import { CIRCUITS_COMPILE_CACHE_FILENAME } from "@src/constants";
|
||||
import { createCircuitsCompileCache } from "@src/cache";
|
||||
import { createReporter } from "@src/reporter";
|
||||
|
||||
import { ResolvedFileData } from "../../../../src/types/core";
|
||||
import { ResolvedFileData } from "@src/types/core";
|
||||
|
||||
describe("CircomFilesParser", () => {
|
||||
describe("parse", () => {
|
||||
33
test/unit/core/compile/utils/ptau-downloader.test.ts
Normal file
33
test/unit/core/compile/utils/ptau-downloader.test.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import fsExtra from "fs-extra";
|
||||
import { expect } from "chai";
|
||||
|
||||
import { PtauDownloader } from "@src/core";
|
||||
import { useEnvironment } from "@test-helpers";
|
||||
|
||||
describe("PtauDownloader", () => {
|
||||
describe("downloadPtau", () => {
|
||||
useEnvironment("with-circuits", true);
|
||||
|
||||
it("should download ptau file correctly", async function () {
|
||||
const ptauPath = this.hre.config.zkit.setupSettings.ptauDir;
|
||||
await PtauDownloader.downloadPtau(ptauPath, 16);
|
||||
|
||||
expect(fsExtra.readdirSync(ptauPath)).to.be.deep.eq(["powers-of-tau-16.ptau"]);
|
||||
});
|
||||
|
||||
it("should throw an error if ptauId is too big", async function () {
|
||||
const maxPtauId = PtauDownloader.getMaxPtauID();
|
||||
await expect(
|
||||
PtauDownloader.downloadPtau(this.hre.config.zkit.setupSettings.ptauDir, maxPtauId + 1),
|
||||
).to.be.rejectedWith(
|
||||
`Circuits has too many constraints. The maximum ptauId to download is ${maxPtauId}. Consider passing "ptauDir=PATH_TO_LOCAL_DIR" with existing ptau files.`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw an error if ptauId is less than 8", async function () {
|
||||
await expect(PtauDownloader.downloadPtau(this.hre.config.zkit.setupSettings.ptauDir, 0)).to.be.rejectedWith(
|
||||
"Failed to download a Ptau file. Please try again or download manually.",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
27
test/unit/core/compile/utils/versioning.test.ts
Normal file
27
test/unit/core/compile/utils/versioning.test.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { getHighestVersion, isVersionValid } from "@src/core/compiler/versioning";
|
||||
|
||||
describe("Versioning", () => {
|
||||
describe("isVersionValid", () => {
|
||||
it("should correctly identify whether circom version is correct", async function () {
|
||||
expect(isVersionValid("2.1.9")).to.be.true;
|
||||
expect(isVersionValid("2.0.0")).to.be.true;
|
||||
|
||||
expect(isVersionValid("")).to.be.false;
|
||||
expect(isVersionValid("1")).to.be.false;
|
||||
expect(isVersionValid("2.1")).to.be.false;
|
||||
expect(isVersionValid("2.a.1")).to.be.false;
|
||||
expect(isVersionValid("2.1.b")).to.be.false;
|
||||
expect(isVersionValid("^2.1.3")).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe("getHighestVersion", () => {
|
||||
it("should correctly get the highest version", async function () {
|
||||
expect(getHighestVersion(["2.1.9", "0.1.1", "2.1.9", "2.0.0", "2.1.8"])).to.be.equal("2.1.9");
|
||||
expect(getHighestVersion(["2.0.0", "2.0.0"])).to.be.equal("2.0.0");
|
||||
expect(getHighestVersion([])).to.be.equal("0.0.0");
|
||||
});
|
||||
});
|
||||
});
|
||||
54
test/utils.ts
Normal file
54
test/utils.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import fsExtra from "fs-extra";
|
||||
|
||||
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 { defaultCompileFlags, defaultContributionSettings } from "./constants";
|
||||
|
||||
export async function getCompileCacheEntry(
|
||||
projectRoot: string,
|
||||
sourceName: string,
|
||||
compileFlags: CompileFlags = defaultCompileFlags,
|
||||
contentHash?: string,
|
||||
): Promise<CompileCacheEntry> {
|
||||
const circuitPath = getNormalizedFullPath(projectRoot, sourceName);
|
||||
|
||||
if (!contentHash) {
|
||||
contentHash = getFileHash(circuitPath);
|
||||
}
|
||||
|
||||
const parser: CircomFilesParser = new CircomFilesParser();
|
||||
const fileData: ResolvedFileData = parser.parse(fsExtra.readFileSync(circuitPath, "utf-8"), circuitPath, contentHash);
|
||||
|
||||
const stats = await fsExtra.stat(circuitPath);
|
||||
const lastModificationDate: Date = new Date(stats.ctime);
|
||||
|
||||
return {
|
||||
sourceName,
|
||||
contentHash,
|
||||
lastModificationDate: lastModificationDate.valueOf(),
|
||||
compileFlags,
|
||||
fileData,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getSetupCacheEntry(
|
||||
sourceName: string,
|
||||
r1csSourcePath: string,
|
||||
contributionSettings: ContributionSettings = defaultContributionSettings,
|
||||
r1csContentHash?: string,
|
||||
): Promise<SetupCacheEntry> {
|
||||
if (!r1csContentHash) {
|
||||
r1csContentHash = getFileHash(r1csSourcePath);
|
||||
}
|
||||
|
||||
return {
|
||||
circuitSourceName: sourceName,
|
||||
r1csSourcePath,
|
||||
r1csContentHash,
|
||||
contributionSettings,
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"ts-node": {
|
||||
"require": ["tsconfig-paths/register"]
|
||||
},
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "commonjs",
|
||||
@@ -14,7 +17,11 @@
|
||||
"experimentalDecorators": true,
|
||||
"types": [
|
||||
"@nomicfoundation/hardhat-ethers"
|
||||
]
|
||||
],
|
||||
"paths": {
|
||||
"@src/*": ["./src/*"],
|
||||
"@test-helpers": ["./test/helpers"]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"./dist",
|
||||
|
||||
Reference in New Issue
Block a user