arnaucube
arnaucube/miksi-corePublic Self-hosted repository
Separate builds for prod & tests for faster tests
arnaucube root@arnaucube.com
Sat, 23 May 2020 16:56:27 +0200
commit

9776f46e4bcbf69825cc23f028e2f7b5f9ec582c

parent

77719dbe4eac914edac8777bdc57ee1ef198c0aa

M .github/workflows/tests.yml → .github/workflows/tests.yml

@@ -20,6 +20,6 @@ - name: Install node_modules

run: npm install - name: Execute tests run: | - sh ./compile-circuits.sh + sh ./test-compile-circuits.sh npm run test-circuits npm run test-sc
M README.md → README.md

@@ -3,6 +3,7 @@

*From Esperanto, **miksi** (miks·i): to mingle, to blend, to mix, to shuffle* Ethereum mixer where all the computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract (for the *deposit* and for the *withdraw*). + This means that the client builds a MerkleTree and makes all the needed computation, and then generates a zk-proof where proves that all the offchain computation is done following all the rules (no leaf deletion, only one leaf addition, correct leaf format). This allows to use only `~325.000 gas` for the *deposit*, and `~308.000 gas` for the withdraw.
M circuits/deposit.circom → circuits/deposit.circom

@@ -107,4 +107,4 @@ smtNew.key <== key;

smtNew.value <== hash.out; } -component main = Deposit(17); // 16 real levels (due circom leaf protection) +/* component main = Deposit(17); // 16 real levels (due circom leaf protection) */
A circuits/main/deposit.circom

@@ -0,0 +1,2 @@

+include "../deposit.circom"; +component main = Deposit(17); // 16 real levels (due circom leaf protection)
A circuits/main/withdraw.circom

@@ -0,0 +1,3 @@

+include "../withdraw.circom"; + +component main = Withdraw(17); // 16 real levels (due circom leaf protection)
M circuits/withdraw.circom → circuits/withdraw.circom

@@ -62,4 +62,4 @@ smtV.key <== key;

smtV.value <== hash.out; } -component main = Withdraw(17); // 16 real levels (due circom leaf protection) +/* component main = Withdraw(17); // 16 real levels (due circom leaf protection) */
M compile-circuits.sh → compile-circuits.sh

@@ -6,9 +6,9 @@ mkdir build

cd build compile_and_ts() { - echo $(date +"%T") "circom ../circuits/$CIRCUIT.circom --r1cs --wasm --sym" + echo $(date +"%T") "circom ../circuits/main/$CIRCUIT.circom --r1cs --wasm --sym" itime="$(date -u +%s)" - ../node_modules/.bin/circom ../circuits/$CIRCUIT.circom --r1cs --wasm --sym + ../node_modules/.bin/circom ../circuits/main/$CIRCUIT.circom --r1cs --wasm --sym ftime="$(date -u +%s)" echo " ($(($(date -u +%s)-$itime))s)"
M migrations/2_deploy_contracts.js → migrations/2_deploy_contracts.js

@@ -1,5 +1,5 @@

-const DepositVerifier = artifacts.require("../contracts/DepositVerifier"); -const WithdrawVerifier = artifacts.require("../contracts/WithdrawVerifier"); +const DepositVerifier = artifacts.require("../test/build/DepositVerifier"); +const WithdrawVerifier = artifacts.require("../test/build/WithdrawVerifier"); module.exports = function(deployer) { deployer.deploy(DepositVerifier);
A test-compile-circuits.sh

@@ -0,0 +1,55 @@

+#!/bin/sh + +# This file compiles the circuits to generate the test files + +# npm install +cd test +rm -r build +mkdir build +cd build + +compile_and_ts() { + echo $(date +"%T") "circom ../circuits/main/$CIRCUIT.circom --r1cs --wasm --sym" + itime="$(date -u +%s)" + ../../node_modules/.bin/circom ../circuits/main/$CIRCUIT.circom --r1cs --wasm --sym + ftime="$(date -u +%s)" + echo " ($(($(date -u +%s)-$itime))s)" + + echo $(date +"%T") "snarkjs info -r $CIRCUIT.r1cs" + ../../node_modules/.bin/snarkjs info -r $CIRCUIT.r1cs + + echo $(date +"%T") "snarkjs setup" + itime="$(date -u +%s)" + ../../node_modules/.bin/snarkjs setup -r $CIRCUIT.r1cs --pk $CIRCUIT-proving_key.json --vk $CIRCUIT-verification_key.json + echo " ($(($(date -u +%s)-$itime))s)" + echo $(date +"%T") "trusted setup generated" + + # sed -i 's/null/["0","0","0"]/g' proving_key.json + + + echo $(date +"%T") "snarkjs generateverifier" + itime="$(date -u +%s)" + ../../node_modules/.bin/snarkjs generateverifier --vk $CIRCUIT-verification_key.json -v $CIRCUIT-verifier.sol + echo " ($(($(date -u +%s)-$itime))s)" + echo $(date +"%T") "generateverifier generated" + + sed -i "s/solidity ^0.5.0/solidity ^0.6.0/g" ${CIRCUIT}-verifier.sol + sed -i "s/gas/gas()/g" ${CIRCUIT}-verifier.sol + sed -i "s/return the sum/return r the sum/g" ${CIRCUIT}-verifier.sol + sed -i "s/return the product/return r the product/g" ${CIRCUIT}-verifier.sol + sed -i "s/contract Verifier/contract ${CONTRACT}Verifier/g" ${CIRCUIT}-verifier.sol + sed -i "s/Pairing/${CONTRACT}Pairing/g" ${CIRCUIT}-verifier.sol + # cp ${CIRCUIT}-verifier.sol ../contracts/ + + node ../../node_modules/wasmsnark/tools/buildpkey.js -i ${CIRCUIT}-proving_key.json -o ${CIRCUIT}-proving_key.bin +} + +CIRCUIT="deposit" +CONTRACT="Deposit" +compile_and_ts +CIRCUIT="withdraw" +CONTRACT="Withdraw" +compile_and_ts + +cp ../../contracts/Miksi.sol ./Miksi.sol +cp -r ../../contracts/helpers ./helpers
M test/circuits/deposit.test.ts → test/circuits/deposit.test.ts

@@ -13,11 +13,11 @@

it("Test Deposit", async () => { const circuit = await tester( - path.join(__dirname, "../../circuits", "deposit.circom"), + path.join(__dirname, "main", "deposit.circom"), {reduceConstraints: false} ); - const nLevels = 17; + const nLevels = 4; const secret = "1234567890"; const coinCode = "0";
A test/circuits/main/deposit.circom

@@ -0,0 +1,3 @@

+include "../../../circuits/deposit.circom"; + +component main = Deposit(4);
A test/circuits/main/withdraw.circom

@@ -0,0 +1,3 @@

+include "../../../circuits/withdraw.circom"; + +component main = Withdraw(4);
M test/circuits/withdraw.test.ts → test/circuits/withdraw.test.ts

@@ -13,11 +13,11 @@

it("Test Withdraw", async () => { const circuit = await tester( - path.join(__dirname, "../../circuits", "withdraw.circom"), + path.join(__dirname, "main", "withdraw.circom"), {reduceConstraints: false} ); - const nLevels = 17; + const nLevels = 4; const secret = "1234567890"; const coinCode = "0";
M test/contracts/miksi.test.ts → test/contracts/miksi.test.ts

@@ -1,6 +1,6 @@

-const DepositVerifier = artifacts.require("../../contracts/DepositVerifier"); -const WithdrawVerifier = artifacts.require("../../contracts/WithdrawVerifier"); -const Miksi = artifacts.require("../../contracts/Miksi.sol"); +const DepositVerifier = artifacts.require("../build/DepositVerifier"); +const WithdrawVerifier = artifacts.require("../build/WithdrawVerifier"); +const Miksi = artifacts.require("../build/Miksi.sol"); const chai = require("chai"); const expect = chai.expect;

@@ -16,7 +16,7 @@

let insVerifier; let insMiksi; -const nLevels = 17; +const nLevels = 4; const secret = ["1234567890", "987654321", "123"]; const coinCode = "0"; // refearing to ETH

@@ -105,7 +105,6 @@ expect(treeTmp.root).to.be.equal(tree.root);

}); it("Calculate witness and generate the zkProof", async () => { - this.timeout(10000000); await genZKProof(0, addr2, "1"); await genZKProof(1, addr4, "2"); await genZKProof(2, addr4, "3");

@@ -193,7 +192,7 @@ siblingsNew[u].push("0");

}; // calculate witness - const wasm = await fs.promises.readFile("./build/deposit.wasm"); + const wasm = await fs.promises.readFile("./test/build/deposit.wasm"); const input = unstringifyBigInts({ "coinCode": coinCode, "amount": amount,

@@ -215,14 +214,14 @@ const w = await wc.calculateWitness(input);

const witness = unstringifyBigInts(stringifyBigInts(w)); // generate zkproof of commitment using snarkjs (as is a test) - const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./build/deposit-proving_key.json", "utf8"))); + const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./test/build/deposit-proving_key.json", "utf8"))); // console.log("Generate zkSNARK proof"); const res = groth.genProof(provingKey, witness); proof[u] = res.proof; publicSignals[u] = res.publicSignals; - const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./build/deposit-verification_key.json", "utf8"))); + const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./test/build/deposit-verification_key.json", "utf8"))); let pubI = unstringifyBigInts([coinCode, amount, rootOld[u].toString(), rootNew[u].toString(), commitment[u], currKey]); let validCheck = groth.isValid(verificationKey, proof[u], pubI); assert(validCheck);

@@ -250,7 +249,7 @@ };

// console.log("siblings", siblings); // calculate witness - const wasm = await fs.promises.readFile("./build/withdraw.wasm"); + const wasm = await fs.promises.readFile("./test/build/withdraw.wasm"); const input = unstringifyBigInts({ "coinCode": coinCode, "amount": amount,

@@ -268,7 +267,7 @@ const w = await wc.calculateWitness(input);

const witness = unstringifyBigInts(stringifyBigInts(w)); // generate zkproof of commitment using snarkjs (as is a test) - const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./build/withdraw-proving_key.json", "utf8"))); + const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./test/build/withdraw-proving_key.json", "utf8"))); // console.log("Generate zkSNARK proof"); const res = groth.genProof(provingKey, witness);
M truffle-config.js → truffle-config.js

@@ -18,6 +18,7 @@ // to customize your Truffle configuration!

enableTimeouts: false, before_timeout: 1000000000, test_timeout: 1000000000, + contracts_directory: "./test/build", compilers: { solc: { version: "0.6.0"