diff --git a/package.json b/package.json
index 1c10f4314..bd60ce650 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,6 @@
"@types/jest": "^27.4.0",
"@types/node": "^17.0.9",
"@types/rimraf": "^3.0.2",
- "@types/snarkjs": "^0.7.5",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"babel-jest": "^27.4.6",
@@ -83,6 +82,7 @@
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"rollup": "^2.64.0",
+ "snarkjs": "^0.7.2",
"ts-node": "^10.4.0",
"tslib": "^2.3.1",
"typedoc": "^0.25.1",
diff --git a/packages/contracts/contracts/Semaphore.sol b/packages/contracts/contracts/Semaphore.sol
index f6f18207e..f050e9b03 100644
--- a/packages/contracts/contracts/Semaphore.sol
+++ b/packages/contracts/contracts/Semaphore.sol
@@ -152,8 +152,8 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
function verifyProof(
uint256 groupId,
uint256 merkleTreeRoot,
- uint256 message,
uint256 nullifier,
+ uint256 message,
uint256 scope,
uint256[8] calldata proof
) external override onlyExistingGroup(groupId) {
@@ -184,10 +184,19 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
revert Semaphore__YouAreUsingTheSameNillifierTwice();
}
- verifier.verifyProof(merkleTreeRoot, nullifier, message, scope, proof);
+ if (
+ !verifier.verifyProof(
+ [proof[0], proof[1]],
+ [[proof[3], proof[2]], [proof[5], proof[4]]],
+ [proof[6], proof[7]],
+ [merkleTreeRoot, nullifier, message, scope]
+ )
+ ) {
+ revert Semaphore__InvalidProof();
+ }
groups[groupId].nullifiers[nullifier] = true;
- emit ProofVerified(groupId, merkleTreeRoot, nullifier, scope, message, proof);
+ emit ProofVerified(groupId, merkleTreeRoot, nullifier, message, scope, proof);
}
}
diff --git a/packages/contracts/contracts/base/Pairing.sol b/packages/contracts/contracts/base/Pairing.sol
deleted file mode 100644
index bdf428f27..000000000
--- a/packages/contracts/contracts/base/Pairing.sol
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2017 Christian Reitwiessner
-// 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.
-//
-// The following Pairing library is a modified version adapted to Semaphore.
-//
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.4;
-
-library Pairing {
- error InvalidProof();
-
- // The prime q in the base field F_q for G1
- uint256 constant BASE_MODULUS = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
-
- // The prime modulus of the scalar field of G1.
- uint256 constant SCALAR_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
-
- struct G1Point {
- uint256 X;
- uint256 Y;
- }
-
- // Encoding of field elements is: X[0] * z + X[1]
- struct G2Point {
- uint256[2] X;
- uint256[2] Y;
- }
-
- /// @return the generator of G1
- function P1() public pure returns (G1Point memory) {
- return G1Point(1, 2);
- }
-
- /// @return the generator of G2
- function P2() public pure returns (G2Point memory) {
- return
- G2Point(
- [
- 11559732032986387107991004021392285783925812861821192530917403151452391805634,
- 10857046999023057135944570762232829481370756359578518086990519993285655852781
- ],
- [
- 4082367875863433681332203403145435568316851327593401208105741076214120093531,
- 8495653923123431417604973247489272438418190587263600148770280649306958101930
- ]
- );
- }
-
- /// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.
- function negate(G1Point memory p) public pure returns (G1Point memory r) {
- if (p.X == 0 && p.Y == 0) {
- return G1Point(0, 0);
- }
-
- // Validate input or revert
- if (p.X >= BASE_MODULUS || p.Y >= BASE_MODULUS) {
- revert InvalidProof();
- }
-
- // We know p.Y > 0 and p.Y < BASE_MODULUS.
- return G1Point(p.X, BASE_MODULUS - p.Y);
- }
-
- /// @return r the sum of two points of G1
- function addition(G1Point memory p1, G1Point memory p2) public view returns (G1Point memory r) {
- // By EIP-196 all input is validated to be less than the BASE_MODULUS and form points
- // on the curve.
- uint256[4] memory input;
-
- input[0] = p1.X;
- input[1] = p1.Y;
- input[2] = p2.X;
- input[3] = p2.Y;
-
- bool success;
-
- // solium-disable-next-line security/no-inline-assembly
- assembly {
- success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
- }
-
- if (!success) {
- revert InvalidProof();
- }
- }
-
- /// @return r the product of a point on G1 and a scalar, i.e.
- /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.
- function scalar_mul(G1Point memory p, uint256 s) public view returns (G1Point memory r) {
- // By EIP-196 the values p.X and p.Y are verified to be less than the BASE_MODULUS and
- // form a valid point on the curve. But the scalar is not verified, so we do that explicitly.
- if (s >= SCALAR_MODULUS) {
- revert InvalidProof();
- }
-
- uint256[3] memory input;
-
- input[0] = p.X;
- input[1] = p.Y;
- input[2] = s;
-
- bool success;
-
- // solium-disable-next-line security/no-inline-assembly
- assembly {
- success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
- }
-
- if (!success) {
- revert InvalidProof();
- }
- }
-
- /// Asserts the pairing check
- /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
- /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should succeed
- function pairingCheck(G1Point[] memory p1, G2Point[] memory p2) public view {
- // By EIP-197 all input is verified to be less than the BASE_MODULUS and form elements in their
- // respective groups of the right order.
- if (p1.length != p2.length) {
- revert InvalidProof();
- }
-
- uint256 elements = p1.length;
- uint256 inputSize = elements * 6;
- uint256[] memory input = new uint256[](inputSize);
-
- for (uint256 i = 0; i < elements; i++) {
- input[i * 6 + 0] = p1[i].X;
- input[i * 6 + 1] = p1[i].Y;
- input[i * 6 + 2] = p2[i].X[0];
- input[i * 6 + 3] = p2[i].X[1];
- input[i * 6 + 4] = p2[i].Y[0];
- input[i * 6 + 5] = p2[i].Y[1];
- }
-
- uint256[1] memory out;
- bool success;
-
- // solium-disable-next-line security/no-inline-assembly
- assembly {
- success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
- }
-
- if (!success || out[0] != 1) {
- revert InvalidProof();
- }
- }
-}
diff --git a/packages/contracts/contracts/base/SemaphoreVerifier.sol b/packages/contracts/contracts/base/SemaphoreVerifier.sol
index 6f0c34067..87bfa4e89 100644
--- a/packages/contracts/contracts/base/SemaphoreVerifier.sol
+++ b/packages/contracts/contracts/base/SemaphoreVerifier.sol
@@ -1,113 +1,196 @@
-//SPDX-License-Identifier: MIT
-pragma solidity 0.8.4;
+// SPDX-License-Identifier: GPL-3.0
+/*
+ Copyright 2021 0KIMS association.
-import "../interfaces/ISemaphoreVerifier.sol";
+ This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
-/// @title Semaphore verifier contract.
-/// @notice Minimal code to allow users to verify their Semaphore proofs.
-/// @dev This contract allows you to verify whether a Semaphore proof is correct.
-/// It is a modified version of the Groth16 verifier template of SnarkJS
-/// (https://github.com/iden3/snarkjs) adapted to Semaphore. The Pairing library
-/// is external.
-contract SemaphoreVerifier is ISemaphoreVerifier {
- using Pairing for *;
+ snarkJS is a 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.
- // prettier-ignore
- // solhint-disable-next-line
- uint256[2][7][1] VK_POINTS = [[[1203033843370190352679536156318647846963070791761882784581562957032940878631,8079358190325697178560398569841376952804277857152452363880610878513176978414],[1709663807054049176405784021595122468175326469739885095843389206914547034049,5323102298870768887773635223311040590195621468735208775728981925050238645973],[7810627885438804854799393101615420860004300484567847086674409667961806655819,17752894058911463947056561254031971003439956976683150238952280384884265610345],[1859027844886249956101358092211425783821368393550326618436626137559481879491,21054817398797605484546956719908640544118839476669181800056403255004730797738],[15796976765804300435452771769828280808531244272386620395606681167033336150695,903968937841233929826399002238948203245370749106069849010375461873649600286],[9939447176137952809861441974771884976492003509733419789700227062163769465749,10252048733134373819769164658668132695840284406808712977431939424744406823235],[7393464059707248328549959352154443030400062088967711800345697753542770722400,7750652018971809526357985723000957185438256496025176410178561237545956517939]]];
+ snarkJS 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 snarkJS. If not, see .
+*/
+
+pragma solidity >=0.7.0 <0.9.0;
+
+contract SemaphoreVerifier {
+ // Scalar field size
+ uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
+ // Base field size
+ uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
+
+ // Verification Key data
+ uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
+ uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
+
+ uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
+ uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
+
+ uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
+ uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
+
+ uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
+ uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
+
+ uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
+ uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
+
+ uint256 constant deltax1 = 4802212656094790438590349860247775075786991105131547807727284652635601493451;
+ uint256 constant deltax2 = 3192001579163161965737706068451660722884189926734050314177195054150514444526;
+
+ uint256 constant deltay1 = 15972350841447731019470651411783473840114797777894828544121644904018624203926;
+ uint256 constant deltay2 = 16736984041748862942817824193402022794140982482563484226161429255394796148810;
+
+ uint256 constant IC0x = 7810627885438804854799393101615420860004300484567847086674409667961806655819;
+ uint256 constant IC0y = 17752894058911463947056561254031971003439956976683150238952280384884265610345;
+
+ uint256 constant IC1x = 1859027844886249956101358092211425783821368393550326618436626137559481879491;
+ uint256 constant IC1y = 21054817398797605484546956719908640544118839476669181800056403255004730797738;
+
+ uint256 constant IC2x = 15796976765804300435452771769828280808531244272386620395606681167033336150695;
+ uint256 constant IC2y = 903968937841233929826399002238948203245370749106069849010375461873649600286;
+
+ uint256 constant IC3x = 9939447176137952809861441974771884976492003509733419789700227062163769465749;
+ uint256 constant IC3y = 10252048733134373819769164658668132695840284406808712977431939424744406823235;
+
+ uint256 constant IC4x = 7393464059707248328549959352154443030400062088967711800345697753542770722400;
+ uint256 constant IC4y = 7750652018971809526357985723000957185438256496025176410178561237545956517939;
+
+ // Memory data
+ uint16 constant pVk = 0;
+ uint16 constant pPairing = 128;
+
+ uint16 constant pLastMem = 896;
- /// @dev See {ISemaphoreVerifier-verifyProof}.
function verifyProof(
- uint256 merkleTreeRoot,
- uint256 nullifierHash,
- uint256 message,
- uint256 scope,
- uint256[8] calldata proof
- ) external view override {
- message = _hash(message);
- scope = _hash(scope);
-
- Proof memory p;
-
- p.A = Pairing.G1Point(proof[0], proof[1]);
- p.B = Pairing.G2Point([proof[2], proof[3]], [proof[4], proof[5]]);
- p.C = Pairing.G1Point(proof[6], proof[7]);
-
- // TODO: get vk dynamically based on tree depth after trusted setup.
- VerificationKey memory vk = _getVerificationKey(0);
-
- Pairing.G1Point memory vk_x = vk.IC[0];
-
- vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[1], merkleTreeRoot));
- vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[2], nullifierHash));
- vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[3], message));
- vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[4], scope));
-
- Pairing.G1Point[] memory p1 = new Pairing.G1Point[](4);
- Pairing.G2Point[] memory p2 = new Pairing.G2Point[](4);
-
- p1[0] = Pairing.negate(p.A);
- p2[0] = p.B;
- p1[1] = vk.alfa1;
- p2[1] = vk.beta2;
- p1[2] = vk_x;
- p2[2] = vk.gamma2;
- p1[3] = p.C;
- p2[3] = vk.delta2;
-
- Pairing.pairingCheck(p1, p2);
- }
+ uint[2] calldata _pA,
+ uint[2][2] calldata _pB,
+ uint[2] calldata _pC,
+ uint[4] calldata _pubSignals
+ ) public view returns (bool) {
+ assembly {
+ function checkField(v) {
+ if iszero(lt(v, q)) {
+ mstore(0, 0)
+ return(0, 0x20)
+ }
+ }
- /// @dev Creates the verification key for a specific Merkle tree depth.
- /// @param vkPointsIndex: Index of the verification key points.
- /// @return Verification key.
- function _getVerificationKey(uint256 vkPointsIndex) private view returns (VerificationKey memory) {
- VerificationKey memory vk;
-
- vk.alfa1 = Pairing.G1Point(
- 20491192805390485299153009773594534940189261866228447918068658471970481763042,
- 9383485363053290200918347156157836566562967994039712273449902621266178545958
- );
-
- vk.beta2 = Pairing.G2Point(
- [
- 4252822878758300859123897981450591353533073413197771768651442665752259397132,
- 6375614351688725206403948262868962793625744043794305715222011528459656738731
- ],
- [
- 21847035105528745403288232691147584728191162732299865338377159692350059136679,
- 10505242626370262277552901082094356697409835680220590971873171140371331206856
- ]
- );
-
- vk.gamma2 = Pairing.G2Point(
- [
- 11559732032986387107991004021392285783925812861821192530917403151452391805634,
- 10857046999023057135944570762232829481370756359578518086990519993285655852781
- ],
- [
- 4082367875863433681332203403145435568316851327593401208105741076214120093531,
- 8495653923123431417604973247489272438418190587263600148770280649306958101930
- ]
- );
-
- vk.delta2 = Pairing.G2Point(VK_POINTS[vkPointsIndex][0], VK_POINTS[vkPointsIndex][1]);
-
- vk.IC = new Pairing.G1Point[](5);
-
- vk.IC[0] = Pairing.G1Point(VK_POINTS[vkPointsIndex][2][0], VK_POINTS[vkPointsIndex][2][1]);
- vk.IC[1] = Pairing.G1Point(VK_POINTS[vkPointsIndex][3][0], VK_POINTS[vkPointsIndex][3][1]);
- vk.IC[2] = Pairing.G1Point(VK_POINTS[vkPointsIndex][4][0], VK_POINTS[vkPointsIndex][4][1]);
- vk.IC[3] = Pairing.G1Point(VK_POINTS[vkPointsIndex][5][0], VK_POINTS[vkPointsIndex][5][1]);
- vk.IC[4] = Pairing.G1Point(VK_POINTS[vkPointsIndex][6][0], VK_POINTS[vkPointsIndex][6][1]);
-
- return vk;
- }
+ // G1 function to multiply a G1 value(x,y) to value in an address
+ function g1_mulAccC(pR, x, y, s) {
+ let success
+ let mIn := mload(0x40)
+ mstore(mIn, x)
+ mstore(add(mIn, 32), y)
+ mstore(add(mIn, 64), s)
+
+ success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
+
+ if iszero(success) {
+ mstore(0, 0)
+ return(0, 0x20)
+ }
+
+ mstore(add(mIn, 64), mload(pR))
+ mstore(add(mIn, 96), mload(add(pR, 32)))
+
+ success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
+
+ if iszero(success) {
+ mstore(0, 0)
+ return(0, 0x20)
+ }
+ }
+
+ function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
+ let _pPairing := add(pMem, pPairing)
+ let _pVk := add(pMem, pVk)
+
+ mstore(_pVk, IC0x)
+ mstore(add(_pVk, 32), IC0y)
+
+ // Compute the linear combination vk_x
+
+ g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
+
+ g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
+
+ g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
+
+ g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
+
+ // -A
+ mstore(_pPairing, calldataload(pA))
+ mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
+
+ // B
+ mstore(add(_pPairing, 64), calldataload(pB))
+ mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
+ mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
+ mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
+
+ // alpha1
+ mstore(add(_pPairing, 192), alphax)
+ mstore(add(_pPairing, 224), alphay)
+
+ // beta2
+ mstore(add(_pPairing, 256), betax1)
+ mstore(add(_pPairing, 288), betax2)
+ mstore(add(_pPairing, 320), betay1)
+ mstore(add(_pPairing, 352), betay2)
+
+ // vk_x
+ mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
+ mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
+
+ // gamma2
+ mstore(add(_pPairing, 448), gammax1)
+ mstore(add(_pPairing, 480), gammax2)
+ mstore(add(_pPairing, 512), gammay1)
+ mstore(add(_pPairing, 544), gammay2)
+
+ // C
+ mstore(add(_pPairing, 576), calldataload(pC))
+ mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
+
+ // delta2
+ mstore(add(_pPairing, 640), deltax1)
+ mstore(add(_pPairing, 672), deltax2)
+ mstore(add(_pPairing, 704), deltay1)
+ mstore(add(_pPairing, 736), deltay2)
+
+ let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
+
+ isOk := and(success, mload(_pPairing))
+ }
+
+ let pMem := mload(0x40)
+ mstore(0x40, add(pMem, pLastMem))
+
+ // Validate that all evaluations ∈ F
+
+ checkField(calldataload(add(_pubSignals, 0)))
+
+ checkField(calldataload(add(_pubSignals, 32)))
+
+ checkField(calldataload(add(_pubSignals, 64)))
+
+ checkField(calldataload(add(_pubSignals, 96)))
+
+ checkField(calldataload(add(_pubSignals, 128)))
+
+ // Validate all evaluations
+ let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
- /// @dev Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
- /// @param message: Message to be hashed.
- /// @return Message digest.
- function _hash(uint256 message) private pure returns (uint256) {
- return uint256(keccak256(abi.encodePacked(message))) >> 8;
+ mstore(0, isValid)
+ return(0, 0x20)
+ }
}
}
diff --git a/packages/contracts/contracts/interfaces/ISemaphore.sol b/packages/contracts/contracts/interfaces/ISemaphore.sol
index 44113ad1d..f3a2f5e02 100644
--- a/packages/contracts/contracts/interfaces/ISemaphore.sol
+++ b/packages/contracts/contracts/interfaces/ISemaphore.sol
@@ -11,6 +11,7 @@ interface ISemaphore {
error Semaphore__MerkleTreeRootIsExpired();
error Semaphore__MerkleTreeRootIsNotPartOfTheGroup();
error Semaphore__YouAreUsingTheSameNillifierTwice();
+ error Semaphore__InvalidProof();
/// It defines all the group parameters, in addition to those in the Merkle tree.
struct Group {
@@ -44,15 +45,15 @@ interface ISemaphore {
/// @param groupId: Id of the group.
/// @param merkleTreeRoot: Root of the Merkle tree.
/// @param nullifier: Nullifier.
- /// @param scope: Scope.
/// @param message: Semaphore message.
+ /// @param scope: Scope.
/// @param proof: Zero-knowledge proof.
event ProofVerified(
uint256 indexed groupId,
uint256 indexed merkleTreeRoot,
uint256 nullifier,
- uint256 indexed scope,
uint256 message,
+ uint256 indexed scope,
uint256[8] proof
);
@@ -60,15 +61,15 @@ interface ISemaphore {
/// if the zero-knowledge proof is valid.
/// @param groupId: Id of the group.
/// @param merkleTreeRoot: Root of the Merkle tree.
- /// @param message: Semaphore message.
/// @param nullifier: Nullifier.
+ /// @param message: Semaphore message.
/// @param scope: Scope.
/// @param proof: Zero-knowledge proof.
function verifyProof(
uint256 groupId,
uint256 merkleTreeRoot,
- uint256 message,
uint256 nullifier,
+ uint256 message,
uint256 scope,
uint256[8] calldata proof
) external;
diff --git a/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol b/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol
index 56bc0a272..68dc51cd1 100644
--- a/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol
+++ b/packages/contracts/contracts/interfaces/ISemaphoreVerifier.sol
@@ -1,35 +1,12 @@
//SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
-import "../base/Pairing.sol";
-
/// @title SemaphoreVerifier contract interface.
interface ISemaphoreVerifier {
- struct VerificationKey {
- Pairing.G1Point alfa1;
- Pairing.G2Point beta2;
- Pairing.G2Point gamma2;
- Pairing.G2Point delta2;
- Pairing.G1Point[] IC;
- }
-
- struct Proof {
- Pairing.G1Point A;
- Pairing.G2Point B;
- Pairing.G1Point C;
- }
-
- /// @dev Verifies whether a Semaphore proof is valid.
- /// @param merkleTreeRoot: Root of the Merkle tree.
- /// @param nullifierHash: Nullifier hash.
- /// @param signal: Semaphore signal.
- /// @param externalNullifier: External nullifier.
- /// @param proof: Zero-knowledge proof.
function verifyProof(
- uint256 merkleTreeRoot,
- uint256 nullifierHash,
- uint256 signal,
- uint256 externalNullifier,
- uint256[8] calldata proof
- ) external view;
+ uint[2] calldata _pA,
+ uint[2][2] calldata _pB,
+ uint[2] calldata _pC,
+ uint[4] calldata _pubSignals
+ ) external view returns (bool);
}
diff --git a/packages/contracts/contracts/package.json b/packages/contracts/contracts/package.json
index a223ec8cf..c41eeae19 100644
--- a/packages/contracts/contracts/package.json
+++ b/packages/contracts/contracts/package.json
@@ -31,6 +31,6 @@
},
"dependencies": {
"@openzeppelin/contracts": "4.7.3",
- "@zk-kit/imt.sol": "2.0.0-beta.1"
+ "@zk-kit/imt.sol": "2.0.0-beta.3"
}
}
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 180d57065..162a2e5a6 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -60,6 +60,6 @@
},
"dependencies": {
"@openzeppelin/contracts": "4.7.3",
- "@zk-kit/imt.sol": "2.0.0-beta.1"
+ "@zk-kit/imt.sol": "2.0.0-beta.3"
}
}
diff --git a/packages/contracts/scripts/utils.ts b/packages/contracts/scripts/utils.ts
index 9ddd4560b..b1d97da12 100644
--- a/packages/contracts/scripts/utils.ts
+++ b/packages/contracts/scripts/utils.ts
@@ -1,7 +1,6 @@
import { readFileSync, writeFileSync } from "fs"
type DeployedContracts = {
- Pairing: string
SemaphoreVerifier: string
Poseidon: string
Semaphore: string
diff --git a/packages/contracts/tasks/deploy-semaphore.ts b/packages/contracts/tasks/deploy-semaphore.ts
index 3c3324b37..f84ca0269 100644
--- a/packages/contracts/tasks/deploy-semaphore.ts
+++ b/packages/contracts/tasks/deploy-semaphore.ts
@@ -2,34 +2,16 @@ import { task, types } from "hardhat/config"
import { saveDeployedContracts } from "../scripts/utils"
task("deploy:semaphore", "Deploy a Semaphore contract")
- .addOptionalParam("pairing", "Pairing library address", undefined, types.string)
.addOptionalParam("semaphoreVerifier", "SemaphoreVerifier contract address", undefined, types.string)
.addOptionalParam("poseidon", "Poseidon library address", undefined, types.string)
.addOptionalParam("logs", "Print the logs", true, types.boolean)
.setAction(
async (
- { logs, pairing: pairingAddress, semaphoreVerifier: semaphoreVerifierAddress, poseidon: poseidonAddress },
+ { logs, semaphoreVerifier: semaphoreVerifierAddress, poseidon: poseidonAddress },
{ ethers, hardhatArguments }
): Promise => {
if (!semaphoreVerifierAddress) {
- if (!pairingAddress) {
- const PairingFactory = await ethers.getContractFactory("Pairing")
- const pairing = await PairingFactory.deploy()
-
- await pairing.deployed()
-
- if (logs) {
- console.info(`Pairing library has been deployed to: ${pairing.address}`)
- }
-
- pairingAddress = pairing.address
- }
-
- const SemaphoreVerifierFactory = await ethers.getContractFactory("SemaphoreVerifier", {
- libraries: {
- Pairing: pairingAddress
- }
- })
+ const SemaphoreVerifierFactory = await ethers.getContractFactory("SemaphoreVerifier")
const semaphoreVerifier = await SemaphoreVerifierFactory.deploy()
@@ -70,7 +52,6 @@ task("deploy:semaphore", "Deploy a Semaphore contract")
}
saveDeployedContracts(hardhatArguments.network, {
- Pairing: pairingAddress,
SemaphoreVerifier: semaphoreVerifierAddress,
Poseidon: poseidonAddress,
Semaphore: semaphore.address
@@ -78,7 +59,6 @@ task("deploy:semaphore", "Deploy a Semaphore contract")
return {
semaphore,
- pairingAddress,
semaphoreVerifierAddress,
poseidonAddress
}
diff --git a/packages/contracts/test/Semaphore.ts b/packages/contracts/test/Semaphore.ts
index 101db39c0..8db277530 100644
--- a/packages/contracts/test/Semaphore.ts
+++ b/packages/contracts/test/Semaphore.ts
@@ -2,16 +2,15 @@
/* eslint-disable jest/valid-expect */
import { Group } from "@semaphore-protocol/group"
import { Identity } from "@semaphore-protocol/identity"
-import { SemaphoreProof, generateProof } from "@semaphore-protocol/proof"
+import { SemaphoreProof, generateProof, verifyProof } from "@semaphore-protocol/proof"
import { expect } from "chai"
import { Signer, constants } from "ethers"
-import { ethers, run } from "hardhat"
-import { Pairing, Semaphore } from "../build/typechain"
+import { run } from "hardhat"
+import { Semaphore } from "../build/typechain"
import { createIdentityCommitments } from "./utils"
describe("Semaphore", () => {
let semaphoreContract: Semaphore
- let pairingContract: Pairing
let signers: Signer[]
let accounts: string[]
@@ -19,12 +18,11 @@ describe("Semaphore", () => {
const members = createIdentityCommitments(3)
before(async () => {
- const { semaphore, pairingAddress } = await run("deploy:semaphore", {
+ const { semaphore } = await run("deploy:semaphore", {
logs: false
})
semaphoreContract = semaphore
- pairingContract = await ethers.getContractAt("Pairing", pairingAddress)
signers = await run("accounts", { logs: false })
accounts = await Promise.all(signers.map((signer: Signer) => signer.getAddress()))
@@ -208,7 +206,7 @@ describe("Semaphore", () => {
})
describe("# verifyProof", () => {
- const signal = 2
+ const message = 2
const identity = new Identity("0")
const group = new Group()
@@ -220,17 +218,17 @@ describe("Semaphore", () => {
before(async () => {
await semaphoreContract.addMembers(groupId, [members[1], members[2]])
- fullProof = await generateProof(identity, group, group.root as string, signal, 10)
+ fullProof = await generateProof(identity, group, message, group.root as string, 10)
})
it("Should not verify a proof if the group does not exist", async () => {
- const transaction = semaphoreContract.verifyProof(10, 1, signal, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0])
+ const transaction = semaphoreContract.verifyProof(10, 1, 0, message, 0, [0, 0, 0, 0, 0, 0, 0, 0])
await expect(transaction).to.be.revertedWithCustomError(semaphoreContract, "Semaphore__GroupDoesNotExist")
})
it("Should not verify a proof if the Merkle tree root is not part of the group", async () => {
- const transaction = semaphoreContract.verifyProof(2, 1, signal, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0])
+ const transaction = semaphoreContract.verifyProof(2, 1, 0, message, 0, [0, 0, 0, 0, 0, 0, 0, 0])
await expect(transaction).to.be.revertedWithCustomError(
semaphoreContract,
@@ -242,36 +240,45 @@ describe("Semaphore", () => {
const transaction = semaphoreContract.verifyProof(
groupId,
fullProof.treeRoot,
- fullProof.message,
fullProof.nullifier,
+ fullProof.message,
0,
fullProof.proof
)
- await expect(transaction).to.be.revertedWithCustomError(pairingContract, "InvalidProof")
+ await expect(transaction).to.be.revertedWithCustomError(semaphoreContract, "Semaphore__InvalidProof")
})
it("Should verify a proof for an onchain group correctly", async () => {
+ console.log(await verifyProof(fullProof), fullProof)
+
const transaction = semaphoreContract.verifyProof(
groupId,
fullProof.treeRoot,
- fullProof.message,
fullProof.nullifier,
+ fullProof.message,
fullProof.treeRoot,
fullProof.proof
)
await expect(transaction)
.to.emit(semaphoreContract, "ProofVerified")
- .withArgs(groupId, fullProof.treeRoot, fullProof.nullifier, fullProof.treeRoot, fullProof.message)
+ .withArgs(
+ groupId,
+ fullProof.treeRoot,
+ fullProof.nullifier,
+ fullProof.message,
+ fullProof.treeRoot,
+ fullProof.proof
+ )
})
it("Should not verify the same proof for an onchain group twice", async () => {
const transaction = semaphoreContract.verifyProof(
groupId,
fullProof.treeRoot,
- fullProof.message,
fullProof.nullifier,
+ fullProof.message,
fullProof.treeRoot,
fullProof.proof
)
@@ -288,13 +295,13 @@ describe("Semaphore", () => {
group.addMembers([members[0], members[1]])
- const fullProof = await generateProof(identity, group, group.root as string, signal, 10)
+ const fullProof = await generateProof(identity, group, message, group.root as string, 10)
const transaction = semaphoreContract.verifyProof(
groupId,
fullProof.treeRoot,
- fullProof.message,
fullProof.nullifier,
+ fullProof.message,
fullProof.treeRoot,
fullProof.proof
)
diff --git a/packages/proof/package.json b/packages/proof/package.json
index b2a51867d..f484eaac3 100644
--- a/packages/proof/package.json
+++ b/packages/proof/package.json
@@ -46,10 +46,6 @@
"@semaphore-protocol/identity": "3.15.2"
},
"dependencies": {
- "@ethersproject/bignumber": "^5.5.0",
- "@ethersproject/bytes": "^5.7.0",
- "@ethersproject/keccak256": "^5.7.0",
- "@ethersproject/strings": "^5.5.0",
"@zk-kit/groth16": "0.3.0",
"download": "^8.0.0",
"tmp": "^0.2.1"
diff --git a/packages/proof/src/generate-proof.ts b/packages/proof/src/generate-proof.ts
index 30fd32f93..da74914f7 100644
--- a/packages/proof/src/generate-proof.ts
+++ b/packages/proof/src/generate-proof.ts
@@ -1,13 +1,9 @@
-import { BigNumber } from "@ethersproject/bignumber"
-import { BytesLike, Hexable } from "@ethersproject/bytes"
import { Group } from "@semaphore-protocol/group"
import type { Identity } from "@semaphore-protocol/identity"
import { prove } from "@zk-kit/groth16"
-import type { NumericString } from "snarkjs"
import getSnarkArtifacts from "./get-snark-artifacts.node"
-import hash from "./hash"
import packProof from "./pack-proof"
-import { SemaphoreProof, SnarkArtifacts } from "./types"
+import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
/**
* Generates a Semaphore proof.
@@ -22,8 +18,8 @@ import { SemaphoreProof, SnarkArtifacts } from "./types"
export default async function generateProof(
identity: Identity,
group: Group,
- scope: BytesLike | Hexable | number | bigint,
- message: BytesLike | Hexable | number | bigint,
+ message: BigNumberish,
+ scope: BigNumberish,
treeDepth?: number,
snarkArtifacts?: SnarkArtifacts
): Promise {
@@ -58,8 +54,8 @@ export default async function generateProof(
treeDepth: merkleProofLength,
treeIndices,
treeSiblings,
- scope: hash(scope),
- message: hash(message)
+ scope,
+ message
},
snarkArtifacts.wasmFilePath,
snarkArtifacts.zkeyFilePath
@@ -68,8 +64,8 @@ export default async function generateProof(
return {
treeRoot: publicSignals[0],
nullifier: publicSignals[1],
- scope: BigNumber.from(scope).toString() as NumericString,
- message: BigNumber.from(message).toString() as NumericString,
+ message: publicSignals[2],
+ scope: publicSignals[3],
proof: packProof(proof)
}
}
diff --git a/packages/proof/src/hash.ts b/packages/proof/src/hash.ts
deleted file mode 100644
index 328b3ef52..000000000
--- a/packages/proof/src/hash.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { BigNumber } from "@ethersproject/bignumber"
-import { BytesLike, Hexable, zeroPad } from "@ethersproject/bytes"
-import { keccak256 } from "@ethersproject/keccak256"
-import { NumericString } from "snarkjs"
-
-/**
- * Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
- * @param message The message to be hashed.
- * @returns The message digest.
- */
-export default function hash(message: BytesLike | Hexable | number | bigint): NumericString {
- message = BigNumber.from(message).toTwos(256).toHexString()
- message = zeroPad(message, 32)
-
- return (BigInt(keccak256(message)) >> BigInt(8)).toString() as NumericString
-}
diff --git a/packages/proof/src/index.test.ts b/packages/proof/src/index.test.ts
index a1153eb9b..d572b84b1 100644
--- a/packages/proof/src/index.test.ts
+++ b/packages/proof/src/index.test.ts
@@ -1,9 +1,7 @@
-import { formatBytes32String } from "@ethersproject/strings"
import { Group } from "@semaphore-protocol/group"
import { Identity } from "@semaphore-protocol/identity"
import { getCurveFromName } from "ffjavascript"
import generateProof from "./generate-proof"
-import hash from "./hash"
import packProof from "./pack-proof"
import { SemaphoreProof } from "./types"
import unpackProof from "./unpack-proof"
@@ -12,8 +10,8 @@ import verifyProof from "./verify-proof"
describe("Proof", () => {
const treeDepth = 10
- const scope = formatBytes32String("Scope")
- const message = formatBytes32String("Hello world")
+ const message = 1
+ const scope = 2
const identity = new Identity(42)
@@ -32,7 +30,7 @@ describe("Proof", () => {
it("Should not generate Semaphore proofs if the identity is not part of the group", async () => {
const group = new Group([BigInt(1), BigInt(2)])
- const fun = () => generateProof(identity, group, scope, message, treeDepth)
+ const fun = () => generateProof(identity, group, message, scope, treeDepth)
await expect(fun).rejects.toThrow("does not exist")
})
@@ -40,7 +38,7 @@ describe("Proof", () => {
it("Should generate a Semaphore proof", async () => {
const group = new Group([BigInt(1), BigInt(2), identity.commitment])
- fullProof = await generateProof(identity, group, scope, message, treeDepth)
+ fullProof = await generateProof(identity, group, message, scope, treeDepth)
expect(typeof fullProof).toBe("object")
expect(fullProof.treeRoot).toBe(group.root)
@@ -55,40 +53,6 @@ describe("Proof", () => {
})
})
- describe("# hash", () => {
- it("Should hash the message correctly", async () => {
- const messageHash = hash(message)
-
- expect(messageHash).toBe("8665846418922331996225934941481656421248110469944536651334918563951783029")
- })
-
- it("Should hash the scope correctly", async () => {
- const scopeHash = hash(scope)
-
- expect(scopeHash).toBe("170164770795872309789133717676167925425155944778337387941930839678899666300")
- })
-
- it("Should hash a number", async () => {
- expect(hash(2)).toBe("113682330006535319932160121224458771213356533826860247409332700812532759386")
- })
-
- it("Should hash a big number", async () => {
- expect(hash(BigInt(2))).toBe("113682330006535319932160121224458771213356533826860247409332700812532759386")
- })
-
- it("Should hash an hex number", async () => {
- expect(hash("0x2")).toBe("113682330006535319932160121224458771213356533826860247409332700812532759386")
- })
-
- it("Should hash an string number", async () => {
- expect(hash("2")).toBe("113682330006535319932160121224458771213356533826860247409332700812532759386")
- })
-
- it("Should hash an array", async () => {
- expect(hash([2])).toBe("113682330006535319932160121224458771213356533826860247409332700812532759386")
- })
- })
-
describe("# packProof/unpackProof", () => {
it("Should return a packed proof", async () => {
const originalProof = unpackProof(fullProof.proof)
diff --git a/packages/proof/src/pack-proof.ts b/packages/proof/src/pack-proof.ts
index 6677eaeab..01ce3c9ab 100644
--- a/packages/proof/src/pack-proof.ts
+++ b/packages/proof/src/pack-proof.ts
@@ -1,4 +1,4 @@
-import { Groth16Proof } from "snarkjs"
+import { Groth16Proof } from "@zk-kit/groth16"
import { PackedProof } from "./types"
/**
diff --git a/packages/proof/src/types/index.ts b/packages/proof/src/types/index.ts
index d9382e6eb..a2d10ecd5 100644
--- a/packages/proof/src/types/index.ts
+++ b/packages/proof/src/types/index.ts
@@ -1,5 +1,7 @@
import type { NumericString } from "@zk-kit/groth16"
+export type BigNumberish = string | number | bigint
+
export type SnarkArtifacts = {
wasmFilePath: string
zkeyFilePath: string
diff --git a/packages/proof/src/unpack-proof.ts b/packages/proof/src/unpack-proof.ts
index 68ba66599..350252840 100644
--- a/packages/proof/src/unpack-proof.ts
+++ b/packages/proof/src/unpack-proof.ts
@@ -1,4 +1,4 @@
-import { Groth16Proof } from "snarkjs"
+import { Groth16Proof } from "@zk-kit/groth16"
import { PackedProof } from "./types"
/**
diff --git a/packages/proof/src/verification-keys.json b/packages/proof/src/verification-keys.json
index 696c2b008..36a146ac1 100644
--- a/packages/proof/src/verification-keys.json
+++ b/packages/proof/src/verification-keys.json
@@ -32,12 +32,12 @@
"vk_delta_2": [
[
[
- "1203033843370190352679536156318647846963070791761882784581562957032940878631",
- "8079358190325697178560398569841376952804277857152452363880610878513176978414"
+ "3192001579163161965737706068451660722884189926734050314177195054150514444526",
+ "4802212656094790438590349860247775075786991105131547807727284652635601493451"
],
[
- "1709663807054049176405784021595122468175326469739885095843389206914547034049",
- "5323102298870768887773635223311040590195621468735208775728981925050238645973"
+ "16736984041748862942817824193402022794140982482563484226161429255394796148810",
+ "15972350841447731019470651411783473840114797777894828544121644904018624203926"
],
["1", "0"]
]
diff --git a/packages/proof/src/verify-proof.ts b/packages/proof/src/verify-proof.ts
index d24f91bc3..4a6333987 100644
--- a/packages/proof/src/verify-proof.ts
+++ b/packages/proof/src/verify-proof.ts
@@ -1,5 +1,4 @@
import { verify } from "@zk-kit/groth16"
-import hash from "./hash"
import { SemaphoreProof } from "./types"
import unpackProof from "./unpack-proof"
import verificationKeys from "./verification-keys.json"
@@ -9,7 +8,7 @@ import verificationKeys from "./verification-keys.json"
* @param fullProof The SnarkJS Semaphore proof.
* @returns True if the proof is valid, false otherwise.
*/
-export default function verifyProof({ treeRoot, nullifier, scope, message, proof }: SemaphoreProof): Promise {
+export default function verifyProof({ treeRoot, nullifier, message, scope, proof }: SemaphoreProof): Promise {
// TODO: support all tree depths after trusted-setup.
// if (treeDepth < 1 || treeDepth > 32) {
// throw new TypeError("The tree depth must be a number between 1 and 32")
@@ -22,7 +21,7 @@ export default function verifyProof({ treeRoot, nullifier, scope, message, proof
}
return verify(verificationKey, {
- publicSignals: [treeRoot, nullifier, hash(message), hash(scope)],
+ publicSignals: [treeRoot, nullifier, message, scope],
proof: unpackProof(proof)
})
}
diff --git a/yarn.lock b/yarn.lock
index 4b7a95913..713981831 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5902,7 +5902,7 @@ __metadata:
languageName: node
linkType: hard
-"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.0.7, @ethersproject/bignumber@npm:^5.5.0, @ethersproject/bignumber@npm:^5.7.0":
+"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.0.7, @ethersproject/bignumber@npm:^5.7.0":
version: 5.7.0
resolution: "@ethersproject/bignumber@npm:5.7.0"
dependencies:
@@ -6167,7 +6167,7 @@ __metadata:
languageName: node
linkType: hard
-"@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:^5.0.4, @ethersproject/strings@npm:^5.5.0, @ethersproject/strings@npm:^5.7.0":
+"@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:^5.0.4, @ethersproject/strings@npm:^5.7.0":
version: 5.7.0
resolution: "@ethersproject/strings@npm:5.7.0"
dependencies:
@@ -8423,7 +8423,7 @@ __metadata:
resolution: "@semaphore-protocol/contracts@workspace:packages/contracts/contracts"
dependencies:
"@openzeppelin/contracts": 4.7.3
- "@zk-kit/imt.sol": 2.0.0-beta.1
+ "@zk-kit/imt.sol": 2.0.0-beta.3
languageName: unknown
linkType: soft
@@ -8499,10 +8499,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@semaphore-protocol/proof@workspace:packages/proof"
dependencies:
- "@ethersproject/bignumber": ^5.5.0
- "@ethersproject/bytes": ^5.7.0
- "@ethersproject/keccak256": ^5.7.0
- "@ethersproject/strings": ^5.5.0
"@rollup/plugin-commonjs": ^24.1.0
"@rollup/plugin-json": ^5.0.1
"@rollup/plugin-node-resolve": ^15.0.2
@@ -10188,13 +10184,6 @@ __metadata:
languageName: node
linkType: hard
-"@types/snarkjs@npm:^0.7.5":
- version: 0.7.5
- resolution: "@types/snarkjs@npm:0.7.5"
- checksum: 5c2adfde23b49c6411d2b28b51d0e061cdb63e7dce6137afd8297571c0d8c7496ef4512194f2bf56f310569cd707a11d894cc2c4c2e38ab3248b34c08a9b4644
- languageName: node
- linkType: hard
-
"@types/sockjs@npm:^0.3.33":
version: 0.3.36
resolution: "@types/sockjs@npm:0.3.36"
@@ -10711,12 +10700,12 @@ __metadata:
languageName: node
linkType: hard
-"@zk-kit/imt.sol@npm:2.0.0-beta.1":
- version: 2.0.0-beta.1
- resolution: "@zk-kit/imt.sol@npm:2.0.0-beta.1"
+"@zk-kit/imt.sol@npm:2.0.0-beta.3":
+ version: 2.0.0-beta.3
+ resolution: "@zk-kit/imt.sol@npm:2.0.0-beta.3"
dependencies:
poseidon-solidity: 0.0.5
- checksum: d64e31fd735219b4ba43d830b7fb9c47794753e6703f6184180c6e075fbd53cc0e945e6e33ae131ae6a2bc8cd14d983132dd244bc0bb890bfabb1f027a2fe459
+ checksum: 53d0096ceb622eadd18a3e5f59d6e0802ee6f5292b3287aa8eaa975a99921403c89f19d1cf276746c0e07e07559c27bc7d277ff680bbdc850a82daffa3d48dea
languageName: node
linkType: hard
@@ -28220,7 +28209,7 @@ __metadata:
"@types/mocha": ^9.1.0
"@types/node": ^17.0.12
"@types/rimraf": ^3.0.2
- "@zk-kit/imt.sol": 2.0.0-beta.1
+ "@zk-kit/imt.sol": 2.0.0-beta.3
chai: ^4.3.5
circomlib: ^2.0.2
circomlibjs: ^0.1.7
@@ -28280,7 +28269,6 @@ __metadata:
"@types/jest": ^27.4.0
"@types/node": ^17.0.9
"@types/rimraf": ^3.0.2
- "@types/snarkjs": ^0.7.5
"@typescript-eslint/eslint-plugin": ^5.9.1
"@typescript-eslint/parser": ^5.9.1
babel-jest: ^27.4.6
@@ -28304,6 +28292,7 @@ __metadata:
prettier: ^2.5.1
rimraf: ^3.0.2
rollup: ^2.64.0
+ snarkjs: ^0.7.2
ts-node: ^10.4.0
tslib: ^2.3.1
typedoc: ^0.25.1
@@ -28850,7 +28839,7 @@ __metadata:
languageName: node
linkType: hard
-"snarkjs@npm:^0.7.0":
+"snarkjs@npm:^0.7.0, snarkjs@npm:^0.7.2":
version: 0.7.2
resolution: "snarkjs@npm:0.7.2"
dependencies: