Pairings for BN254-Nogami and BN254-Snarks (#86)

* Implement optimized final exponentiation for BN254-Nogami

* And BN254 Snarks support

* Optimize D-Twist sparse Fp12 x line multiplication

* Move quadruple/octuple and add to Github issues: https://github.com/mratsim/constantine/issues/88 [skip ci]
This commit is contained in:
Mamy Ratsimbazafy 2020-09-25 21:58:20 +02:00 committed by GitHub
parent f78ed23dad
commit 03ecb31c57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 708 additions and 75 deletions

View File

@ -36,7 +36,7 @@ proc main() =
const curve = AvailableCurves[i]
lineDoubleBench(curve, Iters)
lineAddBench(curve, Iters)
mulFp12byLineBench(curve, Iters)
mulFp12byLine_xy000z_Bench(curve, Iters)
separator()
finalExpEasyBench(curve, Iters)
finalExpHardBLS12Bench(curve, Iters)

View File

@ -0,0 +1,51 @@
# 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
# Internals
../constantine/config/curves,
../constantine/arithmetic,
../constantine/towers,
# Helpers
../helpers/static_for,
./bench_pairing_template,
# Standard library
std/strutils
# ############################################################
#
# Benchmark of pairings
# for BN254-Nogami
#
# ############################################################
const Iters = 50
const AvailableCurves = [
BN254_Nogami,
]
proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
lineDoubleBench(curve, Iters)
lineAddBench(curve, Iters)
mulFp12byLine_xyz000_Bench(curve, Iters)
separator()
finalExpEasyBench(curve, Iters)
finalExpHardBNBench(curve, Iters)
separator()
millerLoopBNBench(curve, Iters)
finalExpBNBench(curve, Iters)
separator()
pairingBNBench(curve, Iters)
separator()
main()
notes()

View File

@ -0,0 +1,51 @@
# 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
# Internals
../constantine/config/curves,
../constantine/arithmetic,
../constantine/towers,
# Helpers
../helpers/static_for,
./bench_pairing_template,
# Standard library
std/strutils
# ############################################################
#
# Benchmark of pairings
# for BN254-Snarks
#
# ############################################################
const Iters = 50
const AvailableCurves = [
BN254_Snarks,
]
proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
lineDoubleBench(curve, Iters)
lineAddBench(curve, Iters)
mulFp12byLine_xyz000_Bench(curve, Iters)
separator()
finalExpEasyBench(curve, Iters)
finalExpHardBNBench(curve, Iters)
separator()
millerLoopBNBench(curve, Iters)
finalExpBNBench(curve, Iters)
separator()
pairingBNBench(curve, Iters)
separator()
main()
notes()

View File

@ -24,7 +24,8 @@ import
cyclotomic_fp12,
lines_projective,
mul_fp12_by_lines,
pairing_bls12
pairing_bls12,
pairing_bn
],
# Helpers
../helpers/[prng_unsafe, static_for],
@ -150,7 +151,20 @@ proc lineAddBench*(C: static Curve, iters: int) =
bench("Line add", C, iters):
line.line_add(T, Qaff, Paff)
proc mulFp12byLineBench*(C: static Curve, iters: int) =
proc mulFp12byLine_xyz000_Bench*(C: static Curve, iters: int) =
var line: Line[Fp2[C], C.getSexticTwist()]
var T = rng.random_point(ECP_SWei_Proj[Fp2[C]])
let P = rng.random_point(ECP_SWei_Proj[Fp[C]])
var Paff: ECP_SWei_Aff[Fp[C]]
Paff.affineFromProjective(P)
line.line_double(T, Paff)
var f = rng.random_unsafe(Fp12[C])
bench("Mul 𝔽p12 by line xyz000", C, iters):
f.mul_sparse_by_line_xyz000(line)
proc mulFp12byLine_xy000z_Bench*(C: static Curve, iters: int) =
var line: Line[Fp2[C], C.getSexticTwist()]
var T = rng.random_point(ECP_SWei_Proj[Fp2[C]])
let P = rng.random_point(ECP_SWei_Proj[Fp[C]])
@ -178,6 +192,21 @@ proc millerLoopBLS12Bench*(C: static Curve, iters: int) =
bench("Miller Loop BLS12", C, iters):
f.millerLoopGenericBLS12(Paff, Qaff)
proc millerLoopBNBench*(C: static Curve, iters: int) =
let
P = rng.random_point(ECP_SWei_Proj[Fp[C]])
Q = rng.random_point(ECP_SWei_Proj[Fp2[C]])
var
Paff: ECP_SWei_Aff[Fp[C]]
Qaff: ECP_SWei_Aff[Fp2[C]]
Paff.affineFromProjective(P)
Qaff.affineFromProjective(Q)
var f: Fp12[C]
bench("Miller Loop BN", C, iters):
f.millerLoopGenericBN(Paff, Qaff)
proc finalExpEasyBench*(C: static Curve, iters: int) =
var r = rng.random_unsafe(Fp12[C])
bench("Final Exponentiation Easy", C, iters):
@ -189,12 +218,24 @@ proc finalExpHardBLS12Bench*(C: static Curve, iters: int) =
bench("Final Exponentiation Hard BLS12", C, iters):
r.finalExpHard_BLS12()
proc finalExpHardBNBench*(C: static Curve, iters: int) =
var r = rng.random_unsafe(Fp12[C])
r.finalExpEasy()
bench("Final Exponentiation Hard BN", C, iters):
r.finalExpHard_BN()
proc finalExpBLS12Bench*(C: static Curve, iters: int) =
var r = rng.random_unsafe(Fp12[C])
bench("Final Exponentiation BLS12", C, iters):
r.finalExpEasy()
r.finalExpHard_BLS12()
proc finalExpBNBench*(C: static Curve, iters: int) =
var r = rng.random_unsafe(Fp12[C])
bench("Final Exponentiation BN", C, iters):
r.finalExpEasy()
r.finalExpHard_BN()
proc pairingBLS12Bench*(C: static Curve, iters: int) =
let
P = rng.random_point(ECP_SWei_Proj[Fp[C]])
@ -204,3 +245,13 @@ proc pairingBLS12Bench*(C: static Curve, iters: int) =
bench("Pairing BLS12", C, iters):
f.pairing_bls12(P, Q)
proc pairingBNBench*(C: static Curve, iters: int) =
let
P = rng.random_point(ECP_SWei_Proj[Fp[C]])
Q = rng.random_point(ECP_SWei_Proj[Fp2[C]])
var f: Fp12[C]
bench("Pairing BN", C, iters):
f.pairing_bn(P, Q)

View File

@ -451,14 +451,44 @@ task bench_ec_g2_clang_noasm, "Run benchmark on Elliptic Curve group 𝔾2 - Sho
task bench_pairing_bls12_381, "Run pairings benchmarks for BLS12-381 - Default compiler":
runBench("bench_pairing_bls12_381")
task bench_pairing_bls12_381_gcc, "Run benchmark on Elliptic Curve group 𝔾2 - Short Weierstrass with Projective Coordinates - GCC":
task bench_pairing_bls12_381_gcc, "Run pairings benchmarks for BLS12-381 - GCC":
runBench("bench_pairing_bls12_381", "gcc")
task bench_pairing_bls12_381_clang, "Run benchmark on Elliptic Curve group 𝔾2 - Short Weierstrass with Projective Coordinates - Clang":
task bench_pairing_bls12_381_clang, "Run pairings benchmarks for BLS12-381 - Clang":
runBench("bench_pairing_bls12_381", "clang")
task bench_pairing_bls12_381_gcc_noasm, "Run benchmark on Elliptic Curve group 𝔾2 - Short Weierstrass with Projective Coordinates - GCC no Assembly":
task bench_pairing_bls12_381_gcc_noasm, "Run pairings benchmarks for BLS12-381 - GCC no Assembly":
runBench("bench_pairing_bls12_381", "gcc", useAsm = false)
task bench_pairing_bls12_381_clang_noasm, "Run benchmark on Elliptic Curve group 𝔾2 - Short Weierstrass with Projective Coordinates - Clang no Assembly":
task bench_pairing_bls12_381_clang_noasm, "Run pairings benchmarks for BLS12-381 - Clang no Assembly":
runBench("bench_pairing_bls12_381", "clang", useAsm = false)
task bench_pairing_bn254_nogami, "Run pairings benchmarks for BN254-Nogami - Default compiler":
runBench("bench_pairing_bn254_nogami")
task bench_pairing_bn254_nogami_gcc, "Run pairings benchmarks for BN254-Nogami - GCC":
runBench("bench_pairing_bn254_nogami", "gcc")
task bench_pairing_bn254_nogami_clang, "Run pairings benchmarks for BN254-Nogami - Clang":
runBench("bench_pairing_bn254_nogami", "clang")
task bench_pairing_bn254_nogami_gcc_noasm, "Run pairings benchmarks for BN254-Nogami - GCC no Assembly":
runBench("bench_pairing_bn254_nogami", "gcc", useAsm = false)
task bench_pairing_bn254_nogami_clang_noasm, "Run pairings benchmarks for BN254-Nogami - Clang no Assembly":
runBench("bench_pairing_bn254_nogami", "clang", useAsm = false)
task bench_pairing_bn254_snarks, "Run pairings benchmarks for BN254-Snarks - Default compiler":
runBench("bench_pairing_bn254_snarks")
task bench_pairing_bn254_snarks_gcc, "Run pairings benchmarks for BN254-Snarks - GCC":
runBench("bench_pairing_bn254_snarks", "gcc")
task bench_pairing_bn254_snarks_clang, "Run pairings benchmarks for BN254-Snarks - Clang":
runBench("bench_pairing_bn254_snarks", "clang")
task bench_pairing_bn254_snarks_gcc_noasm, "Run pairings benchmarks for BN254-Snarks - GCC no Assembly":
runBench("bench_pairing_bn254_snarks", "gcc", useAsm = false)
task bench_pairing_bn254_snarks_clang_noasm, "Run pairings benchmarks for BN254-Snarks - Clang no Assembly":
runBench("bench_pairing_bn254_snarks", "clang", useAsm = false)

View File

@ -103,7 +103,7 @@ declareCurves:
modulus: "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
family: BarretoNaehrig
bn_u_bitwidth: 63
bn_u: "0x44E992B44A6909F1" # u: 4965661367192848881
bn_u: "0x44e992b44a6909f1" # u: 4965661367192848881
cubicRootOfUnity_modP: "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48"
# For sanity checks
cubicRootOfUnity_modR: "0x30644e72e131a029048b6e193fd84104cc37a73fec2bc5e9b8ca0b2d36636f23"

View File

@ -68,7 +68,7 @@ template mulCheckSparse[Fp2](a: var Fp2, b: Fp2) =
# c = (SNR^((p-1)/6)^coef).
# Then for frobenius(2): c * conjugate(c)
# And for frobenius(2): c² * conjugate(c)
# And for frobenius(3): c² * conjugate(c)
const FrobMapConst_BLS12_381 = [
# frobenius(1)
[Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^0
@ -146,23 +146,182 @@ const FrobMapConst_BLS12_381 = [
"0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2"
)]]
func frobenius_map*(r: var Fp4, a: Fp4, k: static int = 1) {.inline.} =
const FrobMapConst_BN254_Nogami = [
# frobenius(1)
[Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^0
"0x1",
"0x0"
),
Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^1
"0x1b377619212e7c8cb6499b50a846953f850974924d3f77c2e17de6c06f2a6de9",
"0x9ebee691ed1837503eab22f57b96ac8dc178b6db2c08850c582193f90d5922a"
),
Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3)
"0x0",
"0x25236482400000017080eb4000000006181800000000000cd98000000000000b"
),
Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2)
"0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5",
"0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5"
),
Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3)
"0x25236482400000017080eb4000000006181800000000000cd98000000000000c",
"0x0"
),
Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^5
"0x19f3db6884cdca43c2b0d5792cd135accb1baea0b017046e859975ab54b5ef9b",
"0xb2f8919bb3235bdf7837806d32eca5b9605515f4fe8fba521668a54ab4a1078"
)],
# frobenius(2)
[Fp2[BN254_Nogami].fromHex( # norm(SNR)^((p-1)/6)^1
"0x1",
"0x0"
),
Fp2[BN254_Nogami].fromHex( # norm(SNR)^((p-1)/6)^2
"0x49b36240000000024909000000000006cd80000000000008",
"0x0"
),
Fp2[BN254_Nogami].fromHex(
"0x49b36240000000024909000000000006cd80000000000007",
"0x0"
),
Fp2[BN254_Nogami].fromHex(
"0x2523648240000001ba344d80000000086121000000000013a700000000000012",
"0x0"
),
Fp2[BN254_Nogami].fromHex(
"0x25236482400000017080eb4000000006181800000000000cd98000000000000b",
"0x0"
),
Fp2[BN254_Nogami].fromHex(
"0x25236482400000017080eb4000000006181800000000000cd98000000000000c",
"0x0"
)],
# frobenius(3)
[Fp2[BN254_Nogami].fromHex(
"0x1",
"0x0"
),
Fp2[BN254_Nogami].fromHex(
"0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e",
"0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5"
),
Fp2[BN254_Nogami].fromHex(
"0x0",
"0x1"
),
Fp2[BN254_Nogami].fromHex(
"0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e",
"0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e"
),
Fp2[BN254_Nogami].fromHex(
"0x2523648240000001ba344d80000000086121000000000013a700000000000012",
"0x0"
),
Fp2[BN254_Nogami].fromHex(
"0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5",
"0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e"
)]]
const FrobMapConst_BN254_Snarks = [
# frobenius(1)
[Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^0
"0x1",
"0x0"
),
Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^1
"0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470",
"0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac"
),
Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3)
"0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d",
"0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2"
),
Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2)
"0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a",
"0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3"
),
Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3)
"0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762",
"0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126"
),
Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^5
"0x183c1e74f798649e93a3661a4353ff4425c459b55aa1bd32ea2c810eab7692f",
"0x12acf2ca76fd0675a27fb246c7729f7db080cb99678e2ac024c6b8ee6e0c2c4b"
)],
# frobenius(2)
[Fp2[BN254_Snarks].fromHex( # norm(SNR)^((p-1)/6)^1
"0x1",
"0x0"
),
Fp2[BN254_Snarks].fromHex( # norm(SNR)^((p-1)/6)^2
"0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49",
"0x0"
),
Fp2[BN254_Snarks].fromHex(
"0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48",
"0x0"
),
Fp2[BN254_Snarks].fromHex(
"0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46",
"0x0"
),
Fp2[BN254_Snarks].fromHex(
"0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe",
"0x0"
),
Fp2[BN254_Snarks].fromHex(
"0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff",
"0x0"
)],
# frobenius(3)
[Fp2[BN254_Snarks].fromHex(
"0x1",
"0x0"
),
Fp2[BN254_Snarks].fromHex(
"0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f",
"0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101"
),
Fp2[BN254_Snarks].fromHex(
"0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d",
"0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de"
),
Fp2[BN254_Snarks].fromHex(
"0x2a275b6d9896aa4cdbf17f1dca9e5ea3bbd689a3bea870f45fcc8ad066dce9ed",
"0x28a411b634f09b8fb14b900e9507e9327600ecc7d8cf6ebab94d0cb3b2594c64"
),
Fp2[BN254_Snarks].fromHex(
"0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066",
"0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f"
),
Fp2[BN254_Snarks].fromHex(
"0x13c49044952c0905711699fa3b4d3f692ed68098967c84a5ebde847076261b43",
"0x16db366a59b1dd0b9fb1b2282a48633d3e2ddaea200280211f25041384282499"
)]]
{.experimental: "dynamicBindSym".}
macro frobMapConst(C: static Curve): untyped =
return bindSym("FrobMapConst_" & $C)
func frobenius_map*[C](r: var Fp4[C], a: Fp4[C], k: static int = 1) {.inline.} =
## Computes a^(p^k)
## The p-power frobenius automorphism on 𝔽p4
r.c0.frobenius_map(a.c0, k)
r.c1.frobenius_map(a.c1, k)
r.c1.mulCheckSparse FrobMapConst_BLS12_381[k-1][3]
r.c1.mulCheckSparse frobMapConst(C)[k-1][3]
func frobenius_map*(r: var Fp6, a: Fp6, k: static int = 1) {.inline.} =
func frobenius_map*[C](r: var Fp6[C], a: Fp6[C], k: static int = 1) {.inline.} =
## Computes a^(p^k)
## The p-power frobenius automorphism on 𝔽p6
r.c0.frobenius_map(a.c0, k)
r.c1.frobenius_map(a.c1, k)
r.c2.frobenius_map(a.c2, k)
r.c1.mulCheckSparse FrobMapConst_BLS12_381[k-1][2]
r.c2.mulCheckSparse FrobMapConst_BLS12_381[k-1][4]
r.c1.mulCheckSparse frobMapConst(C)[k-1][2]
r.c2.mulCheckSparse frobMapConst(C)[k-1][4]
func frobenius_map*(r: var Fp12, a: Fp12, k: static int = 1) {.inline.} =
func frobenius_map*[C](r: var Fp12[C], a: Fp12[C], k: static int = 1) {.inline.} =
## Computes a^(p^k)
## The p-power frobenius automorphism on 𝔽p12
static: doAssert r.c0 is Fp4
@ -170,12 +329,12 @@ func frobenius_map*(r: var Fp12, a: Fp12, k: static int = 1) {.inline.} =
for r_fp2, a_fp2 in fields(r_fp4, a_fp4):
r_fp2.frobenius_map(a_fp2, k)
r.c0.c0.mulCheckSparse FrobMapConst_BLS12_381[k-1][0]
r.c0.c1.mulCheckSparse FrobMapConst_BLS12_381[k-1][3]
r.c1.c0.mulCheckSparse FrobMapConst_BLS12_381[k-1][1]
r.c1.c1.mulCheckSparse FrobMapConst_BLS12_381[k-1][4]
r.c2.c0.mulCheckSparse FrobMapConst_BLS12_381[k-1][2]
r.c2.c1.mulCheckSparse FrobMapConst_BLS12_381[k-1][5]
r.c0.c0.mulCheckSparse frobMapConst(C)[k-1][0]
r.c0.c1.mulCheckSparse frobMapConst(C)[k-1][3]
r.c1.c0.mulCheckSparse frobMapConst(C)[k-1][1]
r.c1.c1.mulCheckSparse frobMapConst(C)[k-1][4]
r.c2.c0.mulCheckSparse frobMapConst(C)[k-1][2]
r.c2.c1.mulCheckSparse frobMapConst(C)[k-1][5]
# ψ (Psi) - Untwist-Frobenius-Twist Endomorphisms on twisted curves
# -----------------------------------------------------------------
@ -270,8 +429,6 @@ const FrobPsiConst_BLS12_381_psi2_coef2 = Fp2[BLS12_381].fromHex(
"0x0"
)
{.experimental: "dynamicBindSym".}
macro frobPsiConst(C: static Curve, psipow, coefpow: static int): untyped =
return bindSym("FrobPsiConst_" & $C & "_psi" & $psipow & "_coef" & $coefpow)

View File

@ -50,6 +50,11 @@
Juan Manuel Gonzalez Nieto, and Kenneth Koon-Ho Wong, 2010
https://eprint.iacr.org/2010/104.pdf
- Faster hashing to G2\
Laura Fuentes-Castañeda, Edward Knapp,\
Francisco Jose Rodríguez-Henríquez, 2011\
https://link.springer.com/content/pdf/10.1007%2F978-3-642-28496-0_25.pdf
- Pairings for beginners\
Craig Costello, 2012 (?)\
http://www.craigcostello.com.au/pairings/PairingsForBeginners.pdf
@ -65,7 +70,8 @@
https://eprint.iacr.org/2012/408.pdf
- The Realm of the Pairings\
Diego F. Aranha and Paulo S. L. M. Barreto and Patrick Longa and Jefferson E. Ricardini\
Diego F. Aranha and Paulo S. L. M. Barreto\
and Patrick Longa and Jefferson E. Ricardini, 2013\
https://eprint.iacr.org/2013/722.pdf\
http://sac2013.irmacs.sfu.ca/slides/s1.pdf
@ -75,6 +81,10 @@
https://scholarworks.rit.edu/cgi/viewcontent.cgi?referer=&httpsredir=1&article=10083&context=theses
https://github.com/rajeevakarv/FiniteFieldComputations
- Memory-saving computation of the pairing final exponentiation on BN curves\
Sylvain Duquesne and Loubna Ghammam, 2015\
https://eprint.iacr.org/2015/192
- A taxonomy of pairings, their security, their complexity\
Razvan Barbulescu, Nadia El Mrabet, and Loubna Ghammam, 2019\
https://hal.archives-ouvertes.fr/hal-02129868/file/2019-485.pdf

View File

@ -224,3 +224,26 @@ func cyclotomic_square*[C](a: var Fp12[C]) =
else:
{.error: "Not implemented".}
iterator unpack(scalarByte: byte): bool =
yield bool((scalarByte and 0b10000000) shr 7)
yield bool((scalarByte and 0b01000000) shr 6)
yield bool((scalarByte and 0b00100000) shr 5)
yield bool((scalarByte and 0b00010000) shr 4)
yield bool((scalarByte and 0b00001000) shr 3)
yield bool((scalarByte and 0b00000100) shr 2)
yield bool((scalarByte and 0b00000010) shr 1)
yield bool( scalarByte and 0b00000001)
func cyclotomic_exp*[C](r: var Fp12[C], a: Fp12[C], exponent: BigInt, invert: bool) =
var eBytes: array[(exponent.bits+7) div 8, byte]
eBytes.exportRawUint(exponent, bigEndian)
r.setOne()
for b in eBytes:
for bit in unpack(b):
r.cyclotomic_square()
if bit:
r *= a
if invert:
r.cyclotomic_inv()

View File

@ -41,9 +41,15 @@ import
# 𝔽p12 by line - Sparse functions
# ----------------------------------------------------------------
func mul_sparse_by_y0*[C: static Curve](r: var Fp4[C], a: Fp4[C], b: Fp2[C]) =
## Sparse multiplication of an Fp4 element
## with coordinates (a₀, a₁) by (b₀, 0)
r.c0.prod(a.c0, b)
r.c1.prod(a.c1, b)
func mul_sparse_by_0y*[C: static Curve](r: var Fp4[C], a: Fp4[C], b: Fp2[C]) =
## Sparse multiplication of an Fp4 element
## with coordinates (a₀, a₁) by (0, b₁, 0)
## with coordinates (a₀, a₁) by (0, b₁)
r.c0.prod(a.c1, b)
r.c0 *= NonResidue
r.c1.prod(a.c0, b)
@ -140,12 +146,49 @@ func mul_sparse_by_line_xyz000*[C: static Curve, Tw: static SexticTwist](
static: doAssert f.c0.typeof is Fp4, "This assumes 𝔽p12 as a cubic extension of 𝔽p4"
var v: Fp12[C]
v.c0.c0 = l.x
v.c0.c1 = l.y
v.c1.c0 = l.z
# In the following equations (taken from cubic extension implementation)
# a = f
# b0 = (x, y)
# b1 = (z, 0)
# b2 = (0, 0)
#
# v0 = a0 b0 = (f00, f01).(x, y)
# v1 = a1 b1 = (f10, f11).(z, 0)
# v2 = a2 b2 = (f20, f21).(0, 0)
#
# r0 = ξ ((a1 + a2) * (b1 + b2) - v1 - v2) + v0
# = ξ (a1 b1 + a2 b1 - v1) + v0
# = ξ a2 b1 + v0
# r1 = (a0 + a1) * (b0 + b1) - v0 - v1 + ξ v2
# = (a0 + a1) * (b0 + b1) - v0 - v1
# r2 = (a0 + a2) * (b0 + b2) - v0 - v2 + v1
# = a0 b0 + a2 b0 - v0 + v1
# = a2 b0 + v1
f *= v
var b0 {.noInit.}, v0{.noInit.}, v1{.noInit.}, t{.noInit.}: Fp4[C]
b0.c0 = l.x
b0.c1 = l.y
v0.prod(f.c0, b0)
v1.mul_sparse_by_y0(f.c1, l.z)
# r1 = (a0 + a1) * (b0 + b1) - v0 - v1
f.c1 += f.c0 # r1 = a0 + a1
t = b0
t.c0 += l.z # t = b0 + b1
f.c1 *= t # r2 = (a0 + a1)(b0 + b1)
f.c1 -= v0
f.c1 -= v1 # r2 = (a0 + a1)(b0 + b1) - v0 - v1
# r0 = ξ a2 b1 + v0
f.c0.mul_sparse_by_y0(f.c2, l.z)
f.c0 *= NonResidue
f.c0 += v0
# r2 = a2 b0 + v1
f.c2 *= b0
f.c2 += v1
func mul_sparse_by_line_xy000z*[C: static Curve, Tw: static SexticTwist](
f: var Fp12[C], l: Line[Fp2[C], Tw]) =

View File

@ -44,10 +44,6 @@ import
# Craig Costello, Tanja Lange, and Michael Naehrig, 2009
# https://eprint.iacr.org/2009/615.pdf
# TODO: implement quadruple-and-add and octuple-and-add
# from Costello2009 to trade multiplications in Fpᵏ
# for multiplications in Fp
# TODO: should be part of curve parameters
const BLS12_381_param = block:
# BLS Miller loop is parametrized by u
@ -242,8 +238,6 @@ func pairing_bls12*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: ECP_SWei_Pro
## Compute the optimal Ate Pairing for BLS12 curves
## Input: P ∈ G1, Q ∈ G2
## Output: e(P, Q) ∈ Gt
##
## Reference implementation
var Paff {.noInit.}: ECP_SWei_Aff[Fp[C]]
var Qaff {.noInit.}: ECP_SWei_Aff[Fp2[C]]
Paff.affineFromProjective(P)

View File

@ -29,21 +29,19 @@ import
#
# ############################################################
# - Efficient Final Exponentiation
# via Cyclotomic Structure for Pairings
# over Families of Elliptic Curves
# Daiki Hayashida and Kenichiro Hayasaka
# and Tadanori Teruya, 2020
# https://eprint.iacr.org/2020/875.pdf
# - Memory-saving computation of the pairing final exponentiation on BN curves
# Sylvain Duquesne and Loubna Ghammam, 2015
# https://eprint.iacr.org/2015/192
#
# - Faster hashing to G2
# Laura Fuentes-Castañeda, Edward Knapp,
# Francisco Jose Rodríguez-Henríquez, 2011
# https://link.springer.com/content/pdf/10.1007%2F978-3-642-28496-0_25.pdf
#
# - Faster Pairing Computations on Curves with High-Degree Twists
# Craig Costello, Tanja Lange, and Michael Naehrig, 2009
# https://eprint.iacr.org/2009/615.pdf
# TODO: implement quadruple-and-add and octuple-and-add
# from Costello2009 to trade multiplications in Fpᵏ
# for multiplications in Fp
# TODO: should be part of curve parameters
const BN254_Snarks_ate_param = block:
# BN Miller loop is parametrized by 6u+2
@ -51,16 +49,19 @@ const BN254_Snarks_ate_param = block:
const BN254_Snarks_ate_param_isNeg = false
const BN254_Snarks_finalexponent = block:
# (p^12 - 1) / r
BigInt[2790].fromHex"0x2f4b6dc97020fddadf107d20bc842d43bf6369b1ff6a1c71015f3f7be2e1e30a73bb94fec0daf15466b2383a5d3ec3d15ad524d8f70c54efee1bd8c3b21377e563a09a1b705887e72eceaddea3790364a61f676baaf977870e88d5c6c8fef0781361e443ae77f5b63a2a2264487f2940a8b1ddb3d15062cd0fb2015dfc6668449aed3cc48a82d0d602d268c7daab6a41294c0cc4ebe5664568dfc50e1648a45a4a1e3a5195846a3ed011a337a02088ec80e0ebae8755cfe107acf3aafb40494e406f804216bb10cf430b0f37856b42db8dc5514724ee93dfb10826f0dd4a0364b9580291d2cd65664814fde37ca80bb4ea44eacc5e641bbadf423f9a2cbf813b8d145da90029baee7ddadda71c7f3811c4105262945bba1668c3be69a3c230974d83561841d766f9c9d570bb7fbe04c7e8a6c3c760c0de81def35692da361102b6b9b2b918837fa97896e84abb40a4efb7e54523a486964b64ca86f120"
const BN254_Nogami_ate_param = block:
# BN Miller loop is parametrized by 6u+2
BigInt[67].fromHex"0x18300000000000004" # 65+2 bit for NAF x3 encoding
const BN254_Nogami_ate_param_isNeg = true
# Generic slow pairing implementation
# ----------------------------------------------------------------
const BN254_Snarks_finalexponent = block:
# (p^12 - 1) / r
BigInt[2790].fromHex"0x2f4b6dc97020fddadf107d20bc842d43bf6369b1ff6a1c71015f3f7be2e1e30a73bb94fec0daf15466b2383a5d3ec3d15ad524d8f70c54efee1bd8c3b21377e563a09a1b705887e72eceaddea3790364a61f676baaf977870e88d5c6c8fef0781361e443ae77f5b63a2a2264487f2940a8b1ddb3d15062cd0fb2015dfc6668449aed3cc48a82d0d602d268c7daab6a41294c0cc4ebe5664568dfc50e1648a45a4a1e3a5195846a3ed011a337a02088ec80e0ebae8755cfe107acf3aafb40494e406f804216bb10cf430b0f37856b42db8dc5514724ee93dfb10826f0dd4a0364b9580291d2cd65664814fde37ca80bb4ea44eacc5e641bbadf423f9a2cbf813b8d145da90029baee7ddadda71c7f3811c4105262945bba1668c3be69a3c230974d83561841d766f9c9d570bb7fbe04c7e8a6c3c760c0de81def35692da361102b6b9b2b918837fa97896e84abb40a4efb7e54523a486964b64ca86f120"
const BN254_Nogami_finalexponent = block:
# (p^12 - 1) / r
BigInt[2786].fromHex"0x2928fbb36b391596ee3fe4cbe857330da83e46fedf04d235a4a8daf5ff9f6eabcb4e3f20aa06f0a0d96b24f9af0cbbce750d61627dcbf5fec9139b8f1c46c86b49b4f8a202af26e4504f2c0f56570e9bd5b94c403f385d1908556486e24b396ddc2cdf13d06542f84fe8e82ccbad7b7423fc1ef4e8cc73d605e3e867c0a75f45ea7f6356d9846ce35d5a34f30396938818ad41914b97b99c289a7259b5d2e09477a77bd3c409b19f19e893f8ade90b0aed1b5fc8a07a3cebb41d4e9eee96b21a832ddb1e93e113edfb704fa532848c18593cd0ee90444a1b3499a800177ea38bdec62ec5191f2b6bbee449722f98d2173ad33077545c2ad10347e125a56fb40f086e9a4e62ad336a72c8b202ac3c1473d73b93d93dc0795ca0ca39226e7b4c1bb92f99248ec0806e0ad70744e9f2238736790f5185ea4c70808442a7d530c6ccd56b55a6973867ec6c73599bbd020bbe105da9c6b5c009ad8946cd6f0"
@ -70,7 +71,7 @@ const BN254_Nogami_finalexponent = block:
macro get(C: static Curve, value: untyped): untyped =
return bindSym($C & "_" & $value)
func millerLoopGenericBN[C: static Curve](
func millerLoopGenericBN*[C: static Curve](
f: var Fp12[C],
P: ECP_SWei_Aff[Fp[C]],
Q: ECP_SWei_Aff[Fp2[C]]
@ -167,13 +168,169 @@ func pairing_bn_reference*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: ECP_S
gt.millerLoopGenericBN(Paff, Qaff)
gt.finalExpGeneric()
func finalExpEasy[C: static Curve](f: var Fp12[C]) =
## Easy part of the final exponentiation
## We need to clear the GT cofactor to obtain
## an unique GT representation
## (reminder, GT is a multiplicative group hence we exponentiate by the cofactor)
# Optimized pairing implementation
# ----------------------------------------------------------------
func cycl_sqr_repeated(f: var Fp12, num: int) =
## Repeated cyclotomic squarings
for _ in 0 ..< num:
f.cyclotomic_square()
func pow_u(r: var Fp12[BN254_Nogami], a: Fp12[BN254_Nogami], invert = BN254_Nogami_ate_param_isNeg) =
## f^u with u the curve parameter
## For BN254_Nogami f^-0x4080000000000001
r = a
r.cycl_sqr_repeated(7)
r *= a
r.cycl_sqr_repeated(55)
r *= a
if invert:
r.cyclotomic_inv()
func pow_u(r: var Fp12[BN254_Snarks], a: Fp12[BN254_Snarks], invert = BN254_Snarks_ate_param_isNeg) =
## f^u with u the curve parameter
## For BN254_Snarks f^0x44e992b44a6909f1
when false:
cyclotomic_exp(
r, a,
BigInt[63].fromHex("0x44e992b44a6909f1"),
invert
)
else:
var # Hopefully the compiler optimizes away unused Fp12
# because those are huge
x10 {.noInit.}: Fp12[BN254_Snarks]
x11 {.noInit.}: Fp12[BN254_Snarks]
x100 {.noInit.}: Fp12[BN254_Snarks]
x110 {.noInit.}: Fp12[BN254_Snarks]
x1100 {.noInit.}: Fp12[BN254_Snarks]
x1111 {.noInit.}: Fp12[BN254_Snarks]
x10010 {.noInit.}: Fp12[BN254_Snarks]
x10110 {.noInit.}: Fp12[BN254_Snarks]
x11100 {.noInit.}: Fp12[BN254_Snarks]
x101110 {.noInit.}: Fp12[BN254_Snarks]
x1001010 {.noInit.}: Fp12[BN254_Snarks]
x1111000 {.noInit.}: Fp12[BN254_Snarks]
x10001110 {.noInit.}: Fp12[BN254_Snarks]
x10 .cyclotomic_square(a)
x11 .prod(x10, a)
x100 .prod(x11, a)
x110 .prod(x10, x100)
x1100 .cyclotomic_square(x110)
x1111 .prod(x11, x1100)
x10010 .prod(x11, x1111)
x10110 .prod(x100, x10010)
x11100 .prod(x110, x10110)
x101110 .prod(x10010, x11100)
x1001010 .prod(x11100, x101110)
x1111000 .prod(x101110, x1001010)
x10001110 .prod(x10110, x1111000)
var
i15 {.noInit.}: Fp12[BN254_Snarks]
i16 {.noInit.}: Fp12[BN254_Snarks]
i17 {.noInit.}: Fp12[BN254_Snarks]
i18 {.noInit.}: Fp12[BN254_Snarks]
i20 {.noInit.}: Fp12[BN254_Snarks]
i21 {.noInit.}: Fp12[BN254_Snarks]
i22 {.noInit.}: Fp12[BN254_Snarks]
i26 {.noInit.}: Fp12[BN254_Snarks]
i27 {.noInit.}: Fp12[BN254_Snarks]
i61 {.noInit.}: Fp12[BN254_Snarks]
i15.cyclotomic_square(x10001110)
i15 *= x1001010
i16.prod(x10001110, i15)
i17.prod(x1111, i16)
i18.prod(i16, i17)
i20.cyclotomic_square(i18)
i20 *= i17
i21.prod(x1111000, i20)
i22.prod(i15, i21)
i26.cyclotomic_square(i22)
i26.cyclotomic_square()
i26 *= i22
i26 *= i18
i27.prod(i22, i26)
i61.prod(i26, i27)
i61.cycl_sqr_repeated(17)
i61 *= i27
i61.cycl_sqr_repeated(14)
i61 *= i21
r = i61
r.cycl_sqr_repeated(16)
r *= i20
if invert:
r.cyclotomic_inv()
func finalExpHard_BN*[C: static Curve](f: var Fp12[C]) =
## Hard part of the final exponentiation
## Specialized for BN curves
##
## With an embedding degree of 12, the easy part of final exponentiation is
##
## f^(p⁶1)(p²+1)
discard
# - Memory-saving computation of the pairing final exponentiation on BN curves
# Sylvain Duquesne and Loubna Ghammam, 2015
# https://eprint.iacr.org/2015/192
# - Faster hashing to G2
# Laura Fuentes-Castañeda, Edward Knapp,
# Francisco Jose Rodríguez-Henríquez, 2011
# https://link.springer.com/content/pdf/10.1007%2F978-3-642-28496-0_25.pdf
#
# We use the Fuentes-Castañeda et al algorithm without
# memory saving optimization
# as that variant has an exponentiation by -2u-1
# that requires another addition chain
var t0 {.noInit.}, t1 {.noinit.}, t2 {.noinit.}, t3 {.noinit.}, t4 {.noinit.}: Fp12[C]
t0.pow_u(f, invert = false) # t0 = f^|u|
t0.cyclotomic_square() # t0 = f^2|u|
t1.cyclotomic_square(t0) # t1 = f^4|u|
t1 *= t0 # t1 = f^6|u|
t2.pow_u(t1, invert = false) # t2 = f^6u²
if C.get(ate_param_is_Neg):
t3.cyclotomic_inv(t1) # t3 = f^6u
else:
t3 = t1 # t3 = f^6u
t1.prod(t2, t3) # t1 = f^6u.f^6u²
t3.cyclotomic_square(t2) # t3 = f^12u²
t4.pow_u(t3) # t4 = f^12u³
t4 *= t1 # t4 = f^(6u + 6u² + 12u³) = f^λ₂
if not C.get(ate_param_is_Neg):
t0.cyclotomic_inv() # t0 = f^-2u
t3.prod(t4, t0) # t3 = f^(4u + 6u² + 12u³)
t0.prod(t2, t4) # t0 = f^6u.f^12u².f^12u³
t0 *= f # t0 = f^(1 + 6u + 12u² + 12u³) = f^λ₀
t2.frobenius_map(t3) # t2 = f^(4u + 6u² + 12u³)p = f^λ₁p
t0 *= t2 # t0 = f^(λ₀+λ₁p)
t2.frobenius_map(t4, 2) # t2 = f^λ₂p²
t0 *= t2 # t0 = f^(λ₀ + λ₁p + λ₂p²)
t2.cyclotomic_inv(f) # t2 = f⁻¹
t2 *= t3 # t3 = f^(-1 + 4u + 6u² + 12u³) = f^λ₃
f.frobenius_map(t2, 3) # r = f^λ₃p³
f *= t0 # r = f^(λ₀ + λ₁p + λ₂p² + λ₃p³) = f^((p⁴-p²+1)/r)
func pairing_bn*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: ECP_SWei_Proj[Fp2[C]]) =
## Compute the optimal Ate Pairing for BLS12 curves
## Input: P ∈ G1, Q ∈ G2
## Output: e(P, Q) ∈ Gt
var Paff {.noInit.}: ECP_SWei_Aff[Fp[C]]
var Qaff {.noInit.}: ECP_SWei_Aff[Fp2[C]]
Paff.affineFromProjective(P)
Qaff.affineFromProjective(Q)
gt.millerLoopGenericBN(Paff, Qaff)
gt.finalExpEasy()
gt.finalExpHard_BN()

View File

@ -50,7 +50,7 @@ def fp2_to_hex(a):
v = vector(a)
return '0x' + Integer(v[0]).hex() + ' + β * ' + '0x' + Integer(v[1]).hex()
# Frobenius map constants (D type: use SNR, M type use 1/SNR)
# Frobenius map constants
print('\nFrobenius extension field constants')
FrobConst_map = SNR^((p-1)/6)
FrobConst_map_list = []

View File

@ -49,9 +49,27 @@ print('')
# Utilities
def fp2_to_hex(a):
v = vector(a)
return Integer(v[0]).hex() + ' + β * ' + Integer(v[1]).hex()
return '0x' + Integer(v[0]).hex() + ' + β * ' + '0x' + Integer(v[1]).hex()
# Frobenius constants (D type: use SNR, M type use 1/SNR)
# Frobenius map constants
print('\nFrobenius extension field constants')
FrobConst_map = SNR^((p-1)/6)
FrobConst_map_list = []
cur = Fp2([1, 0])
for i in range(6):
FrobConst_map_list.append(cur)
print(f'FrobConst_map_{i} : {fp2_to_hex(cur)}')
cur *= FrobConst_map
print('')
for i in range(6):
print(f'FrobConst_map_{i}_pow2 : {fp2_to_hex(FrobConst_map_list[i]*conjugate(FrobConst_map_list[i]))}')
print('')
for i in range(6):
print(f'FrobConst_map_{i}_pow3 : {fp2_to_hex(FrobConst_map_list[i]**2 * conjugate(FrobConst_map_list[i]))}')
# Frobenius psi constants (D type: use SNR, M type use 1/SNR)
print('\nψ (Psi) - Untwist-Frobenius-Twist constants')
FrobConst_psi = SNR^((p-1)/6)
FrobConst_psi_2 = FrobConst_psi * FrobConst_psi
FrobConst_psi_3 = FrobConst_psi_2 * FrobConst_psi

View File

@ -49,9 +49,27 @@ print('')
# Utilities
def fp2_to_hex(a):
v = vector(a)
return Integer(v[0]).hex() + ' + β * ' + Integer(v[1]).hex()
return '0x' + Integer(v[0]).hex() + ' + β * ' + '0x' + Integer(v[1]).hex()
# Frobenius constants (D type: use SNR, M type use 1/SNR)
# Frobenius map constants
print('\nFrobenius extension field constants')
FrobConst_map = SNR^((p-1)/6)
FrobConst_map_list = []
cur = Fp2([1, 0])
for i in range(6):
FrobConst_map_list.append(cur)
print(f'FrobConst_map_{i} : {fp2_to_hex(cur)}')
cur *= FrobConst_map
print('')
for i in range(6):
print(f'FrobConst_map_{i}_pow2 : {fp2_to_hex(FrobConst_map_list[i]*conjugate(FrobConst_map_list[i]))}')
print('')
for i in range(6):
print(f'FrobConst_map_{i}_pow3 : {fp2_to_hex(FrobConst_map_list[i]**2 * conjugate(FrobConst_map_list[i]))}')
# Frobenius psi constants (D type: use SNR, M type use 1/SNR)
print('\nψ (Psi) - Untwist-Frobenius-Twist constants')
FrobConst_psi = SNR^((p-1)/6)
FrobConst_psi_2 = FrobConst_psi * FrobConst_psi
FrobConst_psi_3 = FrobConst_psi_2 * FrobConst_psi

View File

@ -14,8 +14,8 @@ import
./t_fp_tower_frobenius_template
const TestCurves = [
# BN254_Nogami
# BN254_Snarks,
BN254_Nogami,
BN254_Snarks,
# BLS12_377,
BLS12_381,
# BN446

View File

@ -14,7 +14,7 @@ import
./t_fp_tower_frobenius_template
const TestCurves = [
# BN254_Nogami
BN254_Nogami,
BN254_Snarks,
BLS12_377,
BLS12_381,

View File

@ -14,8 +14,8 @@ import
./t_fp_tower_frobenius_template
const TestCurves = [
# BN254_Nogami
# BN254_Snarks,
BN254_Nogami,
BN254_Snarks,
# BLS12_377,
BLS12_381,
# BN446

View File

@ -14,8 +14,8 @@ import
./t_fp_tower_frobenius_template
const TestCurves = [
# BN254_Nogami
# BN254_Snarks,
BN254_Nogami,
BN254_Snarks,
# BLS12_377,
BLS12_381,
# BN446

View File

@ -13,4 +13,5 @@ import
# Test utilities
./t_pairing_template
runPairingTests(4, BN254_Nogami, pairing_bn_reference)
# runPairingTests(4, BN254_Nogami, pairing_bn_reference)
runPairingTests(4, BN254_Nogami, pairing_bn)

View File

@ -13,4 +13,5 @@ import
# Test utilities
./t_pairing_template
runPairingTests(4, BN254_Snarks, pairing_bn_reference)
# runPairingTests(4, BN254_Snarks, pairing_bn_reference)
runPairingTests(4, BN254_Snarks, pairing_bn)

View File

@ -25,7 +25,8 @@ import
const
Iters = 8
TestCurves = [
# BN254_Snarks,
BN254_Nogami,
BN254_Snarks,
BLS12_381
]
@ -189,3 +190,30 @@ suite "Pairing - Sparse 𝔽p12 multiplication by line function is consistent wi
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":
proc test_fp12_xy000z(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], Dtwist](x: x, y: y, z: z)
let b = Fp12[C](
c0: Fp4[C](c0: x, c1: y),
c1: Fp4[C](c0: z ),
# c2:
)
a *= b
a2.mul_sparse_by_line_xyz000(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)