-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathposeidon_utils.patch
112 lines (98 loc) · 3.81 KB
/
poseidon_utils.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
--- venv/lib/python3.9/site-packages/starkware/cairo/common/poseidon_utils.py 2023-08-11 11:27:27.000000000 +0200
+++ tools/make/poseidon_patch.py 2023-09-10 20:25:03.298128497 +0200
@@ -4,12 +4,10 @@
"""
import hashlib
-from typing import Iterable, List, Optional, Type
-
-import numpy as np
+from typing import List, Optional, Type
from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME
-from starkware.python.math_utils import pow_mod, safe_div
+from starkware.python.math_utils import safe_div
def generate_round_constant(fn_name: str, field_prime: int, idx: int) -> int:
@@ -39,9 +37,7 @@
poseidon_small_params: Optional["PoseidonParams"] = None
- def __init__(
- self, field_prime: int, r: int, c: int, r_f: int, r_p: int, mds: Iterable[Iterable[int]]
- ):
+ def __init__(self, field_prime: int, r: int, c: int, r_f: int, r_p: int):
self.field_prime = field_prime
self.r = r
self.c = c
@@ -53,22 +49,16 @@
self.output_size = c
assert self.output_size <= r
# A list of r_f + r_p vectors for the Add-Round Key phase.
- self.ark = np.array(
- [
- [generate_round_constant("Hades", field_prime, m * i + j) for j in range(m)]
- for i in range(n_rounds)
- ],
- dtype=object,
- )
-
- # The MDS matrix for the MixLayer phase.
- self.mds = np.array(mds, dtype=object)
+ self.ark = [
+ [generate_round_constant("Hades", field_prime, m * i + j) for j in range(m)]
+ for i in range(n_rounds)
+ ]
@classmethod
def get_default_poseidon_params(cls: Type["PoseidonParams"]):
if cls.poseidon_small_params is None:
cls.poseidon_small_params = cls(
- field_prime=DEFAULT_PRIME, r=2, c=1, r_f=8, r_p=83, mds=SmallMds
+ field_prime=DEFAULT_PRIME, r=2, c=1, r_f=8, r_p=83
)
return cls.poseidon_small_params
@@ -76,22 +66,22 @@
def hades_round(values, params: PoseidonParams, is_full_round: bool, round_idx: int):
# Add-Round Key.
- values = (values + params.ark[round_idx]) % params.field_prime
-
+ values = [
+ (val + ark) % params.field_prime
+ for val, ark in zip(values, params.ark[round_idx])
+ ]
# SubWords.
if is_full_round:
- values = pow_mod(values, 3, params.field_prime)
+ values = [pow(val, 3, params.field_prime) for val in values]
else:
- values[-1:] = pow_mod(values[-1:], 3, params.field_prime)
+ values[-1] = pow(values[-1], 3, params.field_prime)
# MixLayer.
- values = params.mds.dot(values) % params.field_prime
+ values = mds_mul(values, params.field_prime)
return values
def hades_permutation(values: List[int], params: PoseidonParams) -> List[int]:
- assert len(values) == params.m
- values = np.array(values, dtype=object)
round_idx = 0
# Apply r_f/2 full rounds.
for _ in range(safe_div(params.r_f, 2)):
@@ -105,9 +95,22 @@
for _ in range(safe_div(params.r_f, 2)):
values = hades_round(values, params, True, round_idx)
round_idx += 1
- assert round_idx == params.n_rounds
- return list(values)
+ return values
+
+
+def mds_mul(vector, field):
+ """
+ Multiplies a vector by the SmallMds matrix.
+ [3, 1, 1] [r0] [3* r0 + r1 + r2 ]
+ [1, -1, 1] * [r1] = [r0 - r1 + r2 ]
+ [1, 1, -2] [r2] [r0 + r1 - 2 * r2]
+ """
+ return [
+ (3 * vector[0] + vector[1] + vector[2]) % field,
+ (vector[0] - vector[1] + vector[2]) % field,
+ (vector[0] + vector[1] - 2 * vector[2]) % field,
+ ]
# The actual config to be in use, with extremely small MDS coefficients.
-SmallMds = [[3, 1, 1], [1, -1, 1], [1, 1, -2]]
+# SmallMds = [[3, 1, 1], [1, -1, 1], [1, 1, -2]]