Cleanup: consolidate extensions and instantiation + reorg extension module
This commit is contained in:
parent
8918cabb56
commit
8a7c35af59
|
@ -14,9 +14,9 @@ import
|
||||||
./io_bigints, ./io_fields,
|
./io_bigints, ./io_fields,
|
||||||
../primitives,
|
../primitives,
|
||||||
../arithmetic/finite_fields,
|
../arithmetic/finite_fields,
|
||||||
../tower_field_extensions/tower_instantiation
|
../tower_field_extensions/extension_fields
|
||||||
|
|
||||||
export tower_instantiation
|
export extension_fields
|
||||||
|
|
||||||
# No exceptions allowed
|
# No exceptions allowed
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
./tower_instantiation,
|
./extension_fields,
|
||||||
../arithmetic,
|
../arithmetic,
|
||||||
../primitives,
|
../primitives,
|
||||||
../config/[common, curves],
|
../config/[common, curves],
|
||||||
|
@ -43,9 +43,9 @@ func isSquare*(a: Fp2): SecretBool =
|
||||||
result = tv1.isSquare()
|
result = tv1.isSquare()
|
||||||
|
|
||||||
func sqrt_rotate_extension(
|
func sqrt_rotate_extension(
|
||||||
out_sqrt: var QuadraticExt,
|
out_sqrt: var Fp2,
|
||||||
candidate_sqrt: QuadraticExt,
|
candidate_sqrt: Fp2,
|
||||||
a: QuadraticExt
|
a: Fp2
|
||||||
): SecretBool =
|
): SecretBool =
|
||||||
## From a field element `a` and a candidate Fp2 square root
|
## From a field element `a` and a candidate Fp2 square root
|
||||||
## Search the actual square root by rotating candidate solution
|
## Search the actual square root by rotating candidate solution
|
||||||
|
@ -57,7 +57,7 @@ func sqrt_rotate_extension(
|
||||||
## This avoids expensive trial "isSquare" checks (450+ field multiplications)
|
## This avoids expensive trial "isSquare" checks (450+ field multiplications)
|
||||||
## This requires the sqrt of sqrt of the quadratic non-residue
|
## This requires the sqrt of sqrt of the quadratic non-residue
|
||||||
## to be in Fp2
|
## to be in Fp2
|
||||||
var coeff{.noInit.}, cand2{.noInit.}, t{.noInit.}: QuadraticExt
|
var coeff{.noInit.}, cand2{.noInit.}, t{.noInit.}: Fp2
|
||||||
const Curve = typeof(a.c0).C
|
const Curve = typeof(a.c0).C
|
||||||
|
|
||||||
# We name µ² the quadratic non-residue
|
# We name µ² the quadratic non-residue
|
||||||
|
|
|
@ -1,297 +0,0 @@
|
||||||
# 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.
|
|
||||||
|
|
||||||
# Instantiate the actual tower extensions
|
|
||||||
# that were described in a "conceptualized" way
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
import
|
|
||||||
../arithmetic,
|
|
||||||
../config/[common, curves],
|
|
||||||
../io/io_fields,
|
|
||||||
./extension_fields,
|
|
||||||
./exponentiations
|
|
||||||
|
|
||||||
export extension_fields, exponentiations
|
|
||||||
|
|
||||||
# We assume that the sextic non-residues used to construct
|
|
||||||
# the elliptic curve twists
|
|
||||||
# match with the quadratic and cubic non-residues
|
|
||||||
# chosen to construct the tower of extension fields.
|
|
||||||
|
|
||||||
# 𝔽p
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
func `*=`*(a: var Fp, _: type NonResidue) {.inline.} =
|
|
||||||
## Multiply an element of 𝔽p by the quadratic non-residue
|
|
||||||
## chosen to construct 𝔽p2
|
|
||||||
static: doAssert Fp.C.getNonResidueFp() != -1, "𝔽p2 should be specialized for complex extension"
|
|
||||||
a *= Fp.C.getNonResidueFp()
|
|
||||||
|
|
||||||
func prod*(r: var Fp, a: Fp, _: type NonResidue){.inline.} =
|
|
||||||
## Multiply an element of 𝔽p by the quadratic non-residue
|
|
||||||
## chosen to construct 𝔽p2
|
|
||||||
static: doAssert Fp.C.getNonResidueFp() != -1, "𝔽p2 should be specialized for complex extension"
|
|
||||||
r.prod(a, Fp.C.getNonResidueFp())
|
|
||||||
|
|
||||||
# 𝔽p2
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
type
|
|
||||||
Fp2*[C: static Curve] =
|
|
||||||
QuadraticExt[Fp[C]]
|
|
||||||
|
|
||||||
template fromComplexExtension*[F](elem: F): static bool =
|
|
||||||
## Returns true if the input is a complex extension
|
|
||||||
## i.e. the irreducible polynomial chosen is
|
|
||||||
## x² - µ with µ = -1
|
|
||||||
## and so 𝔽p2 = 𝔽p[x] / x² - µ = 𝔽p[𝑖]
|
|
||||||
when F is Fp2 and F.C.getNonResidueFp() == -1:
|
|
||||||
true
|
|
||||||
else:
|
|
||||||
false
|
|
||||||
|
|
||||||
template mulCheckSparse*(a: var Fp2, b: Fp2) =
|
|
||||||
when b.isOne().bool:
|
|
||||||
discard
|
|
||||||
elif b.isMinusOne().bool:
|
|
||||||
a.neg()
|
|
||||||
elif b.c0.isZero().bool and b.c1.isOne().bool:
|
|
||||||
var t {.noInit.}: type(a.c0)
|
|
||||||
when fromComplexExtension(b):
|
|
||||||
t.neg(a.c1)
|
|
||||||
a.c1 = a.c0
|
|
||||||
a.c0 = t
|
|
||||||
else:
|
|
||||||
t.prod(a.c1, NonResidue)
|
|
||||||
a.c1 = a.c0
|
|
||||||
a.c0 = t
|
|
||||||
elif b.c0.isZero().bool and b.c1.isMinusOne().bool:
|
|
||||||
var t {.noInit.}: type(a.c0)
|
|
||||||
when fromComplexExtension(b):
|
|
||||||
t = a.c1
|
|
||||||
a.c1.neg(a.c0)
|
|
||||||
a.c0 = t
|
|
||||||
else:
|
|
||||||
t.prod(a.c1, NonResidue)
|
|
||||||
a.c1.neg(a.c0)
|
|
||||||
a.c0.neg(t)
|
|
||||||
elif b.c0.isZero().bool:
|
|
||||||
a.mul_sparse_by_0y(b)
|
|
||||||
elif b.c1.isZero().bool:
|
|
||||||
a.mul_sparse_by_x0(b)
|
|
||||||
else:
|
|
||||||
a *= b
|
|
||||||
|
|
||||||
func prod*(r: var Fp2, a: Fp2, _: type NonResidue) {.inline.} =
|
|
||||||
## Multiply an element of 𝔽p2 by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p4
|
|
||||||
## - if cubic non-residue: 𝔽p6
|
|
||||||
## - if sextic non-residue: 𝔽p4, 𝔽p6 or 𝔽p12
|
|
||||||
# Yet another const tuple unpacking bug
|
|
||||||
const u = Fp2.C.getNonResidueFp2()[0]
|
|
||||||
const v = Fp2.C.getNonResidueFp2()[1]
|
|
||||||
const Beta {.used.} = Fp2.C.getNonResidueFp()
|
|
||||||
# ξ = u + v x
|
|
||||||
# and x² = β
|
|
||||||
#
|
|
||||||
# (c0 + c1 x) (u + v x) => u c0 + (u c0 + u c1)x + v c1 x²
|
|
||||||
# => u c0 + β v c1 + (v c0 + u c1) x
|
|
||||||
when a.fromComplexExtension() and u == 1 and v == 1:
|
|
||||||
let t = a.c0
|
|
||||||
r.c0.diff(t, a.c1)
|
|
||||||
r.c1.sum(t, a.c1)
|
|
||||||
else:
|
|
||||||
# Case:
|
|
||||||
# - BN254_Snarks, QNR_Fp: -1, SNR_Fp2: 9+1𝑖 (𝑖 = √-1)
|
|
||||||
# - BLS12_377, QNR_Fp: -5, SNR_Fp2: 0+1j (j = √-5)
|
|
||||||
# - BW6_761, SNR_Fp: -4, CNR_Fp2: 0+1j (j = √-4)
|
|
||||||
when u == 0:
|
|
||||||
# BLS12_377 and BW6_761, use small addition chain
|
|
||||||
r.mul_sparse_by_0y(a, v)
|
|
||||||
else:
|
|
||||||
# BN254_Snarks, u = 9, v = 1, β = -1
|
|
||||||
# Even with u = 9, the 2x9 addition chains (8 additions total)
|
|
||||||
# are cheaper than full Fp2 multiplication
|
|
||||||
var t {.noInit.}: typeof(a.c0)
|
|
||||||
|
|
||||||
t.prod(a.c0, u)
|
|
||||||
when v == 1 and Beta == -1: # Case BN254_Snarks
|
|
||||||
t -= a.c1 # r0 = u c0 + β v c1
|
|
||||||
else:
|
|
||||||
{.error: "Unimplemented".}
|
|
||||||
|
|
||||||
r.c1.prod(a.c1, u)
|
|
||||||
when v == 1: # r1 = v c0 + u c1
|
|
||||||
r.c1 += a.c0
|
|
||||||
# aliasing: a.c0 is unused
|
|
||||||
r.c0 = t
|
|
||||||
else:
|
|
||||||
{.error: "Unimplemented".}
|
|
||||||
|
|
||||||
func `*=`*(a: var Fp2, _: type NonResidue) {.inline.} =
|
|
||||||
## Multiply an element of 𝔽p2 by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p4
|
|
||||||
## - if cubic non-residue: 𝔽p6
|
|
||||||
## - if sextic non-residue: 𝔽p4, 𝔽p6 or 𝔽p12
|
|
||||||
# Yet another const tuple unpacking bug
|
|
||||||
a.prod(a, NonResidue)
|
|
||||||
|
|
||||||
func `/=`*(a: var Fp2, _: type NonResidue) {.inline.} =
|
|
||||||
## Divide an element of 𝔽p by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p4
|
|
||||||
## - if cubic non-residue: 𝔽p6
|
|
||||||
## - if sextic non-residue: 𝔽p4, 𝔽p6 or 𝔽p12
|
|
||||||
# Yet another const tuple unpacking bug
|
|
||||||
# Yet another const tuple unpacking bug
|
|
||||||
const u = Fp2.C.getNonresidueFp2()[0] # Sextic non-residue to construct 𝔽p12
|
|
||||||
const v = Fp2.C.getNonresidueFp2()[1]
|
|
||||||
const Beta = Fp2.C.getNonResidueFp() # Quadratic non-residue to construct 𝔽p2
|
|
||||||
# ξ = u + v x
|
|
||||||
# and x² = β
|
|
||||||
#
|
|
||||||
# (c0 + c1 x) / (u + v x) => (c0 + c1 x)(u - v x) / ((u + vx)(u-vx))
|
|
||||||
# => u c0 - v c1 x² + (u c1 - v c0) x / (u² - x²v²)
|
|
||||||
# => 1/(u² - βv²) * (uc0 - β v c1, u c1 - v c0)
|
|
||||||
# With β = 𝑖 = √-1
|
|
||||||
# 1/(u² + v²) * (u c0 + v c1, u c1 - v c0)
|
|
||||||
#
|
|
||||||
# With β = 𝑖 = √-1 and ξ = 1 + 𝑖
|
|
||||||
# 1/2 * (c0 + c1, c1 - c0)
|
|
||||||
|
|
||||||
when a.fromComplexExtension() and u == 1 and v == 1:
|
|
||||||
let t = a.c0
|
|
||||||
a.c0 += a.c1
|
|
||||||
a.c1 -= t
|
|
||||||
a.div2()
|
|
||||||
else:
|
|
||||||
var a0 = a.c0
|
|
||||||
let a1 = a.c1
|
|
||||||
const u2v2 = u*u - Beta*v*v # (u² - βv²)
|
|
||||||
# TODO can be precomputed (or precompute b/µ the twist coefficient)
|
|
||||||
# and use faster non-constant-time inversion in the VM
|
|
||||||
var u2v2inv {.noInit.}: a.c0.typeof
|
|
||||||
u2v2inv.fromUint(u2v2)
|
|
||||||
u2v2inv.inv()
|
|
||||||
|
|
||||||
a.c0 *= u
|
|
||||||
a.c1 *= Beta * v
|
|
||||||
a.c0 -= a.c1
|
|
||||||
|
|
||||||
a.c1 = a1
|
|
||||||
a.c1 *= u
|
|
||||||
a0 *= v
|
|
||||||
a.c1 -= a0
|
|
||||||
a.c0 *= u2v2inv
|
|
||||||
a.c1 *= u2v2inv
|
|
||||||
|
|
||||||
# 𝔽p4 & 𝔽p6
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
type
|
|
||||||
Fp4*[C: static Curve] =
|
|
||||||
QuadraticExt[Fp2[C]]
|
|
||||||
|
|
||||||
Fp6*[C: static Curve] =
|
|
||||||
CubicExt[Fp2[C]]
|
|
||||||
|
|
||||||
func prod*(r: var Fp4, a: Fp4, _: type NonResidue) =
|
|
||||||
## Multiply an element of 𝔽p4 by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p8
|
|
||||||
## - if cubic non-residue: 𝔽p12
|
|
||||||
## - if sextic non-residue: 𝔽p8, 𝔽p12 or 𝔽p24
|
|
||||||
##
|
|
||||||
## Assumes that it is sqrt(NonResidue_Fp2)
|
|
||||||
let t = a.c0
|
|
||||||
r.c0.prod(a.c1, NonResidue)
|
|
||||||
r.c1 = t
|
|
||||||
|
|
||||||
func `*=`*(a: var Fp4, _: type NonResidue) {.inline.} =
|
|
||||||
## Multiply an element of 𝔽p4 by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p8
|
|
||||||
## - if cubic non-residue: 𝔽p12
|
|
||||||
## - if sextic non-residue: 𝔽p8, 𝔽p12 or 𝔽p24
|
|
||||||
##
|
|
||||||
## Assumes that it is sqrt(NonResidue_Fp2)
|
|
||||||
a.prod(a, NonResidue)
|
|
||||||
|
|
||||||
func prod*(r: var Fp6, a: Fp6, _: type NonResidue) {.inline.} =
|
|
||||||
## Multiply an element of 𝔽p6 by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p12
|
|
||||||
## - if cubic non-residue: 𝔽p18
|
|
||||||
## - if sextic non-residue: 𝔽p12, 𝔽p18 or 𝔽p36
|
|
||||||
##
|
|
||||||
## Assumes that it is cube_root(NonResidue_Fp2)
|
|
||||||
##
|
|
||||||
## For all curves γ = v with v the factor for 𝔽p6 coordinate
|
|
||||||
## and v³ = ξ
|
|
||||||
## (c0 + c1 v + c2 v²) v => ξ c2 + c0 v + c1 v²
|
|
||||||
let t = a.c2
|
|
||||||
r.c1 = a.c0
|
|
||||||
r.c2 = a.c1
|
|
||||||
r.c0.prod(t, NonResidue)
|
|
||||||
|
|
||||||
func `*=`*(a: var Fp6, _: type NonResidue) {.inline.} =
|
|
||||||
## Multiply an element of 𝔽p6 by the non-residue
|
|
||||||
## chosen to construct the next extension or the twist:
|
|
||||||
## - if quadratic non-residue: 𝔽p12
|
|
||||||
## - if cubic non-residue: 𝔽p18
|
|
||||||
## - if sextic non-residue: 𝔽p12, 𝔽p18 or 𝔽p36
|
|
||||||
##
|
|
||||||
## Assumes that it is cube_root(NonResidue_Fp2)
|
|
||||||
##
|
|
||||||
## For all curves γ = v with v the factor for 𝔽p6 coordinate
|
|
||||||
## and v³ = ξ
|
|
||||||
## (c0 + c1 v + c2 v²) v => ξ c2 + c0 v + c1 v²
|
|
||||||
a.prod(a, NonResidue)
|
|
||||||
|
|
||||||
# 𝔽p12
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
type
|
|
||||||
Fp12*[C: static Curve] =
|
|
||||||
CubicExt[Fp4[C]]
|
|
||||||
# QuadraticExt[Fp6[C]]
|
|
||||||
|
|
||||||
# Sparse functions
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
func `*=`*(a: var Fp2, b: Fp) =
|
|
||||||
## Multiply an element of Fp2 by an element of Fp
|
|
||||||
a.c0 *= b
|
|
||||||
a.c1 *= b
|
|
||||||
|
|
||||||
func mul_sparse_by_0y0*[C: static Curve](r: var Fp6[C], a: Fp6[C], b: Fp2[C]) =
|
|
||||||
## Sparse multiplication of an Fp6 element
|
|
||||||
## with coordinates (a₀, a₁, a₂) by (0, b₁, 0)
|
|
||||||
# TODO: make generic and move to tower_field_extensions
|
|
||||||
|
|
||||||
# v0 = a0 b0 = 0
|
|
||||||
# v1 = a1 b1
|
|
||||||
# v2 = a2 b2 = 0
|
|
||||||
#
|
|
||||||
# r0 = ξ ((a1 + a2) * (b1 + b2) - v1 - v2) + v0
|
|
||||||
# = ξ (a1 b1 + a2 b1 - v1)
|
|
||||||
# = ξ a2 b1
|
|
||||||
# r1 = (a0 + a1) * (b0 + b1) - v0 - v1 + ξ v2
|
|
||||||
# = a0 b1 + a1 b1 - v1
|
|
||||||
# = a0 b1
|
|
||||||
# r2 = (a0 + a2) * (b0 + b2) - v0 - v2 + v1
|
|
||||||
# = v1
|
|
||||||
# = a1 b1
|
|
||||||
|
|
||||||
r.c0.prod(a.c2, b)
|
|
||||||
r.c0 *= NonResidue
|
|
||||||
r.c1.prod(a.c0, b)
|
|
||||||
r.c2.prod(a.c1, b)
|
|
|
@ -8,8 +8,9 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
tower_field_extensions/[
|
tower_field_extensions/[
|
||||||
tower_instantiation,
|
square_root_fp2,
|
||||||
square_root_fp2
|
exponentiations,
|
||||||
|
extension_fields
|
||||||
]
|
]
|
||||||
|
|
||||||
export tower_instantiation, square_root_fp2
|
export extension_fields, square_root_fp2, exponentiations
|
||||||
|
|
Loading…
Reference in New Issue