from zkpyc.types import Array, field from .constants import POSEIDON_C, POSEIDON_M
def ark(state: Array[field, 7], c: Array[field, 497], it: int) -> Array[field, 7]:
out: Array[field, 7] = [*state]
for i in range(0, 7):
out[i] = out[i] + c[it + i]
return out
def sbox(state: Array[field, 7], f: int, p: int, r: int) -> Array[field, 7]:
out: Array[field, 7] = [*state]
out[0] = out[0]**5
for i in range(1, 7):
out[i] = out[i]**5 if ((r < f/2) or (r >= f/2 + p)) else out[i]
return out
def mix(state: Array[field, 7], m: Array[Array[field, 7], 7]) -> Array[field, 7]:
out: Array[field, 7] = [field(0) for _ in range(7)]
for i in range(0, 7):
acc: field = field(0)
for j in range(0, 7):
acc = acc + (state[j] * m[i][j])
out[i] = acc
return out
def poseidon(inputs: Array[field, 6]) -> field:
rounds_p: Array[int, 8] = [56, 57, 56, 60, 60, 63, 64, 63]
f: int = 8
p: int = rounds_p[(7 - 2)]
c: Array[field, 497] = POSEIDON_C[7 - 2]
m: Array[Array[field, 7], 7] = POSEIDON_M[7 - 2]
state: Array[field, 7] = [field(0) for _ in range(7)]
for i in range(1, 7):
state[i] = inputs[i - 1]
for r in range(0, f + p):
state = ark(state, c, r * 7)
state = sbox(state, f, p, r)
state = mix(state, m)
return state[0]