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.

110 lines
3.7 KiB

  1. /*
  2. # deposit.circom
  3. +----------+ +----------+
  4. PUB_nullifier+------>+ | | |
  5. | | | SMT |
  6. PUB_coinCode+------->+ | | Poseidon +<------+PUB_rootOld
  7. | Poseidon +-+----------->+ Verifier |
  8. PUB_amount+--------->+ | | | Non |
  9. | | | | Existance+<------+PRI_siblings
  10. PRI_secret+--------->+ | | | | +
  11. +----------+ | +----------+ |
  12. | |
  13. | |
  14. | +----------+ |
  15. | | | |
  16. | | | |
  17. +----+ | | SMT +<---------+
  18. PUB_commitment+----> == +<--------+----------->+ Poseidon |
  19. +----+ | Verifier |
  20. | +<------+PUB_rootNew
  21. | |
  22. +----------+
  23. */
  24. include "../node_modules/circomlib/circuits/comparators.circom";
  25. include "../node_modules/circomlib/circuits/poseidon.circom";
  26. include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
  27. template Deposit(nLevels) {
  28. signal input coinCode;
  29. signal input amount;
  30. signal private input secret;
  31. signal private input nullifier;
  32. signal private input oldKey;
  33. signal private input oldValue;
  34. signal private input siblingsOld[nLevels];
  35. signal private input siblingsNew[nLevels];
  36. signal input rootOld;
  37. signal input rootNew;
  38. signal input commitment;
  39. signal input key;
  40. component hash = Poseidon(4, 6, 8, 57);
  41. hash.inputs[0] <== coinCode;
  42. hash.inputs[1] <== amount;
  43. hash.inputs[2] <== secret;
  44. hash.inputs[3] <== nullifier; // nullifier
  45. component comCheck = IsEqual();
  46. comCheck.in[0] <== hash.out;
  47. comCheck.in[1] <== commitment;
  48. comCheck.out === 1;
  49. // TODO instead of 2 siblings input, get siblingsOld from
  50. // siblingsNew[len-1] both siblingsOld & siblingsNew have same values
  51. // except for one, can be merged into one, to ensure that the circuit
  52. // checks that the leaf non existing under rootOld is in the same
  53. // position than the check that the leaf exists under the rootNew
  54. // check that nLevels-1 siblings match from siblingsOld & siblingsNew
  55. component siblEq[nLevels];
  56. signal count[nLevels];
  57. for (var i=0; i<nLevels; i++) {
  58. siblEq[i] = IsEqual();
  59. siblEq[i].in[0] <== siblingsOld[i];
  60. siblEq[i].in[1] <== siblingsNew[i];
  61. if (i==0) {
  62. count[0] <== siblEq[i].out;
  63. } else {
  64. count[i] <== siblEq[i].out + count[i-1];
  65. }
  66. }
  67. component countCheck = IsEqual();
  68. countCheck.in[0] <== count[nLevels-1];
  69. countCheck.in[1] <== nLevels-1;
  70. countCheck.out === 1;
  71. component smtOld = SMTVerifier(nLevels);
  72. smtOld.enabled <== 1;
  73. smtOld.fnc <== 1;
  74. smtOld.root <== rootOld;
  75. for (var i=0; i<nLevels; i++) {
  76. smtOld.siblings[i] <== siblingsOld[i];
  77. }
  78. /* smtOld.oldKey <== 1; */
  79. smtOld.oldKey <== oldKey;
  80. smtOld.oldValue <== oldValue;
  81. smtOld.isOld0 <== 0;
  82. smtOld.key <== key;
  83. smtOld.value <== hash.out;
  84. component smtNew = SMTVerifier(nLevels);
  85. smtNew.enabled <== 1;
  86. smtNew.fnc <== 0;
  87. smtNew.root <== rootNew;
  88. for (var i=0; i<nLevels; i++) {
  89. smtNew.siblings[i] <== siblingsNew[i];
  90. }
  91. smtNew.oldKey <== 0;
  92. smtNew.oldValue <== 0;
  93. smtNew.isOld0 <== 0;
  94. smtNew.key <== key;
  95. smtNew.value <== hash.out;
  96. }
  97. /* component main = Deposit(17); // 16 real levels (due circom leaf protection) */