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.

97 lines
2.4 KiB

  1. pragma circom 2.0.0;
  2. include "./poseidon_constants.circom";
  3. template Sigma() {
  4. signal input in;
  5. signal output out;
  6. signal in2;
  7. signal in4;
  8. in2 <== in*in;
  9. in4 <== in2*in2;
  10. out <== in4*in;
  11. }
  12. template Ark(t, C, r) {
  13. signal input in[t];
  14. signal output out[t];
  15. for (var i=0; i<t; i++) {
  16. out[i] <== in[i] + C[i + r];
  17. }
  18. }
  19. template Mix(t, M) {
  20. signal input in[t];
  21. signal output out[t];
  22. var lc;
  23. for (var i=0; i<t; i++) {
  24. lc = 0;
  25. for (var j=0; j<t; j++) {
  26. lc += M[i][j]*in[j];
  27. }
  28. out[i] <== lc;
  29. }
  30. }
  31. template Poseidon(nInputs) {
  32. signal input inputs[nInputs];
  33. signal output out;
  34. // Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8)
  35. // Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
  36. // And rounded up to nearest integer that divides by t
  37. var N_ROUNDS_P[16] = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68];
  38. var t = nInputs + 1;
  39. var nRoundsF = 8;
  40. var nRoundsP = N_ROUNDS_P[t - 2];
  41. var C[t*(nRoundsF + nRoundsP)] = POSEIDON_C(t);
  42. var M[t][t] = POSEIDON_M(t);
  43. component ark[nRoundsF + nRoundsP];
  44. component sigmaF[nRoundsF][t];
  45. component sigmaP[nRoundsP];
  46. component mix[nRoundsF + nRoundsP];
  47. var k;
  48. for (var i=0; i<nRoundsF + nRoundsP; i++) {
  49. ark[i] = Ark(t, C, t*i);
  50. for (var j=0; j<t; j++) {
  51. if (i==0) {
  52. if (j>0) {
  53. ark[i].in[j] <== inputs[j-1];
  54. } else {
  55. ark[i].in[j] <== 0;
  56. }
  57. } else {
  58. ark[i].in[j] <== mix[i-1].out[j];
  59. }
  60. }
  61. if (i < nRoundsF/2 || i >= nRoundsP + nRoundsF/2) {
  62. k = i < nRoundsF/2 ? i : i - nRoundsP;
  63. mix[i] = Mix(t, M);
  64. for (var j=0; j<t; j++) {
  65. sigmaF[k][j] = Sigma();
  66. sigmaF[k][j].in <== ark[i].out[j];
  67. mix[i].in[j] <== sigmaF[k][j].out;
  68. }
  69. } else {
  70. k = i - nRoundsF/2;
  71. mix[i] = Mix(t, M);
  72. sigmaP[k] = Sigma();
  73. sigmaP[k].in <== ark[i].out[0];
  74. mix[i].in[0] <== sigmaP[k].out;
  75. for (var j=1; j<t; j++) {
  76. mix[i].in[j] <== ark[i].out[j];
  77. }
  78. }
  79. }
  80. out <== mix[nRoundsF + nRoundsP -1].out[0];
  81. }