You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
4.5 KiB

  1. var circuit = {};
  2. var provingKey = {};
  3. var witnessCalc = {};
  4. 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"}]`);
  5. const miksiAddress = "0x6E77f4bB1356426baD1Bd014d04388eFAc197Fe1";
  6. function loadCircuit(circuitname) {
  7. fetch("circuits-files/"+circuitname+"-proving_key.bin").then( (response) => {
  8. return response.arrayBuffer();
  9. }).then( (b) => {
  10. provingKey[circuitname] = b;
  11. console.log("proving_key loaded for", circuitname);
  12. });
  13. fetch("circuits-files/"+circuitname+".wasm").then( (response) => {
  14. return response.arrayBuffer();
  15. }).then( (b) => {
  16. witnessCalc[circuitname] = b;
  17. console.log("w", b);
  18. console.log("witnessCalc loaded for", circuitname);
  19. });
  20. }
  21. async function deposit(circuitname) {
  22. document.getElementById("depositRes").innerHTML = `
  23. Generating zkProof & making the deposit
  24. `;
  25. console.log("circuit:", circuitname);
  26. // TODO
  27. const secret = "1234567890";
  28. const nullifier = "567891234";
  29. const commitments = [];
  30. // getCommitments from the tree
  31. // calculate witness
  32. console.log(witnessCalc[circuitname]);
  33. const cw = await miksi.calcWitness(witnessCalc[circuitname], secret, nullifier, commitments);
  34. const witness = cw.witness;
  35. const publicInputs = cw.publicInputs;
  36. console.log("w", witness);
  37. console.log("pi", publicInputs);
  38. // generate proof
  39. const start = new Date().getTime();
  40. console.log(provingKey[circuitname]);
  41. const proof = await window.groth16GenProof(witness.buffer, provingKey[circuitname]);
  42. const end = new Date().getTime();
  43. const time = end - start;
  44. console.log("circuit " + circuitname + " took " + time + "ms to compute");
  45. console.log(proof);
  46. // send tx
  47. const accounts = await web3.eth.getAccounts();
  48. const sender = accounts[0];
  49. console.log("SENDER", sender);
  50. console.log("sc call data",
  51. publicInputs.commitment,
  52. publicInputs.root.toString(),
  53. [proof.pi_a[0], proof.pi_a[1]],
  54. [
  55. [proof.pi_b[0][1], proof.pi_b[0][0]],
  56. [proof.pi_b[1][1], proof.pi_b[1][0]]
  57. ],
  58. [proof.pi_c[0], proof.pi_c[1]],
  59. );
  60. miksiContract.methods.deposit(
  61. publicInputs.commitment,
  62. publicInputs.root.toString(),
  63. [proof.pi_a[0], proof.pi_a[1]],
  64. [
  65. [proof.pi_b[0][1], proof.pi_b[0][0]],
  66. [proof.pi_b[1][1], proof.pi_b[1][0]]
  67. ],
  68. [proof.pi_c[0], proof.pi_c[1]],
  69. ).send(
  70. {from: sender, value: 1000000000000000000},
  71. function(error, transactionHash){
  72. console.log("https://goerli.etherscan.io/tx/"+transactionHash);
  73. console.log(error);
  74. });
  75. // print secret & nullifier
  76. document.getElementById("depositRes").innerHTML = `
  77. Secret: <b>`+secret+`</b><br>
  78. Nullifier: <b>`+nullifier+`</b><br>
  79. `;
  80. }
  81. loadCircuit("deposit");
  82. loadCircuit("withdraw");
  83. let miksiContract;
  84. function connectMetamask() {
  85. const ethEnabled = () => {
  86. if (window.web3) {
  87. window.web3 = new Web3(window.web3.currentProvider);
  88. window.ethereum.enable();
  89. return true;
  90. }
  91. return false;
  92. }
  93. if (!ethEnabled()) {
  94. alert("Please install MetaMask to use miksi");
  95. }
  96. console.log("abi", abi);
  97. miksiContract = new web3.eth.Contract(abi, miksiAddress);
  98. console.log("miksiContract", miksiContract);
  99. web3.eth.getBalance("0x35d4dCDdB728CeBF80F748be65bf84C776B0Fbaf", function(err, res){console.log("BAL", JSON.stringify(res));});
  100. miksiContract.methods.getCommitments().call()
  101. .then(console.log);
  102. }