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.

159 lines
4.3 KiB

  1. const fs = require("fs");
  2. const bigInt = require("big-integer");
  3. const { groth } = require('snarkjs');
  4. const { Fr } = require('ffjavascript').bn128;
  5. const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils;
  6. const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
  7. const circomlib = require("circomlib");
  8. const smt = require("circomlib").smt;
  9. const Web3 = require("web3");
  10. // const buildBn128 = require("wasmsnark").buildBn128;
  11. const coinCode = "0"; // refearing to ETH
  12. const ethAmount = '1';
  13. const amount = Web3.utils.toWei(ethAmount, 'ether');
  14. exports.randBigInt = () => {
  15. return Fr.random();
  16. };
  17. exports.calcCommitment = (key, secret) => {
  18. const poseidon = circomlib.poseidon.createHash(6, 8, 57);
  19. const nullifier = poseidon([key, secret]).toString();
  20. const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
  21. return commitment;
  22. };
  23. exports.calcDepositWitness = async (wasm, nLevels, key, secret, commitments) => {
  24. const poseidon = circomlib.poseidon.createHash(6, 8, 57);
  25. const nullifier = poseidon([key, secret]).toString();
  26. const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
  27. console.log("Commitment", commitment.toString());
  28. // rebuild the tree
  29. let tree = await smt.newMemEmptyTrie();
  30. await tree.insert(0, 0);
  31. for (let i=0; i <commitments.length; i++) {
  32. await tree.insert(i+1, commitments[i]);
  33. }
  34. let res = await tree.insert(key, commitment);
  35. // new root
  36. let siblings = res.siblings;
  37. console.log(res);
  38. // while (siblings.length < nLevels) {
  39. // siblings.push("0");
  40. // };
  41. // calculate witness
  42. const input = unstringifyBigInts({
  43. "coinCode": coinCode,
  44. "amount": amount,
  45. "secret": secret,
  46. "oldKey": res.isOld0 ? 0 : res.oldKey,
  47. "oldValue": res.isOld0 ? 0 : res.oldValue,
  48. "isOld0": res.isOld0 ? 1 : 0,
  49. "siblings": siblings,
  50. "rootOld": res.oldRoot,
  51. "rootNew": res.newRoot,
  52. "commitment": commitment,
  53. "key": key
  54. });
  55. console.log("input", input);
  56. // const options = {};
  57. // const wc = await WitnessCalculatorBuilder(wasm, options);
  58. const wc = await WitnessCalculatorBuilder(wasm);
  59. const witness = await wc.calculateWitness(input, {sanityCheck: true});
  60. const wBuff = Buffer.allocUnsafe(witness.length*32);
  61. for (let i=0; i <witness.length; i++) {
  62. for (let j=0; j <8; j++) {
  63. const bi = witness[i];
  64. const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
  65. // wBuff.writeUInt32LE(v, i*32 + j*4, 4)
  66. wBuff.writeUInt32LE(v, i*32 + j*4)
  67. }
  68. }
  69. // const witness = unstringifyBigInts(stringifyBigInts(w));
  70. // return wBuff;
  71. return {
  72. witness: wBuff,
  73. publicInputs: {
  74. commitment:commitment,
  75. root:res.newRoot
  76. }
  77. };
  78. }
  79. exports.calcWithdrawWitness = async (wasm, nLevels, key, secret, commitments, addr) => {
  80. const poseidon = circomlib.poseidon.createHash(6, 8, 57);
  81. const nullifier = poseidon([key, secret]).toString();
  82. const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
  83. // rebuild the tree
  84. let tree = await smt.newMemEmptyTrie();
  85. await tree.insert(0, 0);
  86. for (let i=0; i <commitments.length; i++) {
  87. await tree.insert(i+1, commitments[i]);
  88. }
  89. // await tree.insert(commitment, 0);
  90. // root
  91. const root = tree.root;
  92. const res = await tree.find(key);
  93. if (!res.found) {
  94. console.error("leaf expect to exist but not exists, key:", key);
  95. }
  96. let siblings = res.siblings;
  97. while (siblings.length < nLevels) {
  98. siblings.push("0");
  99. };
  100. // calculate witness
  101. const input = unstringifyBigInts({
  102. "coinCode": coinCode,
  103. "amount": amount,
  104. "secret": secret,
  105. "nullifier": nullifier,
  106. "siblings": siblings,
  107. "root": root,
  108. "address": addr,
  109. "key": key
  110. });
  111. console.log("input", input);
  112. // const options = {};
  113. // const wc = await WitnessCalculatorBuilder(wasm, options);
  114. const wc = await WitnessCalculatorBuilder(wasm);
  115. const witness = await wc.calculateWitness(input, {sanityCheck: true});
  116. const wBuff = Buffer.allocUnsafe(witness.length*32);
  117. for (let i=0; i <witness.length; i++) {
  118. for (let j=0; j <8; j++) {
  119. const bi = witness[i];
  120. const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
  121. // wBuff.writeUInt32LE(v, i*32 + j*4, 4)
  122. wBuff.writeUInt32LE(v, i*32 + j*4)
  123. }
  124. }
  125. // const witness = unstringifyBigInts(stringifyBigInts(w));
  126. return {
  127. witness: wBuff,
  128. publicInputs: {
  129. address:addr,
  130. nullifier:nullifier
  131. }
  132. };
  133. }