400 lines
13 KiB
Nim
400 lines
13 KiB
Nim
# Constantine
|
||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||
# Licensed and distributed under either of
|
||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||
|
||
import
|
||
# Standard library
|
||
std/[tables, unittest, times],
|
||
# Internals
|
||
../constantine/config/common,
|
||
../constantine/[arithmetic, primitives],
|
||
../constantine/towers,
|
||
../constantine/config/curves,
|
||
../constantine/io/io_towers,
|
||
../constantine/pairing/[
|
||
lines_projective,
|
||
mul_fp12_by_lines
|
||
],
|
||
# Test utilities
|
||
../helpers/[prng_unsafe, static_for]
|
||
|
||
const
|
||
Iters = 8
|
||
TestCurves = [
|
||
BN254_Nogami,
|
||
BN254_Snarks,
|
||
BLS12_377,
|
||
BLS12_381
|
||
]
|
||
|
||
type
|
||
RandomGen = enum
|
||
Uniform
|
||
HighHammingWeight
|
||
Long01Sequence
|
||
|
||
var rng: RngState
|
||
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
|
||
rng.seed(seed)
|
||
echo "\n------------------------------------------------------\n"
|
||
echo "test_pairing_fp12_sparse xoshiro512** seed: ", seed
|
||
|
||
func random_elem(rng: var RngState, F: typedesc, gen: RandomGen): F {.inline, noInit.} =
|
||
if gen == Uniform:
|
||
result = rng.random_unsafe(F)
|
||
elif gen == HighHammingWeight:
|
||
result = rng.random_highHammingWeight(F)
|
||
else:
|
||
result = rng.random_long01Seq(F)
|
||
|
||
suite "Pairing - Sparse 𝔽p12 multiplication by line function is consistent with dense 𝔽p12 mul":
|
||
test "Dense 𝔽p4 by Sparse 0y":
|
||
proc test_fp4_0y(C: static Curve, gen: static RandomGen) =
|
||
for _ in 0 ..< Iters:
|
||
let a = rng.random_elem(Fp4[C], gen)
|
||
let y = rng.random_elem(Fp2[C], gen)
|
||
let b = Fp4[C](coords: [Fp2[C](), y])
|
||
|
||
var r {.noInit.}, r2 {.noInit.}: Fp4[C]
|
||
|
||
r.prod(a, b)
|
||
r2.mul_sparse_by_0y(a, y)
|
||
|
||
check: bool(r == r2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp4_0y(curve, gen = Uniform)
|
||
test_fp4_0y(curve, gen = HighHammingWeight)
|
||
test_fp4_0y(curve, gen = Long01Sequence)
|
||
|
||
test "Dense 𝔽p6 by Sparse 0y0":
|
||
proc test_fp6_0y0(C: static Curve, gen: static RandomGen) =
|
||
for _ in 0 ..< Iters:
|
||
let a = rng.random_elem(Fp6[C], gen)
|
||
let y = rng.random_elem(Fp2[C], gen)
|
||
let b = Fp6[C](coords: [Fp2[C](), y, Fp2[C]()])
|
||
|
||
var r {.noInit.}, r2 {.noInit.}: Fp6[C]
|
||
|
||
r.prod(a, b)
|
||
r2.mul_sparse_by_0y0(a, y)
|
||
|
||
check: bool(r == r2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp6_0y0(curve, gen = Uniform)
|
||
test_fp6_0y0(curve, gen = HighHammingWeight)
|
||
test_fp6_0y0(curve, gen = Long01Sequence)
|
||
|
||
test "Dense 𝔽p6 by Sparse xy0":
|
||
proc test_fp6_xy0(C: static Curve, gen: static RandomGen) =
|
||
for _ in 0 ..< Iters:
|
||
let a = rng.random_elem(Fp6[C], gen)
|
||
let x = rng.random_elem(Fp2[C], gen)
|
||
let y = rng.random_elem(Fp2[C], gen)
|
||
let b = Fp6[C](coords: [x, y, Fp2[C]()])
|
||
let line = Line[Fp2[C]](x: x, y: y)
|
||
|
||
var r {.noInit.}, r2 {.noInit.}: Fp6[C]
|
||
|
||
r.prod(a, b)
|
||
r2.mul_by_line_xy0(a, line)
|
||
|
||
check: bool(r == r2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp6_xy0(curve, gen = Uniform)
|
||
test_fp6_xy0(curve, gen = HighHammingWeight)
|
||
test_fp6_xy0(curve, gen = Long01Sequence)
|
||
|
||
when Fp12[BN254_Snarks]().c0.typeof is Fp6:
|
||
test "Sparse 𝔽p12/𝔽p6 resulting from xy00z0 line function":
|
||
proc test_fp12_xy00z0(C: static Curve, gen: static RandomGen) =
|
||
for _ in 0 ..< Iters:
|
||
var a = rng.random_elem(Fp12[C], gen)
|
||
var a2 = a
|
||
|
||
var x = rng.random_elem(Fp2[C], gen)
|
||
var y = rng.random_elem(Fp2[C], gen)
|
||
var z = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line = Line[Fp2[C]](x: x, y: y, z: z)
|
||
let b = Fp12[C](
|
||
c0: Fp6[C](coords: [ x, y, Fp2[C]()]),
|
||
c1: Fp6[C](coords: [Fp2[C](), z, Fp2[C]()])
|
||
)
|
||
|
||
a *= b
|
||
a2.mul_sparse_by_line_xy00z0(line)
|
||
|
||
check: bool(a == a2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_xy00z0(curve, gen = Uniform)
|
||
test_fp12_xy00z0(curve, gen = HighHammingWeight)
|
||
test_fp12_xy00z0(curve, gen = Long01Sequence)
|
||
|
||
test "Sparse 𝔽p12/𝔽p6 resulting from xyz000 line function":
|
||
proc test_fp12_xyz000(C: static Curve, gen: static RandomGen) =
|
||
for _ in 0 ..< Iters:
|
||
var a = rng.random_elem(Fp12[C], gen)
|
||
var a2 = a
|
||
|
||
var x = rng.random_elem(Fp2[C], gen)
|
||
var y = rng.random_elem(Fp2[C], gen)
|
||
var z = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line = Line[Fp2[C]](x: x, y: y, z: z)
|
||
let b = Fp12[C](
|
||
c0: Fp6[C](coords: [x, y, z])
|
||
)
|
||
|
||
a *= b
|
||
a2.mul_sparse_by_line_xyz000(line)
|
||
|
||
check: bool(a == a2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_xyz000(curve, gen = Uniform)
|
||
test_fp12_xyz000(curve, gen = HighHammingWeight)
|
||
test_fp12_xyz000(curve, gen = Long01Sequence)
|
||
else:
|
||
static: doAssert Fp12[BN254_Snarks]().c0.typeof is Fp4
|
||
|
||
test "Sparse 𝔽p12/𝔽p4 resulting from xy000z line function (M-twist only)":
|
||
proc test_fp12_xy000z(C: static Curve, gen: static RandomGen) =
|
||
when C.getSexticTwist() == M_Twist:
|
||
for _ in 0 ..< Iters:
|
||
var a = rng.random_elem(Fp12[C], gen)
|
||
var a2 = a
|
||
|
||
var x = rng.random_elem(Fp2[C], gen)
|
||
var y = rng.random_elem(Fp2[C], gen)
|
||
var z = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line = Line[Fp2[C]](x: x, y: y, z: z)
|
||
let b = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x, y]),
|
||
Fp4[C](),
|
||
Fp4[C](coords: [Fp2[C](), z])
|
||
]
|
||
)
|
||
|
||
a *= b
|
||
a2.mul_sparse_by_line_xy000z(line)
|
||
|
||
check: bool(a == a2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_xy000z(curve, gen = Uniform)
|
||
test_fp12_xy000z(curve, gen = HighHammingWeight)
|
||
test_fp12_xy000z(curve, gen = Long01Sequence)
|
||
|
||
test "Sparse 𝔽p12/𝔽p4 resulting from xyz000 line function (D-twist only)":
|
||
proc test_fp12_xyz000(C: static Curve, gen: static RandomGen) =
|
||
when C.getSexticTwist() == D_Twist:
|
||
for _ in 0 ..< Iters:
|
||
var a = rng.random_elem(Fp12[C], gen)
|
||
var a2 = a
|
||
|
||
var x = rng.random_elem(Fp2[C], gen)
|
||
var y = rng.random_elem(Fp2[C], gen)
|
||
var z = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line = Line[Fp2[C]](x: x, y: y, z: z)
|
||
let b = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x, y]),
|
||
Fp4[C](coords: [z, Fp2[C]()]),
|
||
Fp4[C]()
|
||
]
|
||
)
|
||
|
||
a *= b
|
||
a2.mul_sparse_by_line_xyz000(line)
|
||
|
||
check: bool(a == a2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_xyz000(curve, gen = Uniform)
|
||
test_fp12_xyz000(curve, gen = HighHammingWeight)
|
||
test_fp12_xyz000(curve, gen = Long01Sequence)
|
||
|
||
test "Somewhat-sparse 𝔽p12/𝔽p4 resulting from xy000z*xy000z line functions (M-twist only)":
|
||
proc test_fp12_xy000z_xy000z(C: static Curve, gen: static RandomGen) =
|
||
when C.getSexticTwist() == M_Twist:
|
||
for _ in 0 ..< Iters:
|
||
var x0 = rng.random_elem(Fp2[C], gen)
|
||
var y0 = rng.random_elem(Fp2[C], gen)
|
||
var z0 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line0 = Line[Fp2[C]](x: x0, y: y0, z: z0)
|
||
let f0 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x0, y0]),
|
||
Fp4[C](),
|
||
Fp4[C](coords: [Fp2[C](), z0])
|
||
]
|
||
)
|
||
|
||
var x1 = rng.random_elem(Fp2[C], gen)
|
||
var y1 = rng.random_elem(Fp2[C], gen)
|
||
var z1 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line1 = Line[Fp2[C]](x: x1, y: y1, z: z1)
|
||
let f1 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x1, y1]),
|
||
Fp4[C](),
|
||
Fp4[C](coords: [Fp2[C](), z1])
|
||
]
|
||
)
|
||
|
||
var r: Fp12[C]
|
||
r.prod(f0, f1)
|
||
|
||
var rl: Fp12[C]
|
||
rl.prod_xy000z_xy000z_into_abcd00efghij(line0, line1)
|
||
|
||
check: bool(r == rl)
|
||
|
||
test "Somewhat-sparse 𝔽p12/𝔽p4 resulting from xyz000*xyz000 line functions (D-twist only)":
|
||
proc test_fp12_xyz000_xyz000(C: static Curve, gen: static RandomGen) =
|
||
when C.getSexticTwist() == D_Twist:
|
||
for _ in 0 ..< Iters:
|
||
var x0 = rng.random_elem(Fp2[C], gen)
|
||
var y0 = rng.random_elem(Fp2[C], gen)
|
||
var z0 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line0 = Line[Fp2[C]](x: x0, y: y0, z: z0)
|
||
let f0 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x0, y0]),
|
||
Fp4[C](coords: [z0, Fp2[C]()]),
|
||
Fp4[C]()
|
||
]
|
||
)
|
||
|
||
var x1 = rng.random_elem(Fp2[C], gen)
|
||
var y1 = rng.random_elem(Fp2[C], gen)
|
||
var z1 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line1 = Line[Fp2[C]](x: x1, y: y1, z: z1)
|
||
let f1 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x1, y1]),
|
||
Fp4[C](coords: [z1, Fp2[C]()]),
|
||
Fp4[C]()
|
||
]
|
||
)
|
||
|
||
var r: Fp12[C]
|
||
r.prod(f0, f1)
|
||
|
||
var rl: Fp12[C]
|
||
rl.prod_xyz000_xyz000_into_abcdefghij00(line0, line1)
|
||
|
||
check: bool(r == rl)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_xyz000_xyz000(curve, gen = Uniform)
|
||
test_fp12_xyz000_xyz000(curve, gen = HighHammingWeight)
|
||
test_fp12_xyz000_xyz000(curve, gen = Long01Sequence)
|
||
|
||
test "Somewhat-sparse 𝔽p12/𝔽p4 mul by the product (xyz000*xyz000) of line functions (D-twist only)":
|
||
proc test_fp12_abcdefghij00(C: static Curve, gen: static RandomGen) =
|
||
when C.getSexticTwist() == D_Twist:
|
||
for _ in 0 ..< Iters:
|
||
var x0 = rng.random_elem(Fp2[C], gen)
|
||
var y0 = rng.random_elem(Fp2[C], gen)
|
||
var z0 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line0 = Line[Fp2[C]](x: x0, y: y0, z: z0)
|
||
let f0 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x0, y0]),
|
||
Fp4[C](coords: [z0, Fp2[C]()]),
|
||
Fp4[C]()
|
||
]
|
||
)
|
||
|
||
var x1 = rng.random_elem(Fp2[C], gen)
|
||
var y1 = rng.random_elem(Fp2[C], gen)
|
||
var z1 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line1 = Line[Fp2[C]](x: x1, y: y1, z: z1)
|
||
let f1 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x1, y1]),
|
||
Fp4[C](coords: [z1, Fp2[C]()]),
|
||
Fp4[C]()
|
||
]
|
||
)
|
||
|
||
var rl: Fp12[C]
|
||
rl.prod_xyz000_xyz000_into_abcdefghij00(line0, line1)
|
||
|
||
var f = rng.random_elem(Fp12[C], gen)
|
||
var f2 = f
|
||
|
||
f *= rl
|
||
f2.mul_sparse_by_abcdefghij00(rl)
|
||
|
||
check: bool(f == f2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_abcdefghij00(curve, gen = Uniform)
|
||
test_fp12_abcdefghij00(curve, gen = HighHammingWeight)
|
||
test_fp12_abcdefghij00(curve, gen = Long01Sequence)
|
||
|
||
test "Somewhat-sparse 𝔽p12/𝔽p4 mul by the product (xy000z*xy000z) of line functions (M-twist only)":
|
||
proc test_fp12_abcd00efghij(C: static Curve, gen: static RandomGen) =
|
||
when C.getSexticTwist() == M_Twist:
|
||
for _ in 0 ..< Iters:
|
||
var x0 = rng.random_elem(Fp2[C], gen)
|
||
var y0 = rng.random_elem(Fp2[C], gen)
|
||
var z0 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line0 = Line[Fp2[C]](x: x0, y: y0, z: z0)
|
||
let f0 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x0, y0]),
|
||
Fp4[C](),
|
||
Fp4[C](coords: [Fp2[C](), z0])
|
||
]
|
||
)
|
||
|
||
var x1 = rng.random_elem(Fp2[C], gen)
|
||
var y1 = rng.random_elem(Fp2[C], gen)
|
||
var z1 = rng.random_elem(Fp2[C], gen)
|
||
|
||
let line1 = Line[Fp2[C]](x: x1, y: y1, z: z1)
|
||
let f1 = Fp12[C](
|
||
coords: [
|
||
Fp4[C](coords: [x1, y1]),
|
||
Fp4[C](),
|
||
Fp4[C](coords: [Fp2[C](), z1])
|
||
]
|
||
)
|
||
|
||
var rl: Fp12[C]
|
||
rl.prod_xy000z_xy000z_into_abcd00efghij(line0, line1)
|
||
|
||
var f = rng.random_elem(Fp12[C], gen)
|
||
var f2 = f
|
||
|
||
f *= rl
|
||
f2.mul_sparse_by_abcd00efghij(rl)
|
||
|
||
check: bool(f == f2)
|
||
|
||
staticFor(curve, TestCurves):
|
||
test_fp12_abcd00efghij(curve, gen = Uniform)
|
||
test_fp12_abcd00efghij(curve, gen = HighHammingWeight)
|
||
test_fp12_abcd00efghij(curve, gen = Long01Sequence)
|