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.

98 lines
2.6 KiB

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