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.

186 lines
5.0 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 nLevels = 17;
  12. const coinCode = "0"; // refearing to ETH
  13. const ethAmount = '1';
  14. const amount = Web3.utils.toWei(ethAmount, 'ether');
  15. exports.randBigInt = () => {
  16. return Fr.random();
  17. };
  18. exports.calcCommitment = (key, secret) => {
  19. const poseidon = circomlib.poseidon.createHash(6, 8, 57);
  20. const nullifier = poseidon([key, secret]).toString();
  21. const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
  22. return commitment;
  23. };
  24. exports.calcDepositWitness = async (wasm, key, secret, commitments) => {
  25. const poseidon = circomlib.poseidon.createHash(6, 8, 57);
  26. const nullifier = poseidon([key, secret]).toString();
  27. const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
  28. console.log("PROVA", poseidon([key, commitment]).toString());
  29. // rebuild the tree
  30. let tree = await smt.newMemEmptyTrie();
  31. await tree.insert(0, 0);
  32. for (let i=0; i<commitments.length; i++) {
  33. await tree.insert(i+1, commitments[i]);
  34. }
  35. // old root
  36. const rootOld = tree.root;
  37. const resOld = await tree.find(key);
  38. console.log("FIND old", resOld);
  39. let oldKey = "0";
  40. let oldValue = "0";
  41. if (!resOld.found) {
  42. oldKey = resOld.notFoundKey.toString();
  43. oldValue = resOld.notFoundValue.toString();
  44. }
  45. console.log("oldKey", oldKey);
  46. console.log("oldValue", oldValue);
  47. // if (resOld.found) {
  48. // console.error("leaf expect to not exist but exists");
  49. // }
  50. let siblingsOld = resOld.siblings;
  51. while (siblingsOld.length < nLevels) {
  52. siblingsOld.push("0");
  53. };
  54. await tree.insert(key, commitment);
  55. // new root
  56. const rootNew = tree.root;
  57. const resNew = await tree.find(key);
  58. console.log("FIND new", resNew);
  59. if (!resNew.found) {
  60. console.error("leaf with the new commitment expect to exist but not exists");
  61. }
  62. let siblingsNew = resNew.siblings;
  63. while (siblingsNew.length < nLevels) {
  64. siblingsNew.push("0");
  65. };
  66. // calculate witness
  67. const input = unstringifyBigInts({
  68. "coinCode": coinCode,
  69. "amount": amount,
  70. "secret": secret,
  71. "nullifier": nullifier,
  72. "oldKey": oldKey,
  73. "oldValue": oldValue,
  74. "siblingsOld": siblingsOld,
  75. "siblingsNew": siblingsNew,
  76. "rootOld": rootOld,
  77. "rootNew": rootNew,
  78. "commitment": commitment,
  79. "key": key
  80. });
  81. console.log("input", input);
  82. // const options = {};
  83. // const wc = await WitnessCalculatorBuilder(wasm, options);
  84. const wc = await WitnessCalculatorBuilder(wasm);
  85. const witness = await wc.calculateWitness(input, {sanityCheck: true});
  86. const wBuff = Buffer.allocUnsafe(witness.length*32);
  87. for (let i=0; i<witness.length; i++) {
  88. for (let j=0; j<8; j++) {
  89. const bi = witness[i];
  90. const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
  91. // wBuff.writeUInt32LE(v, i*32 + j*4, 4)
  92. wBuff.writeUInt32LE(v, i*32 + j*4)
  93. }
  94. }
  95. // const witness = unstringifyBigInts(stringifyBigInts(w));
  96. // return wBuff;
  97. return {
  98. witness: wBuff,
  99. publicInputs: {
  100. commitment:commitment,
  101. root:rootNew
  102. }
  103. };
  104. }
  105. exports.calcWithdrawWitness = async (wasm, key, secret, commitments, addr) => {
  106. const poseidon = circomlib.poseidon.createHash(6, 8, 57);
  107. const nullifier = poseidon([key, secret]).toString();
  108. const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
  109. // rebuild the tree
  110. let tree = await smt.newMemEmptyTrie();
  111. await tree.insert(0, 0);
  112. for (let i=0; i<commitments.length; i++) {
  113. await tree.insert(i+1, commitments[i]);
  114. }
  115. // await tree.insert(commitment, 0);
  116. // root
  117. const root = tree.root;
  118. const res = await tree.find(key);
  119. if (!res.found) {
  120. console.error("leaf expect to exist but not exists, key:", key);
  121. }
  122. let siblings = res.siblings;
  123. while (siblings.length < nLevels) {
  124. siblings.push("0");
  125. };
  126. // calculate witness
  127. const input = unstringifyBigInts({
  128. "coinCode": coinCode,
  129. "amount": amount,
  130. "secret": secret,
  131. "nullifier": nullifier,
  132. "siblings": siblings,
  133. "root": root,
  134. "address": addr,
  135. "key": key
  136. });
  137. console.log("input", input);
  138. // const options = {};
  139. // const wc = await WitnessCalculatorBuilder(wasm, options);
  140. const wc = await WitnessCalculatorBuilder(wasm);
  141. const witness = await wc.calculateWitness(input, {sanityCheck: true});
  142. const wBuff = Buffer.allocUnsafe(witness.length*32);
  143. for (let i=0; i<witness.length; i++) {
  144. for (let j=0; j<8; j++) {
  145. const bi = witness[i];
  146. const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
  147. // wBuff.writeUInt32LE(v, i*32 + j*4, 4)
  148. wBuff.writeUInt32LE(v, i*32 + j*4)
  149. }
  150. }
  151. // const witness = unstringifyBigInts(stringifyBigInts(w));
  152. return {
  153. witness: wBuff,
  154. publicInputs: {
  155. address:addr,
  156. nullifier:nullifier
  157. }
  158. };
  159. }