From 63ff1f5fa1a974bfc7d264c7dca4aa4ec130db39 Mon Sep 17 00:00:00 2001 From: Kobi Gurkan Date: Wed, 26 Jun 2019 18:36:34 +0300 Subject: [PATCH] Circuit updates (#8) * feat: moves code to use mimcsponge, uses blake2s for commitment * fix: makes ci timeout larger * fix: updates sbmtjs's reference to circomlib to mimcsponge * fix: replaces rinkeby sponge address * fix: moves to a wasm compatible blake2 library * fix: attempts removing blake2.wasm from webpack * fix: moves to native js blake2 * fix: fixes webpack config to remove blake2 * fix: makes generate_identity sync * fix: changes mimc7 to mimcsponge in client_web * fix: updates websnark for smaller memory * fix: updates websnark for smaller memory * fix: adds enlarged heap for compilation * fix: adds enlarged heap for compilation * fix: makes tests pass * fix: makes MerkleTree use mimc sponge * feat: adds position to the nullifiers hash * feat: makes identity_nullifier 256 bits again, and makes external_nullifier 224 bits to make room for position * fix: makes sure that we index identity_path_index correctly in hash * feat: moves back to iden3's websnark version * feat: uses (8*pk).x for identity commitment * fix: changes identity_commitment to match circuit * fix: fixes contract end-to-end test to use new primitives * fix: ci uses local version of zkp-sbmtjs * feat: updates package versions * fix: removes npm link from ci * fix: changes tests to use MimcSpongeHasher * feat: attempts storing artifacts * feat: updates rinkeby contract address * feat: updates package-lock --- .circleci/config.yml | 6 +- sbmtjs/package-lock.json | 3 +- sbmtjs/package.json | 4 +- sbmtjs/src/hasher/mimcsponge/index.js | 33 ++++++++ semaphorejs/contracts/MerkleTree.sol | 44 ++++------- semaphorejs/contracts/MerkleTreeLib.sol | 18 +++-- semaphorejs/migrations/2_deploy_mimc.js | 6 +- semaphorejs/package-lock.json | 54 ++++--------- semaphorejs/package.json | 7 +- semaphorejs/scripts/ci.sh | 1 + semaphorejs/scripts/compile.sh | 1 + semaphorejs/scripts/convert_to_wasm.sh | 1 + semaphorejs/scripts/do_setup.sh | 1 + semaphorejs/scripts/run_all_test.sh | 1 + semaphorejs/snark/blake2s/blake2s.circom | 32 +++++--- semaphorejs/snark/semaphore-base.circom | 78 ++++++++++++------- semaphorejs/snark/semaphore.circom | 2 +- semaphorejs/src/client/client.js | 1 - semaphorejs/src/client/semaphore.js | 53 +++++++++---- semaphorejs/src/server/server.js | 4 +- semaphorejs/src/test_util.js | 8 +- semaphorejs/src/web/client_web.js | 4 +- semaphorejs/src/web/template.html | 2 +- semaphorejs/test/circuits/blake2s/blake2s.js | 10 +-- .../test/circuits/blake2s/blake2s_test.circom | 2 +- .../test/circuits/semaphore/circuit.js | 37 +++++++-- semaphorejs/test/contracts/merkle_tree.js | 6 +- semaphorejs/test/contracts/semaphore.js | 30 ++++--- 28 files changed, 277 insertions(+), 172 deletions(-) create mode 100644 sbmtjs/src/hasher/mimcsponge/index.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 29b0cec6..11560cf6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,4 +38,8 @@ jobs: - run: name: end-to-end command: cd scripts && ./ci.sh - no_output_timeout: 30m + no_output_timeout: 600m + + - store_artifacts: + path: ~/semaphore/semaphorejs/build + diff --git a/sbmtjs/package-lock.json b/sbmtjs/package-lock.json index cb937335..cc76af4b 100644 --- a/sbmtjs/package-lock.json +++ b/sbmtjs/package-lock.json @@ -1,6 +1,6 @@ { "name": "zkp-sbmtjs", - "version": "0.2.0", + "version": "0.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -340,6 +340,7 @@ "requires": { "blake-hash": "^1.1.0", "snarkjs": "0.1.11", + "typedarray-to-buffer": "^3.1.5", "web3": "^1.0.0-beta.36" } }, diff --git a/sbmtjs/package.json b/sbmtjs/package.json index 1ebc9e5b..31e45354 100644 --- a/sbmtjs/package.json +++ b/sbmtjs/package.json @@ -1,6 +1,6 @@ { "name": "zkp-sbmtjs", - "version": "0.2.1", + "version": "0.3.0", "description": "Storage-backed Merkle tree", "main": "index.js", "scripts": { @@ -16,7 +16,7 @@ "await-lock": "^1.1.3", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "circomlib": "git+https://github.com/kobigurk/circomlib.git", + "circomlib": "git+https://github.com/kobigurk/circomlib.git#f4a7f30faa9867be77522aea42332585338c235d", "del": "^4.0.0", "level-rocksdb": "^3.0.1", "snarkjs": "^0.1.11", diff --git a/sbmtjs/src/hasher/mimcsponge/index.js b/sbmtjs/src/hasher/mimcsponge/index.js new file mode 100644 index 00000000..a7a406b7 --- /dev/null +++ b/sbmtjs/src/hasher/mimcsponge/index.js @@ -0,0 +1,33 @@ +/* + * sbmtjs - Storage-backed Merkle tree + * Copyright (C) 2019 Kobi Gurkan + * + * This file is part of sbmtjs. + * + * sbmtjs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * sbmtjs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with sbmtjs. If not, see . + */ + +const circomlib = require('circomlib'); +const mimcsponge = circomlib.mimcsponge; +const snarkjs = require('snarkjs'); + +const bigInt = snarkjs.bigInt; + +class MimcSpongeHasher { + hash(level, left, right) { + return mimcsponge.multiHash([bigInt(left), bigInt(right)]).toString(); + } +} + +module.exports = MimcSpongeHasher; diff --git a/semaphorejs/contracts/MerkleTree.sol b/semaphorejs/contracts/MerkleTree.sol index 8b89f20b..22027786 100644 --- a/semaphorejs/contracts/MerkleTree.sol +++ b/semaphorejs/contracts/MerkleTree.sol @@ -21,7 +21,7 @@ pragma solidity >=0.4.21; library MiMC { - function MiMCpe7(uint256 in_x, uint256 in_k) pure public returns (uint256 out_x); + function MiMCSponge(uint256 in_xL, uint256 in_xR, uint256 in_k) pure public returns (uint256 xL, uint256 xR); } contract MerkleTree { @@ -52,12 +52,16 @@ contract MerkleTree { function HashLeftRight(uint256 left, uint256 right) public pure returns (uint256 mimc_hash) { uint256 k = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - uint256 r0 = 0; - uint256 h0 = MiMC.MiMCpe7(left, r0); - uint256 r1 = addmod(r0, addmod(left, h0, k), k); - uint256 h1 = MiMC.MiMCpe7(right, r1); - uint256 r2 = addmod(r1, addmod(right, h1, k), k); - mimc_hash = r2; + uint256 R = 0; + uint256 C = 0; + + R = addmod(R, left, k); + (R, C) = MiMC.MiMCSponge(R, C, 0); + + R = addmod(R, right, k); + (R, C) = MiMC.MiMCSponge(R, C, 0); + + mimc_hash = R; } function insert(uint256 leaf) internal { @@ -90,34 +94,14 @@ contract MerkleTree { emit LeafAdded(leaf, leaf_index); } - function update(uint256 old_leaf, uint256 leaf, uint32 leaf_index, uint256[] memory old_path, uint256[] memory path) internal { + function update(uint256 leaf, uint32 leaf_index, uint256[] memory path) internal { uint32 current_index = leaf_index; - uint256 current_level_hash = old_leaf; + uint256 current_level_hash = leaf; uint256 left; uint256 right; for (uint8 i = 0; i < levels; i++) { - if (current_index % 2 == 0) { - left = current_level_hash; - right = old_path[i]; - } else { - left = old_path[i]; - right = current_level_hash; - } - - current_level_hash = HashLeftRight(left, right); - - current_index /= 2; - } - - require(root == current_level_hash); - - current_index = leaf_index; - - current_level_hash = leaf; - - for (i = 0; i < levels; i++) { if (current_index % 2 == 0) { left = current_level_hash; right = path[i]; @@ -131,8 +115,6 @@ contract MerkleTree { current_index /= 2; } - root = current_level_hash; - emit LeafUpdated(leaf, leaf_index); } } diff --git a/semaphorejs/contracts/MerkleTreeLib.sol b/semaphorejs/contracts/MerkleTreeLib.sol index f3d4b842..2f92fae1 100644 --- a/semaphorejs/contracts/MerkleTreeLib.sol +++ b/semaphorejs/contracts/MerkleTreeLib.sol @@ -21,7 +21,7 @@ pragma solidity >=0.4.21; library MiMC { - function MiMCpe7(uint256 in_x, uint256 in_k) pure public returns (uint256 out_x); + function MiMCSponge(uint256 in_xL, uint256 in_xR, uint256 in_k) pure public returns (uint256 xL, uint256 xR); } contract MultipleMerkleTree { @@ -61,12 +61,16 @@ contract MultipleMerkleTree { function HashLeftRight(uint256 left, uint256 right) public pure returns (uint256 mimc_hash) { uint256 k = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - uint256 r0 = 0; - uint256 h0 = MiMC.MiMCpe7(left, r0); - uint256 r1 = addmod(r0, addmod(left, h0, k), k); - uint256 h1 = MiMC.MiMCpe7(right, r1); - uint256 r2 = addmod(r1, addmod(right, h1, k), k); - mimc_hash = r2; + uint256 R = 0; + uint256 C = 0; + + R = addmod(R, left, k); + (R, C) = MiMC.MiMCSponge(R, C, 0); + + R = addmod(R, right, k); + (R, C) = MiMC.MiMCSponge(R, C, 0); + + mimc_hash = R; } function insert(uint8 tree_index, uint256 leaf) internal { diff --git a/semaphorejs/migrations/2_deploy_mimc.js b/semaphorejs/migrations/2_deploy_mimc.js index 3a0db467..a3ed3e11 100644 --- a/semaphorejs/migrations/2_deploy_mimc.js +++ b/semaphorejs/migrations/2_deploy_mimc.js @@ -20,10 +20,10 @@ const path = require('path'); -const mimcGenContract = require('circomlib/src/mimc_gencontract.js'); +const mimcGenContract = require('circomlib/src/mimcsponge_gencontract.js'); const Artifactor = require('truffle-artifactor'); -const SEED = 'mimc'; +const SEED = 'mimcsponge'; module.exports = function(deployer) { @@ -34,7 +34,7 @@ module.exports = function(deployer) { await artifactor.save({ contractName: mimcContractName, abi: mimcGenContract.abi, - unlinked_binary: mimcGenContract.createCode(SEED, 91), + unlinked_binary: mimcGenContract.createCode(SEED, 220), }) .then(async () => { const MiMC = artifacts.require(mimcContractName); diff --git a/semaphorejs/package-lock.json b/semaphorejs/package-lock.json index 61cede7c..e6a8a4cf 100644 --- a/semaphorejs/package-lock.json +++ b/semaphorejs/package-lock.json @@ -1,6 +1,6 @@ { "name": "zkp-semaphorejs", - "version": "0.2.1", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1302,6 +1302,11 @@ "nan": "^2.2.1" } }, + "blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -1757,8 +1762,8 @@ } }, "circomlib": { - "version": "git+https://github.com/iden3/circomlib.git#d91afa804ace6481f4468eebc0bf55229771e24c", - "from": "git+https://github.com/iden3/circomlib.git#d91afa804ace6481f4468eebc0bf55229771e24c", + "version": "git+https://github.com/kobigurk/circomlib.git#f4a7f30faa9867be77522aea42332585338c235d", + "from": "git+https://github.com/kobigurk/circomlib.git#f4a7f30faa9867be77522aea42332585338c235d", "requires": { "blake-hash": "^1.1.0", "snarkjs": "0.1.11", @@ -12271,9 +12276,9 @@ } }, "node-abi": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.8.0.tgz", - "integrity": "sha512-1/aa2clS0pue0HjckL62CsbhWWU35HARvBDXcJtYKbYR7LnIutmpxmXbuDMV9kEviD2lP/wACOgWmmwljghHyQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.9.0.tgz", + "integrity": "sha512-jmEOvv0eanWjhX8dX1pmjb7oJl1U1oR4FOh0b2GnvALwSYoOdU7sj+kLDSAyjo4pfC9aj/IxkloxdLJQhSSQBA==", "requires": { "semver": "^5.4.1" } @@ -16461,8 +16466,8 @@ } }, "websnark": { - "version": "git+https://github.com/kobigurk/websnark.git#30a4b3d7fba78421aaf9e6b11e6c8b399eacced2", - "from": "git+https://github.com/kobigurk/websnark.git#30a4b3d7fba78421aaf9e6b11e6c8b399eacced2", + "version": "git+https://github.com/iden3/websnark.git#3b6cf0c77e48ab0867a2d710c0b35794b16bde7d", + "from": "git+https://github.com/iden3/websnark.git", "requires": { "big-integer": "^1.6.42" } @@ -16752,43 +16757,18 @@ } }, "zkp-sbmtjs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/zkp-sbmtjs/-/zkp-sbmtjs-0.2.1.tgz", - "integrity": "sha512-v2xSE1Wm3qA+hyh3g+wCEQNM6xGH3q9FauZDGd9q6NI0h3z07GuVADpEVNYs2BEKj5t8ZrGuJLGhpFaMALcZCg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/zkp-sbmtjs/-/zkp-sbmtjs-0.3.0.tgz", + "integrity": "sha512-0x+o+JEJBFDTnupf9H2RyC2JufEA7OgRJfZ8unzqq2/fjgmMzZiai1T7+McucyEvpuE76hMvVwGmFy8ZFBUa+A==", "requires": { "await-lock": "^1.1.3", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "circomlib": "git+https://github.com/kobigurk/circomlib.git", + "circomlib": "git+https://github.com/kobigurk/circomlib.git#f4a7f30faa9867be77522aea42332585338c235d", "del": "^4.0.0", "level-rocksdb": "^3.0.1", "snarkjs": "^0.1.11", "uuid": "^3.3.2" - }, - "dependencies": { - "circomlib": { - "version": "git+https://github.com/kobigurk/circomlib.git#b254beaa50db7857ff6d8163c24d579c3f338f4b", - "from": "git+https://github.com/kobigurk/circomlib.git", - "requires": { - "blake-hash": "^1.1.0", - "snarkjs": "0.1.11", - "web3": "^1.0.0-beta.36" - }, - "dependencies": { - "snarkjs": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.11.tgz", - "integrity": "sha512-NoMNn03Uwbt18V340ZlHSZscyfIu8F6fMOL7LT9Xr1zQY/nmzScM8442ATyJfzSI5bDTAz1QQGbCerP2BCKljA==", - "requires": { - "big-integer": "^1.6.35", - "chai": "^4.1.2", - "escape-string-regexp": "^1.0.5", - "eslint": "^5.3.0", - "yargs": "^12.0.2" - } - } - } - } } } } diff --git a/semaphorejs/package.json b/semaphorejs/package.json index c42bd7d0..5823b1d7 100644 --- a/semaphorejs/package.json +++ b/semaphorejs/package.json @@ -1,6 +1,6 @@ { "name": "zkp-semaphorejs", - "version": "0.2.5", + "version": "0.3.0", "description": "Zero-knowledge signaling on Ethereum", "main": "index.js", "scripts": { @@ -18,8 +18,9 @@ "url": "https://github.com/kobigurk/semaphore.git" }, "dependencies": { + "blakejs": "^1.1.0", "circom": "0.0.27", - "circomlib": "git+https://github.com/iden3/circomlib.git#d91afa804ace6481f4468eebc0bf55229771e24c", + "circomlib": "git+https://github.com/kobigurk/circomlib.git#f4a7f30faa9867be77522aea42332585338c235d", "cors": "^2.8.5", "del": "^4.1.0", "file-saver": "^2.0.1", @@ -39,7 +40,7 @@ "webpack": "^4.30.0", "websnark": "git+https://github.com/iden3/websnark.git", "winston": "^3.2.1", - "zkp-sbmtjs": "^0.2.1" + "zkp-sbmtjs": "^0.3.0" }, "devDependencies": { "npm-update-git-deps": "^1.2.4", diff --git a/semaphorejs/scripts/ci.sh b/semaphorejs/scripts/ci.sh index 579b6536..e8a1d368 100755 --- a/semaphorejs/scripts/ci.sh +++ b/semaphorejs/scripts/ci.sh @@ -24,6 +24,7 @@ echo "Working directory: `pwd`" ./do_setup.sh ./convert_to_wasm.sh ./build_verifier.sh + npx mocha --recursive ../test/circuits ../node_modules/.bin/ganache-cli -p 7545 -l 8800000 -i 5777 --account='0x6738837df169e8d6ffc6e33a2947e58096d644fa4aa6d74358c8d9d57c12cd21,100000000000000000000000000' --account='0x6738837df169e8d6ffc6e33a2947e58096d644fa4aa6d74358c8d9d57c12cd21,10000000000000000000000000' -q & ../node_modules/.bin/truffle migrate --reset diff --git a/semaphorejs/scripts/compile.sh b/semaphorejs/scripts/compile.sh index a363d045..7a0b5acf 100755 --- a/semaphorejs/scripts/compile.sh +++ b/semaphorejs/scripts/compile.sh @@ -22,5 +22,6 @@ mkdir -p ../build cd ../build +export NODE_OPTIONS=--max-old-space-size=4096 npx circom ../snark/semaphore.circom diff --git a/semaphorejs/scripts/convert_to_wasm.sh b/semaphorejs/scripts/convert_to_wasm.sh index dadde9e5..126fcf15 100755 --- a/semaphorejs/scripts/convert_to_wasm.sh +++ b/semaphorejs/scripts/convert_to_wasm.sh @@ -19,5 +19,6 @@ # along with semaphorejs. If not, see . # +export NODE_OPTIONS=--max-old-space-size=4096 node ../node_modules/websnark/tools/buildpkey.js -i ../build/proving_key.json -o ../build/proving_key.bin diff --git a/semaphorejs/scripts/do_setup.sh b/semaphorejs/scripts/do_setup.sh index 2df33447..7f705a3f 100755 --- a/semaphorejs/scripts/do_setup.sh +++ b/semaphorejs/scripts/do_setup.sh @@ -22,5 +22,6 @@ mkdir -p ../build cd ../build +export NODE_OPTIONS=--max-old-space-size=4096 npx snarkjs setup --protocol groth diff --git a/semaphorejs/scripts/run_all_test.sh b/semaphorejs/scripts/run_all_test.sh index a1b8b17b..7f4d9ebb 100755 --- a/semaphorejs/scripts/run_all_test.sh +++ b/semaphorejs/scripts/run_all_test.sh @@ -63,6 +63,7 @@ CREATION_HASH=`cat ../build/contracts/Semaphore.json | jq ".networks.\"${CHAIN_I CHAIN_ID=${CHAIN_ID} CONTRACT_ADDRESS=$ADDRESS FROM_ADDRESS=0x1929c15f4e818abf2549510622a50c440c474223 FROM_PRIVATE_KEY=0x6738837df169e8d6ffc6e33a2947e58096d644fa4aa6d74358c8d9d57c12cd21 NODE_URL=${NODE_URL} EXTERNAL_NULLIFIER=12312 SEMAPHORE_SERVER_URL=http://localhost:3000 CONFIG_ENV=true BASE_DIR=../.. npx semaphorejs-client generate_identity IDENTITY_COMMITMENT=`cat ./semaphore_identity.json | jq '.identity_commitment' | sed 's/"//g'` +echo ${IDENTITY_COMMITMENT} tmux \ new-session "source ~/.bashrc; export CONFIG_ENV=true LOG_LEVEL=${LOG_LEVEL} CHAIN_ID=${CHAIN_ID} CONTRACT_ADDRESS=$ADDRESS NODE_URL=${SERVER_NODE_URL} SEMAPHORE_PORT=3000 FROM_ADDRESS=0x1929c15f4e818abf2549510622a50c440c474223 FROM_PRIVATE_KEY=0x6738837df169e8d6ffc6e33a2947e58096d644fa4aa6d74358c8d9d57c12cd21 TRANSACTION_CONFIRMATION_BLOCKS=1 CREATION_HASH=${CREATION_HASH}; npx semaphorejs-server fund; npx semaphorejs-server; bash -i" \; \ diff --git a/semaphorejs/snark/blake2s/blake2s.circom b/semaphorejs/snark/blake2s/blake2s.circom index 11e45369..0ca36e2b 100644 --- a/semaphorejs/snark/blake2s/blake2s.circom +++ b/semaphorejs/snark/blake2s/blake2s.circom @@ -122,10 +122,12 @@ template Blake2sCompression(t, f) { } signal v_pass_1[16][32]; + component v_12_xor = Uint32Xor(); + component v_13_xor = Uint32Xor(); + component v_14_xor = Uint32Xor(); for (var i = 0; i < 16; i++) { if (i == 12) { - component v_12_xor = Uint32Xor(); for (var j = 0; j < 32; j++) { v_12_xor.a_bits[j] <== v_h[i][j]; v_12_xor.b_bits[j] <== (t >> j) & 1; @@ -134,7 +136,6 @@ template Blake2sCompression(t, f) { v_pass_1[i][j] <== v_12_xor.out_bits[j]; } } else if (i == 13) { - component v_13_xor = Uint32Xor(); for (var j = 0; j < 32; j++) { v_13_xor.a_bits[j] <== v_h[i][j]; v_13_xor.b_bits[j] <== (t >> (32 + j)) & 1; @@ -142,14 +143,23 @@ template Blake2sCompression(t, f) { for (var j = 0; j < 32; j++) { v_pass_1[i][j] <== v_13_xor.out_bits[j]; } - } else if ((i == 14) && (f == 1)) { - component v_14_xor = Uint32Xor(); - for (var j = 0; j < 32; j++) { - v_14_xor.a_bits[j] <== v_h[i][j]; - v_14_xor.b_bits[j] <== 1; - } - for (var j = 0; j < 32; j++) { - v_pass_1[i][j] <== v_14_xor.out_bits[j]; + } else if ((i == 14)) { + if (f == 1) { + for (var j = 0; j < 32; j++) { + v_14_xor.a_bits[j] <== v_h[i][j]; + v_14_xor.b_bits[j] <== 1; + } + for (var j = 0; j < 32; j++) { + v_pass_1[i][j] <== v_14_xor.out_bits[j]; + } + } else { + for (var j = 0; j < 32; j++) { + v_14_xor.a_bits[j] <== v_h[i][j]; + v_14_xor.b_bits[j] <== 0; + } + for (var j = 0; j < 32; j++) { + v_pass_1[i][j] <== v_h[i][j]; + } } } else { for (var j = 0; j < 32; j++) { @@ -352,7 +362,7 @@ template Blake2s(n_bits, personalization) { } } for (var l = 0; l < 16; l++) { - current_bit = 32*l + j; + current_bit = 512*i + 32*l + j; if (current_bit < n_bits) { compressions[i].in_m[l][j] <== in_bits[current_bit]; } else { diff --git a/semaphorejs/snark/semaphore-base.circom b/semaphorejs/snark/semaphore-base.circom index 0bbd7439..146a59e0 100644 --- a/semaphorejs/snark/semaphore-base.circom +++ b/semaphorejs/snark/semaphore-base.circom @@ -1,6 +1,6 @@ -include "../node_modules/circomlib/circuits/mimc.circom"; +include "../node_modules/circomlib/circuits/mimcsponge.circom"; include "../node_modules/circomlib/circuits/bitify.circom"; -include "../node_modules/circomlib/circuits/eddsamimc.circom"; +include "../node_modules/circomlib/circuits/eddsamimcsponge.circom"; include "./blake2s/blake2s.circom"; template HashLeftRight(n_rounds) { @@ -9,12 +9,12 @@ template HashLeftRight(n_rounds) { signal output hash; - component hasher = MultiMiMC7(2, n_rounds); - left ==> hasher.in[0]; - right ==> hasher.in[1]; + component hasher = MiMCSponge(2, n_rounds, 1); + left ==> hasher.ins[0]; + right ==> hasher.ins[1]; hasher.k <== 0; - hash <== hasher.out; + hash <== hasher.outs[0]; } template Selector() { @@ -51,7 +51,6 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { // mimc vector commitment signal private input identity_pk[2]; signal private input identity_nullifier; - signal private input identity_r; signal private input identity_path_elements[n_levels]; signal private input identity_path_index[n_levels]; @@ -59,20 +58,36 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { signal private input auth_sig_r[2]; signal private input auth_sig_s; + // get a prime subgroup element derived from identity_pk + component dbl1 = BabyDbl(); + dbl1.x <== identity_pk[0]; + dbl1.y <== identity_pk[1]; + component dbl2 = BabyDbl(); + dbl2.x <== dbl1.xout; + dbl2.y <== dbl1.yout; + component dbl3 = BabyDbl(); + dbl3.x <== dbl2.xout; + dbl3.y <== dbl2.yout; + // mimc hash signal output root; signal output nullifiers_hash; // END signals - component identity_commitment = MultiMiMC7(4, n_rounds); + component identity_nullifier_bits = Num2Bits(256); + identity_nullifier_bits.in <== identity_nullifier; + + component identity_pk_0_bits = Num2Bits(256); + identity_pk_0_bits.in <== dbl3.xout; + + component identity_commitment = Blake2s(2*256, 0); // BEGIN identity commitment - identity_commitment.in[0] <== identity_pk[0]; - identity_commitment.in[1] <== identity_pk[1]; - identity_commitment.in[2] <== identity_nullifier; - identity_commitment.in[3] <== identity_r; - identity_commitment.k <== 0; + for (var i = 0; i < 256; i++) { + identity_commitment.in_bits[i] <== identity_pk_0_bits.out[i]; + identity_commitment.in_bits[i + 256] <== identity_nullifier_bits.out[i]; + } // END identity commitment // BEGIN tree @@ -90,7 +105,12 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { selectors[i].right ==> hashers[i].right; } - identity_commitment.out ==> selectors[0].input_elem; + component identity_commitment_num = Bits2Num(253); + for (var i = 0; i < 253; i++) { + identity_commitment_num.in[i] <== identity_commitment.out[i]; + } + + identity_commitment_num.out ==> selectors[0].input_elem; for (var i = 1; i < n_levels; i++) { hashers[i-1].hash ==> selectors[i].input_elem; @@ -100,15 +120,21 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { // END tree // BEGIN nullifiers - component identity_nullifier_bits = Num2Bits(254); - identity_nullifier_bits.in <== identity_nullifier; - component external_nullifier_bits = Num2Bits(254); + component external_nullifier_bits = Num2Bits(256); external_nullifier_bits.in <== external_nullifier; - component nullifiers_hasher = Blake2s(508, 248018401820981); - for (var i = 0; i < 254; i++) { + component nullifiers_hasher = Blake2s(512, 0); + for (var i = 0; i < 256; i++) { nullifiers_hasher.in_bits[i] <== identity_nullifier_bits.out[i]; - nullifiers_hasher.in_bits[254 + i] <== external_nullifier_bits.out[i]; + if (i < 224) { + nullifiers_hasher.in_bits[256 + i] <== external_nullifier_bits.out[i]; + } else { + if ( (i-224) < n_levels ) { + nullifiers_hasher.in_bits[256 + i] <== identity_path_index[i - 224]; + } else { + nullifiers_hasher.in_bits[256 + i] <== 0; + } + } } component nullifiers_hash_num = Bits2Num(253); @@ -121,20 +147,20 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { // END nullifiers // BEGIN verify sig - component msg_hasher = MultiMiMC7(3, n_rounds); - msg_hasher.in[0] <== external_nullifier; - msg_hasher.in[1] <== signal_hash; - msg_hasher.in[2] <== broadcaster_address; + component msg_hasher = MiMCSponge(3, n_rounds, 1); + msg_hasher.ins[0] <== external_nullifier; + msg_hasher.ins[1] <== signal_hash; + msg_hasher.ins[2] <== broadcaster_address; msg_hasher.k <== 0; - component sig_verifier = EdDSAMiMCVerifier(); + component sig_verifier = EdDSAMiMCSpongeVerifier(); 1 ==> sig_verifier.enabled; identity_pk[0] ==> sig_verifier.Ax; identity_pk[1] ==> sig_verifier.Ay; auth_sig_r[0] ==> sig_verifier.R8x; auth_sig_r[1] ==> sig_verifier.R8y; auth_sig_s ==> sig_verifier.S; - msg_hasher.out ==> sig_verifier.M; + msg_hasher.outs[0] ==> sig_verifier.M; // END verify sig } diff --git a/semaphorejs/snark/semaphore.circom b/semaphorejs/snark/semaphore.circom index 36a5df29..ce9d7f9c 100644 --- a/semaphorejs/snark/semaphore.circom +++ b/semaphorejs/snark/semaphore.circom @@ -1,3 +1,3 @@ include "./semaphore-base.circom"; -component main = Semaphore(251, 20, 91); +component main = Semaphore(251, 20, 220); diff --git a/semaphorejs/src/client/client.js b/semaphorejs/src/client/client.js index 7759a504..67174d30 100755 --- a/semaphorejs/src/client/client.js +++ b/semaphorejs/src/client/client.js @@ -35,7 +35,6 @@ const circomlib = require('circomlib'); const bigInt = snarkjs.bigInt; const eddsa = circomlib.eddsa; -const mimc7 = circomlib.mimc7; const groth = snarkjs.groth; diff --git a/semaphorejs/src/client/semaphore.js b/semaphorejs/src/client/semaphore.js index 254177af..94d20244 100644 --- a/semaphorejs/src/client/semaphore.js +++ b/semaphorejs/src/client/semaphore.js @@ -21,7 +21,7 @@ const crypto = require('crypto'); const path = require('path'); const {unstringifyBigInts, stringifyBigInts} = require('websnark/tools/stringifybigint.js'); - +const blake2 = require('blakejs'); const chai = require('chai'); const assert = chai.assert; @@ -32,7 +32,7 @@ const circomlib = require('circomlib'); const bigInt = snarkjs.bigInt; const eddsa = circomlib.eddsa; -const mimc7 = circomlib.mimc7; +const mimcsponge = circomlib.mimcsponge; const proof_util = require('../util'); @@ -42,6 +42,20 @@ const Web3 = require('web3'); let logger; +/* uint8array to hex */ + +function hex(byteArray) { + return Array.prototype.map.call(byteArray, function(byte) { + return ('0' + (byte & 0xFF).toString(16)).slice(-2); + }).join(''); +} + +const cutDownBits = function(b, bits) { + let mask = bigInt(1); + mask = mask.shl(bits).sub(bigInt(1)); + return b.and(mask); +} + beBuff2int = function(buff) { let res = bigInt.zero; for (let i=0; i x.leInt2Buff(32)) + ); + this.identity_commitment_buffer = identity_commitment_buffer; this.web3 = new Web3(node_url); this.web3.eth.transactionConfirmationBlocks = transaction_confirmation_blocks; @@ -98,6 +114,13 @@ class SemaphoreClient { async broadcast_signal(signal_str) { logger.info(`broadcasting signal ${signal_str}`); + + const identity_commitment_digest = blake2.blake2sHex(this.identity_commitment_buffer); + logger.verbose(`identity_commitment digest: ${identity_commitment_digest}`); + const identity_commitment_uncut = beBuff2int(new Buffer(identity_commitment_digest, 'hex')); + logger.verbose(`identity_commitment_uncut: ${identity_commitment_uncut}`); + this.identity_commitment = cutDownBits(identity_commitment_uncut, 253); + logger.verbose(`identity_commitment: ${this.identity_commitment}`); //const prvKey = Buffer.from('0001020304050607080900010203040506070809000102030405060708090001', 'hex'); const prvKey = Buffer.from(this.private_key, 'hex'); @@ -115,13 +138,12 @@ class SemaphoreClient { const signal_hash = beBuff2int(signal_hash_raw.slice(0, 31)); const broadcaster_address = bigInt(this.broadcaster_address); - const msg = mimc7.multiHash([external_nullifier, signal_hash, broadcaster_address]); - const signature = eddsa.signMiMC(prvKey, msg); + const msg = mimcsponge.multiHash([external_nullifier, signal_hash, broadcaster_address]); + const signature = eddsa.signMiMCSponge(prvKey, msg); - assert(eddsa.verifyMiMC(msg, signature, pubKey)); + assert(eddsa.verifyMiMCSponge(msg, signature, pubKey)); const identity_nullifier = this.identity_nullifier; - const identity_r = this.identity_r; let identity_path; if (this.identity_index === null) { @@ -152,7 +174,6 @@ class SemaphoreClient { signal_hash, external_nullifier, identity_nullifier, - identity_r, identity_path_elements, identity_path_index, broadcaster_address, @@ -165,6 +186,7 @@ class SemaphoreClient { const root = w[this.circuit.getSignalIdx('main.root')]; const nullifiers_hash = w[this.circuit.getSignalIdx('main.nullifiers_hash')]; assert(this.circuit.checkWitness(w)); + logger.info(`identity commitment from proof: ${w[this.circuit.getSignalIdx('main.identity_commitment_num.out')].toString()}`); assert.equal(w[this.circuit.getSignalIdx('main.root')].toString(), identity_path.root); logger.info(`generating proof (started at ${Date.now()})`); @@ -253,21 +275,24 @@ class SemaphoreClient { } function generate_identity(logger) { + const private_key = crypto.randomBytes(32).toString('hex'); const prvKey = Buffer.from(private_key, 'hex'); const pubKey = eddsa.prv2pub(prvKey); const identity_nullifier = '0x' + crypto.randomBytes(31).toString('hex'); - const identity_r = '0x' + crypto.randomBytes(31).toString('hex'); - logger.info(`generate identity from (private_key, public_key[0], public_key[1], identity_nullifier, identity_r): (${private_key}, ${pubKey[0]}, ${pubKey[1]}, ${identity_nullifier}, ${identity_r})`); + logger.info(`generate identity from (private_key, public_key[0], public_key[1], identity_nullifier): (${private_key}, ${pubKey[0]}, ${pubKey[1]}, ${identity_nullifier})`); - const identity_commitment = mimc7.multiHash([bigInt(pubKey[0]), bigInt(pubKey[1]), bigInt(identity_nullifier), bigInt(identity_r)]); + const identity_commitment_ints = [bigInt(circomlib.babyJub.mulPointEscalar(pubKey, 8)[0]), bigInt(identity_nullifier)]; + const identity_commitment_buffer = Buffer.concat( + identity_commitment_ints.map(x => x.leInt2Buff(32)) + ); + const identity_commitment = cutDownBits(beBuff2int(new Buffer(blake2.blake2sHex(identity_commitment_buffer), 'hex')), 253); logger.info(`identity_commitment : ${identity_commitment}`); const generated_identity = { private_key, identity_nullifier: identity_nullifier.toString(), - identity_r: identity_r.toString(), identity_commitment: identity_commitment.toString(), }; diff --git a/semaphorejs/src/server/server.js b/semaphorejs/src/server/server.js index aba8c985..6c4b561a 100755 --- a/semaphorejs/src/server/server.js +++ b/semaphorejs/src/server/server.js @@ -22,7 +22,7 @@ const RocksDb = require('zkp-sbmtjs/src/storage/rocksdb'); const MerkleTree = require('zkp-sbmtjs/src/tree'); -const Mimc7Hasher = require('zkp-sbmtjs/src/hasher/mimc7'); +const MimcSpongeHasher = require('zkp-sbmtjs/src/hasher/mimcsponge'); const Web3 = require('web3'); const SemaphoreABI = require('../../build/contracts/Semaphore.json'); @@ -284,7 +284,7 @@ class SemaphoreServer { const prefix = 'semaphore'; const storage = new RocksDb(server_config.DB_PATH || 'semaphore_server.db'); -const hasher = new Mimc7Hasher(); +const hasher = new MimcSpongeHasher(); const default_value = '0'; const tree = new MerkleTree( diff --git a/semaphorejs/src/test_util.js b/semaphorejs/src/test_util.js index 2a42a9a9..ea985175 100644 --- a/semaphorejs/src/test_util.js +++ b/semaphorejs/src/test_util.js @@ -24,7 +24,7 @@ const circomlib = require('circomlib'); const bigInt = snarkjs.bigInt; -const mimc7 = circomlib.mimc7; +const mimcsponge = circomlib.mimcsponge; let build_merkle_tree_example = (n_levels, identity_commitment) => { let current_index = 0; @@ -33,7 +33,7 @@ let build_merkle_tree_example = (n_levels, identity_commitment) => { let current_element = identity_commitment; for (let i = 0; i < n_levels; i++) { path_elements.push(bigInt(0)); - current_element = mimc7.multiHash([ bigInt(current_element), bigInt(0) ]); + current_element = mimcsponge.multiHash([ bigInt(current_element), bigInt(0) ]); path_index.push(current_index % 2); current_index = Math.floor(current_index / 2); @@ -60,7 +60,7 @@ let build_full_merkle_tree_example = (n_levels, index, identity_commitment) => { tree_level.push(bigInt(j)); } } else { - tree_level.push(mimc7.multiHash([ tree[i-1][2*j], tree[i-1][2*j+1] ])); + tree_level.push(mimcsponge.multiHash([ tree[i-1][2*j], tree[i-1][2*j+1] ])); } } if (current_index % 2 == 0) { @@ -73,7 +73,7 @@ let build_full_merkle_tree_example = (n_levels, index, identity_commitment) => { current_index = Math.floor(current_index / 2); } - const root = mimc7.multiHash([ tree[n_levels - 1][0], tree[n_levels - 1][1] ]); + const root = mimcsponge.multiHash([ tree[n_levels - 1][0], tree[n_levels - 1][1] ]); return [root, tree, path_elements, path_index]; }; diff --git a/semaphorejs/src/web/client_web.js b/semaphorejs/src/web/client_web.js index 774b421d..4dc56046 100644 --- a/semaphorejs/src/web/client_web.js +++ b/semaphorejs/src/web/client_web.js @@ -29,7 +29,7 @@ const snarkjs = require('snarkjs'); const bigInt = snarkjs.bigInt; const eddsa = require('circomlib/src/eddsa'); -const mimc7 = require('circomlib/src/mimc7'); +const mimcsponge = require('circomlib/src/mimcsponge'); const groth = snarkjs.groth; @@ -136,7 +136,7 @@ const SemaphoreABI = require('../../build/contracts/Semaphore.json'); left = data.path.path_elements[i]; right = current_hash; } - current_hash = bigInt(mimc7.multiHash([bigInt(left), bigInt(right)])); + current_hash = bigInt(mimcsponge.multiHash([bigInt(left), bigInt(right)])); } const expected_root = '0x' + current_hash.toString(16); const signals_root = $('#s_signals_root').text(); diff --git a/semaphorejs/src/web/template.html b/semaphorejs/src/web/template.html index efc88400..8227d7b7 100644 --- a/semaphorejs/src/web/template.html +++ b/semaphorejs/src/web/template.html @@ -106,7 +106,7 @@ external_nullifier: 'auto', semaphore_server_url: 'https://semaphore-server.kobi.one', semaphore_server_address: '0x1929c15f4e818abf2549510622a50c440c474223', - semaphore_contract_address: '0xde297a7213b238F4a65F0a5B65F19C25c165dB38', + semaphore_contract_address: '0x7A1f706D1051b320E876088cB38E28001f3E6130', from_private_key: '0x6738837df169e8d6ffc6e33a2947e58096d644fa4aa6d74358c8d9d57c12cd21', from_address: '0x1929c15f4e818abf2549510622a50c440c474223', chain_id: '4', diff --git a/semaphorejs/test/circuits/blake2s/blake2s.js b/semaphorejs/test/circuits/blake2s/blake2s.js index 376c236b..08a2f8a5 100644 --- a/semaphorejs/test/circuits/blake2s/blake2s.js +++ b/semaphorejs/test/circuits/blake2s/blake2s.js @@ -33,15 +33,15 @@ describe("blake2s test", () => { }).timeout(1000000); it("Should run blake2s", async () => { - const cirDef = await compiler(path.join(__dirname, "blake2s_test.circom")); - fs.writeFileSync('blake2sdef.json', JSON.stringify(cirDef)); - //const cirDef = JSON.parse(fs.readFileSync('blake2sdef.json')); + const cirDef = await compiler(path.join(__dirname, "blake2s_test.circom")); + fs.writeFileSync('blake2sdef.json', JSON.stringify(cirDef)); + //const cirDef = JSON.parse(fs.readFileSync('blake2sdef.json')); const circuit = new snarkjs.Circuit(cirDef); console.log("Vars: "+circuit.nVars); console.log("Constraints: "+circuit.nConstraints); - const bits = '00001000001110010010000001101001110100110001101010001101011010110001011101100001111111100000010000000000101010111001101001011110010100001111101011000010010000011010001111010100110100011001000110010001000000001001100011111011110010100000010000101011011000010000010111100110110011110111000100110110000101100100011011010010011010100110100101000010111010100000011101101011100000110111100011100000100000101110100011001101100001100100111011111111110011111101011110001011011001010011011100011000010111111001111010101010'; + const bits = '1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; const inputs = {}; for (let i = 0; i < bits.length; i++) { inputs[`in_bits[${i}]`] = bigInt(bits[i]); @@ -56,7 +56,7 @@ describe("blake2s test", () => { coeff = coeff.shl(1); } console.log(`blake2s hash: 0x${result.toString(16)}`); - assert.equal(result.toString(16), '96dbac58ccef5c10e5226b1da1b20b44ea0ca52aa21abe80279a85686e838118'); + assert.equal(result.toString(16), 'c8a7a6e87d10557e3214979b2dda05b16a0e845a7367bcacb1890bfed50aaa97'); for (let i = 0; i < witness.length; i++) { //console.log(circuit.signalNames(i)); diff --git a/semaphorejs/test/circuits/blake2s/blake2s_test.circom b/semaphorejs/test/circuits/blake2s/blake2s_test.circom index d71c1c16..f617f026 100644 --- a/semaphorejs/test/circuits/blake2s/blake2s_test.circom +++ b/semaphorejs/test/circuits/blake2s/blake2s_test.circom @@ -1,6 +1,6 @@ include "../../../snark/blake2s/blake2s.circom"; -component main = Blake2s(512, 248018401820981); +component main = Blake2s(1024, 0); /* 49 * 2**(0*8) + 50 * 2**(1*8) + diff --git a/semaphorejs/test/circuits/semaphore/circuit.js b/semaphorejs/test/circuits/semaphore/circuit.js index 1a31c99e..a5153fd8 100644 --- a/semaphorejs/test/circuits/semaphore/circuit.js +++ b/semaphorejs/test/circuits/semaphore/circuit.js @@ -24,6 +24,7 @@ const snarkjs = require('snarkjs'); const compiler = require('circom'); const fs = require('fs'); const circomlib = require('circomlib'); +const blake2 = require('blakejs'); const test_util = require('../../../src/test_util'); const build_merkle_tree_example = test_util.build_merkle_tree_example; @@ -33,7 +34,24 @@ const assert = chai.assert; const bigInt = snarkjs.bigInt; const eddsa = circomlib.eddsa; -const mimc7 = circomlib.mimc7; +const mimcsponge = circomlib.mimcsponge; + +const cutDownBits = function(b, bits) { + let mask = bigInt(1); + mask = mask.shl(bits).sub(bigInt(1)); + return b.and(mask); +} + +beBuff2int = function(buff) { + let res = bigInt.zero; + for (let i=0; i x.leInt2Buff(32)) + ); + const identity_commitment = cutDownBits(beBuff2int(new Buffer(blake2.blake2sHex(identity_commitment_buffer), 'hex')), 253); + + + const tree = build_merkle_tree_example(20, identity_commitment); const identity_path_elements = tree[1]; const identity_path_index = tree[2]; @@ -78,7 +102,6 @@ describe('circuit test', function () { signal_hash, external_nullifier, identity_nullifier, - identity_r, identity_path_elements, identity_path_index, broadcaster_address, diff --git a/semaphorejs/test/contracts/merkle_tree.js b/semaphorejs/test/contracts/merkle_tree.js index 323422da..356c5a40 100644 --- a/semaphorejs/test/contracts/merkle_tree.js +++ b/semaphorejs/test/contracts/merkle_tree.js @@ -32,7 +32,7 @@ const MerkleTreeTester = artifacts.require('MerkleTreeTester'); const RocksDb = require('zkp-sbmtjs/src/storage/rocksdb'); const MerkleTreeLib = require('zkp-sbmtjs/src/tree'); -const Mimc7Hasher = require('zkp-sbmtjs/src/hasher/mimc7'); +const MimcSpongeHasher = require('zkp-sbmtjs/src/hasher/mimcsponge'); @@ -44,7 +44,7 @@ contract('MerkleTree', () => { } const default_value = '4'; const storage = new RocksDb(storage_path); - const hasher = new Mimc7Hasher(); + const hasher = new MimcSpongeHasher(); const prefix = 'semaphore'; const tree = new MerkleTreeLib( prefix, @@ -67,7 +67,7 @@ contract('MerkleTree', () => { } const default_value = '4'; const storage = new RocksDb(storage_path); - const hasher = new Mimc7Hasher(); + const hasher = new MimcSpongeHasher(); const prefix = 'semaphore'; const tree = new MerkleTreeLib( prefix, diff --git a/semaphorejs/test/contracts/semaphore.js b/semaphorejs/test/contracts/semaphore.js index 805eadef..f6b6d63c 100644 --- a/semaphorejs/test/contracts/semaphore.js +++ b/semaphorejs/test/contracts/semaphore.js @@ -34,7 +34,7 @@ const test_util = require('../../src/test_util'); const bigInt = snarkjs.bigInt; const eddsa = circomlib.eddsa; -const mimc7 = circomlib.mimc7; +const mimcsponge = circomlib.mimcsponge; const groth = snarkjs.groth; const {unstringifyBigInts} = require('snarkjs/src/stringifybigint.js'); @@ -47,7 +47,9 @@ const proof_util = require('../../src/util'); const RocksDb = require('zkp-sbmtjs/src/storage/rocksdb'); const MerkleTree = require('zkp-sbmtjs/src/tree'); -const Mimc7Hasher = require('zkp-sbmtjs/src/hasher/mimc7'); +const MimcSpongeHasher = require('zkp-sbmtjs/src/hasher/mimcsponge'); + +const blake2 = require('blakejs'); beBuff2int = function(buff) { let res = bigInt.zero; @@ -58,6 +60,12 @@ beBuff2int = function(buff) { return res; }; +const cutDownBits = function(b, bits) { + let mask = bigInt(1); + mask = mask.shl(bits).sub(bigInt(1)); + return b.and(mask); +} + contract('Semaphore', function () { it('tests proof', async () => { const cirDef = JSON.parse(fs.readFileSync(path.join(__dirname,'../../build/circuit.json')).toString()); @@ -75,13 +83,12 @@ contract('Semaphore', function () { const accounts = await web3.eth.getAccounts(); const broadcaster_address = bigInt(accounts[0].toString()); - const msg = mimc7.multiHash([bigInt(external_nullifier), bigInt(signal_hash), bigInt(broadcaster_address)]); - const signature = eddsa.signMiMC(prvKey, msg); + const msg = mimcsponge.multiHash([bigInt(external_nullifier), bigInt(signal_hash), bigInt(broadcaster_address)]); + const signature = eddsa.signMiMCSponge(prvKey, msg); - assert(eddsa.verifyMiMC(msg, signature, pubKey)); + assert(eddsa.verifyMiMCSponge(msg, signature, pubKey)); const identity_nullifier = bigInt('230'); - const identity_r = bigInt('12311'); const storage_path = '/tmp/rocksdb_semaphore_test'; if (fs.existsSync(storage_path)) { @@ -89,7 +96,7 @@ contract('Semaphore', function () { } const default_value = '0'; const storage = new RocksDb(storage_path); - const hasher = new Mimc7Hasher(); + const hasher = new MimcSpongeHasher(); const prefix = 'semaphore'; const tree = new MerkleTree( prefix, @@ -99,7 +106,13 @@ contract('Semaphore', function () { default_value, ); - const identity_commitment = mimc7.multiHash([bigInt(pubKey[0]), bigInt(pubKey[1]), bigInt(identity_nullifier), bigInt(identity_r)]); + const identity_commitment_ints = [bigInt(circomlib.babyJub.mulPointEscalar(pubKey, 8)[0]), bigInt(identity_nullifier)]; + const identity_commitment_buffer = Buffer.concat( + identity_commitment_ints.map(x => x.leInt2Buff(32)) + ); + const identity_commitment = cutDownBits(beBuff2int(new Buffer(blake2.blake2sHex(identity_commitment_buffer), 'hex')), 253); + + const semaphore = await Semaphore.deployed(); const receipt = await semaphore.insertIdentity(identity_commitment.toString()); assert.equal(receipt.logs[0].event, 'LeafAdded'); @@ -124,7 +137,6 @@ contract('Semaphore', function () { signal_hash, external_nullifier, identity_nullifier, - identity_r, identity_path_elements, identity_path_index, broadcaster_address,