From bde111658eb0bfa9a38833e9c54429a9829539de Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 22 Nov 2023 17:17:37 +0000 Subject: [PATCH 01/17] feat(circuits): create new package for circuits --- package.json | 3 +- packages/circuits/.gitignore | 2 + packages/circuits/LICENSE | 1 + packages/circuits/README.md | 1 + .../components/binary-merkle-root.circom | 5 ++ .../circuits/components/poseidon-proof.circom | 5 ++ packages/circuits/package.json | 9 ++++ packages/circuits/templates/LICENSE | 21 ++++++++ packages/circuits/templates/README.md | 50 +++++++++++++++++++ .../templates/binary-merkle-root.circom | 32 ++++++++++++ packages/circuits/templates/package.json | 24 +++++++++ .../circuits/templates/poseidon-proof.circom | 24 +++++++++ yarn.lock | 14 ++++++ 13 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 packages/circuits/.gitignore create mode 120000 packages/circuits/LICENSE create mode 120000 packages/circuits/README.md create mode 100644 packages/circuits/components/binary-merkle-root.circom create mode 100644 packages/circuits/components/poseidon-proof.circom create mode 100644 packages/circuits/package.json create mode 100644 packages/circuits/templates/LICENSE create mode 100644 packages/circuits/templates/README.md create mode 100644 packages/circuits/templates/binary-merkle-root.circom create mode 100644 packages/circuits/templates/package.json create mode 100644 packages/circuits/templates/poseidon-proof.circom diff --git a/package.json b/package.json index 933d4dd40..e7772aad6 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "circom" ], "workspaces": [ - "packages/*" + "packages/*", + "packages/circuits/templates" ], "packageManager": "yarn@3.2.1", "devDependencies": { diff --git a/packages/circuits/.gitignore b/packages/circuits/.gitignore new file mode 100644 index 000000000..64183cbe9 --- /dev/null +++ b/packages/circuits/.gitignore @@ -0,0 +1,2 @@ +*.r1cs +*.wasm diff --git a/packages/circuits/LICENSE b/packages/circuits/LICENSE new file mode 120000 index 000000000..8e505bcde --- /dev/null +++ b/packages/circuits/LICENSE @@ -0,0 +1 @@ +templates/LICENSE \ No newline at end of file diff --git a/packages/circuits/README.md b/packages/circuits/README.md new file mode 120000 index 000000000..6cb99675b --- /dev/null +++ b/packages/circuits/README.md @@ -0,0 +1 @@ +templates/README.md \ No newline at end of file diff --git a/packages/circuits/components/binary-merkle-root.circom b/packages/circuits/components/binary-merkle-root.circom new file mode 100644 index 000000000..7f59cddd4 --- /dev/null +++ b/packages/circuits/components/binary-merkle-root.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.5; + +include "../templates/binary-merkle-root.circom"; + +component main {public [depth]} = BinaryMerkleRoot(16); diff --git a/packages/circuits/components/poseidon-proof.circom b/packages/circuits/components/poseidon-proof.circom new file mode 100644 index 000000000..4b45a3c87 --- /dev/null +++ b/packages/circuits/components/poseidon-proof.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.5; + +include "../templates/poseidon-proof.circom"; + +component main {public [scope]} = PoseidonProof(); diff --git a/packages/circuits/package.json b/packages/circuits/package.json new file mode 100644 index 000000000..1b913981c --- /dev/null +++ b/packages/circuits/package.json @@ -0,0 +1,9 @@ +{ + "name": "circuits", + "private": true, + "description": "A comprehensive library of general-purpose Circom circuits.", + "license": "MIT", + "scripts": { + "compile": "circom --r1cs -l ../../node_modules/circomlib/circuits" + } +} diff --git a/packages/circuits/templates/LICENSE b/packages/circuits/templates/LICENSE new file mode 100644 index 000000000..4377091ec --- /dev/null +++ b/packages/circuits/templates/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ethereum Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/circuits/templates/README.md b/packages/circuits/templates/README.md new file mode 100644 index 000000000..f8980fab3 --- /dev/null +++ b/packages/circuits/templates/README.md @@ -0,0 +1,50 @@ +

+

+ ZK-kit circuits +

+

A comprehensive library of general-purpose Circom circuits.

+

+ +

+ + + + + Github license + + + NPM version + + + Downloads + + + npm bundle size (scoped) + +

+ +
+

+ + 🗣️ Chat & Support + +

+
+ +--- + +## 🛠 Install + +### npm or yarn + +Install the `@zk-kit/circuits` package with npm: + +```bash +npm i @zk-kit/circuits --save +``` + +or yarn: + +```bash +yarn add @zk-kit/circuits +``` diff --git a/packages/circuits/templates/binary-merkle-root.circom b/packages/circuits/templates/binary-merkle-root.circom new file mode 100644 index 000000000..238de32f6 --- /dev/null +++ b/packages/circuits/templates/binary-merkle-root.circom @@ -0,0 +1,32 @@ +pragma circom 2.1.5; + +include "poseidon.circom"; +include "mux1.circom"; +include "comparators.circom"; + +template BinaryMerkleRoot(MAX_DEPTH) { + signal input leaf, depth, indices[MAX_DEPTH], siblings[MAX_DEPTH]; + + signal output out; + + signal nodes[MAX_DEPTH + 1]; + nodes[0] <== leaf; + + signal roots[MAX_DEPTH]; + var root = 0; + + for (var i = 0; i < MAX_DEPTH; i++) { + var a = IsEqual()([depth, i]); + + roots[i] <== a * nodes[i]; + + root += roots[i]; + + var c[2][2] = [ [nodes[i], siblings[i]], [siblings[i], nodes[i]] ]; + var childNodes[2] = MultiMux1(2)(c, indices[i]); + + nodes[i + 1] <== Poseidon(2)(childNodes); + } + + out <== root; +} diff --git a/packages/circuits/templates/package.json b/packages/circuits/templates/package.json new file mode 100644 index 000000000..3fb074be9 --- /dev/null +++ b/packages/circuits/templates/package.json @@ -0,0 +1,24 @@ +{ + "name": "@zk-kit/circuits", + "version": "0.1.0", + "description": "A comprehensive library of general-purpose Circom circuits.", + "license": "MIT", + "files": [ + "**/*.circom", + "LICENSE", + "README.md" + ], + "keywords": [ + "zk-kit", + "circom", + "circuits" + ], + "repository": "git@github.com:privacy-scaling-explorations/zk-kit.git", + "homepage": "https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/circuits.sol", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "circomlib": "^2.0.5" + } +} diff --git a/packages/circuits/templates/poseidon-proof.circom b/packages/circuits/templates/poseidon-proof.circom new file mode 100644 index 000000000..286d364cc --- /dev/null +++ b/packages/circuits/templates/poseidon-proof.circom @@ -0,0 +1,24 @@ +pragma circom 2.1.5; + +include "poseidon.circom"; + +// This circuit can be used to prove the possession of a pre-image of a +// hash without revealing the pre-image itself. It utilizes the Poseidon +// hash function, a highly efficient and secure hash function suited +// for zero-knowledge proof contexts. +// A scope value can be used to define a nullifier to prevent the same +// proof from being re-used twice. +template PoseidonProof() { + // The circuit takes two inputs: the pre-image (in) and an additional scope parameter (scope). + signal input in; + signal input scope; + + // It applies the Poseidon hash function to the pre-image to produce a hash output (out). + signal output out; + out <== Poseidon(1)([in]); + + // A nullifier is also computed using both the pre-image and the scope, providing a value + // to prevent the same proof from being reused twice. + signal output nullifier; + nullifier <== Poseidon(2)([scope, in]); +} diff --git a/yarn.lock b/yarn.lock index 5888ea146..0994e94aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4399,6 +4399,14 @@ __metadata: languageName: node linkType: hard +"@zk-kit/circuits@workspace:packages/circuits/templates": + version: 0.0.0-use.local + resolution: "@zk-kit/circuits@workspace:packages/circuits/templates" + dependencies: + circomlib: ^2.0.5 + languageName: unknown + linkType: soft + "@zk-kit/groth16@0.4.0, @zk-kit/groth16@workspace:packages/groth16": version: 0.0.0-use.local resolution: "@zk-kit/groth16@workspace:packages/groth16" @@ -6447,6 +6455,12 @@ __metadata: languageName: node linkType: hard +"circuits@workspace:packages/circuits": + version: 0.0.0-use.local + resolution: "circuits@workspace:packages/circuits" + languageName: unknown + linkType: soft + "cjs-module-lexer@npm:^0.6.0": version: 0.6.0 resolution: "cjs-module-lexer@npm:0.6.0" From 3f1ccadfd2fbff1b879a19ab91a40d3d25accd1e Mon Sep 17 00:00:00 2001 From: cedoor Date: Tue, 28 Nov 2023 18:25:16 +0000 Subject: [PATCH 02/17] chore(circuits): new setup with circomkit re #73 --- .../circomkit-npm-0.0.18-e33b63f27f.patch | 76 +++++++++++++++++++ package.json | 6 +- packages/circuits/.gitignore | 2 + packages/circuits/LICENSE | 22 +++++- packages/circuits/README.md | 51 ++++++++++++- .../binary-merkle-root.circom | 0 packages/circuits/circom/circuits.json | 11 +++ .../poseidon-proof.circom | 0 packages/circuits/circomkit.json | 17 +++++ .../components/binary-merkle-root.circom | 5 -- .../circuits/components/poseidon-proof.circom | 5 -- packages/circuits/noir/.gitkeep | 0 packages/circuits/package.json | 26 ++++++- packages/circuits/templates/LICENSE | 21 ----- packages/circuits/templates/README.md | 50 ------------ packages/circuits/templates/package.json | 24 ------ yarn.lock | 68 ++++++++++++++--- 17 files changed, 261 insertions(+), 123 deletions(-) create mode 100644 .yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch mode change 120000 => 100644 packages/circuits/LICENSE mode change 120000 => 100644 packages/circuits/README.md rename packages/circuits/{templates => circom}/binary-merkle-root.circom (100%) create mode 100644 packages/circuits/circom/circuits.json rename packages/circuits/{templates => circom}/poseidon-proof.circom (100%) create mode 100644 packages/circuits/circomkit.json delete mode 100644 packages/circuits/components/binary-merkle-root.circom delete mode 100644 packages/circuits/components/poseidon-proof.circom create mode 100644 packages/circuits/noir/.gitkeep delete mode 100644 packages/circuits/templates/LICENSE delete mode 100644 packages/circuits/templates/README.md delete mode 100644 packages/circuits/templates/package.json diff --git a/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch b/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch new file mode 100644 index 000000000..22086de6f --- /dev/null +++ b/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch @@ -0,0 +1,76 @@ +diff --git a/dist/utils/instantiate.js b/dist/utils/instantiate.js +index 33cdff152e8b23d6853eb475097bda8c02712e01..418f57072c9c0ebf3778c8a9a50d379728128e5f 100644 +--- a/dist/utils/instantiate.js ++++ b/dist/utils/instantiate.js +@@ -1,15 +1,17 @@ +-"use strict"; +-Object.defineProperty(exports, "__esModule", { value: true }); +-exports.instantiate = void 0; +-const fs_1 = require("fs"); ++"use strict" ++Object.defineProperty(exports, "__esModule", { value: true }) ++exports.instantiate = void 0 ++const fs_1 = require("fs") + /** Circuit builder, kinda like `ejs.render`. **Be very careful when editing this file.** */ + const makeCircuit = (config) => `// auto-generated by circomkit + pragma circom ${config.version}; + + include "../${config.file}.circom"; + +-component main${config.pubs.length === 0 ? '' : ' {public[' + config.pubs.join(', ') + ']}'} = ${config.template}(${config.params.join(', ')}); +-`; ++component main${config.pubs.length === 0 ? "" : " {public[" + config.pubs.join(", ") + "]}"} = ${ ++ config.template ++}(${config.params.join(", ")}); ++` + /** + * Programmatically generate the `main` component of a circuit + * @param name name of the circuit to be generated +@@ -18,31 +20,32 @@ component main${config.pubs.length === 0 ? '' : ' {public[' + config.pubs.join(' + */ + function instantiate(name, circuitConfig) { + // directory to output the file +- const directory = circuitConfig.dir || 'test'; ++ const directory = circuitConfig.dir || "test" + // add "../" to the filename in include, one for each "/" in directory name + // if none, the prefix becomes empty string +- const filePrefixMatches = directory.match(/\//g); +- let file = circuitConfig.file; ++ const filePrefixMatches = directory.match(/\//g) ++ let file = circuitConfig.file + if (filePrefixMatches !== null) { +- file = '../'.repeat(filePrefixMatches.length) + file; ++ file = "../".repeat(filePrefixMatches.length) + file + } + const circuitCode = makeCircuit({ + file: file, + template: circuitConfig.template, +- version: circuitConfig.version || '2.0.0', ++ version: circuitConfig.version || "2.0.0", + dir: directory, + pubs: circuitConfig.pubs || [], +- params: circuitConfig.params || [], +- }); +- const targetDir = `./circuits/${directory}`; ++ params: circuitConfig.params || [] ++ }) ++ const targetDir = `./circom/${directory}` + if (!(0, fs_1.existsSync)(targetDir)) { +- (0, fs_1.mkdirSync)(targetDir, { +- recursive: true, +- }); ++ ;(0, fs_1.mkdirSync)(targetDir, { ++ recursive: true ++ }) + } +- const targetPath = `${targetDir}/${name}.circom`; +- (0, fs_1.writeFileSync)(targetPath, circuitCode); +- return targetPath; ++ const targetPath = `${targetDir}/${name}.circom` ++ ;(0, fs_1.writeFileSync)(targetPath, circuitCode) ++ return targetPath + } +-exports.instantiate = instantiate; ++exports.instantiate = instantiate + //# sourceMappingURL=instantiate.js.map ++ diff --git a/package.json b/package.json index e7772aad6..8d549fd88 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,7 @@ "circom" ], "workspaces": [ - "packages/*", - "packages/circuits/templates" + "packages/*" ], "packageManager": "yarn@3.2.1", "devDependencies": { @@ -76,5 +75,8 @@ "commitizen": { "path": "./node_modules/cz-conventional-changelog" } + }, + "resolutions": { + "circomkit@0.0.18": "patch:circomkit@npm:0.0.18#.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch" } } diff --git a/packages/circuits/.gitignore b/packages/circuits/.gitignore index 64183cbe9..928abb6f2 100644 --- a/packages/circuits/.gitignore +++ b/packages/circuits/.gitignore @@ -1,2 +1,4 @@ +ptau +main *.r1cs *.wasm diff --git a/packages/circuits/LICENSE b/packages/circuits/LICENSE deleted file mode 120000 index 8e505bcde..000000000 --- a/packages/circuits/LICENSE +++ /dev/null @@ -1 +0,0 @@ -templates/LICENSE \ No newline at end of file diff --git a/packages/circuits/LICENSE b/packages/circuits/LICENSE new file mode 100644 index 000000000..4377091ec --- /dev/null +++ b/packages/circuits/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ethereum Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/circuits/README.md b/packages/circuits/README.md deleted file mode 120000 index 6cb99675b..000000000 --- a/packages/circuits/README.md +++ /dev/null @@ -1 +0,0 @@ -templates/README.md \ No newline at end of file diff --git a/packages/circuits/README.md b/packages/circuits/README.md new file mode 100644 index 000000000..4694f39e1 --- /dev/null +++ b/packages/circuits/README.md @@ -0,0 +1,50 @@ +

+

+ ZK-kit circuits +

+

A comprehensive library of general-purpose zero-knowledge circuits.

+

+ +

+ + + + + Github license + + + NPM version + + + Downloads + + + npm bundle size (scoped) + +

+ +
+

+ + 🗣️ Chat & Support + +

+
+ +--- + +## 🛠 Install + +### npm or yarn + +Install the `@zk-kit/circuits` package with npm: + +```bash +npm i @zk-kit/circuits --save +``` + +or yarn: + +```bash +yarn add @zk-kit/circuits +``` diff --git a/packages/circuits/templates/binary-merkle-root.circom b/packages/circuits/circom/binary-merkle-root.circom similarity index 100% rename from packages/circuits/templates/binary-merkle-root.circom rename to packages/circuits/circom/binary-merkle-root.circom diff --git a/packages/circuits/circom/circuits.json b/packages/circuits/circom/circuits.json new file mode 100644 index 000000000..5f6fa74fb --- /dev/null +++ b/packages/circuits/circom/circuits.json @@ -0,0 +1,11 @@ +{ + "poseidon-proof": { + "file": "poseidon-proof", + "template": "PoseidonProof" + }, + "binary-merkle-root": { + "file": "binary-merkle-root", + "template": "BinaryMerkleRoot", + "params": [20] + } +} diff --git a/packages/circuits/templates/poseidon-proof.circom b/packages/circuits/circom/poseidon-proof.circom similarity index 100% rename from packages/circuits/templates/poseidon-proof.circom rename to packages/circuits/circom/poseidon-proof.circom diff --git a/packages/circuits/circomkit.json b/packages/circuits/circomkit.json new file mode 100644 index 000000000..936e64b6e --- /dev/null +++ b/packages/circuits/circomkit.json @@ -0,0 +1,17 @@ +{ + "protocol": "groth16", + "prime": "bn128", + "version": "2.1.5", + "circuits": "./circom/circuits.json", + "dirPtau": "./ptau", + "dirCircuits": "./circom", + "dirInputs": "./inputs", + "dirBuild": "./build", + "optimization": 1, + "inspect": true, + "include": ["../../node_modules/circomlib/circuits"], + "groth16numContributions": 1, + "groth16askForEntropy": false, + "logLevel": "INFO", + "verbose": true +} diff --git a/packages/circuits/components/binary-merkle-root.circom b/packages/circuits/components/binary-merkle-root.circom deleted file mode 100644 index 7f59cddd4..000000000 --- a/packages/circuits/components/binary-merkle-root.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.5; - -include "../templates/binary-merkle-root.circom"; - -component main {public [depth]} = BinaryMerkleRoot(16); diff --git a/packages/circuits/components/poseidon-proof.circom b/packages/circuits/components/poseidon-proof.circom deleted file mode 100644 index 4b45a3c87..000000000 --- a/packages/circuits/components/poseidon-proof.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.5; - -include "../templates/poseidon-proof.circom"; - -component main {public [scope]} = PoseidonProof(); diff --git a/packages/circuits/noir/.gitkeep b/packages/circuits/noir/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/circuits/package.json b/packages/circuits/package.json index 1b913981c..07fcbaab5 100644 --- a/packages/circuits/package.json +++ b/packages/circuits/package.json @@ -1,9 +1,27 @@ { - "name": "circuits", - "private": true, - "description": "A comprehensive library of general-purpose Circom circuits.", + "name": "@zk-kit/circuits", + "version": "0.2.0", + "description": "A comprehensive library of general-purpose zero-knowledge circuits.", "license": "MIT", + "files": [ + "circom", + "noir", + "LICENSE", + "README.md" + ], + "repository": "git@github.com:privacy-scaling-explorations/zk-kit.git", + "homepage": "https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/circuits.sol", "scripts": { - "compile": "circom --r1cs -l ../../node_modules/circomlib/circuits" + "circom:compile": "circomkit compile", + "circom:setup": "circomkit setup" + }, + "dependencies": { + "circomlib": "^2.0.5" + }, + "devDependencies": { + "circomkit": "^0.0.18" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/circuits/templates/LICENSE b/packages/circuits/templates/LICENSE deleted file mode 100644 index 4377091ec..000000000 --- a/packages/circuits/templates/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Ethereum Foundation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/circuits/templates/README.md b/packages/circuits/templates/README.md deleted file mode 100644 index f8980fab3..000000000 --- a/packages/circuits/templates/README.md +++ /dev/null @@ -1,50 +0,0 @@ -

-

- ZK-kit circuits -

-

A comprehensive library of general-purpose Circom circuits.

-

- -

- - - - - Github license - - - NPM version - - - Downloads - - - npm bundle size (scoped) - -

- -
-

- - 🗣️ Chat & Support - -

-
- ---- - -## 🛠 Install - -### npm or yarn - -Install the `@zk-kit/circuits` package with npm: - -```bash -npm i @zk-kit/circuits --save -``` - -or yarn: - -```bash -yarn add @zk-kit/circuits -``` diff --git a/packages/circuits/templates/package.json b/packages/circuits/templates/package.json deleted file mode 100644 index 3fb074be9..000000000 --- a/packages/circuits/templates/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@zk-kit/circuits", - "version": "0.1.0", - "description": "A comprehensive library of general-purpose Circom circuits.", - "license": "MIT", - "files": [ - "**/*.circom", - "LICENSE", - "README.md" - ], - "keywords": [ - "zk-kit", - "circom", - "circuits" - ], - "repository": "git@github.com:privacy-scaling-explorations/zk-kit.git", - "homepage": "https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/circuits.sol", - "publishConfig": { - "access": "public" - }, - "dependencies": { - "circomlib": "^2.0.5" - } -} diff --git a/yarn.lock b/yarn.lock index 0994e94aa..31977182a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4399,10 +4399,11 @@ __metadata: languageName: node linkType: hard -"@zk-kit/circuits@workspace:packages/circuits/templates": +"@zk-kit/circuits@workspace:packages/circuits": version: 0.0.0-use.local - resolution: "@zk-kit/circuits@workspace:packages/circuits/templates" + resolution: "@zk-kit/circuits@workspace:packages/circuits" dependencies: + circomkit: ^0.0.18 circomlib: ^2.0.5 languageName: unknown linkType: soft @@ -6080,7 +6081,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.2.0, chai@npm:^4.3.6": +"chai@npm:^4.2.0, chai@npm:^4.3.6, chai@npm:^4.3.7": version: 4.3.10 resolution: "chai@npm:4.3.10" dependencies: @@ -6409,6 +6410,20 @@ __metadata: languageName: node linkType: hard +"circomkit@npm:^0.0.18": + version: 0.0.18 + resolution: "circomkit@npm:0.0.18" + dependencies: + chai: ^4.3.7 + circom_tester: ^0.0.19 + loglevel: ^1.8.1 + snarkjs: ^0.7.0 + bin: + circomkit: dist/bin/index.js + checksum: 4120fdf8523f8d595a85e673bb74b8d683a302a401bf049ecb1a0ff4ad178e8f77ed7d12a50856c1be5f56bb8666f861a240d432f2ada78faa13dec161780cf1 + languageName: node + linkType: hard + "circomlib@npm:0.5.1": version: 0.5.1 resolution: "circomlib@npm:0.5.1" @@ -6455,12 +6470,6 @@ __metadata: languageName: node linkType: hard -"circuits@workspace:packages/circuits": - version: 0.0.0-use.local - resolution: "circuits@workspace:packages/circuits" - languageName: unknown - linkType: soft - "cjs-module-lexer@npm:^0.6.0": version: 0.6.0 resolution: "cjs-module-lexer@npm:0.6.0" @@ -9123,7 +9132,7 @@ __metadata: languageName: node linkType: hard -"ffjavascript@npm:^0.2.30, ffjavascript@npm:^0.2.35, ffjavascript@npm:^0.2.38": +"ffjavascript@npm:0.2.62, ffjavascript@npm:^0.2.30, ffjavascript@npm:^0.2.35, ffjavascript@npm:^0.2.38": version: 0.2.62 resolution: "ffjavascript@npm:0.2.62" dependencies: @@ -13351,6 +13360,13 @@ __metadata: languageName: node linkType: hard +"loglevel@npm:^1.8.1": + version: 1.8.1 + resolution: "loglevel@npm:1.8.1" + checksum: a1a62db40291aaeaef2f612334c49e531bff71cc1d01a2acab689ab80d59e092f852ab164a5aedc1a752fdc46b7b162cb097d8a9eb2cf0b299511106c29af61d + languageName: node + linkType: hard + "logplease@npm:^1.2.15": version: 1.2.15 resolution: "logplease@npm:1.2.15" @@ -15501,6 +15517,18 @@ __metadata: languageName: node linkType: hard +"r1csfile@npm:0.0.47": + version: 0.0.47 + resolution: "r1csfile@npm:0.0.47" + dependencies: + "@iden3/bigarray": 0.0.2 + "@iden3/binfileutils": 0.0.11 + fastfile: 0.0.20 + ffjavascript: 0.2.60 + checksum: edeb325b83851a71cbca2e5de56eb622ee5347ecae921b526a5fc484c4825b6b30c73b6fde40e9bc5112b9d21e046af885bf212ed9cee2efbc6de93b8454ec06 + languageName: node + linkType: hard + "randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -16839,6 +16867,26 @@ __metadata: languageName: node linkType: hard +"snarkjs@npm:^0.7.0": + version: 0.7.2 + resolution: "snarkjs@npm:0.7.2" + dependencies: + "@iden3/binfileutils": 0.0.11 + bfj: ^7.0.2 + blake2b-wasm: ^2.4.0 + circom_runtime: 0.1.24 + ejs: ^3.1.6 + fastfile: 0.0.20 + ffjavascript: 0.2.62 + js-sha3: ^0.8.0 + logplease: ^1.2.15 + r1csfile: 0.0.47 + bin: + snarkjs: build/cli.cjs + checksum: c784e2171278403b2356ddc42fac47093e7cf4c48c0ef46ac3c269c308795d2da63a00dd6b92521b166f3d0349d0b8301454f5a9633b5db447755b4568c4b5e7 + languageName: node + linkType: hard + "socks-proxy-agent@npm:^8.0.1": version: 8.0.2 resolution: "socks-proxy-agent@npm:8.0.2" From 8c3bf7c96c216062293b75f4455f993867b28789 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Tue, 28 Nov 2023 18:57:34 +0000 Subject: [PATCH 03/17] docs(circuits): add more info to README.md --- packages/circuits/README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/circuits/README.md b/packages/circuits/README.md index 4694f39e1..5014d0dd9 100644 --- a/packages/circuits/README.md +++ b/packages/circuits/README.md @@ -18,9 +18,6 @@ Downloads - - npm bundle size (scoped) -

@@ -31,7 +28,15 @@
---- + +| This package offers a collection of reusable circuits designed for integration into other projects or protocols, promoting code modularization within the zero-knowledge ecosystem. | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + +## Circuits + +* Circom: + * [PoseidonProof](./circom/poseidon-proof.circom): It proves the possession of a Posidon pre-image without revealing the pre-image itself. + * [BinaryMerkleRoot](./circom/binary-merkle-root.circom): It calculates the root of a binary Merkle tree using a provided proof-of-membership. ## 🛠 Install From 31640eac731205e4391b269277bb632ee78ab06f Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 10:44:37 +0000 Subject: [PATCH 04/17] style(circuits): format code with prettier --- packages/circuits/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/circuits/README.md b/packages/circuits/README.md index 5014d0dd9..4ce514aa5 100644 --- a/packages/circuits/README.md +++ b/packages/circuits/README.md @@ -28,15 +28,14 @@ - | This package offers a collection of reusable circuits designed for integration into other projects or protocols, promoting code modularization within the zero-knowledge ecosystem. | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ## Circuits -* Circom: - * [PoseidonProof](./circom/poseidon-proof.circom): It proves the possession of a Posidon pre-image without revealing the pre-image itself. - * [BinaryMerkleRoot](./circom/binary-merkle-root.circom): It calculates the root of a binary Merkle tree using a provided proof-of-membership. +- Circom: + - [PoseidonProof](./circom/poseidon-proof.circom): It proves the possession of a Posidon pre-image without revealing the pre-image itself. + - [BinaryMerkleRoot](./circom/binary-merkle-root.circom): It calculates the root of a binary Merkle tree using a provided proof-of-membership. ## 🛠 Install From f71909d4da05d72e3587d4778323561ee6502b6a Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 10:53:27 +0000 Subject: [PATCH 05/17] docs(circuits): fix typo --- packages/circuits/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/circuits/README.md b/packages/circuits/README.md index 4ce514aa5..7ac1fb160 100644 --- a/packages/circuits/README.md +++ b/packages/circuits/README.md @@ -34,7 +34,7 @@ ## Circuits - Circom: - - [PoseidonProof](./circom/poseidon-proof.circom): It proves the possession of a Posidon pre-image without revealing the pre-image itself. + - [PoseidonProof](./circom/poseidon-proof.circom): It proves the possession of a Poseidon pre-image without revealing the pre-image itself. - [BinaryMerkleRoot](./circom/binary-merkle-root.circom): It calculates the root of a binary Merkle tree using a provided proof-of-membership. ## 🛠 Install From a6119502408c1e7e7fac1c3c94ad5a20606e9ac4 Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 12:25:49 +0000 Subject: [PATCH 06/17] chore: remove eslint jest config --- .eslintrc.json | 4 ++-- package.json | 1 - packages/imt.sol/test/BinaryIMT.ts | 1 - packages/imt.sol/test/LazyIMT.ts | 1 - packages/imt.sol/test/LeanIMT.ts | 1 - packages/imt.sol/test/QuinaryIMT.ts | 1 - packages/lazytower.sol/test/LazyTowerHashChainTest.ts | 1 - 7 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 21e030869..6d0404b92 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,14 +3,14 @@ "env": { "es6": true }, - "extends": ["airbnb-base", "airbnb-typescript/base", "plugin:jest/recommended", "plugin:jest/style", "prettier"], + "extends": ["airbnb-base", "airbnb-typescript/base", "prettier"], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 6, "sourceType": "module", "project": ["./tsconfig.json", "./packages/**/tsconfig.json"] }, - "plugins": ["@typescript-eslint", "jest"], + "plugins": ["@typescript-eslint"], "rules": { "no-console": ["warn", { "allow": ["info", "warn", "error"] }], "no-restricted-syntax": "off", diff --git a/package.json b/package.json index 8d549fd88..76bb21a6f 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,6 @@ "eslint-config-airbnb-typescript": "^16.1.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jest": "^25.7.0", "husky": "^8.0.3", "jest": "^27.4.1", "jest-config": "^27.4.7", diff --git a/packages/imt.sol/test/BinaryIMT.ts b/packages/imt.sol/test/BinaryIMT.ts index ae8adc7d5..bdb28a78e 100644 --- a/packages/imt.sol/test/BinaryIMT.ts +++ b/packages/imt.sol/test/BinaryIMT.ts @@ -5,7 +5,6 @@ import { run } from "hardhat" import { poseidon2 } from "poseidon-lite" import { BinaryIMT, BinaryIMTTest } from "../typechain-types" -/* eslint-disable jest/valid-expect */ describe("BinaryIMT", () => { let binaryIMTTest: BinaryIMTTest let binaryIMT: BinaryIMT diff --git a/packages/imt.sol/test/LazyIMT.ts b/packages/imt.sol/test/LazyIMT.ts index fd6ddd68d..4f62c8aff 100644 --- a/packages/imt.sol/test/LazyIMT.ts +++ b/packages/imt.sol/test/LazyIMT.ts @@ -6,7 +6,6 @@ import { LazyIMT, LazyIMTTest } from "../typechain-types" const random = () => poseidon2([Math.floor(Math.random() * 2 ** 40), 0]) -/* eslint-disable jest/valid-expect */ describe("LazyIMT", () => { let lazyIMTTest: LazyIMTTest let lazyIMT: LazyIMT diff --git a/packages/imt.sol/test/LeanIMT.ts b/packages/imt.sol/test/LeanIMT.ts index 94fd34fc8..2a0494daf 100644 --- a/packages/imt.sol/test/LeanIMT.ts +++ b/packages/imt.sol/test/LeanIMT.ts @@ -4,7 +4,6 @@ import { run } from "hardhat" import { poseidon2 } from "poseidon-lite" import { LeanIMT, LeanIMTTest } from "../typechain-types" -/* eslint-disable jest/valid-expect */ describe("LeanIMT", () => { let leanIMTTest: LeanIMTTest let leanIMT: LeanIMT diff --git a/packages/imt.sol/test/QuinaryIMT.ts b/packages/imt.sol/test/QuinaryIMT.ts index 8fc085972..c6c7c874f 100644 --- a/packages/imt.sol/test/QuinaryIMT.ts +++ b/packages/imt.sol/test/QuinaryIMT.ts @@ -4,7 +4,6 @@ import { run } from "hardhat" import { poseidon5 } from "poseidon-lite" import { QuinaryIMT, QuinaryIMTTest } from "../typechain-types" -/* eslint-disable jest/valid-expect */ describe("QuinaryIMT", () => { let quinaryIMTTest: QuinaryIMTTest let quinaryIMT: QuinaryIMT diff --git a/packages/lazytower.sol/test/LazyTowerHashChainTest.ts b/packages/lazytower.sol/test/LazyTowerHashChainTest.ts index bb774b40f..6c1b8b126 100644 --- a/packages/lazytower.sol/test/LazyTowerHashChainTest.ts +++ b/packages/lazytower.sol/test/LazyTowerHashChainTest.ts @@ -4,7 +4,6 @@ import { ethers, run } from "hardhat" import { poseidon } from "circomlibjs" import ShiftTower from "./utils" -/* eslint-disable jest/valid-expect */ describe("LazyTowerHashChainTest", () => { let contract: Contract From 71501e6c8eeb0f4b6bc56ec9ad564d105b6bb9c5 Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 12:26:47 +0000 Subject: [PATCH 07/17] chore: update test npm scripts --- .github/workflows/production.yml | 7 ++++--- .github/workflows/pull-requests.yml | 2 +- README.md | 5 +++-- jest.config.ts | 3 +++ package.json | 7 ++++--- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index b91de5ee0..70f7ba18f 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -51,8 +51,9 @@ jobs: strategy: matrix: type: - - js - - sol + - circuits + - contracts + - libraries steps: - name: Checkout @@ -86,7 +87,7 @@ jobs: - name: Install dependencies run: yarn - - name: Test contracts or libraries + - name: Test libraries, contracts and circuits run: yarn test:${{ matrix.type }} - name: Coveralls diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index 2c5127ef6..08df69724 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -79,5 +79,5 @@ jobs: - name: Install dependencies run: yarn - - name: Test contracts and libraries + - name: Test libraries, contracts and circuits run: yarn test diff --git a/README.md b/README.md index 9eaedde15..1a16c4ea9 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,8 @@ ♚ [Yarn workspaces](https://yarnpkg.com/features/workspaces): minimal monorepo package management (`yarn`, `yarn build`, `yarn docs`)\ ♛ [Conventional Commits](https://www.conventionalcommits.org): human and machine readable meaning to commit messages (`yarn commit`)\ -♜ [Jest](https://jestjs.io/): tests and test coverage for all packages (`yarn test`, `yarn test:all`)\ +♜ [Jest](https://jestjs.io/): tests and test coverage for all libraries (`yarn test:libraries`)\ +♜ [Mocha](https://mochajs.org/): tests for circuits and contracts (`yarn test:circuits`, `yarn test:contracts`)\ ♞ [ESLint](https://eslint.org/), [Prettier](https://prettier.io/): code quality and formatting (`yarn prettier` & `yarn lint`)\ ♝ [Typedocs](https://typedoc.org/): documentation generator for TypeScript (`yarn docs`)\ ♟ [Benny](https://github.com/caderek/benny): simple benchmarking framework for JavaScript/TypeScript (`yarn benchmarks`)\ @@ -277,7 +278,7 @@ It will also automatically check that the modified files comply with ESLint and ### Testing -Test the code with coverage: +Test the code: ```bash yarn test diff --git a/jest.config.ts b/jest.config.ts index 0fcf75517..9a5df9f0c 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,9 +1,12 @@ import fs from "fs" import type { Config } from "@jest/types" +const exclude = ["circuits", "imt.sol", "rollup-plugin-rust", "lazytower.sol", "lazytower.circom"] + const projects: any = fs .readdirSync("./packages", { withFileTypes: true }) .filter((directory) => directory.isDirectory()) + .filter((directory) => !exclude.includes(directory.name)) .map(({ name }) => ({ rootDir: `packages/${name}`, displayName: name, diff --git a/package.json b/package.json index 76bb21a6f..9cbf72359 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ "build": "yarn build:js && yarn compile:sol", "build:js": "yarn workspaces foreach --no-private run build", "compile:sol": "yarn workspaces foreach run compile", - "test": "yarn test:js && yarn test:sol", - "test:js": "jest --coverage", - "test:sol": "yarn workspace imt.sol test:coverage", + "test": "yarn test:libraries && yarn test:contracts && test:circuits", + "test:libraries": "jest --coverage", + "test:circuits": "yarn workspace @zk-kit/circuits test", + "test:contracts": "yarn workspace imt.sol test:coverage", "lint": "eslint . --ext .js,.ts && yarn workspace imt.sol lint", "prettier": "prettier -c .", "prettier:write": "prettier -w .", From ab1135fb5f88deaab7ae971235d034ab629fde0e Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 12:26:53 +0000 Subject: [PATCH 08/17] chore: update yarn lockfile --- yarn.lock | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/yarn.lock b/yarn.lock index 31977182a..c7c524fac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4047,7 +4047,7 @@ __metadata: languageName: node linkType: hard -"@types/mocha@npm:>=9.1.0": +"@types/mocha@npm:>=9.1.0, @types/mocha@npm:^10.0.6": version: 10.0.6 resolution: "@types/mocha@npm:10.0.6" checksum: f7c836cf6cf27dc0f5970d262591b56f2a3caeaec8cfdc612c12e1cfbb207f601f710ece207e935164d4e3343b93be5054d0db5544f31f453b3923775d82099f @@ -4266,17 +4266,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/experimental-utils@npm:^5.0.0": - version: 5.62.0 - resolution: "@typescript-eslint/experimental-utils@npm:5.62.0" - dependencies: - "@typescript-eslint/utils": 5.62.0 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: ce55d9f74eac5cb94d66d5db9ead9a5d734f4301519fb5956a57f4b405a5318a115b0316195a3c039e0111489138680411709cb769085d71e1e1db1376ea0949 - languageName: node - linkType: hard - "@typescript-eslint/parser@npm:^5.9.1": version: 5.62.0 resolution: "@typescript-eslint/parser@npm:5.62.0" @@ -4403,8 +4392,12 @@ __metadata: version: 0.0.0-use.local resolution: "@zk-kit/circuits@workspace:packages/circuits" dependencies: + "@types/mocha": ^10.0.6 + "@zk-kit/smt": "workspace:^" circomkit: ^0.0.18 circomlib: ^2.0.5 + mocha: ^10.2.0 + poseidon-lite: ^0.2.0 languageName: unknown linkType: soft @@ -4495,7 +4488,7 @@ __metadata: languageName: unknown linkType: soft -"@zk-kit/smt@workspace:packages/smt": +"@zk-kit/smt@workspace:^, @zk-kit/smt@workspace:packages/smt": version: 0.0.0-use.local resolution: "@zk-kit/smt@workspace:packages/smt" dependencies: @@ -8211,23 +8204,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jest@npm:^25.7.0": - version: 25.7.0 - resolution: "eslint-plugin-jest@npm:25.7.0" - dependencies: - "@typescript-eslint/experimental-utils": ^5.0.0 - peerDependencies: - "@typescript-eslint/eslint-plugin": ^4.0.0 || ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - "@typescript-eslint/eslint-plugin": - optional: true - jest: - optional: true - checksum: fc6da96131f4cbf33d15ef911ec8e600ccd71deb97d73c0ca340427cef7b01ff41a797e2e7d1e351abf97321a46ed0c0acff5ee8eeedac94961dd6dad1f718a9 - languageName: node - linkType: hard - "eslint-scope@npm:^5.1.1": version: 5.1.1 resolution: "eslint-scope@npm:5.1.1" @@ -19638,7 +19614,6 @@ __metadata: eslint-config-airbnb-typescript: ^16.1.0 eslint-config-prettier: ^8.3.0 eslint-plugin-import: ^2.25.2 - eslint-plugin-jest: ^25.7.0 husky: ^8.0.3 jest: ^27.4.1 jest-config: ^27.4.7 From 9296c69f9de92744bb08107b9404ba8dddbdf7b9 Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 12:27:08 +0000 Subject: [PATCH 09/17] test(circuits): add circuit tests with mocha --- packages/circuits/.gitignore | 5 +- packages/circuits/.mocharc.json | 7 +++ .../circuits/circom/poseidon-proof.circom | 12 ++-- packages/circuits/package.json | 9 ++- .../circuits/tests/binary-merkle-root.test.ts | 58 +++++++++++++++++++ packages/circuits/tests/common.ts | 12 ++++ .../circuits/tests/poseidon-proof.test.ts | 33 +++++++++++ 7 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 packages/circuits/.mocharc.json create mode 100644 packages/circuits/tests/binary-merkle-root.test.ts create mode 100644 packages/circuits/tests/common.ts create mode 100644 packages/circuits/tests/poseidon-proof.test.ts diff --git a/packages/circuits/.gitignore b/packages/circuits/.gitignore index 928abb6f2..3527e0da8 100644 --- a/packages/circuits/.gitignore +++ b/packages/circuits/.gitignore @@ -1,4 +1,3 @@ ptau -main -*.r1cs -*.wasm +circom/main +circom/test diff --git a/packages/circuits/.mocharc.json b/packages/circuits/.mocharc.json new file mode 100644 index 000000000..2c4219f8f --- /dev/null +++ b/packages/circuits/.mocharc.json @@ -0,0 +1,7 @@ +{ + "extension": ["ts"], + "require": "ts-node/register", + "spec": "./**/*.test.ts", + "timeout": 100000, + "exit": true +} diff --git a/packages/circuits/circom/poseidon-proof.circom b/packages/circuits/circom/poseidon-proof.circom index 286d364cc..65f7c003b 100644 --- a/packages/circuits/circom/poseidon-proof.circom +++ b/packages/circuits/circom/poseidon-proof.circom @@ -9,16 +9,16 @@ include "poseidon.circom"; // A scope value can be used to define a nullifier to prevent the same // proof from being re-used twice. template PoseidonProof() { - // The circuit takes two inputs: the pre-image (in) and an additional scope parameter (scope). - signal input in; + // The circuit takes two inputs: the pre-image and an additional scope parameter. + signal input preimage; signal input scope; - // It applies the Poseidon hash function to the pre-image to produce a hash output (out). - signal output out; - out <== Poseidon(1)([in]); + // It applies the Poseidon hash function to the pre-image to produce a hash digest. + signal output digest; + digest <== Poseidon(1)([preimage]); // A nullifier is also computed using both the pre-image and the scope, providing a value // to prevent the same proof from being reused twice. signal output nullifier; - nullifier <== Poseidon(2)([scope, in]); + nullifier <== Poseidon(2)([scope, preimage]); } diff --git a/packages/circuits/package.json b/packages/circuits/package.json index 07fcbaab5..b5e2f530e 100644 --- a/packages/circuits/package.json +++ b/packages/circuits/package.json @@ -13,13 +13,18 @@ "homepage": "https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/circuits.sol", "scripts": { "circom:compile": "circomkit compile", - "circom:setup": "circomkit setup" + "circom:setup": "circomkit setup", + "test": "mocha" }, "dependencies": { "circomlib": "^2.0.5" }, "devDependencies": { - "circomkit": "^0.0.18" + "@types/mocha": "^10.0.6", + "@zk-kit/smt": "workspace:^", + "circomkit": "^0.0.18", + "mocha": "^10.2.0", + "poseidon-lite": "^0.2.0" }, "publishConfig": { "access": "public" diff --git a/packages/circuits/tests/binary-merkle-root.test.ts b/packages/circuits/tests/binary-merkle-root.test.ts new file mode 100644 index 000000000..8515c2f33 --- /dev/null +++ b/packages/circuits/tests/binary-merkle-root.test.ts @@ -0,0 +1,58 @@ +import { LeanIMT } from "@zk-kit/imt" +import { WitnessTester } from "circomkit" +import { poseidon2 } from "poseidon-lite" +import { circomkit } from "./common" + +describe("binary-merkle-root", () => { + let circuit: WitnessTester<["leaf", "depth", "indices", "siblings"], ["out"]> + + const MAX_DEPTH = 20 + + const tree = new LeanIMT((a, b) => poseidon2([a, b])) + const leaf = BigInt(0) + + tree.insert(leaf) + + for (let i = 1; i < 8; i += 1) { + tree.insert(BigInt(i)) + } + + const { siblings, index } = tree.generateProof(0) + + // The index must be converted to a list of indices, 1 for each tree level. + // The circuit tree depth is 20, so the number of siblings must be 20, even if + // the tree depth is actually 3. The missing siblings can be set to 0, as they + // won't be used to calculate the root in the circuit. + const indices = [] + + for (let i = 0; i < MAX_DEPTH; i += 1) { + indices.push((index >> i) & 1) + + if (siblings[i] === undefined) { + siblings[i] = BigInt(0) + } + } + + const INPUT = { + leaf, + depth: tree.depth, + indices, + siblings + } + + const OUTPUT = { + out: tree.root + } + + before(async () => { + circuit = await circomkit.WitnessTester("binary-merkle-root", { + file: "binary-merkle-root", + template: "BinaryMerkleRoot", + params: [MAX_DEPTH] + }) + }) + + it("Should calculate the root correctly", async () => { + await circuit.expectPass(INPUT, OUTPUT) + }) +}) diff --git a/packages/circuits/tests/common.ts b/packages/circuits/tests/common.ts new file mode 100644 index 000000000..20f153fce --- /dev/null +++ b/packages/circuits/tests/common.ts @@ -0,0 +1,12 @@ +import { Circomkit } from "circomkit" +import { readFileSync } from "fs" +import path from "path" + +const configFilePath = path.join(__dirname, "../circomkit.json") +const config = JSON.parse(readFileSync(configFilePath, "utf-8")) + +// eslint-disable-next-line import/prefer-default-export +export const circomkit = new Circomkit({ + ...config, + verbose: false +}) diff --git a/packages/circuits/tests/poseidon-proof.test.ts b/packages/circuits/tests/poseidon-proof.test.ts new file mode 100644 index 000000000..1662e87c4 --- /dev/null +++ b/packages/circuits/tests/poseidon-proof.test.ts @@ -0,0 +1,33 @@ +import { WitnessTester } from "circomkit" +import { poseidon1, poseidon2 } from "poseidon-lite" +import { circomkit } from "./common" + +describe("poseidon-proof", () => { + let circuit: WitnessTester<["preimage", "scope"], ["digest", "nullifier"]> + + const preimage = 3 + const scope = 2 + const digest = poseidon1([preimage]) + const nullifier = poseidon2([scope, preimage]) + + const INPUT = { + preimage, + scope + } + + const OUTPUT = { + digest, + nullifier + } + + before(async () => { + circuit = await circomkit.WitnessTester("poseidon-proof", { + file: "poseidon-proof", + template: "PoseidonProof" + }) + }) + + it("Should compute hash correctly", async () => { + await circuit.expectPass(INPUT, OUTPUT) + }) +}) From cff44f0221ef434fbe4e96b4c10a4ef9ce30d6cb Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 12:37:51 +0000 Subject: [PATCH 10/17] style: format code with prettier --- packages/circuits/.mocharc.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/circuits/.mocharc.json b/packages/circuits/.mocharc.json index 2c4219f8f..ba10deedd 100644 --- a/packages/circuits/.mocharc.json +++ b/packages/circuits/.mocharc.json @@ -1,7 +1,7 @@ { - "extension": ["ts"], - "require": "ts-node/register", - "spec": "./**/*.test.ts", - "timeout": 100000, - "exit": true + "extension": ["ts"], + "require": "ts-node/register", + "spec": "./**/*.test.ts", + "timeout": 100000, + "exit": true } From 74b2c35b4f44f1062b5d660a7c860cca0efe47fd Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 12:41:25 +0000 Subject: [PATCH 11/17] chore(lazytower.circom): remove eslint comment --- packages/lazytower.circom/tests/index.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/lazytower.circom/tests/index.test.ts b/packages/lazytower.circom/tests/index.test.ts index 269a524f0..9d5eb53c9 100644 --- a/packages/lazytower.circom/tests/index.test.ts +++ b/packages/lazytower.circom/tests/index.test.ts @@ -3,8 +3,6 @@ import { poseidon2 } from "poseidon-lite" import { LazyTowerHashChainProofBuilder } from "../../lazytower/src" import { getTester, getUtils } from "./utils" -/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "ok", "fail"] }] */ - async function utils(templateName: string, args: number[]) { const srcPath = path.join(__dirname, "..", "circuits", "lazytower-hash-chain.circom") const libPath = path.join(__dirname, "..", "..", "..", "node_modules") // for circomlib From 07b9b233207cd6cae6fdbb4d8c6dc8ecc65d728f Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 13:34:41 +0000 Subject: [PATCH 12/17] docs(circuits): document binary merkle root circuit --- packages/circuits/circom/binary-merkle-root.circom | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/circuits/circom/binary-merkle-root.circom b/packages/circuits/circom/binary-merkle-root.circom index 238de32f6..204d82dc3 100644 --- a/packages/circuits/circom/binary-merkle-root.circom +++ b/packages/circuits/circom/binary-merkle-root.circom @@ -4,6 +4,15 @@ include "poseidon.circom"; include "mux1.circom"; include "comparators.circom"; +// This circuit is designed to calculate the root of a binary Merkle +// tree given a leaf, its depth, and the necessary sibling +// information (aka proof of membership). +// A circuit is designed without the capability to iterate through +// a dynamic array. To address this, a parameter with the static maximum +// tree depth is defined (i.e. 'MAX_DEPTH'). And additionally, the circuit +// receives a dynamic depth as an input, which is utilized in calculating the +// true root of the Merkle tree. The actual depth of the Merkle tree +// may be equal to or less than the static maximum depth. template BinaryMerkleRoot(MAX_DEPTH) { signal input leaf, depth, indices[MAX_DEPTH], siblings[MAX_DEPTH]; From df6083f62f483689fc94c6439970dd03ed05fe1a Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 13:36:23 +0000 Subject: [PATCH 13/17] chore: set correct command to run circuit tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9cbf72359..cb99fb709 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "yarn build:js && yarn compile:sol", "build:js": "yarn workspaces foreach --no-private run build", "compile:sol": "yarn workspaces foreach run compile", - "test": "yarn test:libraries && yarn test:contracts && test:circuits", + "test": "yarn test:libraries && yarn test:contracts && yarn test:circuits", "test:libraries": "jest --coverage", "test:circuits": "yarn workspace @zk-kit/circuits test", "test:contracts": "yarn workspace imt.sol test:coverage", From 9bf4443ef648763b330108640388fdc3222f5312 Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 13:53:29 +0000 Subject: [PATCH 14/17] fix(circuits): patch correct line of code in circomkit --- .../circomkit-npm-0.0.18-e33b63f27f.patch | 77 ++----------------- 1 file changed, 7 insertions(+), 70 deletions(-) diff --git a/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch b/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch index 22086de6f..5424bd559 100644 --- a/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch +++ b/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch @@ -1,76 +1,13 @@ diff --git a/dist/utils/instantiate.js b/dist/utils/instantiate.js -index 33cdff152e8b23d6853eb475097bda8c02712e01..418f57072c9c0ebf3778c8a9a50d379728128e5f 100644 +index 33cdff152e8b23d6853eb475097bda8c02712e01..0fa0568671878c68101fc95a4c9b096b0dbd8e2b 100644 --- a/dist/utils/instantiate.js +++ b/dist/utils/instantiate.js -@@ -1,15 +1,17 @@ --"use strict"; --Object.defineProperty(exports, "__esModule", { value: true }); --exports.instantiate = void 0; --const fs_1 = require("fs"); -+"use strict" -+Object.defineProperty(exports, "__esModule", { value: true }) -+exports.instantiate = void 0 -+const fs_1 = require("fs") - /** Circuit builder, kinda like `ejs.render`. **Be very careful when editing this file.** */ - const makeCircuit = (config) => `// auto-generated by circomkit - pragma circom ${config.version}; - - include "../${config.file}.circom"; - --component main${config.pubs.length === 0 ? '' : ' {public[' + config.pubs.join(', ') + ']}'} = ${config.template}(${config.params.join(', ')}); --`; -+component main${config.pubs.length === 0 ? "" : " {public[" + config.pubs.join(", ") + "]}"} = ${ -+ config.template -+}(${config.params.join(", ")}); -+` - /** - * Programmatically generate the `main` component of a circuit - * @param name name of the circuit to be generated -@@ -18,31 +20,32 @@ component main${config.pubs.length === 0 ? '' : ' {public[' + config.pubs.join(' - */ - function instantiate(name, circuitConfig) { - // directory to output the file -- const directory = circuitConfig.dir || 'test'; -+ const directory = circuitConfig.dir || "test" - // add "../" to the filename in include, one for each "/" in directory name - // if none, the prefix becomes empty string -- const filePrefixMatches = directory.match(/\//g); -- let file = circuitConfig.file; -+ const filePrefixMatches = directory.match(/\//g) -+ let file = circuitConfig.file - if (filePrefixMatches !== null) { -- file = '../'.repeat(filePrefixMatches.length) + file; -+ file = "../".repeat(filePrefixMatches.length) + file - } - const circuitCode = makeCircuit({ - file: file, - template: circuitConfig.template, -- version: circuitConfig.version || '2.0.0', -+ version: circuitConfig.version || "2.0.0", - dir: directory, +@@ -34,7 +34,7 @@ function instantiate(name, circuitConfig) { pubs: circuitConfig.pubs || [], -- params: circuitConfig.params || [], -- }); + params: circuitConfig.params || [], + }); - const targetDir = `./circuits/${directory}`; -+ params: circuitConfig.params || [] -+ }) -+ const targetDir = `./circom/${directory}` ++ const targetDir = `./circom/${directory}`; if (!(0, fs_1.existsSync)(targetDir)) { -- (0, fs_1.mkdirSync)(targetDir, { -- recursive: true, -- }); -+ ;(0, fs_1.mkdirSync)(targetDir, { -+ recursive: true -+ }) - } -- const targetPath = `${targetDir}/${name}.circom`; -- (0, fs_1.writeFileSync)(targetPath, circuitCode); -- return targetPath; -+ const targetPath = `${targetDir}/${name}.circom` -+ ;(0, fs_1.writeFileSync)(targetPath, circuitCode) -+ return targetPath - } --exports.instantiate = instantiate; -+exports.instantiate = instantiate - //# sourceMappingURL=instantiate.js.map -+ + (0, fs_1.mkdirSync)(targetDir, { + recursive: true, From 656c2b1c5f270336921ad039d15d0f2334d9e185 Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 14:10:01 +0000 Subject: [PATCH 15/17] chore(circuits): set specific dependency version --- packages/circuits/package.json | 2 +- yarn.lock | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/circuits/package.json b/packages/circuits/package.json index b5e2f530e..bd607fd15 100644 --- a/packages/circuits/package.json +++ b/packages/circuits/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@types/mocha": "^10.0.6", "@zk-kit/smt": "workspace:^", - "circomkit": "^0.0.18", + "circomkit": "0.0.18", "mocha": "^10.2.0", "poseidon-lite": "^0.2.0" }, diff --git a/yarn.lock b/yarn.lock index c7c524fac..667afb38d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4394,7 +4394,7 @@ __metadata: dependencies: "@types/mocha": ^10.0.6 "@zk-kit/smt": "workspace:^" - circomkit: ^0.0.18 + circomkit: 0.0.18 circomlib: ^2.0.5 mocha: ^10.2.0 poseidon-lite: ^0.2.0 @@ -6403,7 +6403,7 @@ __metadata: languageName: node linkType: hard -"circomkit@npm:^0.0.18": +"circomkit@npm:0.0.18": version: 0.0.18 resolution: "circomkit@npm:0.0.18" dependencies: @@ -6417,6 +6417,20 @@ __metadata: languageName: node linkType: hard +"circomkit@patch:circomkit@npm:0.0.18#.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch::locator=zk-kit%40workspace%3A.": + version: 0.0.18 + resolution: "circomkit@patch:circomkit@npm%3A0.0.18#.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch::version=0.0.18&hash=723f17&locator=zk-kit%40workspace%3A." + dependencies: + chai: ^4.3.7 + circom_tester: ^0.0.19 + loglevel: ^1.8.1 + snarkjs: ^0.7.0 + bin: + circomkit: dist/bin/index.js + checksum: 2c09e6463d1376230cd3693a6bf632511d54566d46f030323f6f778bae5cb8dbbe6f845f0c1fd30ab0ef243b70604b357e875c9349328751b4795b6fd04484b9 + languageName: node + linkType: hard + "circomlib@npm:0.5.1": version: 0.5.1 resolution: "circomlib@npm:0.5.1" From 11103b94e17bb9c9e336a79ce6bc27fa2387436f Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 15:34:32 +0000 Subject: [PATCH 16/17] chore(circuits): update circomkit and remove patch --- .../circomkit-npm-0.0.18-e33b63f27f.patch | 13 ---------- package.json | 3 --- packages/circuits/package.json | 2 +- yarn.lock | 24 ++++--------------- 4 files changed, 6 insertions(+), 36 deletions(-) delete mode 100644 .yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch diff --git a/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch b/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch deleted file mode 100644 index 5424bd559..000000000 --- a/.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/dist/utils/instantiate.js b/dist/utils/instantiate.js -index 33cdff152e8b23d6853eb475097bda8c02712e01..0fa0568671878c68101fc95a4c9b096b0dbd8e2b 100644 ---- a/dist/utils/instantiate.js -+++ b/dist/utils/instantiate.js -@@ -34,7 +34,7 @@ function instantiate(name, circuitConfig) { - pubs: circuitConfig.pubs || [], - params: circuitConfig.params || [], - }); -- const targetDir = `./circuits/${directory}`; -+ const targetDir = `./circom/${directory}`; - if (!(0, fs_1.existsSync)(targetDir)) { - (0, fs_1.mkdirSync)(targetDir, { - recursive: true, diff --git a/package.json b/package.json index cb99fb709..5c7f00fad 100644 --- a/package.json +++ b/package.json @@ -75,8 +75,5 @@ "commitizen": { "path": "./node_modules/cz-conventional-changelog" } - }, - "resolutions": { - "circomkit@0.0.18": "patch:circomkit@npm:0.0.18#.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch" } } diff --git a/packages/circuits/package.json b/packages/circuits/package.json index bd607fd15..effc74938 100644 --- a/packages/circuits/package.json +++ b/packages/circuits/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@types/mocha": "^10.0.6", "@zk-kit/smt": "workspace:^", - "circomkit": "0.0.18", + "circomkit": "0.0.19", "mocha": "^10.2.0", "poseidon-lite": "^0.2.0" }, diff --git a/yarn.lock b/yarn.lock index 667afb38d..614d0c04c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4394,7 +4394,7 @@ __metadata: dependencies: "@types/mocha": ^10.0.6 "@zk-kit/smt": "workspace:^" - circomkit: 0.0.18 + circomkit: 0.0.19 circomlib: ^2.0.5 mocha: ^10.2.0 poseidon-lite: ^0.2.0 @@ -6403,23 +6403,9 @@ __metadata: languageName: node linkType: hard -"circomkit@npm:0.0.18": - version: 0.0.18 - resolution: "circomkit@npm:0.0.18" - dependencies: - chai: ^4.3.7 - circom_tester: ^0.0.19 - loglevel: ^1.8.1 - snarkjs: ^0.7.0 - bin: - circomkit: dist/bin/index.js - checksum: 4120fdf8523f8d595a85e673bb74b8d683a302a401bf049ecb1a0ff4ad178e8f77ed7d12a50856c1be5f56bb8666f861a240d432f2ada78faa13dec161780cf1 - languageName: node - linkType: hard - -"circomkit@patch:circomkit@npm:0.0.18#.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch::locator=zk-kit%40workspace%3A.": - version: 0.0.18 - resolution: "circomkit@patch:circomkit@npm%3A0.0.18#.yarn/patches/circomkit-npm-0.0.18-e33b63f27f.patch::version=0.0.18&hash=723f17&locator=zk-kit%40workspace%3A." +"circomkit@npm:0.0.19": + version: 0.0.19 + resolution: "circomkit@npm:0.0.19" dependencies: chai: ^4.3.7 circom_tester: ^0.0.19 @@ -6427,7 +6413,7 @@ __metadata: snarkjs: ^0.7.0 bin: circomkit: dist/bin/index.js - checksum: 2c09e6463d1376230cd3693a6bf632511d54566d46f030323f6f778bae5cb8dbbe6f845f0c1fd30ab0ef243b70604b357e875c9349328751b4795b6fd04484b9 + checksum: b3d7ef5b29277ee31af7fcb7a53af46c43321d16ab238b803e2fb65a88143a8aae02eebc7c8387e6d0158450ca8bee053adb40e34331392b5fa0f1d2dabc6b40 languageName: node linkType: hard From b90767e40dbe0cebcdf0269b2bb0fcb51d1a38bb Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 29 Nov 2023 15:49:18 +0000 Subject: [PATCH 17/17] chore(circuits): update binary merkle root parameter --- packages/circuits/circom/circuits.json | 2 +- packages/circuits/tests/binary-merkle-root.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/circuits/circom/circuits.json b/packages/circuits/circom/circuits.json index 5f6fa74fb..6a94add26 100644 --- a/packages/circuits/circom/circuits.json +++ b/packages/circuits/circom/circuits.json @@ -6,6 +6,6 @@ "binary-merkle-root": { "file": "binary-merkle-root", "template": "BinaryMerkleRoot", - "params": [20] + "params": [4] } } diff --git a/packages/circuits/tests/binary-merkle-root.test.ts b/packages/circuits/tests/binary-merkle-root.test.ts index 8515c2f33..700717f1a 100644 --- a/packages/circuits/tests/binary-merkle-root.test.ts +++ b/packages/circuits/tests/binary-merkle-root.test.ts @@ -23,7 +23,7 @@ describe("binary-merkle-root", () => { // The circuit tree depth is 20, so the number of siblings must be 20, even if // the tree depth is actually 3. The missing siblings can be set to 0, as they // won't be used to calculate the root in the circuit. - const indices = [] + const indices: number[] = [] for (let i = 0; i < MAX_DEPTH; i += 1) { indices.push((index >> i) & 1)