Closed BlakeMScurr closed 1 year ago
Amazing stuff, I'll try it out!
+1 to using SHA256 instead of SHA512. @Divide-By-0, did we chat about this some time ago?
Amazing stuff, I'll try it out!
+1 to using SHA256 instead of SHA512. @Divide-By-0, did we chat about this some time ago?
We probably did, I don't remember. sha256 sounds good, happy to switch over the standard and existing code! I assume the main reason would be for efficiency and having a pre-existing circuit?
SHA256 would drop the security to 128 bits for the hash, but since BTC/ETH keys only have 128 bits of security anyways, that seems fine to me.
I assume the main reason would be for efficiency and having a pre-existing circuit?
Yup! I'm thinking the same!
Suggestion to modify the readme to add test instructions; feel free to edit as you see fit
diff --git a/README.md b/README.md
index 7d620fe..df3dc0c 100644
--- a/README.md
+++ b/README.md
@@ -8,10 +8,26 @@ This allows for the construction of deterministic nullifiers. We intend to deplo
- `rust-arkworks`: Rust, using arkworks
- `javascript`: JavaScript, using MIRACL
+## Testing the circom circuit
+
+First, clone this repository and navigate to the `circuits/` directory.
+
+Install dependencies:
+
+```bash
+npm i
+```
+
+Run the tests:
+```bash
+npm run npm run flatten-deps && \
+npm run test
+```
+
+Be prepared to wait around 20-40 minutes for the tests to complete.
+
## TODO
-- zk verifier circuits (WIP Circom here: https://github.com/geometryresearch/secp256k1_hash_to_curve/tree/main/circuits)
-- change SHA512 to Poseidon (wallets are onboard)
- improve `rust-k256` to use a similar interface as `rust-arkworks` - i.e.
generate/accept arbitrary keypairs and `r` values, and not just hardcoded
values
Attempted to run npm i
, but ran into this error:
$ npm i
npm WARN skipping integrity check for git dependency ssh://git@github.com/weijiekoh/circomlib.git
npm WARN deprecated crypto@1.0.1: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.
npm WARN tarball tarball data for secp256k1_hash_to_curve_circom@https://gitpkg.now.sh/geometryresearch/secp256k1_hash_to_curve/circuits?main (sha512-kTtN+pSxEITN3Co28HORjrlGSs1pmLRNrwBPGXyMY1fCUIxBMc7TtW3zkrDxd7cSKb1i70tLHD8eAPSHmZ6RRQ==) seems to be corrupted. Trying again.
npm WARN tarball tarball data for secp256k1_hash_to_curve_circom@https://gitpkg.now.sh/geometryresearch/secp256k1_hash_to_curve/circuits?main (sha512-kTtN+pSxEITN3Co28HORjrlGSs1pmLRNrwBPGXyMY1fCUIxBMc7TtW3zkrDxd7cSKb1i70tLHD8eAPSHmZ6RRQ==) seems to be corrupted. Trying again.
npm ERR! code EINTEGRITY
npm ERR! sha512-kTtN+pSxEITN3Co28HORjrlGSs1pmLRNrwBPGXyMY1fCUIxBMc7TtW3zkrDxd7cSKb1i70tLHD8eAPSHmZ6RRQ== integrity checksum failed when using sha512: wanted sha512-kTtN+pSxEITN3Co28HORjrlGSs1pmLRNrwBPGXyMY1fCUIxBMc7TtW3zkrDxd7cSKb1i70tLHD8eAPSHmZ6RRQ== but got sha512-KDaov5Lz44OeGcuLHhElC8+Lbup6x43LIFRd7em1lJPqO5Vw5IOFBOK8QVKSsGJTxvqFfSzXHHbpu/X/umRpIQ==. (143888 bytes)
It seems that npm i
failed so Jest was not installed:
$ npm run test
> zk-nullifier-sig-circuit@1.0.0 test
> NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand
sh: 1: jest: not found
@weijiekoh thanks for the feedback! I couldn't recreate your issue exactly, but I think the issue was that I manually edited the hash to curve dependency while I was waiting for my PR to be merged. Since it's merged I reinstalled the dependency, so I don't see why the integrity check should fail now. Are you able to install now?
Also, I kept the TODO item "change SHA256 to Poseidon (wallets are onboard)" since that would probably still be a significant improvement, even if we use SHA256 as opposed to SHA512.
Got this error when running npm run test
:
$ npm run test
> zk-nullifier-sig-circuit@1.0.0 test
> NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand
FAIL test/vfy_nullifier.test.ts
● Test suite failed to run
test/vfy_nullifier.test.ts:23:103 - error TS2769: No overload matches this call.
Overload 1 of 2, '(...items: ConcatArray<number>[]): number[]', gave the following error.
Argument of type 'unknown[]' is not assignable to parameter of type 'ConcatArray<number>'.
The types returned by 'slice(...)' are incompatible between these types.
Type 'unknown[]' is not assignable to type 'number[]'.
Type 'unknown' is not assignable to type 'number'.
Overload 2 of 2, '(...items: (number | ConcatArray<number>)[]): number[]', gave the following error.
Argument of type 'unknown[]' is not assignable to parameter of type 'number | ConcatArray<number>'.
Type 'unknown[]' is not assignable to type 'ConcatArray<number>'.
23 const hash_to_curve_inputs = utils.stringifyBigInts(generate_inputs_from_array(message_bytes.concat(public_key_bytes)));
~~~~~~~~~~~~~~~~
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 1.926 s
Ran all test suites.
@weijiekoh strange, I don't get that error. Also, my IDE is able to infer that public_key_bytes
is a number[]
. Perhaps we are running with a different version/configuration of typescript that is somehow specified outside the repo. Could you please check your typescript version using tsc -v
? Mine is Version 4.0.2
.
For a sanity check, does that error go away if you declare the type of public_key_bytes
? I.e., change line 16 to const public_key_bytes: number[] = Array.from(testPublicKey);
I don't have tsc installed globally, but it is installed locally:
$ npx tsc --version
Version 4.9.5
The error does go away after I edit line 16 but there are more build errors:
$ npx tsc
../javascript/src/index.ts:1:23 - error TS2307: Cannot find module '@noble/secp256k1' or its corresponding type declarations.
1 import { Point } from "@noble/secp256k1";
~~~~~~~~~~~~~~~~~~
../javascript/src/utils/curve.ts:1:23 - error TS2307: Cannot find module '@noble/secp256k1' or its corresponding type declarations.
1 import { Point } from "@noble/secp256k1";
~~~~~~~~~~~~~~~~~~
../javascript/src/utils/hashToCurve.ts:1:21 - error TS2307: Cannot find module 'amcl-js' or its corresponding type declarations.
1 import { CTX } from "amcl-js";
~~~~~~~~~
../javascript/test/test_consts.ts:1:44 - error TS2307: Cannot find module '@noble/secp256k1' or its corresponding type declarations.
1 import { CURVE, getPublicKey, Point } from "@noble/secp256k1";
~~~~~~~~~~~~~~~~~~
Found 4 errors in 4 files.
Errors Files
1 ../javascript/src/index.ts:1
1 ../javascript/src/utils/curve.ts:1
1 ../javascript/src/utils/hashToCurve.ts:1
1 ../javascript/test/test_consts.ts:1
There's also another error:
$ npm run test
> zk-nullifier-sig-circuit@1.0.0 test
> NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand
FAIL dist/circuits/test/vfy_nullifier.test.js
● Test suite failed to run
Cannot find module 'amcl-js' from 'dist/javascript/src/utils/hashToCurve.js'
Require stack:
dist/javascript/src/utils/hashToCurve.js
dist/javascript/src/index.js
dist/javascript/test/test_consts.js
dist/circuits/test/vfy_nullifier.test.js
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
> 3 | const amcl_js_1 = require("amcl-js");
| ^
4 | const encoding_1 = require("./encoding");
5 | // Refactored from miracl-core
6 | const ctx = new amcl_js_1.CTX("SECP256K1");
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:427:11)
at Object.<anonymous> (dist/javascript/src/utils/hashToCurve.js:3:19)
at Object.<anonymous> (dist/javascript/src/index.js:9:39)
at Object.<anonymous> (dist/javascript/test/test_consts.js:5:15)
at Object.<anonymous> (dist/circuits/test/vfy_nullifier.test.js:7:23)
FAIL test/vfy_nullifier.test.ts
● Test suite failed to run
../javascript/test/test_consts.ts:1:44 - error TS2307: Cannot find module '@noble/secp256k1' or its corresponding type declarations.
1 import { CURVE, getPublicKey, Point } from "@noble/secp256k1";
~~~~~~~~~~~~~~~~~~
Test Suites: 2 failed, 2 total
Tests: 0 total
Snapshots: 0 total
Time: 1.824 s
Ran all test suites.
@weijiekoh ooh OK, thank you. I just realised the problem is that you have to go to ../javascript
and run npm install
there too. I guess it's kinda janky - we have two different npm packages, since they're used for different purposes, javascript
goes in the wallet, whereas circuit
is for generating proofs in the browser. Yet the circuit tests depend on javascript. I guess I could make the javascript
package an actual dependency in package.json, but for now I'll just update the readme to require another npm install
.
By the way, you might want to run npm run test -- -t "compressed"
to make sure we've solved all the typescript issues. That test should finish in less than 10 seconds.
Still having trouble...
$ npm run flatten-deps
> zk-nullifier-sig-circuit@1.0.0 flatten-deps
> bash flatten-nested-dependencies.sh
sed: can't read s/"\.\.\/\.\.\/node_modules\/circomlib/"\.\.\/\.\.\/\.\.\/circomlib/: No such file or directory
sed: can't read s/"\.\.\/node_modules\/circomlib/"\.\.\/\.\.\/circomlib/: No such file or directory
This is followed by a lot of the same error messages from sed
.
$ npm run test
> zk-nullifier-sig-circuit@1.0.0 test
> NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand
FAIL test/vfy_nullifier.test.ts
Nullifier Circuit
✕ hash_to_curve outputs same value (46 ms)
✕ Correct sha256 value (28 ms)
✕ Correct compressed values are calculated (25 ms)
✕ Compressed points are permitted iff they are valid (25 ms)
✕ Circuit verifies valid nullifier (25 ms)
✕ a/b^c subcircuit (25 ms)
✓ bigint <-> register conversion (1 ms)
● Nullifier Circuit › hash_to_curve outputs same value
ENOENT: no such file or directory, open '/tmp/circom_-884456-AhxreDf8s0Bo/hash_to_curve_test_js/hash_to_curve_test.wasm'
● Nullifier Circuit › Correct sha256 value
ENOENT: no such file or directory, open '/tmp/circom_-884456-UribBMDkquMV/12_point_sha_256_test_js/12_point_sha_256_test.wasm'
● Nullifier Circuit › Correct compressed values are calculated
ENOENT: no such file or directory, open '/tmp/circom_-884456-0A56qadS5gzk/compression_test_js/compression_test.wasm'
● Nullifier Circuit › Compressed points are permitted iff they are valid
ENOENT: no such file or directory, open '/tmp/circom_-884456-2iLq0m0rfPeD/compression_verification_test_js/compression_verification_test.wasm'
● Nullifier Circuit › Circuit verifies valid nullifier
ENOENT: no such file or directory, open '/tmp/circom_-884456-7OVtL1TXzOts/vfy_test_js/vfy_test.wasm'
● Nullifier Circuit › a/b^c subcircuit
ENOENT: no such file or directory, open '/tmp/circom_-884456-T4Hk8zZce05A/a_div_b_pow_c_test_js/a_div_b_pow_c_test.wasm'
Test Suites: 1 failed, 1 total
Tests: 6 failed, 1 passed, 7 total
Snapshots: 0 total
Time: 2.918 s
Ran all test suites.
I'm using sed v4.8 and node v18.14.0.
I assume you're using Linux? It looks like sed
is failing because I'm using a Mac specific syntax to specify interactive mode. So the circom isn't properly edited, and doesn't compile, which causes the no such file or directory
errors (this is a common circom-tester error).
I have replaced the syntax with something that should be compatible across Mac and Linux. Let me know if it works!
@BlakeMScurr I am getting all the same errors as @weijiekoh when trying to run the test suite.
npm WARN skipping integrity check for git dependency ssh://git@github.com/weijiekoh/circomlib.git
Fixed that one by dumping and recreating package-lock.json
Consider restricting the node version between 16 and 19 (>= 16 <19
) with the engines
option in package.json
.
I had node-gyp
errors otherwise.
Maybe specify in the PR description which circom version is required? I first had 2.0.0
and had some errors when running the test.
Finally after
cd javascript && npm i
cd circuits && npm i && npm flatten-deps
npm t
ran all circuits tests successfully for me on macOS only.
On linux, I have lot of
So maybe there is still an issue with the flatten-deps
script?
Thanks @r1oga, I was able to recreate your issues on Linux and fix them. It looks like I had a capitalization typo, but it wasn't causing a problem on Mac for whatever reason. Let me know if it works for you now!
Thanks @r1oga, I was able to recreate your issues on Linux and fix them. It looks like I had a capitalization typo, but it wasn't causing a problem on Mac for whatever reason. Let me know if it works for you now!
Yep! I confirm I could run all the tests on linux successfully too.
Cool! Ready to merge once the conflict is fixed. Constraint breakdown from Blake here: 6.5 million constraints. Mostly dominated by EC operations, but the hashes are very expensive too.
sha256 ~1.5M hash_to_curve ~0.5M a/b^c ~1.5 each (this is the sub circuit for the first 2 verification equations) the remaining 1.5M is probably dominated by calculating g^s and h^s
Sweet! @Divide-By-0 merge conflicts fixed, all tests still passing.
@Divide-By-0, just resolved conflicts again, tests still working.
We should get this merged soon, since I've had to re-fix the CURVE.P
vs CURVE.n
bug each time I've resolved conflicts, which feels kinda error prone.
Merged! Sorry about delay, I'll give you merge access for the future as well.
Thanks!! No problem!
Implement the nullifier verification circuits in circom as specified here. The entire circuit is in
verify_nullifier.circom
, and the entry point is theverify_nullifier
template.The circuit is tested over the same values as the wallet js code.
c
comes out to the right value, as shown by the"Circuit verifies valid nullifier"
test. All sub-circuits are also tested.NOTE: I made 3 changes to the wallet code:
CURVE.n
rather thanCURVE.p
. Note thatn
is the size of the scalar field (i.e., the number of group elements) whereasp
is the size of the base field over which the elliptic curve is defined. This was critical in getting any equation of the form $g^{a + b}/g^b = g^a$ to work (the form of the first two equations).To run the tests, run
npm run flatten-dependencies
thennpm run test
(the longest test took ~20mins on my 8GB ram macbook pro, so be prepared to wait - the whole suite would probably take about 35 mins). Known to work with circom 2.1.2.