Skip to content

Commit 3ef664f

Browse files
authored
[protocols] Add missing script to find optimal poseidon (#2007)
1 parent b4a5caa commit 3ef664f

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import sys
2+
from math import *
3+
4+
def poseidon_params(p, t, nRoundsF, nRoundsP, e, constants_C=None, constants_M=None, security_target=None):
5+
assert nRoundsF % 2 == 0 and nRoundsF >= 6
6+
assert nRoundsP > 0
7+
assert t >= 2
8+
9+
n = floor(log2(p))
10+
if security_target is None:
11+
M = n # security target, in bits
12+
else:
13+
M = security_target
14+
assert n >= M
15+
16+
# Size of the state (in bits)
17+
N = n * t
18+
19+
if p % 2 == 3:
20+
assert e == 3
21+
grobner_attack_ratio_rounds = 0.32
22+
grobner_attack_ratio_sboxes = 0.18
23+
interpolation_attack_ratio = 0.63
24+
elif p % 5 != 1:
25+
assert e == 5
26+
grobner_attack_ratio_rounds = 0.21
27+
grobner_attack_ratio_sboxes = 0.14
28+
interpolation_attack_ratio = 0.43
29+
else:
30+
# XXX: in other cases use, can we use 7?
31+
raise ValueError('Invalid p for congruency')
32+
33+
# Verify that the parameter choice exceeds the recommendations to prevent attacks
34+
# iacr.org/2019/458 § 3 Cryptanalysis Summary of Starkad and Poseidon Hashes (pg 10)
35+
# Figure 1
36+
#print('(nRoundsF + nRoundsP)', (nRoundsF + nRoundsP))
37+
#print('Interpolation Attackable Rounds', ((interpolation_attack_ratio * min(n, M)) + log2(t)))
38+
assert (nRoundsF + nRoundsP) > ((interpolation_attack_ratio * min(n, M)) + log2(t))
39+
# Figure 3
40+
#print('grobner_attack_ratio_rounds', ((2 + min(M, n)) * grobner_attack_ratio_rounds))
41+
assert (nRoundsF + nRoundsP) > ((2 + min(M, n)) * grobner_attack_ratio_rounds)
42+
# Figure 4
43+
#print('grobner_attack_ratio_sboxes', (M * grobner_attack_ratio_sboxes))
44+
assert (nRoundsF + (t * nRoundsP)) > (M * grobner_attack_ratio_sboxes)
45+
46+
47+
# iacr.org/2019/458 § 4.1 6 SNARKs Application via Poseidon-π
48+
# page 16 formula (8) and (9)
49+
n_constraints = (nRoundsF * t) + nRoundsP
50+
if e == 5:
51+
n_constraints *= 3
52+
elif e == 3:
53+
n_constraints *= 2
54+
55+
return n_constraints
56+
57+
58+
e = 5
59+
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
60+
61+
if len(sys.argv) != 2:
62+
print("Invalid arguments! Pass in the number of inputs into the hash function.")
63+
sys.exit()
64+
65+
t = int(sys.argv[1]) + 1
66+
67+
best_constraints = 9999999
68+
best_nRoundsF = 0
69+
best_nRoundsP = 0
70+
71+
for nRoundsF in range(1, 16):
72+
for nRoundsP in range(1, 128):
73+
try:
74+
constraints = poseidon_params(p, t, nRoundsF, nRoundsP, e, None, None, 128)
75+
#print("constraints: " + str(constraints))
76+
if constraints < best_constraints:
77+
best_constraints = constraints
78+
best_nRoundsF = int(nRoundsF)
79+
best_nRoundsP = int(nRoundsP)
80+
except:
81+
pass
82+
83+
print("t: " + str(t))
84+
print("best_constraints: " + str(best_constraints))
85+
print("best_nRoundsF: " + str(best_nRoundsF))
86+
print("best_nRoundsP: " + str(best_nRoundsP))
87+
88+
print("cost: " + str(best_constraints / (t - 1)))

0 commit comments

Comments
 (0)