mirror of
https://github.com/status-im/constantine.git
synced 2025-02-24 01:48:10 +00:00
Add elliptic doubling in projective coordinates
This commit is contained in:
parent
f7818b566b
commit
44350d08af
@ -49,6 +49,8 @@ proc main() =
|
|||||||
const curve = AvailableCurves[i]
|
const curve = AvailableCurves[i]
|
||||||
addBench(ECP_SWei_Proj[Fp[curve]], Iters)
|
addBench(ECP_SWei_Proj[Fp[curve]], Iters)
|
||||||
separator()
|
separator()
|
||||||
|
doublingBench(ECP_SWei_Proj[Fp[curve]], Iters)
|
||||||
|
separator()
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -98,7 +98,13 @@ template bench(op: string, T: typedesc, iters: int, body: untyped): untyped =
|
|||||||
|
|
||||||
proc addBench*(T: typedesc, iters: int) =
|
proc addBench*(T: typedesc, iters: int) =
|
||||||
var r {.noInit.}: T
|
var r {.noInit.}: T
|
||||||
let x = rng.random_unsafe(T)
|
let P = rng.random_unsafe(T)
|
||||||
let y = rng.random_unsafe(T)
|
let Q = rng.random_unsafe(T)
|
||||||
bench("EC Add G1", T, iters):
|
bench("EC Add G1", T, iters):
|
||||||
r.sum(x, y)
|
r.sum(P, Q)
|
||||||
|
|
||||||
|
proc doublingBench*(T: typedesc, iters: int) =
|
||||||
|
var r {.noInit.}: T
|
||||||
|
let P = rng.random_unsafe(T)
|
||||||
|
bench("EC Double G1", T, iters):
|
||||||
|
r.double(P)
|
||||||
|
@ -105,6 +105,9 @@ func sum*[F](
|
|||||||
P, Q: ECP_SWei_Proj[F]
|
P, Q: ECP_SWei_Proj[F]
|
||||||
) =
|
) =
|
||||||
## Elliptic curve point addition for Short Weierstrass curves in projective coordinate
|
## Elliptic curve point addition for Short Weierstrass curves in projective coordinate
|
||||||
|
##
|
||||||
|
## R = P + Q
|
||||||
|
##
|
||||||
## Short Weierstrass curves have the following equation in projective coordinates
|
## Short Weierstrass curves have the following equation in projective coordinates
|
||||||
## Y²Z = X³ + aXZ² + bZ³
|
## Y²Z = X³ + aXZ² + bZ³
|
||||||
## from the affine equation
|
## from the affine equation
|
||||||
@ -121,8 +124,8 @@ func sum*[F](
|
|||||||
#
|
#
|
||||||
# Implementation:
|
# Implementation:
|
||||||
# Algorithms 1 (generic case), 4 (a == -3), 7 (a == 0) of
|
# Algorithms 1 (generic case), 4 (a == -3), 7 (a == 0) of
|
||||||
# Complete addition formulas for prime order elliptic curves\
|
# Complete addition formulas for prime order elliptic curves
|
||||||
# Joost Renes and Craig Costello and Lejla Batina, 2015\
|
# Joost Renes and Craig Costello and Lejla Batina, 2015
|
||||||
# https://eprint.iacr.org/2015/1060
|
# https://eprint.iacr.org/2015/1060
|
||||||
#
|
#
|
||||||
# with the indices 1 corresponding to ``P``, 2 to ``Q`` and 3 to the result ``r``
|
# with the indices 1 corresponding to ``P``, 2 to ``Q`` and 3 to the result ``r``
|
||||||
@ -132,14 +135,18 @@ func sum*[F](
|
|||||||
# Y3 = (3 X1 X2 + a Z1 Z2)(a X1 X2 + 3b (X1 Z2 + X2 Z1) - a² Z1 Z2)
|
# Y3 = (3 X1 X2 + a Z1 Z2)(a X1 X2 + 3b (X1 Z2 + X2 Z1) - a² Z1 Z2)
|
||||||
# + (Y1 Y2 + a (X1 Z2 + X2 Z1) + 3b Z1 Z2)(Y1 Y2 - a(X1 Z2 + X2 Z1) - 3b Z1 Z2)
|
# + (Y1 Y2 + a (X1 Z2 + X2 Z1) + 3b Z1 Z2)(Y1 Y2 - a(X1 Z2 + X2 Z1) - 3b Z1 Z2)
|
||||||
# Z3 = (Y1 Z2 + Y2 Z1)(Y1 Y2 + a(X1 Z2 + X2 Z1) + 3b Z1 Z2) + (X1 Y2 + X2 Y1)(3 X1 X2 + a Z1 Z2)
|
# Z3 = (Y1 Z2 + Y2 Z1)(Y1 Y2 + a(X1 Z2 + X2 Z1) + 3b Z1 Z2) + (X1 Y2 + X2 Y1)(3 X1 X2 + a Z1 Z2)
|
||||||
|
#
|
||||||
|
# Cost: 12M + 3 mul(a) + 2 mul(3b) + 23 a
|
||||||
|
|
||||||
# TODO: static doAssert odd order
|
# TODO: static doAssert odd order
|
||||||
|
|
||||||
|
when F.C.getCoefA() == 0:
|
||||||
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}, t3 {.noInit.}, t4 {.noInit.}: F
|
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}, t3 {.noInit.}, t4 {.noInit.}: F
|
||||||
const b3 = 3 * F.C.getCoefB()
|
const b3 = 3 * F.C.getCoefB()
|
||||||
|
|
||||||
when F.C.getCoefA() == 0:
|
|
||||||
# Algorithm 7 for curves: y² = x³ + b
|
# Algorithm 7 for curves: y² = x³ + b
|
||||||
# 12M + 2 mul(3b) + 19A
|
# 12M + 2 mul(3b) + 19A
|
||||||
|
#
|
||||||
# X3 = (X1 Y2 + X2 Y1)(Y1 Y2 − 3b Z1 Z2)
|
# X3 = (X1 Y2 + X2 Y1)(Y1 Y2 − 3b Z1 Z2)
|
||||||
# − 3b(Y1 Z2 + Y2 Z1)(X1 Z2 + X2 Z1)
|
# − 3b(Y1 Z2 + Y2 Z1)(X1 Z2 + X2 Z1)
|
||||||
# Y3 = (Y1 Y2 + 3b Z1 Z2)(Y1 Y2 − 3b Z1 Z2)
|
# Y3 = (Y1 Y2 + 3b Z1 Z2)(Y1 Y2 − 3b Z1 Z2)
|
||||||
@ -191,3 +198,70 @@ func sum*[F](
|
|||||||
r.z += t0 # 33. Z3 <- Z3 + t0 Z3 = (Y1 Z2 + Y2 Z1)(Y1 Y2 + 3b Z1 Z2) + 3 X1 X2 (X1.Y2 + X2.Y1)
|
r.z += t0 # 33. Z3 <- Z3 + t0 Z3 = (Y1 Z2 + Y2 Z1)(Y1 Y2 + 3b Z1 Z2) + 3 X1 X2 (X1.Y2 + X2.Y1)
|
||||||
else:
|
else:
|
||||||
{.error: "Not implemented.".}
|
{.error: "Not implemented.".}
|
||||||
|
|
||||||
|
func double*[F](
|
||||||
|
r: var ECP_SWei_Proj[F],
|
||||||
|
P: ECP_SWei_Proj[F]
|
||||||
|
) =
|
||||||
|
## Elliptic curve point doubling for Short Weierstrass curves in projective coordinate
|
||||||
|
##
|
||||||
|
## R = [2] P
|
||||||
|
##
|
||||||
|
## Short Weierstrass curves have the following equation in projective coordinates
|
||||||
|
## Y²Z = X³ + aXZ² + bZ³
|
||||||
|
## from the affine equation
|
||||||
|
## y² = x³ + a x + b
|
||||||
|
##
|
||||||
|
## ``r`` is initialized/overwritten with the sum
|
||||||
|
##
|
||||||
|
## Implementation is constant-time, in particular it will not expose
|
||||||
|
## that `P` is an infinity point.
|
||||||
|
## This is done by using a "complete" or "exception-free" addition law.
|
||||||
|
##
|
||||||
|
## This requires the order of the curve to be odd
|
||||||
|
#
|
||||||
|
# Implementation:
|
||||||
|
# Algorithms 3 (generic case), 6 (a == -3), 9 (a == 0) of
|
||||||
|
# Complete addition formulas for prime order elliptic curves
|
||||||
|
# Joost Renes and Craig Costello and Lejla Batina, 2015
|
||||||
|
# https://eprint.iacr.org/2015/1060
|
||||||
|
#
|
||||||
|
# X3 = 2XY (Y² - 2aXZ - 3bZ²)
|
||||||
|
# - 2YZ (aX² + 6bXZ - a²Z²)
|
||||||
|
# Y3 = (Y² + 2aXZ + 3bZ²)(Y² - 2aXZ - 3bZ²)
|
||||||
|
# + (3X² + aZ²)(aX² + 6bXZ - a²Z²)
|
||||||
|
# Z3 = 8Y³Z
|
||||||
|
#
|
||||||
|
# Cost: 8M + 3S + 3 mul(a) + 2 mul(3b) + 15a
|
||||||
|
|
||||||
|
when F.C.getCoefA() == 0:
|
||||||
|
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}: F
|
||||||
|
const b3 = 3 * F.C.getCoefB()
|
||||||
|
|
||||||
|
# Algorithm 9 for curves:
|
||||||
|
# 6M + 2S + 1 mul(3b) + 9a
|
||||||
|
#
|
||||||
|
# X3 = 2XY(Y² - 9bZ²)
|
||||||
|
# Y3 = (Y² - 9bZ²)(Y² + 3bZ²) + 24bY²Z²
|
||||||
|
# Z3 = 8Y³Z
|
||||||
|
|
||||||
|
t0.square(P.y) # 1. t0 <- Y Y
|
||||||
|
r.z.double(t0) # 2. Z3 <- t0 + t0
|
||||||
|
r.z.double() # 3. Z3 <- Z3 + Z3
|
||||||
|
r.z.double() # 4. Z3 <- Z3 + Z3 Z3 = 8Y²
|
||||||
|
t1.prod(P.y, P.z) # 5. t1 <- Y Z
|
||||||
|
t2.square(P.z) # 6. t2 <- Z Z
|
||||||
|
t2 *= b3 # 7. t2 <- b3 t2
|
||||||
|
r.x.prod(t2, r.z) # 8. X3 <- t2 Z3
|
||||||
|
r.y.sum(t0, t2) # 9. Y3 <- t0 + t2
|
||||||
|
r.z *= t1 # 10. Z3 <- t1 Z3
|
||||||
|
t1.double(t2) # 11. t1 <- t2 + t2
|
||||||
|
t2 += t1 # 12. t2 <- t1 + t2
|
||||||
|
t0 -= t2 # 13. t0 <- t0 - t2
|
||||||
|
r.y *= t0 # 14. Y3 <- t0 Y3
|
||||||
|
r.y += r.x # 15. Y3 <- X3 + Y3
|
||||||
|
t1.prod(P.x, P.y) # 16. t1 <- X Y
|
||||||
|
r.x.prod(t0, t1) # 17. X3 <- t0 t1
|
||||||
|
r.x.double() # 18. X3 <- X3 + X3
|
||||||
|
else:
|
||||||
|
{.error: "Not implemented.".}
|
||||||
|
@ -50,6 +50,9 @@ suite "Elliptic curve in Short Weierstrass form y² = x³ + a x + b with project
|
|||||||
r.sum(inf, P)
|
r.sum(inf, P)
|
||||||
check: bool(r == P)
|
check: bool(r == P)
|
||||||
|
|
||||||
|
|
||||||
|
test(Fp[BN254_Snarks], randZ = false)
|
||||||
|
test(Fp[BN254_Snarks], randZ = true)
|
||||||
test(Fp[BLS12_381], randZ = false)
|
test(Fp[BLS12_381], randZ = false)
|
||||||
test(Fp[BLS12_381], randZ = true)
|
test(Fp[BLS12_381], randZ = true)
|
||||||
|
|
||||||
@ -70,6 +73,8 @@ suite "Elliptic curve in Short Weierstrass form y² = x³ + a x + b with project
|
|||||||
r.sum(Q, P)
|
r.sum(Q, P)
|
||||||
check: bool r.isInf()
|
check: bool r.isInf()
|
||||||
|
|
||||||
|
test(Fp[BN254_Snarks], randZ = false)
|
||||||
|
test(Fp[BN254_Snarks], randZ = true)
|
||||||
test(Fp[BLS12_381], randZ = false)
|
test(Fp[BLS12_381], randZ = false)
|
||||||
test(Fp[BLS12_381], randZ = true)
|
test(Fp[BLS12_381], randZ = true)
|
||||||
|
|
||||||
@ -88,6 +93,8 @@ suite "Elliptic curve in Short Weierstrass form y² = x³ + a x + b with project
|
|||||||
r1.sum(Q, P)
|
r1.sum(Q, P)
|
||||||
check: bool(r0 == r1)
|
check: bool(r0 == r1)
|
||||||
|
|
||||||
|
test(Fp[BN254_Snarks], randZ = false)
|
||||||
|
test(Fp[BN254_Snarks], randZ = true)
|
||||||
test(Fp[BLS12_381], randZ = false)
|
test(Fp[BLS12_381], randZ = false)
|
||||||
test(Fp[BLS12_381], randZ = true)
|
test(Fp[BLS12_381], randZ = true)
|
||||||
|
|
||||||
@ -138,5 +145,27 @@ suite "Elliptic curve in Short Weierstrass form y² = x³ + a x + b with project
|
|||||||
bool(r0 == r3)
|
bool(r0 == r3)
|
||||||
bool(r0 == r4)
|
bool(r0 == r4)
|
||||||
|
|
||||||
|
test(Fp[BN254_Snarks], randZ = false)
|
||||||
|
test(Fp[BN254_Snarks], randZ = true)
|
||||||
|
test(Fp[BLS12_381], randZ = false)
|
||||||
|
test(Fp[BLS12_381], randZ = true)
|
||||||
|
|
||||||
|
test "EC double and EC add are consistent":
|
||||||
|
proc test(F: typedesc, randZ: static bool) =
|
||||||
|
for _ in 0 ..< Iters:
|
||||||
|
when randZ:
|
||||||
|
let a = rng.random_unsafe_with_randZ(ECP_SWei_Proj[F])
|
||||||
|
else:
|
||||||
|
let a = rng.random_unsafe(ECP_SWei_Proj[F])
|
||||||
|
|
||||||
|
var r0{.noInit.}, r1{.noInit.}: ECP_SWei_Proj[F]
|
||||||
|
|
||||||
|
r0.double(a)
|
||||||
|
r1.sum(a, a)
|
||||||
|
|
||||||
|
check: bool(r0 == r1)
|
||||||
|
|
||||||
|
test(Fp[BN254_Snarks], randZ = false)
|
||||||
|
test(Fp[BN254_Snarks], randZ = true)
|
||||||
test(Fp[BLS12_381], randZ = false)
|
test(Fp[BLS12_381], randZ = false)
|
||||||
test(Fp[BLS12_381], randZ = true)
|
test(Fp[BLS12_381], randZ = true)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user