@@ -2,20 +2,21 @@ package field
22
33import (
44 "encoding/binary"
5+ "math"
56 "testing"
67
78 g "github.com/elliottech/poseidon_crypto/field/goldilocks"
89 gFp5 "github.com/elliottech/poseidon_crypto/field/goldilocks_quintic_extension"
910
10- "math/rand"
11+ "math/big"
12+ "math/rand/v2"
1113)
1214
1315func TestBytes (t * testing.T ) {
1416 e1 := g .Sample ()
1517
1618 leBytes := g .ToLittleEndianBytes (e1 )
17- beBytess := e1 .Bytes ()
18- beBytes := beBytess [:]
19+ beBytes := e1 .Bytes ()
1920 for i := 0 ; i < g .Bytes ; i ++ {
2021 if beBytes [i ] != leBytes [g .Bytes - i - 1 ] {
2122 t .Fatalf ("Big endian and little endian bytes are not reversed" )
@@ -27,19 +28,208 @@ func TestBytes(t *testing.T) {
2728 t .Fatalf ("bytes do not match" )
2829 }
2930
30- randUint64 := rand .Uint64 ()
31- elem := g .FromUint64 (randUint64 )
31+ r := rand .Uint64N (g .ORDER )
3232
3333 leBytesUint64 := make ([]byte , 8 )
34- binary .LittleEndian .PutUint64 (leBytesUint64 , randUint64 )
35- leBytesElem := g .ToLittleEndianBytes (elem )
34+ binary .LittleEndian .PutUint64 (leBytesUint64 , r )
35+
36+ leBytesElem := g .ToLittleEndianBytes (g .FromUint64 (r ))
3637 for i := 0 ; i < 8 ; i ++ {
3738 if leBytesUint64 [i ] != leBytesElem [i ] {
3839 t .Fatalf ("Little-endian bytes do not match at index %d: expected %x, got %x" , i , leBytesUint64 [i ], leBytesElem [i ])
3940 }
4041 }
4142}
4243
44+ func TestBytesF (t * testing.T ) {
45+ r := rand .Uint64N (g .ORDER )
46+ f := g .GoldilocksField (r )
47+
48+ rBytes := make ([]byte , 8 )
49+ binary .LittleEndian .PutUint64 (rBytes , r )
50+
51+ fBytes := g .ToLittleEndianBytesF (f )
52+ for i := 0 ; i < 8 ; i ++ {
53+ if rBytes [i ] != fBytes [i ] {
54+ t .Fatalf ("Little-endian bytes do not match at index %d: expected %x, got %x" , i , rBytes [i ], fBytes [i ])
55+ }
56+ }
57+
58+ ff := g .FromCanonicalLittleEndianBytesF (fBytes )
59+ if ff != f {
60+ t .Fatalf ("bytes do not match" )
61+ }
62+ }
63+
64+ // Goldilocks field tests
65+
66+ // Inputs that covers several input ranges
67+ var inputs = []uint64 {
68+ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 2147483638 , 2147483639 , 2147483640 , 2147483641 , 2147483642 , 2147483643 , 2147483644 , 2147483645 , 2147483646 , 2147483647 , 2147483648 , 2147483649 ,
69+ 2147483650 , 2147483651 , 2147483652 , 2147483653 , 2147483654 , 2147483655 , 2147483656 , 2147483657 , 4294967286 , 4294967287 , 4294967288 , 4294967289 , 4294967290 , 4294967291 ,
70+ 4294967292 , 4294967293 , 4294967294 , 4294967295 , 4294967296 , 4294967297 , 4294967298 , 4294967299 , 4294967300 , 4294967301 , 4294967302 , 4294967303 , 4294967304 , 4294967305 ,
71+ 9223372036854775798 , 9223372036854775799 , 9223372036854775800 , 9223372036854775801 , 9223372036854775802 , 9223372036854775803 , 9223372036854775804 , 9223372036854775805 ,
72+ 9223372036854775806 , 9223372036854775807 , 9223372036854775808 , 9223372036854775809 , 9223372036854775810 , 9223372036854775811 , 9223372036854775812 , 9223372036854775813 ,
73+ 9223372036854775814 , 9223372036854775815 , 9223372036854775816 , 9223372036854775817 , 18446744069414584311 , 18446744069414584312 , 18446744069414584313 , 18446744069414584314 ,
74+ 18446744069414584315 , 18446744069414584316 , 18446744069414584317 , 18446744069414584318 , 18446744069414584319 , 18446744069414584320 ,
75+ }
76+
77+ func NewBigInt (x uint64 ) * big.Int {
78+ return big .NewInt (0 ).SetUint64 (x )
79+ }
80+
81+ func SumMod (x , y uint64 ) uint64 {
82+ sum := NewBigInt (x ).Add (NewBigInt (x ), NewBigInt (y ))
83+ res := sum .Mod (sum , NewBigInt (g .ORDER ))
84+ if ! res .IsUint64 () {
85+ panic ("sum is not uint64" )
86+ }
87+ return res .Uint64 ()
88+ }
89+
90+ func SubMod (x , y uint64 ) uint64 {
91+ sub := NewBigInt (x ).Sub (NewBigInt (x ), NewBigInt (y ))
92+ res := sub .Mod (sub , NewBigInt (g .ORDER ))
93+ if ! res .IsUint64 () {
94+ panic ("difference is not uint64" )
95+ }
96+ return res .Uint64 ()
97+ }
98+
99+ func MulMod (x , y uint64 ) uint64 {
100+ mul := NewBigInt (x ).Mul (NewBigInt (x ), NewBigInt (y ))
101+ res := mul .Mod (mul , NewBigInt (g .ORDER ))
102+ if ! res .IsUint64 () {
103+ panic ("product is not uint64" )
104+ }
105+ return res .Uint64 ()
106+ }
107+
108+ func NegMod (x uint64 ) uint64 {
109+ neg := NewBigInt (x ).Neg (NewBigInt (x ))
110+ res := neg .Mod (neg , NewBigInt (g .ORDER ))
111+ if ! res .IsUint64 () {
112+ panic ("negative number is not uint64" )
113+ }
114+ return res .Uint64 ()
115+ }
116+
117+ func SquareMod (x uint64 ) uint64 {
118+ square := NewBigInt (x ).Mul (NewBigInt (x ), NewBigInt (x ))
119+ res := square .Mod (square , NewBigInt (g .ORDER ))
120+ if ! res .IsUint64 () {
121+ panic ("square is not uint64" )
122+ }
123+ return res .Uint64 ()
124+ }
125+
126+ func TestAddF (t * testing.T ) {
127+ for _ , lhs := range inputs {
128+ for _ , rhs := range inputs {
129+ fLhs := g .GoldilocksField (lhs )
130+ fRhs := g .GoldilocksField (rhs )
131+ sum := g .AddF (fLhs , fRhs ).ToCanonicalUint64 ()
132+ expected := SumMod (lhs , rhs )
133+ if sum != expected {
134+ t .Fatalf ("Expected %d + %d = %d, but got %d" , lhs , rhs , expected , sum )
135+ }
136+ }
137+ }
138+ }
139+
140+ func TestSubF (t * testing.T ) {
141+ for _ , lhs := range inputs {
142+ for _ , rhs := range inputs {
143+ fLhs := g .GoldilocksField (lhs )
144+ fRhs := g .GoldilocksField (rhs )
145+ diff := g .SubF (fLhs , fRhs ).ToCanonicalUint64 ()
146+ expected := SubMod (lhs , rhs )
147+ if diff != expected {
148+ t .Fatalf ("Expected %d - %d = %d, but got %d" , lhs , rhs , expected , diff )
149+ }
150+ }
151+ }
152+ }
153+
154+ func TestMulF (t * testing.T ) {
155+ for _ , lhs := range inputs {
156+ for _ , rhs := range inputs {
157+ fLhs := g .GoldilocksField (lhs )
158+ fRhs := g .GoldilocksField (rhs )
159+ mul := g .MulF (fLhs , fRhs ).ToCanonicalUint64 ()
160+ expected := MulMod (lhs , rhs )
161+ if mul != expected {
162+ t .Fatalf ("Expected %d * %d = %d, but got %d" , lhs , rhs , expected , mul )
163+ }
164+ }
165+ }
166+ }
167+
168+ func TestNegF (t * testing.T ) {
169+ for _ , lhs := range inputs {
170+ fLhs := g .GoldilocksField (lhs )
171+ neg := g .NegF (fLhs ).ToCanonicalUint64 ()
172+ expected := NegMod (lhs )
173+ if neg != expected {
174+ t .Fatalf ("Expected Neg(%d) = %d, but got %d" , lhs , expected , neg )
175+ }
176+ }
177+ }
178+
179+ func TestSquareF (t * testing.T ) {
180+ for _ , lhs := range inputs {
181+ fLhs := g .GoldilocksField (lhs )
182+ sqr := g .SquareF (fLhs ).ToCanonicalUint64 ()
183+ expected := SquareMod (lhs )
184+ if sqr != expected {
185+ t .Fatalf ("Expected (%d)^2 = %d, but got %d" , lhs , expected , sqr )
186+ }
187+ }
188+ }
189+
190+ func TestSubFDoubleWraparound (t * testing.T ) {
191+ /*
192+ let (a, b) = (F::from_canonical_u64((F::ORDER + 1u64) / 2u64), F::TWO);
193+ let x = a * b;
194+ assert_eq!(x, F::ONE);
195+ assert_eq!(F::ZERO - x, F::NEG_ONE);
196+ */
197+
198+ a := g .GoldilocksField ((g .ORDER + 1 ) / 2 )
199+ b := g .GoldilocksField (2 )
200+ x := g .MulF (a , b )
201+ if x .ToCanonicalUint64 () != g .OneF ().ToCanonicalUint64 () {
202+ t .Fatalf ("Expected a*b to be 1, but got %v" , x )
203+ }
204+ if g .SubF (g .ZeroF (), x ).ToCanonicalUint64 () != g .NegOneF ().ToCanonicalUint64 () {
205+ t .Fatalf ("Expected 0 - x to be -1, but got %v" , g .SubF (g .ZeroF (), x ))
206+ }
207+ }
208+
209+ func TestAddFDoubleWraparound (t * testing.T ) {
210+ /*
211+ let a = F::from_canonical_u64(u64::MAX - F::ORDER);
212+ let b = F::NEG_ONE;
213+
214+ let c = (a + a) + (b + b);
215+ let d = (a + b) + (a + b);
216+
217+ assert_eq!(c, d);
218+ */
219+
220+ a := g .GoldilocksField (math .MaxUint64 - g .ORDER )
221+ b := g .NegOneF ()
222+
223+ c := g .AddF (g .AddF (a , a ), g .AddF (b , b ))
224+ d := g .AddF (g .AddF (a , b ), g .AddF (a , b ))
225+
226+ if c .ToCanonicalUint64 () != d .ToCanonicalUint64 () {
227+ t .Fatalf ("Expected c to be equal to d, but got %v and %v" , c , d )
228+ }
229+ }
230+
231+ // Quintic extension tests
232+
43233func TestQuinticExtensionAddSubMulSquare (t * testing.T ) {
44234 val1 := gFp5.Element {
45235 g .FromUint64 (0x1234567890ABCDEF ),
@@ -59,23 +249,78 @@ func TestQuinticExtensionAddSubMulSquare(t *testing.T) {
59249 add := gFp5 .Add (val1 , val2 )
60250 expectedAdd := [5 ]uint64 {1311768471589866989 , 1147797413325783839 , 1234605620731475846 , 9833440832084189711 , 12302652064957136911 }
61251 for i := 0 ; i < 5 ; i ++ {
62- if add [i ] != g .FromUint64 (expectedAdd [i ]) {
252+ if add [i ].Uint64 () != expectedAdd [i ] {
253+ t .Fatalf ("Addition: Expected limb %d to be %x, but got %x" , i , expectedAdd [i ], add [i ])
254+ }
255+ }
256+
257+ sub := gFp5 .Sub (val1 , val2 )
258+ expectedSub := [5 ]uint64 {1311768462999932401 , 1147797404735849251 , 1234605612141541258 , 9833440823494255123 , 12302652056367202323 }
259+ for i := 0 ; i < 5 ; i ++ {
260+ if sub [i ].Uint64 () != expectedSub [i ] {
261+ t .Fatalf ("Subtraction: Expected limb %d to be %x, but got %x" , i , expectedSub [i ], sub [i ])
262+ }
263+ }
264+
265+ mul := gFp5 .Mul (val1 , val2 )
266+ expectedMul := [5 ]uint64 {12801331769143413385 , 14031114708135177824 , 4192851210753422088 , 14031114723597060086 , 4193451712464626164 }
267+ for i := 0 ; i < 5 ; i ++ {
268+ if mul [i ].Uint64 () != expectedMul [i ] {
269+ t .Fatalf ("Multiplication: Expected limb %d to be %x, but got %x" , i , expectedMul [i ], mul [i ])
270+ }
271+ }
272+
273+ square := gFp5 .Square (val1 )
274+ expectedSquare := [5 ]uint64 {
275+ 2711468769317614959 ,
276+ 15562737284369360677 ,
277+ 48874032493986270 ,
278+ 11211402278708723253 ,
279+ 2864528669572451733 ,
280+ }
281+ for i := 0 ; i < 5 ; i ++ {
282+ if square [i ].Uint64 () != expectedSquare [i ] {
283+ t .Fatalf ("Square: Expected limb %d to be %x, but got %x" , i , expectedSquare [i ], square [i ])
284+ }
285+ }
286+ }
287+
288+ func TestQuinticExtensionAddSubMulSquareF (t * testing.T ) {
289+ val1 := gFp5 .FromPlonky2GoldilocksField ([]g.GoldilocksField {
290+ g .GoldilocksField (0x1234567890ABCDEF ),
291+ g .GoldilocksField (0x0FEDCBA987654321 ),
292+ g .GoldilocksField (0x1122334455667788 ),
293+ g .GoldilocksField (0x8877665544332211 ),
294+ g .GoldilocksField (0xAABBCCDDEEFF0011 ),
295+ })
296+ val2 := gFp5 .FromPlonky2GoldilocksField ([]g.GoldilocksField {
297+ g .GoldilocksField (0xFFFFFFFFFFFFFFFF ),
298+ g .GoldilocksField (0xFFFFFFFFFFFFFFFF ),
299+ g .GoldilocksField (0xFFFFFFFFFFFFFFFF ),
300+ g .GoldilocksField (0xFFFFFFFFFFFFFFFF ),
301+ g .GoldilocksField (0xFFFFFFFFFFFFFFFF ),
302+ })
303+
304+ add := gFp5 .Add (val1 , val2 )
305+ expectedAdd := [5 ]uint64 {1311768471589866989 , 1147797413325783839 , 1234605620731475846 , 9833440832084189711 , 12302652064957136911 }
306+ for i := 0 ; i < 5 ; i ++ {
307+ if add [i ].Uint64 () != expectedAdd [i ] {
63308 t .Fatalf ("Addition: Expected limb %d to be %x, but got %x" , i , expectedAdd [i ], add [i ])
64309 }
65310 }
66311
67312 sub := gFp5 .Sub (val1 , val2 )
68313 expectedSub := [5 ]uint64 {1311768462999932401 , 1147797404735849251 , 1234605612141541258 , 9833440823494255123 , 12302652056367202323 }
69314 for i := 0 ; i < 5 ; i ++ {
70- if sub [i ] != g . FromUint64 ( expectedSub [i ]) {
315+ if sub [i ]. Uint64 () != expectedSub [i ] {
71316 t .Fatalf ("Subtraction: Expected limb %d to be %x, but got %x" , i , expectedSub [i ], sub [i ])
72317 }
73318 }
74319
75320 mul := gFp5 .Mul (val1 , val2 )
76321 expectedMul := [5 ]uint64 {12801331769143413385 , 14031114708135177824 , 4192851210753422088 , 14031114723597060086 , 4193451712464626164 }
77322 for i := 0 ; i < 5 ; i ++ {
78- if mul [i ] != g . FromUint64 ( expectedMul [i ]) {
323+ if mul [i ]. Uint64 () != expectedMul [i ] {
79324 t .Fatalf ("Multiplication: Expected limb %d to be %x, but got %x" , i , expectedMul [i ], mul [i ])
80325 }
81326 }
@@ -89,7 +334,7 @@ func TestQuinticExtensionAddSubMulSquare(t *testing.T) {
89334 2864528669572451733 ,
90335 }
91336 for i := 0 ; i < 5 ; i ++ {
92- if square [i ] != g . FromUint64 ( expectedSquare [i ]) {
337+ if square [i ]. Uint64 () != expectedSquare [i ] {
93338 t .Fatalf ("Square: Expected limb %d to be %x, but got %x" , i , expectedSquare [i ], square [i ])
94339 }
95340 }
0 commit comments