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.

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