Skip to content

Commit 0fb6ae8

Browse files
committed
tests for koala and babybear field ops
1 parent 0bf4eae commit 0fb6ae8

File tree

4 files changed

+328
-1
lines changed

4 files changed

+328
-1
lines changed

constantine/named/config_fields_and_curves.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,12 @@ declareCurves:
7777
# -----------------------------------------------------------------------------
7878

7979
curve BabyBear: # BabyBear field used in SNARKs and zkVMs
80+
testingCurve: true
8081
bitwidth: 31
8182
modulus: "0x78000001" # `0b1111000000000000000000000000001 = 15·2²⁷ + 1 = 2³¹ - 2²⁷ + 1`
8283

8384
curve KoalaBear: # KoalaBear field used in SNARKs and zkVMs
85+
testingCurve: true
8486
bitwidth: 31
8587
modulus: "0x7f000001" # `0b11111111000000000000000000000001 = 255·2²⁴ + 1 = 2³¹ - 2²⁴ + 1`
8688

tests/math_fields/t_finite_fields.nim

Lines changed: 234 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,240 @@ proc main() =
166166
# Check equality when converting back to natural domain
167167
9'u64 == cast[uint64](r_bytes)
168168

169+
test "Addition mod 2^31 - 2^27 + 1":
170+
block:
171+
var x, y, z: Fp[BabyBear]
172+
173+
x.fromUint(80'u32)
174+
y.fromUint(10'u32)
175+
z.fromUint(90'u32)
176+
177+
x += y
178+
179+
var x_bytes: array[4, byte]
180+
x_bytes.marshal(x, cpuEndian)
181+
let new_x = cast[uint32](x_bytes)
182+
183+
check:
184+
# Check equality in the Montgomery domain
185+
bool(z == x)
186+
# Check equality when converting back to natural domain
187+
new_x == 90'u32
188+
189+
block:
190+
var x, y, z: Fp[BabyBear]
191+
192+
x.fromUint(0x78000000'u32) # p-1
193+
y.fromUint(1'u32)
194+
z.fromUint(0'u32)
195+
196+
x += y
197+
198+
var x_bytes: array[4, byte]
199+
x_bytes.marshal(x, cpuEndian)
200+
let new_x = cast[uint32](x_bytes)
201+
202+
check:
203+
# Check equality in the Montgomery domain
204+
bool(z == x)
205+
# Check equality when converting back to natural domain
206+
new_x == 0'u32
207+
208+
test "Substraction mod 2^31 - 2^27 + 1":
209+
block:
210+
var x, y, z: Fp[BabyBear]
211+
212+
x.fromUint(80'u32)
213+
y.fromUint(10'u32)
214+
z.fromUint(70'u32)
215+
216+
x -= y
217+
218+
var x_bytes: array[4, byte]
219+
x_bytes.marshal(x, cpuEndian)
220+
let new_x = cast[uint32](x_bytes)
221+
222+
check:
223+
# Check equality in the Montgomery domain
224+
bool(z == x)
225+
# Check equality when converting back to natural domain
226+
new_x == 70'u32
227+
228+
block:
229+
var x, y, z: Fp[BabyBear]
230+
231+
x.fromUint(0'u32)
232+
y.fromUint(1'u32)
233+
z.fromUint(0x78000000'u32) # p-1
234+
235+
x -= y
236+
237+
var x_bytes: array[4, byte]
238+
x_bytes.marshal(x, cpuEndian)
239+
let new_x = cast[uint32](x_bytes)
240+
241+
check:
242+
# Check equality in the Montgomery domain
243+
bool(z == x)
244+
# Check equality when converting back to natural domain
245+
new_x == 0x78000000'u32
246+
247+
test "Multiplication mod 2^31 - 2^27 + 1":
248+
block:
249+
var x, y, z, r: Fp[BabyBear]
250+
251+
x.fromUint(10'u32)
252+
y.fromUint(10'u32)
253+
z.fromUint(100'u32)
254+
255+
r.prod(x, y)
256+
257+
var r_bytes: array[4, byte]
258+
r_bytes.marshal(r, cpuEndian)
259+
let new_r = cast[uint32](r_bytes)
260+
261+
check:
262+
# Check equality in the Montgomery domain
263+
bool(z == r)
264+
# Check equality when converting back to natural domain
265+
new_r == 100'u32
266+
267+
block:
268+
var x, y, z, r: Fp[BabyBear]
269+
270+
x.fromUint(0x10000'u32)
271+
y.fromUint(0x10000'u32)
272+
z.fromUint(uint32((0x10000'u64 * 0x10000'u64) mod 0x78000001'u64))
273+
274+
r.prod(x, y)
275+
276+
var r_bytes: array[4, byte]
277+
r_bytes.marshal(r, cpuEndian)
278+
let new_r = cast[uint32](r_bytes)
279+
280+
check:
281+
# Check equality in the Montgomery domain
282+
bool(z == r)
283+
# Check equality when converting back to natural domain
284+
new_r == uint32((0x10000'u64 * 0x10000'u64) mod 0x78000001'u64)
285+
286+
test "Addition mod 2^31 - 2^24 + 1":
287+
block:
288+
var x, y, z: Fp[KoalaBear]
289+
290+
x.fromUint(50'u32)
291+
y.fromUint(20'u32)
292+
z.fromUint(70'u32)
293+
294+
x += y
295+
296+
var x_bytes: array[4, byte]
297+
x_bytes.marshal(x, cpuEndian)
298+
let new_x = cast[uint32](x_bytes)
299+
300+
check:
301+
# Check equality in the Montgomery domain
302+
bool(z == x)
303+
# Check equality when converting back to natural domain
304+
new_x == 70'u32
305+
306+
block:
307+
var x, y, z: Fp[KoalaBear]
308+
309+
x.fromUint(0x7f000000'u32) # p-1
310+
y.fromUint(1'u32)
311+
z.fromUint(0'u32)
312+
313+
x += y
314+
315+
var x_bytes: array[4, byte]
316+
x_bytes.marshal(x, cpuEndian)
317+
let new_x = cast[uint32](x_bytes)
318+
319+
check:
320+
# Check equality in the Montgomery domain
321+
bool(z == x)
322+
# Check equality when converting back to natural domain
323+
new_x == 0'u32
324+
325+
test "Substraction mod 2^31 - 2^24 + 1":
326+
block:
327+
var x, y, z: Fp[KoalaBear]
328+
329+
x.fromUint(70'u32)
330+
y.fromUint(20'u32)
331+
z.fromUint(50'u32)
332+
333+
x -= y
334+
335+
var x_bytes: array[4, byte]
336+
x_bytes.marshal(x, cpuEndian)
337+
let new_x = cast[uint32](x_bytes)
338+
339+
check:
340+
# Check equality in the Montgomery domain
341+
bool(z == x)
342+
# Check equality when converting back to natural domain
343+
new_x == 50'u32
344+
345+
block:
346+
var x, y, z: Fp[KoalaBear]
347+
348+
x.fromUint(0'u32)
349+
y.fromUint(1'u32)
350+
z.fromUint(0x7f000000'u32) # p-1
351+
352+
x -= y
353+
354+
var x_bytes: array[4, byte]
355+
x_bytes.marshal(x, cpuEndian)
356+
let new_x = cast[uint32](x_bytes)
357+
358+
check:
359+
# Check equality in the Montgomery domain
360+
bool(z == x)
361+
# Check equality when converting back to natural domain
362+
new_x == 0x7f000000'u32
363+
364+
test "Multiplication mod 2^31 - 2^24 + 1":
365+
block:
366+
var x, y, z, r: Fp[KoalaBear]
367+
368+
x.fromUint(12'u32)
369+
y.fromUint(12'u32)
370+
z.fromUint(144'u32)
371+
372+
r.prod(x, y)
373+
374+
var r_bytes: array[4, byte]
375+
r_bytes.marshal(r, cpuEndian)
376+
let new_r = cast[uint32](r_bytes)
377+
378+
check:
379+
# Check equality in the Montgomery domain
380+
bool(z == r)
381+
# Check equality when converting back to natural domain
382+
new_r == 144'u32
383+
384+
block:
385+
var x, y, z, r: Fp[KoalaBear]
386+
387+
x.fromUint(0x10000'u32)
388+
y.fromUint(0x20000'u32)
389+
z.fromUint(uint32((0x10000'u64 * 0x20000'u64) mod 0x7f000001'u64))
390+
391+
r.prod(x, y)
392+
393+
var r_bytes: array[4, byte]
394+
r_bytes.marshal(r, cpuEndian)
395+
let new_r = cast[uint32](r_bytes)
396+
397+
check:
398+
# Check equality in the Montgomery domain
399+
bool(z == r)
400+
# Check equality when converting back to natural domain
401+
new_r == uint32((0x10000'u64 * 0x20000'u64) mod 0x7f000001'u64)
402+
169403
test "Addition mod 2^61 - 1":
170404
block:
171405
var x, y, z: Fp[Mersenne61]
@@ -302,7 +536,6 @@ proc main() =
302536
# Check equality when converting back to natural domain
303537
new_r == 2'u64
304538

305-
306539
main()
307540

308541
proc largeField() =

tests/math_fields/t_finite_fields_mulsquare.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ proc mainSanity() =
8181
suite "Modular squaring is consistent with multiplication on special elements" & " [" & $WordBitWidth & "-bit words]":
8282
sanity Fake101
8383
sanity Mersenne61
84+
sanity BabyBear
85+
sanity KoalaBear
8486
sanity Mersenne127
8587
sanity P224 # P224 uses the fast-path with 64-bit words and the slow path with 32-bit words
8688
sanity P256

tests/math_fields/t_io_fields.nim

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,96 @@ proc main() =
4646
marshal(r_bytes, f, littleEndian)
4747
check: x_bytes == r_bytes
4848

49+
# BabyBear ---------------------------------
50+
block:
51+
# "Little-endian" - 0
52+
let x = 0'u64
53+
let x_bytes = cast[array[8, byte]](x)
54+
var f: Fp[BabyBear]
55+
f.fromUint(x)
56+
57+
var r_bytes: array[8, byte]
58+
marshal(r_bytes, f, littleEndian)
59+
check: x_bytes == r_bytes
60+
61+
block:
62+
# "Little-endian" - 1
63+
let x = 1'u64
64+
let x_bytes = cast[array[8, byte]](x)
65+
var f: Fp[BabyBear]
66+
f.fromUint(x)
67+
68+
var r_bytes: array[8, byte]
69+
marshal(r_bytes, f, littleEndian)
70+
check: x_bytes == r_bytes
71+
72+
block:
73+
# "Little-endian" - 2^15
74+
let x = 1'u64 shl 15
75+
let x_bytes = cast[array[8, byte]](x)
76+
var f: Fp[BabyBear]
77+
f.fromUint(x)
78+
79+
var r_bytes: array[8, byte]
80+
marshal(r_bytes, f, littleEndian)
81+
check: x_bytes == r_bytes
82+
83+
block:
84+
# "Little-endian" - p-1
85+
let x = 2013265921'u64 - 1
86+
let x_bytes = cast[array[8, byte]](x)
87+
var f: Fp[BabyBear]
88+
f.fromUint(x)
89+
90+
var r_bytes: array[8, byte]
91+
marshal(r_bytes, f, littleEndian)
92+
check: x_bytes == r_bytes
93+
94+
# KoalaBear ---------------------------------
95+
block:
96+
# "Little-endian" - 0
97+
let x = 0'u64
98+
let x_bytes = cast[array[8, byte]](x)
99+
var f: Fp[KoalaBear]
100+
f.fromUint(x)
101+
102+
var r_bytes: array[8, byte]
103+
marshal(r_bytes, f, littleEndian)
104+
check: x_bytes == r_bytes
105+
106+
block:
107+
# "Little-endian" - 1
108+
let x = 1'u64
109+
let x_bytes = cast[array[8, byte]](x)
110+
var f: Fp[KoalaBear]
111+
f.fromUint(x)
112+
113+
var r_bytes: array[8, byte]
114+
marshal(r_bytes, f, littleEndian)
115+
check: x_bytes == r_bytes
116+
117+
block:
118+
# "Little-endian" - 2^15
119+
let x = 1'u64 shl 15
120+
let x_bytes = cast[array[8, byte]](x)
121+
var f: Fp[KoalaBear]
122+
f.fromUint(x)
123+
124+
var r_bytes: array[8, byte]
125+
marshal(r_bytes, f, littleEndian)
126+
check: x_bytes == r_bytes
127+
128+
block:
129+
# "Little-endian" - p-1
130+
let x = 2130706433'u64 - 1
131+
let x_bytes = cast[array[8, byte]](x)
132+
var f: Fp[KoalaBear]
133+
f.fromUint(x)
134+
135+
var r_bytes: array[8, byte]
136+
marshal(r_bytes, f, littleEndian)
137+
check: x_bytes == r_bytes
138+
49139
# Mersenne 61 ---------------------------------
50140
block:
51141
# "Little-endian" - 0

0 commit comments

Comments
 (0)