11// circuit code (with more inputs) with reference from zokrates core library
22// https://github.com/Zokrates/ZoKrates/blob/develop/zokrates_stdlib/stdlib/hashes/poseidon/constants.zok
33
4- from "./constants.zok" import POSEIDON_C, POSEIDON_M
5-
6- def ark<N>(field[N] state, field[1292] c, u32 it) -> field[N]:
7- for u32 i in 0..N do
8- state[i] = state[i] + c[it + i]
9- endfor
10- return state
11-
12- def sbox<N>(field[N] state, u32 f, u32 p, u32 r) -> field[N]:
13- state[0] = state[0]**5
14- for u32 i in 1..N do
15- state[i] = if ((r < f/2) || (r >= f/2 + p)) then state[i]**5 else state[i] fi
16- endfor
17- return state
18-
19- def mix<N>(field[N] state, field[17][17] m) -> field[N]:
20- field[N] out = [0; N]
21- for u32 i in 0..N do
22- field acc = 0
23- for u32 j in 0..N do
24- acc = acc + (state[j] * m[i][j])
25- endfor
26- out[i] = acc
27- endfor
28- return out
29-
30- def main<N>(field[N] inputs) -> field:
31- assert(N > 0 && N <= 16) // max 16 inputs
32-
33- u32 t = N + 1
34- u32[16] rounds_p = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68]
35-
36- u32 f = 8
37- u32 p = rounds_p[(t - 2)]
4+ from "./constants.zok" import POSEIDON_C, POSEIDON_M;
5+
6+ def ark<N>(field[N] mut state, field[1292] c, u32 it) -> field[N] {
7+ for u32 i in 0..N {
8+ state[i] = state[i] + c[it + i];
9+ }
10+ return state;
11+ }
12+
13+ def sbox<N>(field[N] mut state, u32 f, u32 p, u32 r) -> field[N] {
14+ state[0] = state[0]**5;
15+ for u32 i in 1..N {
16+ state[i] = if ((r < f/2) || (r >= f/2 + p)) { state[i]**5 } else { state[i] };
17+ }
18+ return state;
19+ }
20+
21+ def mix<N>(field[N] mut state, field[17][17] m) -> field[N] {
22+ field[N] mut out = [0; N];
23+ for u32 i in 0..N {
24+ field mut acc = 0;
25+ for u32 j in 0..N {
26+ acc = acc + (state[j] * m[i][j]);
27+ }
28+ out[i] = acc;
29+ }
30+ return out;
31+ }
32+
33+ def main<N>(field[N] inputs) -> field {
34+ assert(N > 0 && N <= 16); // max 16 inputs
35+
36+ u32 t = N + 1;
37+ u32[16] rounds_p = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68];
38+
39+ u32 f = 8;
40+ u32 p = rounds_p[(t - 2)];
3841
3942 // Constants are padded with zeroes to the maximum value calculated by
4043 // t * (f + p) = 497, where `t` (number of inputs + 1) is a max of 7.
4144 // This is done to keep the function generic, as resulting array size depends on `t`
4245 // and we do not want callers passing down constants.
4346 // This should be revisited once compiler limitations are gone.
44- field[1292] c = POSEIDON_C[t - 2]
45- field[17][17] m = POSEIDON_M[t - 2]
46-
47- field[t] state = [0; t]
48- for u32 i in 1..t do
49- state[i] = inputs[i - 1]
50- endfor
51-
52- for u32 r in 0..f+p do
53- state = ark(state, c, r * t)
54- state = sbox(state, f, p, r)
55- state = mix(state, m)
56- endfor
57-
58- return state[0]
59-
60-
47+ field[1292] c = POSEIDON_C[t - 2];
48+ field[17][17] m = POSEIDON_M[t - 2];
49+
50+ field[t] mut state = [0; t];
51+ for u32 i in 1..t {
52+ state[i] = inputs[i - 1];
53+ }
54+
55+ for u32 r in 0..f+p {
56+ state = ark(state, c, r * t);
57+ state = sbox(state, f, p, r);
58+ state = mix(state, m);
59+ }
60+
61+ return state[0];
62+ }
0 commit comments