diff --git a/circuits/withdraw.circom b/circuits/withdraw.circom index f331220..c33c25c 100644 --- a/circuits/withdraw.circom +++ b/circuits/withdraw.circom @@ -11,6 +11,10 @@ PUB_amount+--------->+Poseidon+------->+ == +<-----+PUB_commitment PRI_secret+--------->+ | +--------+ + +----+ +PUB_address+--->+ != +<---+0 + +----+ + */ @@ -27,6 +31,7 @@ template Withdraw() { signal input amount; signal input commitment; signal private input secret; + signal input address; component hash = Poseidon(3, 6, 8, 57); hash.inputs[0] <== coinCode; @@ -37,6 +42,10 @@ template Withdraw() { eq.in[0] <== hash.out; eq.in[1] <== commitment; eq.out === 1; + + component z = IsZero(); + z.in <== address; + z.out === 0; } component main = Withdraw(); diff --git a/contracts/Miksi.sol b/contracts/Miksi.sol index c8ca843..72c6f27 100644 --- a/contracts/Miksi.sol +++ b/contracts/Miksi.sol @@ -18,10 +18,10 @@ contract Miksi { function deposit( uint256 coinCode, - uint256 amount, + // uint256 amount, uint256 commitment - ) public { - deposits[commitment] = Deposit(coinCode, amount); + ) public payable { + deposits[commitment] = Deposit(coinCode, msg.value); } function getDeposit( @@ -35,18 +35,22 @@ contract Miksi { function withdraw( uint256 commitment, + address payable _address, uint[2] memory a, uint[2][2] memory b, uint[2] memory c ) public { - uint256[3] memory input = [ + uint256[4] memory input = [ deposits[commitment].coinCode, deposits[commitment].amount, - commitment + commitment, + uint256(_address) ]; require(verifier.verifyProof(a, b, c, input), "zkProof withdraw could not be verified"); - // zk verification passed, proceed with the withdraw + _address.send(deposits[commitment].amount); + // _address.call.value(deposits[commitment].amount).gas(20317)(); + } } diff --git a/contracts/verifier.sol b/contracts/verifier.sol index dd7cca9..061ba45 100644 --- a/contracts/verifier.sol +++ b/contracts/verifier.sol @@ -174,15 +174,16 @@ contract Verifier { Pairing.G1Point C; } function verifyingKey() internal pure returns (VerifyingKey memory vk) { - vk.alfa1 = Pairing.G1Point(14097801211944906051089174223297219347615673653483074396722237348255135354793,11521805996213505094241296676841118790602800394351210524781678600259635687017); - vk.beta2 = Pairing.G2Point([10568113084382768459048600842325733541704319994390569016962727798975578285556,12153127494717088082185264166292331483064881810067105818973650106079389053760], [15466853815350922606512198371753750557123426982658771465057849995060646541965,19455599286846641316750628844277996370086220302684811162394897510245086369063]); - vk.gamma2 = Pairing.G2Point([9953206108281020354042857864759150528133680155656326486566810703438203105960,2135441618643414785978676900143212634198799871478347410262755821177928527954], [12268954056182736147684854354337352872362113322749551731236862327324643375709,1876815956335882350254399331991656204647508838653345904292805224558359111754]); - vk.delta2 = Pairing.G2Point([2663201400823710456782609562902977142452976016992514856722909325946187937310,14978203394907966123099039365683754435614065359984166192966572314168591418734], [21214052898049569224905859982289894645182104181183009284067141977584101227593,5359205214835186177822827375213125847159194113298572556544149883988483807673]); - vk.IC = new Pairing.G1Point[](4); - vk.IC[0] = Pairing.G1Point(13408366362878504901998541398762720605356468458453065115215476638573116973612,5444591120479812671974498312523952995185895771090546719531123873877970703107); - vk.IC[1] = Pairing.G1Point(17521475475731634509173671006849258017401865133255449322161532195113052551951,9591040297172512635747124918118916335434286018868426662476696440648139959562); - vk.IC[2] = Pairing.G1Point(10318918062415458864931153468077926819897264015796609757736600478356825989809,2525805381962488186604363053663950289666098935158384096965441697921773574413); - vk.IC[3] = Pairing.G1Point(12285798798872837559598057721617037310744162378880792291377164843222236229469,16499092667373175512569946766276627516609608654521959670983218776858111396618); + vk.alfa1 = Pairing.G1Point(5185992386807636752062921178966578257539151042202977558020078229066726353735,19116203848700332781926088278955228321025476213248649030230870938462300903297); + vk.beta2 = Pairing.G2Point([19030978247664556689560141272090896525855193446598104251860042964819095406467,19780960404766112404848074878225825567855499848739061882556607695385088991192], [20402461031267926255530100927046942331147898484488092600018001239630447470368,17604138488196164031519027655960050500952176071938159024932979559575610655320]); + vk.gamma2 = Pairing.G2Point([20383216224167453593158000496263161259331265217720672612685782338425828607013,12285091765781487940062490824680322009247635572831566743154406937445855014141], [2724044019507218108155409647671037824297854833037683233209628555415178462971,4800441398018446385507678136399891972502082696226688244556543968658013445721]); + vk.delta2 = Pairing.G2Point([17491660837811889973732218736865963003206037853732483884984507582280081743890,18194603073278150162885840058572458854817989194824624275670491325570842555401], [14259520890547064112120136619441621870946603290427647212804054747278532372550,14237711745170441984980821720645206187129227373288931343140891164943633394176]); + vk.IC = new Pairing.G1Point[](5); + vk.IC[0] = Pairing.G1Point(5800430773422603830326865012746294458553705291090306505082228589953960548435,525261600745641876890318660619064985918284670178585976847597013044968033805); + vk.IC[1] = Pairing.G1Point(13962429114312903407632291539456657530314035590343134693033142826413285622014,9649969769508662299834286176418790329944910509961747776147748835638371066986); + vk.IC[2] = Pairing.G1Point(15449758800146945182032375987369505286936830519651791301171981724664755129658,20429634243561140221481565627307606983692378272988345590135001254474940660921); + vk.IC[3] = Pairing.G1Point(6593016958529739953865018414912427672210776178723941512691424600884151791016,2330860586625886543272754640931712670362458263865839970599736410727810605340); + vk.IC[4] = Pairing.G1Point(17799933908098896756054489526152304776886935915002907298028930270007186443766,16808221405053081411172376396342768077671335058872875437488630198515891174714); } function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { @@ -208,7 +209,7 @@ contract Verifier { uint[2] memory a, uint[2][2] memory b, uint[2] memory c, - uint[3] memory input + uint[4] memory input ) public view returns (bool r) { Proof memory proof; proof.A = Pairing.G1Point(a[0], a[1]); diff --git a/test/circuits/withdraw.test.ts b/test/circuits/withdraw.test.ts index 34c814c..19d0821 100644 --- a/test/circuits/withdraw.test.ts +++ b/test/circuits/withdraw.test.ts @@ -29,7 +29,8 @@ describe("withdraw test", function () { "coinCode": coinCode, "amount": amount, "commitment": commitment, - "secret": secret + "secret": secret, + "address": "987654321" }); await circuit.checkConstraints(witness); }); diff --git a/test/contracts/miksi.test.ts b/test/contracts/miksi.test.ts index fd6fe66..18e5057 100644 --- a/test/contracts/miksi.test.ts +++ b/test/contracts/miksi.test.ts @@ -15,9 +15,9 @@ contract("miksi", (accounts) => { const { 0: owner, - 1: idEth1, - 2: idEth2, - 3: idEth3, + 1: addr1, // used for the deposit + 2: addr2, // used for the withdraw + 3: addr3, } = accounts; let insVerifier; @@ -32,14 +32,24 @@ contract("miksi", (accounts) => { it("miksi flow", async () => { const secret = "123456789"; - const coinCode = "1"; - const amount = "100"; + const coinCode = "0"; // refearing to ETH + const ethAmount = '0.5'; + const amount = web3.utils.toWei(ethAmount, 'ether'); + + let balance_wei = await web3.eth.getBalance(addr1); + console.log("Balance at " + addr1, web3.utils.fromWei(balance_wei, 'ether')); + expect(balance_wei).to.be.equal('100000000000000000000'); const poseidon = circomlib.poseidon.createHash(6, 8, 57); const commitment = poseidon([coinCode, amount, secret]).toString(); // deposit - await insMiksi.deposit(coinCode, amount, commitment); + console.log("Deposit of " + ethAmount + " ETH from " + addr1); + await insMiksi.deposit(coinCode, commitment, {from: addr1, value: amount}); + + balance_wei = await web3.eth.getBalance(addr1); + console.log("Balance at " + addr1, web3.utils.fromWei(balance_wei, 'ether')); + expect(balance_wei).to.be.equal('99499141300000000000'); // getDeposit data const res = await insMiksi.getDeposit(commitment); @@ -53,9 +63,11 @@ contract("miksi", (accounts) => { "coinCode": coinCode, "amount": amount, "commitment": commitment, - "secret": secret + "secret": secret, + "address": addr2 }); const options = {}; + console.log("Calculate witness"); const wc = await WitnessCalculatorBuilder(wasm, options); const w = await wc.calculateWitness(input); const witness = unstringifyBigInts(stringifyBigInts(w)); @@ -63,11 +75,14 @@ contract("miksi", (accounts) => { // generate zkproof of commitment using snarkjs (as is a test) const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./build/proving_key.json", "utf8"))); + console.log("Generate zkSNARK proof"); const {proof, publicSignals} = groth.genProof(provingKey, witness); // withdraw + console.log("Withdraw of " + ethAmount + " ETH to " + addr2); const resW = await insMiksi.withdraw( commitment, + addr2, [proof.pi_a[0].toString(), proof.pi_a[1].toString()], [ [proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString()], @@ -75,7 +90,10 @@ contract("miksi", (accounts) => { ], [proof.pi_c[0].toString(), proof.pi_c[1].toString()] ); - console.log("resW", resW); + // console.log("resW", resW); + balance_wei = await web3.eth.getBalance(addr2); + console.log("Balance at " + addr2, web3.utils.fromWei(balance_wei, 'ether')); + expect(balance_wei).to.be.equal('100500000000000000000'); }); });