From fccedd776fb76e4855f24324297fd01faa94173b Mon Sep 17 00:00:00 2001 From: Koh Wei Jie Date: Wed, 31 Jul 2019 19:39:05 +0800 Subject: [PATCH] Remove broadcaster check in Semaphore.sol and the circuit (#22) * added require revert strings to contracts; modified semaphore contract test to check for said strings upgraded snarkjs commit hash added revert reason test for verifier-gte-snark-scalar-field updated package-lock.json and circleci snark file cache * removed broadcaster address check from semaphore contract; added solidity syntax highlighting for github * Removed broadcaster address public input in the circuit and in the contract Updated tests Updated snark cache for circleci --- .circleci/config.yml | 8 ++++---- .gitattributes | 1 + semaphorejs/contracts/Semaphore.sol | 13 ++++++------- semaphorejs/snark/semaphore-base.circom | 4 +--- semaphorejs/test/circuits/semaphore/circuit.js | 4 +--- semaphorejs/test/contracts/semaphore.js | 10 ++++------ 6 files changed, 17 insertions(+), 23 deletions(-) create mode 100644 .gitattributes diff --git a/.circleci/config.yml b/.circleci/config.yml index d7d46ebbb..025e7bd4e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,14 +19,14 @@ jobs: - restore_cache: name: restore-npm-cache keys: - - v1.7-dependencies-{{ checksum "package-lock.json" }} + - v1.8-dependencies-{{ checksum "package-lock.json" }} - run: npm install - save_cache: paths: - node_modules - key: v1.7-dependencies-{{ checksum "package-lock.json" }} + key: v1.8-dependencies-{{ checksum "package-lock.json" }} # checksum the snarks definitions - run: @@ -37,7 +37,7 @@ jobs: - restore_cache: name: restore-snark-cache keys: - - v1.7-dependencies-{{ checksum "build/.snark_checksum" }} + - v1.8-dependencies-{{ checksum "build/.snark_checksum" }} # build snarks - run: @@ -47,7 +47,7 @@ jobs: # cache generated snark circuit and keys - save_cache: - key: v1.7-dependencies-{{ checksum "build/.snark_checksum" }} + key: v1.8-dependencies-{{ checksum "build/.snark_checksum" }} paths: - build/circuit.json - build/proving_key.bin diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..52031de51 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sol linguist-language=Solidity diff --git a/semaphorejs/contracts/Semaphore.sol b/semaphorejs/contracts/Semaphore.sol index ec0388ada..4cd750acb 100644 --- a/semaphorejs/contracts/Semaphore.sol +++ b/semaphorejs/contracts/Semaphore.sol @@ -72,7 +72,7 @@ contract Semaphore is Verifier, MultipleMerkleTree, Ownable { uint[2] memory a, uint[2][2] memory b, uint[2] memory c, - uint[5] memory input, + uint[4] memory input, uint256 signal_hash ) public view returns (bool) { return hasNullifier(input[1]) == false && @@ -86,9 +86,12 @@ contract Semaphore is Verifier, MultipleMerkleTree, Ownable { uint[2] memory a, uint[2][2] memory b, uint[2] memory c, - uint[5] memory input, + uint[4] memory input, uint256 signal_hash ) public { + // Note that we only verify the broadcaster's address (input[4]) in the + // snark via verifyProof(). + require(hasNullifier(input[1]) == false, "Semaphore: nullifier already seen"); require(signal_hash == input[2], "Semaphore: signal hash mismatch"); require(external_nullifier == input[3], "Semaphore: external nullifier mismatch"); @@ -101,7 +104,7 @@ contract Semaphore is Verifier, MultipleMerkleTree, Ownable { uint[2] memory a, uint[2][2] memory b, uint[2] memory c, - uint[5] memory input // (root, nullifiers_hash, signal_hash, external_nullifier, broadcaster_address) + uint[4] memory input // [root, nullifiers_hash, signal_hash, external_nullifier] ) public { // Hash the signal uint256 signal_hash = uint256(sha256(signal)) >> 8; @@ -109,10 +112,6 @@ contract Semaphore is Verifier, MultipleMerkleTree, Ownable { // Check the inputs preBroadcastRequire(a, b, c, input, signal_hash); - // Verify the broadcaster's address - address broadcaster = address(input[4]); - require(broadcaster == msg.sender, "Semaphore: wrong broadcaster's address"); - signals[current_signal_index++] = signal; nullifiers_set[input[1]] = true; emit SignalBroadcast(signal, input[1], external_nullifier); diff --git a/semaphorejs/snark/semaphore-base.circom b/semaphorejs/snark/semaphore-base.circom index 62e6e8c68..eba57f919 100644 --- a/semaphorejs/snark/semaphore-base.circom +++ b/semaphorejs/snark/semaphore-base.circom @@ -47,7 +47,6 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { signal input signal_hash; signal input external_nullifier; - signal input broadcaster_address; // mimc vector commitment signal private input identity_pk[2]; @@ -143,10 +142,9 @@ template Semaphore(jubjub_field_size, n_levels, n_rounds) { // END nullifiers // BEGIN verify sig - component msg_hasher = MiMCSponge(3, n_rounds, 1); + component msg_hasher = MiMCSponge(2, 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 = EdDSAMiMCSpongeVerifier(); diff --git a/semaphorejs/test/circuits/semaphore/circuit.js b/semaphorejs/test/circuits/semaphore/circuit.js index afa5381d0..df9baa047 100644 --- a/semaphorejs/test/circuits/semaphore/circuit.js +++ b/semaphorejs/test/circuits/semaphore/circuit.js @@ -81,7 +81,7 @@ describe('circuit test', function () { const signal_hash = bigInt('5'); const broadcaster_address = bigInt('0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413'); - const msg = mimcsponge.multiHash([bigInt(external_nullifier), bigInt(signal_hash), bigInt(broadcaster_address)]); + const msg = mimcsponge.multiHash([bigInt(external_nullifier), bigInt(signal_hash)]); const signature = eddsa.signMiMCSponge(prvKey, msg); assert(eddsa.verifyMiMCSponge(msg, signature, pubKey)); @@ -106,11 +106,9 @@ describe('circuit test', function () { identity_nullifier, identity_path_elements, identity_path_index, - broadcaster_address, }); //console.log(w[circuit.getSignalIdx('main.signal_hash')]); //console.log(w[circuit.getSignalIdx('main.root')]); - assert.equal(w[circuit.getSignalIdx('main.broadcaster_address')].toString(16), broadcaster_address.toString(16)); assert(circuit.checkWitness(w)); assert(w[circuit.getSignalIdx('main.root')] == tree[0]); }); diff --git a/semaphorejs/test/contracts/semaphore.js b/semaphorejs/test/contracts/semaphore.js index 185004d0e..38991ad8a 100644 --- a/semaphorejs/test/contracts/semaphore.js +++ b/semaphorejs/test/contracts/semaphore.js @@ -100,9 +100,8 @@ contract('Semaphore', function (accounts) { const signal_hash = beBuff2int(signal_hash_raw.slice(0, 31)); const signal_to_contract = web3.utils.asciiToHex(signal_str); const accounts = await web3.eth.getAccounts(); - const broadcaster_address = bigInt(accounts[0].toString()); - const msg = mimcsponge.multiHash([bigInt(external_nullifier), bigInt(signal_hash), bigInt(broadcaster_address)]); + const msg = mimcsponge.multiHash([bigInt(external_nullifier), bigInt(signal_hash)]); const signature = eddsa.signMiMCSponge(prvKey, msg); assert(eddsa.verifyMiMCSponge(msg, signature, pubKey)); @@ -166,7 +165,6 @@ contract('Semaphore', function (accounts) { identity_nullifier, identity_path_elements, identity_path_index, - broadcaster_address, }); const root = w[circuit.getSignalIdx('main.root')]; @@ -198,7 +196,7 @@ contract('Semaphore', function (accounts) { [ proof.pi_a[0].toString(), proof.pi_a[1].toString() ], [ [ proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString() ], [ proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString() ] ], [ proof.pi_c[0].toString(), proof.pi_c[1].toString() ], - [ publicSignals[1].toString(), publicSignals[0].toString(), publicSignals[2].toString(), publicSignals[3].toString(), publicSignals[4].toString() ], + [ publicSignals[1].toString(), publicSignals[0].toString(), publicSignals[2].toString(), publicSignals[3].toString() ], ); } catch(e) { failed = true; @@ -214,7 +212,7 @@ contract('Semaphore', function (accounts) { [ proof.pi_a[0].toString(), proof.pi_a[1].toString() ], [ [ proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString() ], [ proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString() ] ], [ proof.pi_c[0].toString(), proof.pi_c[1].toString() ], - [ publicSignals[0].toString(), (publicSignals[1].add(bigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'))).toString(), publicSignals[2].toString(), publicSignals[3].toString(), publicSignals[4].toString() ], + [ publicSignals[0].toString(), (publicSignals[1].add(bigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'))).toString(), publicSignals[2].toString(), publicSignals[3].toString() ], ); } catch(e) { failed = true; @@ -226,7 +224,7 @@ contract('Semaphore', function (accounts) { const a = [ proof.pi_a[0].toString(), proof.pi_a[1].toString() ] const b = [ [ proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString() ], [ proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString() ] ] const c = [ proof.pi_c[0].toString(), proof.pi_c[1].toString() ] - const input = [ publicSignals[0].toString(), publicSignals[1].toString(), publicSignals[2].toString(), publicSignals[3].toString(), publicSignals[4].toString() ] + const input = [ publicSignals[0].toString(), publicSignals[1].toString(), publicSignals[2].toString(), publicSignals[3].toString() ] const check = await semaphore.preBroadcastCheck(a, b, c, input, bigInt(signal_hash).toString()) assert.isTrue(check)