withdraw.circom 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. include "../node_modules/circomlib/circuits/bitify.circom";
  2. include "../node_modules/circomlib/circuits/pedersen.circom";
  3. include "merkleTree.circom";
  4. // computes Pedersen(nullifier + secret)
  5. template CommitmentHasher() {
  6. signal input nullifier;
  7. signal input secret;
  8. signal output commitment;
  9. signal output nullifierHash;
  10. component commitmentHasher = Pedersen(496);
  11. component nullifierHasher = Pedersen(248);
  12. component nullifierBits = Num2Bits(248);
  13. component secretBits = Num2Bits(248);
  14. nullifierBits.in <== nullifier;
  15. secretBits.in <== secret;
  16. for (var i = 0; i < 248; i++) {
  17. nullifierHasher.in[i] <== nullifierBits.out[i];
  18. commitmentHasher.in[i] <== nullifierBits.out[i];
  19. commitmentHasher.in[i + 248] <== secretBits.out[i];
  20. }
  21. commitment <== commitmentHasher.out[0];
  22. nullifierHash <== nullifierHasher.out[0];
  23. }
  24. // Verifies that commitment that corresponds to given secret and nullifier is included in the merkle tree of deposits
  25. template Withdraw(levels) {
  26. signal input root;
  27. signal input nullifierHash;
  28. signal input recipient; // not taking part in any computations
  29. signal input relayer; // not taking part in any computations
  30. signal input fee; // not taking part in any computations
  31. signal input refund; // not taking part in any computations
  32. signal private input nullifier;
  33. signal private input secret;
  34. signal private input pathElements[levels];
  35. signal private input pathIndices[levels];
  36. component hasher = CommitmentHasher();
  37. hasher.nullifier <== nullifier;
  38. hasher.secret <== secret;
  39. hasher.nullifierHash === nullifierHash;
  40. component tree = MerkleTreeChecker(levels);
  41. tree.leaf <== hasher.commitment;
  42. tree.root <== root;
  43. for (var i = 0; i < levels; i++) {
  44. tree.pathElements[i] <== pathElements[i];
  45. tree.pathIndices[i] <== pathIndices[i];
  46. }
  47. // Add hidden signals to make sure that tampering with recipient or fee will invalidate the snark proof
  48. // Most likely it is not required, but it's better to stay on the safe side and it only takes 2 constraints
  49. // Squares are used to prevent optimizer from removing those constraints
  50. signal recipientSquare;
  51. signal feeSquare;
  52. signal relayerSquare;
  53. signal refundSquare;
  54. recipientSquare <== recipient * recipient;
  55. feeSquare <== fee * fee;
  56. relayerSquare <== relayer * relayer;
  57. refundSquare <== refund * refund;
  58. }
  59. component main = Withdraw(20);