mirror of
https://github.com/arnaucube/miksi-app.git
synced 2026-02-06 19:26:49 +01:00
Contract Withdraw call successfully called with zkproof
This commit is contained in:
@@ -6,15 +6,16 @@
|
|||||||
.card,
|
.card,
|
||||||
.list-group-item,
|
.list-group-item,
|
||||||
input,
|
input,
|
||||||
|
textarea,
|
||||||
.nav-link {
|
.nav-link {
|
||||||
background: none!important;
|
background: none!important;
|
||||||
border-color: #3b4145;
|
border-color: #3b4145;
|
||||||
}
|
}
|
||||||
.dark-theme input {
|
.dark-theme input, textarea {
|
||||||
color: #FF00B9;
|
color: #FF00B9!important;
|
||||||
}
|
}
|
||||||
.dark-theme input:focus {
|
.dark-theme input:focus, textarea:focus {
|
||||||
color: #FF00B9;
|
color: #FF00B9!important;
|
||||||
box-shadow: 0px 0px 5px #FF00B9!important;
|
box-shadow: 0px 0px 5px #FF00B9!important;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit.
|
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit.
|
||||||
<br><br>
|
<br><br>
|
||||||
<button onclick="deposit('deposit')" class="btn color_primary float-right">Deposit 1 ETH</button>
|
<button onclick="deposit('deposit')" class="btn color_primary float-right">Deposit 1 ETH</button>
|
||||||
<br>
|
<br><br>
|
||||||
<div id="depositRes"></div>
|
<div id="depositRes"></div>
|
||||||
<br><br>
|
<br><br>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
<hr>
|
<hr>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.
|
||||||
<br><br>
|
<br><br>
|
||||||
<input id="secret" type="text" class="form-control" placeholder="secret" value="1234567890"></input>
|
<textarea id="jsonWithdraw" class="form-control" style="width:100%;" placeholder="paste here your secret & nullifier"></textarea>
|
||||||
<br>
|
<br>
|
||||||
<input id="nullifier" type="text" class="form-control" placeholder="nullifier" value="567891234"></input>
|
<input id="withdrawAddress" class="form-control" placeholder="address where to withdraw"></input>
|
||||||
<br>
|
<br>
|
||||||
<button onclick="withdraw('withdraw')" class="btn color_primary float-right">Withdraw 1 ETH</button>
|
<button onclick="withdraw('withdraw')" class="btn color_primary float-right">Withdraw 1 ETH</button>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
104
index.js
104
index.js
@@ -2,7 +2,8 @@ var circuit = {};
|
|||||||
var provingKey = {};
|
var provingKey = {};
|
||||||
var witnessCalc = {};
|
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 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) {
|
function loadCircuit(circuitname) {
|
||||||
fetch("circuits-files/"+circuitname+"-proving_key.bin").then( (response) => {
|
fetch("circuits-files/"+circuitname+"-proving_key.bin").then( (response) => {
|
||||||
@@ -28,18 +29,20 @@ async function deposit(circuitname) {
|
|||||||
console.log("circuit:", circuitname);
|
console.log("circuit:", circuitname);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
const secret = "1234567890";
|
const secret = miksi.randBigInt().toString();
|
||||||
const nullifier = "567891234";
|
const nullifier = miksi.randBigInt().toString();
|
||||||
|
// const secret = "1234567890";
|
||||||
|
// const nullifier = "5678901234";
|
||||||
const commitments = [];
|
const commitments = [];
|
||||||
// getCommitments from the tree
|
// getCommitments from the tree
|
||||||
|
|
||||||
// calculate witness
|
// calculate witness
|
||||||
console.log(witnessCalc[circuitname]);
|
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 witness = cw.witness;
|
||||||
const publicInputs = cw.publicInputs;
|
const publicInputs = cw.publicInputs;
|
||||||
console.log("w", witness);
|
console.log("w", witness);
|
||||||
console.log("pi", publicInputs);
|
console.log("publicInputs", publicInputs);
|
||||||
|
|
||||||
// generate proof
|
// generate proof
|
||||||
const start = new Date().getTime();
|
const start = new Date().getTime();
|
||||||
@@ -82,10 +85,89 @@ async function deposit(circuitname) {
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// print secret & nullifier
|
||||||
|
let jw = {
|
||||||
|
secret: secret,
|
||||||
|
nullifier: nullifier
|
||||||
|
};
|
||||||
|
console.log("jw", JSON.stringify(jw));
|
||||||
|
document.getElementById("depositRes").innerHTML = `
|
||||||
|
<b>Please store the secret data in a safe place:</b><br>
|
||||||
|
<input class="form-control" onClick="this.select();" readonly value='`+JSON.stringify(jw)+`'>
|
||||||
|
</input>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// print secret & nullifier
|
||||||
document.getElementById("depositRes").innerHTML = `
|
document.getElementById("depositRes").innerHTML = `
|
||||||
Secret: <b>`+secret+`</b><br>
|
|
||||||
Nullifier: <b>`+nullifier+`</b><br>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +179,7 @@ loadCircuit("withdraw");
|
|||||||
|
|
||||||
let miksiContract;
|
let miksiContract;
|
||||||
|
|
||||||
function connectMetamask() {
|
async function connectMetamask() {
|
||||||
const ethEnabled = () => {
|
const ethEnabled = () => {
|
||||||
if (window.web3) {
|
if (window.web3) {
|
||||||
window.web3 = new Web3(window.web3.currentProvider);
|
window.web3 = new Web3(window.web3.currentProvider);
|
||||||
@@ -115,8 +197,8 @@ function connectMetamask() {
|
|||||||
miksiContract = new web3.eth.Contract(abi, miksiAddress);
|
miksiContract = new web3.eth.Contract(abi, miksiAddress);
|
||||||
console.log("miksiContract", miksiContract);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76276,12 +76276,12 @@ function extend() {
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
const { groth } = require('snarkjs');
|
const { groth } = require('snarkjs');
|
||||||
|
const { Fr } = require('ffjavascript').bn128;
|
||||||
const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils;
|
const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils;
|
||||||
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
|
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
|
||||||
const circomlib = require("circomlib");
|
const circomlib = require("circomlib");
|
||||||
const smt = require("circomlib").smt;
|
const smt = require("circomlib").smt;
|
||||||
const Web3 = require("web3");
|
const Web3 = require("web3");
|
||||||
// const buildBn128 = require("wasmsnark").buildBn128;
|
|
||||||
|
|
||||||
|
|
||||||
const nLevels = 5;
|
const nLevels = 5;
|
||||||
@@ -76289,18 +76289,26 @@ const coinCode = "0"; // refearing to ETH
|
|||||||
const ethAmount = '1';
|
const ethAmount = '1';
|
||||||
const amount = Web3.utils.toWei(ethAmount, 'ether');
|
const amount = Web3.utils.toWei(ethAmount, 'ether');
|
||||||
|
|
||||||
// let bn128;
|
exports.randBigInt = () => {
|
||||||
//
|
return Fr.random();
|
||||||
// exports.init = async () => {
|
};
|
||||||
// bn128 = await buildBn128();
|
|
||||||
// }
|
|
||||||
|
|
||||||
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 poseidon = circomlib.poseidon.createHash(6, 8, 57);
|
||||||
const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
|
const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
|
||||||
|
|
||||||
|
// rebuild the tree
|
||||||
let tree = await smt.newMemEmptyTrie();
|
let tree = await smt.newMemEmptyTrie();
|
||||||
await tree.insert(1, 0);
|
await tree.insert(1, 0);
|
||||||
|
for (let i=0; i<commitments.length; i++) {
|
||||||
|
await tree.insert(commitments[i], 0);
|
||||||
|
}
|
||||||
|
|
||||||
// old root
|
// old root
|
||||||
const rootOld = tree.root;
|
const rootOld = tree.root;
|
||||||
@@ -76367,6 +76375,67 @@ exports.calcWitness = async (wasm, secret, nullifier, commitments) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<commitments.length; i++) {
|
||||||
|
await tree.insert(commitments[i], 0);
|
||||||
|
}
|
||||||
|
// await tree.insert(commitment, 0);
|
||||||
|
|
||||||
|
// root
|
||||||
|
const root = tree.root;
|
||||||
|
const res = await tree.find(commitment);
|
||||||
|
if (!res.found) {
|
||||||
|
console.error("leaf expect to exist but not exists");
|
||||||
|
}
|
||||||
|
let siblings = res.siblings;
|
||||||
|
while (siblings.length < nLevels) {
|
||||||
|
siblings.push("0");
|
||||||
|
};
|
||||||
|
|
||||||
|
// calculate witness
|
||||||
|
const input = unstringifyBigInts({
|
||||||
|
"coinCode": coinCode,
|
||||||
|
"amount": amount,
|
||||||
|
"secret": secret,
|
||||||
|
"nullifier": nullifier,
|
||||||
|
"siblings": siblings,
|
||||||
|
"root": root,
|
||||||
|
"address": addr
|
||||||
|
});
|
||||||
|
console.log("input", input);
|
||||||
|
// const options = {};
|
||||||
|
// const wc = await WitnessCalculatorBuilder(wasm, options);
|
||||||
|
|
||||||
|
const wc = await WitnessCalculatorBuilder(wasm);
|
||||||
|
|
||||||
|
const witness = await wc.calculateWitness(input, {sanityCheck: true});
|
||||||
|
|
||||||
|
const wBuff = Buffer.allocUnsafe(witness.length*32);
|
||||||
|
|
||||||
|
for (let i=0; i<witness.length; i++) {
|
||||||
|
for (let j=0; j<8; j++) {
|
||||||
|
const bi = witness[i];
|
||||||
|
const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
|
||||||
|
wBuff.writeUInt32LE(v, i*32 + j*4, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// const witness = unstringifyBigInts(stringifyBigInts(w));
|
||||||
|
return {
|
||||||
|
witness: wBuff,
|
||||||
|
publicInputs: {
|
||||||
|
address:addr,
|
||||||
|
nullifier:nullifier
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}).call(this,require("buffer").Buffer)
|
}).call(this,require("buffer").Buffer)
|
||||||
|
|||||||
Reference in New Issue
Block a user