Skip to content

Commit

Permalink
scalar-mul: prepare for bandersnatch endomorphisms and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mratsim committed Jun 7, 2024
1 parent e5f0bd8 commit 6cdc3dc
Show file tree
Hide file tree
Showing 14 changed files with 335 additions and 106 deletions.
11 changes: 11 additions & 0 deletions constantine.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,12 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
("tests/math_elliptic_curves/t_ec_twedwards_prj_mul_sanity", false),
("tests/math_elliptic_curves/t_ec_twedwards_prj_mul_distri", false),

# ("tests/math_elliptic_curves/t_ec_shortw_jac_g1_mul_endomorphism_bls12_381", false),
# ("tests/math_elliptic_curves/t_ec_shortw_prj_g1_mul_endomorphism_bls12_381", false),
# ("tests/math_elliptic_curves/t_ec_shortw_jac_g1_mul_endomorphism_bn254_snarks", false),
# ("tests/math_elliptic_curves/t_ec_shortw_prj_g1_mul_endomorphism_bn254_snarks", false),
# ("tests/math_elliptic_curves/t_ec_twedwards_mul_endomorphism_bandersnatch", false),


# Elliptic curve arithmetic G2
# ----------------------------------------------------------
Expand Down Expand Up @@ -476,6 +482,11 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
("tests/math_elliptic_curves/t_ec_shortw_jac_g2_mul_vs_ref_bw6_761.nim", false),
# ("tests/math_elliptic_curves/t_ec_shortw_jac_g2_mixed_add_bw6_761.nim", false),

# ("tests/math_elliptic_curves/t_ec_shortw_jac_g2_mul_endomorphism_bls12_381", false),
# ("tests/math_elliptic_curves/t_ec_shortw_prj_g2_mul_endomorphism_bls12_381", false),
# ("tests/math_elliptic_curves/t_ec_shortw_jac_g2_mul_endomorphism_bn254_snarks", false),
# ("tests/math_elliptic_curves/t_ec_shortw_prj_g2_mul_endomorphism_bn254_snarks", false),

# Elliptic curve arithmetic vs Sagemath
# ----------------------------------------------------------
("tests/math_elliptic_curves/t_ec_frobenius.nim", false),
Expand Down
13 changes: 10 additions & 3 deletions constantine/math/constants/zoo_endomorphisms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import
../isogenies/frobenius,
../elliptic/ec_shortweierstrass_affine,
../elliptic/ec_twistededwards_projective,
../io/io_fields,

./bandersnatch_endomorphisms,
./banderwagon_endomorphisms,
./bls12_377_endomorphisms,
./bls12_381_endomorphisms,
./bn254_nogami_endomorphisms,
Expand Down Expand Up @@ -52,8 +55,8 @@ func computeEndoBander[F](r {.noalias.}: var ECP_TwEdwards_Prj[F], P: ECP_TwEdwa
yy.square(P.y)
zz.square(P.z)

const b = ECP_TwEdwards_Prj[F].fromHex("0x52c9f28b828426a561f00d3a63511a882ea712770d9af4d6ee0f014d172510b4")
const c = ECP_TwEdwards_Prj[F].fromHex("0x6cc624cf865457c3a97c6efd6c17d1078456abcfff36f4e9515c806cdf650b3d")
const b = F.fromHex("0x52c9f28b828426a561f00d3a63511a882ea712770d9af4d6ee0f014d172510b4")
const c = F.fromHex("0x6cc624cf865457c3a97c6efd6c17d1078456abcfff36f4e9515c806cdf650b3d")

r.x.diff(zz, yy)
r.x *= c
Expand All @@ -78,7 +81,8 @@ func computeEndomorphism*[EC](endo: var EC, P: EC) =
elif P.G == G1:
endo.x.prod(P.x, C.getCubicRootOfUnity_mod_p())
endo.y = P.y
endo.z = P.z
when P isnot ECP_ShortW_Aff:
endo.z = P.z
else: # For BW6-761, both G1 and G2 are on Fp
endo.frobenius_psi(P, 2)

Expand All @@ -97,6 +101,9 @@ func computeEndomorphisms*[EC; M: static int](endos: var array[M-1, EC], P: EC)

func hasEndomorphismAcceleration*(C: static Curve): bool =
C in {
# TODO: MSM assumes that endomorphism can be computed with affine coordinates
# Bandersnatch,
# Banderwagon,
BN254_Nogami,
BN254_Snarks,
BLS12_377,
Expand Down
4 changes: 3 additions & 1 deletion constantine/math/elliptic/ec_endomorphism_accel.nim
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import
./ec_shortweierstrass_affine,
./ec_shortweierstrass_jacobian,
./ec_shortweierstrass_projective,
./ec_twistededwards_affine,
./ec_twistededwards_projective,
./ec_shortweierstrass_batch_ops
./ec_shortweierstrass_batch_ops,
./ec_twistededwards_batch_ops

# ############################################################
#
Expand Down
15 changes: 4 additions & 11 deletions constantine/math/elliptic/ec_multi_scalar_mul.nim
Original file line number Diff line number Diff line change
Expand Up @@ -372,17 +372,10 @@ proc applyEndomorphism[bits: static int, ECaff](
else:
endoBasis[i][0] = points[i]

when ECaff.F is Fp:
endoBasis[i][1].x.prod(points[i].x, ECaff.F.C.getCubicRootOfUnity_mod_p())
if negatePoints[1].bool:
endoBasis[i][1].y.neg(points[i].y)
else:
endoBasis[i][1].y = points[i].y
else:
staticFor m, 1, M:
endoBasis[i][m].frobenius_psi(points[i], m)
if negatePoints[m].bool:
endoBasis[i][m].neg()
cast[ptr array[M-1, ECaff]](endoBasis[i][1].addr)[].computeEndomorphisms(points[i])
for m in 1 ..< M:
if negatePoints[m].bool:
endoBasis[i][m].neg()

let endoCoefs = cast[ptr UncheckedArray[BigInt[L]]](splitCoefs)
let endoPoints = cast[ptr UncheckedArray[ECaff]](endoBasis)
Expand Down
15 changes: 4 additions & 11 deletions constantine/math/elliptic/ec_multi_scalar_mul_parallel.nim
Original file line number Diff line number Diff line change
Expand Up @@ -477,17 +477,10 @@ proc applyEndomorphism_parallel[bits: static int, ECaff](
else:
endoBasis[i][0] = points[i]

when ECaff.F is Fp:
endoBasis[i][1].x.prod(points[i].x, ECaff.F.C.getCubicRootOfUnity_mod_p())
if negatePoints[1].bool:
endoBasis[i][1].y.neg(points[i].y)
else:
endoBasis[i][1].y = points[i].y
else:
staticFor m, 1, M:
endoBasis[i][m].frobenius_psi(points[i], m)
if negatePoints[m].bool:
endoBasis[i][m].neg()
cast[ptr array[M-1, ECaff]](endoBasis[i][1].addr)[].computeEndomorphisms(points[i])
for m in 1 ..< M:
if negatePoints[m].bool:
endoBasis[i][m].neg()

let endoCoefs = cast[ptr UncheckedArray[BigInt[L]]](splitCoefs)
let endoPoints = cast[ptr UncheckedArray[ECaff]](endoBasis)
Expand Down
30 changes: 9 additions & 21 deletions constantine/math/elliptic/ec_scalar_mul_vartime.nim
Original file line number Diff line number Diff line change
Expand Up @@ -252,25 +252,13 @@ func scalarMulEndo_minHammingWeight_windowed_vartime*[scalBits: static int; EC](
const precompSize = 1 shl (window - 2)
static: doAssert window < 8, "Window is too large and precomputation would use " & $(precompSize * sizeof(EC)) & " stack space."

when P.F is Fp:
const M = 2
# 1. Compute endomorphisms
var endomorphisms {.noInit.}: array[M-1, EC]
when P.G == G1:
endomorphisms[0] = P
endomorphisms[0].x *= EC.F.C.getCubicRootOfUnity_mod_p()
else:
endomorphisms[0].frobenius_psi(P, 2)
# 1. Compute endomorphisms
const M = when P.F is Fp: 2
elif P.F is Fp2: 4
else: {.error: "Unconfigured".}

elif P.F is Fp2:
const M = 4
# 1. Compute endomorphisms
var endomorphisms {.noInit.}: array[M-1, EC]
endomorphisms[0].frobenius_psi(P)
endomorphisms[1].frobenius_psi(P, 2)
endomorphisms[2].frobenius_psi(P, 3)
else:
{.error: "Unconfigured".}
var endos {.noInit.}: array[M-1, EC]
endos.computeEndomorphisms(P)

# 2. Decompose scalar into mini-scalars
const L = scalBits.ceilDiv_vartime(M) + 1
Expand All @@ -283,7 +271,7 @@ func scalarMulEndo_minHammingWeight_windowed_vartime*[scalBits: static int; EC](
P.neg()
for m in 1 ..< M:
if negatePoints[m].bool:
endomorphisms[m-1].neg()
endos[m-1].neg()

# 4. EC precomputed table
var tabEC {.noinit.}: array[M, array[precompSize, EC]]
Expand All @@ -293,8 +281,8 @@ func scalarMulEndo_minHammingWeight_windowed_vartime*[scalBits: static int; EC](
tabEC[0][0] = P
P2.double(P)
else:
tabEC[m][0] = endomorphisms[m-1]
P2.double(endomorphisms[m-1])
tabEC[m][0] = endos[m-1]
P2.double(endos[m-1])
for i in 1 ..< tabEC[m].len:
tabEC[m][i].sum_vartime(tabEC[m][i-1], P2)

Expand Down
23 changes: 15 additions & 8 deletions constantine/math/elliptic/ec_twistededwards_affine.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ func setInf*(P: var ECP_TwEdwards_Aff) {.inline.} =
P.x.setZero()
P.y.setOne()

func ccopy*(P: var ECP_TwEdwards_Aff, Q: ECP_TwEdwards_Aff, ctl: SecretBool) {.inline.} =
## Constant-time conditional copy
## If ctl is true: Q is copied into P
## if ctl is false: Q is not copied and P is unmodified
## Time and memory accesses are the same whether a copy occurs or not
for fP, fQ in fields(P, Q):
ccopy(fP, fQ, ctl)

func isOnCurve*[F](x, y: F): SecretBool =
## Returns true if the (x, y) coordinates
Expand All @@ -52,7 +59,7 @@ func isOnCurve*[F](x, y: F): SecretBool =
var t0{.noInit.}, t1{.noInit.}, t2{.noInit.}: F
t0.square(x)
t1.square(y)

# ax²+y²
when F.C.getCoefA() is int:
when F.C.getCoefA() == -1:
Expand Down Expand Up @@ -84,10 +91,10 @@ func isOnCurve*[F](x, y: F): SecretBool =
func trySetFromCoordX*[F](P: var ECP_TwEdwards_Aff[F], x: F): SecretBool =
## Try to create a point on the elliptic curve from X co-ordinate
## ax²+y²=1+dx²y² (affine coordinate)
##
##
## return true and update `P` if `y` leads to a valid point
## return false otherwise, in that case `P` is undefined.

# y² = (1 - ax²)/(1 - dx²)
var t {.noInit.}: F
var one {.noInit.}: F
Expand Down Expand Up @@ -129,10 +136,10 @@ func trySetFromCoordX_vartime*[F](P: var ECP_TwEdwards_Aff[F], x: F): SecretBool
## This is not in constant time
## Try to create a point on the elliptic curve from X co-ordinate
## ax²+y²=1+dx²y² (affine coordinate)
##
##
## return true and update `P` if `y` leads to a valid point
## return false otherwise, in that case `P` is undefined.

# y² = (1 - ax²)/(1 - dx²)
var t {.noInit.}: F
var one {.noInit.}: F
Expand Down Expand Up @@ -180,7 +187,7 @@ func trySetFromCoordY*[F](P: var ECP_TwEdwards_Aff[F], y: F): SecretBool =
##
## Note: Dedicated robust procedures for hashing-to-curve
## will be provided, this is intended for testing purposes.
##
##
## For **test case generation only**,
## this is preferred to generating random point
## via random scalar multiplication of the curve generator
Expand Down Expand Up @@ -252,9 +259,9 @@ func `==`*(P, Q: ECP_TwEdwards_Aff[Fp[Banderwagon]]): SecretBool =
## Equality check for points in the Banderwagon Group
## The equality check is optimized for the quotient group
## see: https://hackmd.io/@6iQDuIePQjyYBqDChYw_jg/BJBNcv9fq#Equality-check
##
##
## Check for the (0,0) point, which is possible
##
##
## This is a costly operation

var lhs{.noInit.}, rhs{.noInit.}: typeof(P).F
Expand Down
Loading

0 comments on commit 6cdc3dc

Please sign in to comment.