From ae07f704444f19e47a123a8725e8d1c1fdba2450 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Thu, 14 May 2020 19:43:30 +0200 Subject: [PATCH] Contract Withdraw call successfully called with zkproof --- css/dark-theme.css | 9 ++-- index.html | 6 +-- index.js | 104 ++++++++++++++++++++++++++++++++++++++----- lib/miksi-browser.js | 83 +++++++++++++++++++++++++++++++--- 4 files changed, 177 insertions(+), 25 deletions(-) diff --git a/css/dark-theme.css b/css/dark-theme.css index 05ce12a..56e3a5f 100644 --- a/css/dark-theme.css +++ b/css/dark-theme.css @@ -6,15 +6,16 @@ .card, .list-group-item, input, + textarea, .nav-link { background: none!important; border-color: #3b4145; } -.dark-theme input { - color: #FF00B9; +.dark-theme input, textarea { + color: #FF00B9!important; } -.dark-theme input:focus { - color: #FF00B9; +.dark-theme input:focus, textarea:focus { + color: #FF00B9!important; box-shadow: 0px 0px 5px #FF00B9!important; border: none; } diff --git a/index.html b/index.html index 620c1bb..6590f7c 100644 --- a/index.html +++ b/index.html @@ -67,7 +67,7 @@ Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit.

-
+



@@ -76,9 +76,9 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.

- +
- +

diff --git a/index.js b/index.js index fdc5653..036ee42 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,8 @@ var circuit = {}; var provingKey = {}; var witnessCalc = {}; const abi = JSON.parse(`[{"inputs":[{"internalType":"address","name":"_depositVerifierContractAddr","type":"address"},{"internalType":"address","name":"_withdrawVerifierContractAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_commitment","type":"uint256"},{"internalType":"uint256","name":"_root","type":"uint256"},{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getCommitments","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_address","type":"address"},{"internalType":"uint256","name":"nullifier","type":"uint256"},{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]`); -const miksiAddress = "0x6E77f4bB1356426baD1Bd014d04388eFAc197Fe1"; +// const miksiAddress = "0x6E77f4bB1356426baD1Bd014d04388eFAc197Fe1"; +const miksiAddress = "0xc9009d9Df413883B6064503FDA93A7A8ab9B7afb"; function loadCircuit(circuitname) { fetch("circuits-files/"+circuitname+"-proving_key.bin").then( (response) => { @@ -28,18 +29,20 @@ async function deposit(circuitname) { console.log("circuit:", circuitname); // TODO - const secret = "1234567890"; - const nullifier = "567891234"; + const secret = miksi.randBigInt().toString(); + const nullifier = miksi.randBigInt().toString(); + // const secret = "1234567890"; + // const nullifier = "5678901234"; const commitments = []; // getCommitments from the tree // calculate witness console.log(witnessCalc[circuitname]); - const cw = await miksi.calcWitness(witnessCalc[circuitname], secret, nullifier, commitments); + const cw = await miksi.calcDepositWitness(witnessCalc[circuitname], secret, nullifier, commitments); const witness = cw.witness; const publicInputs = cw.publicInputs; console.log("w", witness); - console.log("pi", publicInputs); + console.log("publicInputs", publicInputs); // generate proof const start = new Date().getTime(); @@ -82,10 +85,89 @@ async function deposit(circuitname) { console.log(error); }); + // print secret & nullifier + let jw = { + secret: secret, + nullifier: nullifier + }; + console.log("jw", JSON.stringify(jw)); + document.getElementById("depositRes").innerHTML = ` + Please store the secret data in a safe place:
+ + + `; +} + +async function withdraw(circuitname) { + document.getElementById("withdrawRes").innerHTML = ` + Generating zkProof & making the withdraw + `; + console.log("circuit:", circuitname); + const jw = JSON.parse(document.getElementById("jsonWithdraw").value); + const secret = jw.secret; + const nullifier = jw.nullifier; + console.log(secret, nullifier); + const commitment = miksi.calcCommitment(secret, nullifier); + + // getCommitments from the tree + let res = await miksiContract.methods.getCommitments().call(); + console.log("res", res); + const commitments = res[0]; + console.log("commitments", commitments); + + // calculate witness + console.log(witnessCalc[circuitname]); + const proverAccounts = await web3.eth.getAccounts(); + const addr = proverAccounts[0]; + const cw = await miksi.calcWithdrawWitness(witnessCalc[circuitname], secret, nullifier, commitments, addr); + const witness = cw.witness; + const publicInputs = cw.publicInputs; + console.log("w", witness); + console.log("publicInputs", publicInputs); + + // generate proof + const start = new Date().getTime(); + console.log(provingKey[circuitname]); + const proof = await window.groth16GenProof(witness.buffer, provingKey[circuitname]); + const end = new Date().getTime(); + const time = end - start; + console.log("circuit " + circuitname + " took " + time + "ms to compute"); + console.log(proof); + + + // send tx + const accounts = await web3.eth.getAccounts(); + const sender = accounts[0]; + console.log("SENDER", sender); + + console.log("sc call data", + publicInputs.address, + publicInputs.nullifier, + [proof.pi_a[0], proof.pi_a[1]], + [ + [proof.pi_b[0][1], proof.pi_b[0][0]], + [proof.pi_b[1][1], proof.pi_b[1][0]] + ], + [proof.pi_c[0], proof.pi_c[1]], + ); + miksiContract.methods.withdraw( + publicInputs.address, + publicInputs.nullifier, + [proof.pi_a[0], proof.pi_a[1]], + [ + [proof.pi_b[0][1], proof.pi_b[0][0]], + [proof.pi_b[1][1], proof.pi_b[1][0]] + ], + [proof.pi_c[0], proof.pi_c[1]], + ).send( + {from: sender}, + function(error, transactionHash){ + console.log("https://goerli.etherscan.io/tx/"+transactionHash); + console.log(error); + }); + // print secret & nullifier document.getElementById("depositRes").innerHTML = ` - Secret: `+secret+`
- Nullifier: `+nullifier+`
`; } @@ -97,7 +179,7 @@ loadCircuit("withdraw"); let miksiContract; -function connectMetamask() { +async function connectMetamask() { const ethEnabled = () => { if (window.web3) { window.web3 = new Web3(window.web3.currentProvider); @@ -115,8 +197,8 @@ function connectMetamask() { miksiContract = new web3.eth.Contract(abi, miksiAddress); console.log("miksiContract", miksiContract); - web3.eth.getBalance("0x35d4dCDdB728CeBF80F748be65bf84C776B0Fbaf", function(err, res){console.log("BAL", JSON.stringify(res));}); + const acc = await web3.eth.getAccounts(); + const addr = acc[0]; + web3.eth.getBalance(addr, function(err, res){console.log("BAL", JSON.stringify(res));}); - miksiContract.methods.getCommitments().call() - .then(console.log); } diff --git a/lib/miksi-browser.js b/lib/miksi-browser.js index 590e460..de621ea 100644 --- a/lib/miksi-browser.js +++ b/lib/miksi-browser.js @@ -76276,12 +76276,12 @@ function extend() { const fs = require("fs"); const bigInt = require("big-integer"); const { groth } = require('snarkjs'); +const { Fr } = require('ffjavascript').bn128; const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils; const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder; const circomlib = require("circomlib"); const smt = require("circomlib").smt; const Web3 = require("web3"); -// const buildBn128 = require("wasmsnark").buildBn128; const nLevels = 5; @@ -76289,18 +76289,26 @@ const coinCode = "0"; // refearing to ETH const ethAmount = '1'; const amount = Web3.utils.toWei(ethAmount, 'ether'); -// let bn128; -// -// exports.init = async () => { -// bn128 = await buildBn128(); -// } +exports.randBigInt = () => { + return Fr.random(); +}; -exports.calcWitness = async (wasm, secret, nullifier, commitments) => { +exports.calcCommitment = (secret, nullifier) => { const poseidon = circomlib.poseidon.createHash(6, 8, 57); const commitment = poseidon([coinCode, amount, secret, nullifier]).toString(); + return commitment; +}; +exports.calcDepositWitness = async (wasm, secret, nullifier, commitments) => { + const poseidon = circomlib.poseidon.createHash(6, 8, 57); + const commitment = poseidon([coinCode, amount, secret, nullifier]).toString(); + + // rebuild the tree let tree = await smt.newMemEmptyTrie(); await tree.insert(1, 0); + for (let i=0; i { }; } +exports.calcWithdrawWitness = async (wasm, secret, nullifier, commitments, addr) => { + const poseidon = circomlib.poseidon.createHash(6, 8, 57); + const commitment = poseidon([coinCode, amount, secret, nullifier]).toString(); + + // rebuild the tree + let tree = await smt.newMemEmptyTrie(); + await tree.insert(1, 0); + for (let i=0; i