Fix squaring in 𝔽p6 (𝔽p2 squaring require separate target and source buffer)

This commit is contained in:
Mamy André-Ratsimbazafy 2020-04-09 13:20:05 +02:00
parent f24d87fb00
commit d081fca612
No known key found for this signature in database
GPG Key ID: 7B88AD1FE79492E1
5 changed files with 76 additions and 43 deletions

View File

@ -71,7 +71,7 @@ template `*`(a: Fp6, _: typedesc[Gamma]): Fp6 =
func `*=`(a: var Fp6, _: typedesc[Gamma]) {.inline.} = func `*=`(a: var Fp6, _: typedesc[Gamma]) {.inline.} =
a = Gamma * a a = Gamma * a
func square*[C](r: var Fp12[C], a: Fp12[C]) = func square*(r: var Fp12, a: Fp12) =
## Return a² in ``r`` ## Return a² in ``r``
## ``r`` is initialized/overwritten ## ``r`` is initialized/overwritten
# (c0, c1)² => (c0 + c1 w)² # (c0, c1)² => (c0 + c1 w)²
@ -106,3 +106,22 @@ func square*[C](r: var Fp12[C], a: Fp12[C]) =
# r1 = 2 c0c1 # r1 = 2 c0c1
r.c1.double() r.c1.double()
func prod*[C](r: var Fp12[C], a, b: Fp12[C]) =
## Returns r = a * b
var t {.noInit.}: Fp6[C]
# r1 <- (a0 + a1)(b0 + b1)
r.c0.sum(a.c0, a.c1)
t.sum(b.c0, b.c1)
r.c1.prod(r.c0, t)
# r0 <- a0 b0 + γ a1 b1
# r1 <- (a0 + a1)(b0 + b1) - a0 b0 - a1 b1
r.c0.prod(a.c0, b.c0)
t.prod(a.c1, b.c1)
r.c1 -= r.c0
r.c1 -= t
# r0 <- a0 b0 + γ a1 b1
r.c0 -= Gamma * t

View File

@ -158,8 +158,12 @@ func inv*(r: var Fp2, a: Fp2) =
t1.neg(t0) # t0 = -1 / (a0² + a1²) t1.neg(t0) # t0 = -1 / (a0² + a1²)
r.c1.prod(a.c1, t1) # r1 = -a1 / (a0² + a1²) r.c1.prod(a.c1, t1) # r1 = -a1 / (a0² + a1²)
func square*(a: var Fp2) {.inline.} =
let t = a
a.square(t)
func `*=`*(a: var Fp2, b: Fp2) {.inline.} = func `*=`*(a: var Fp2, b: Fp2) {.inline.} =
a.prod(a, b) a.prod(a, b)
func `*`*(a, b: Fp2): Fp2 {.inline.} = func `*`*(a, b: Fp2): Fp2 {.inline, noInit.} =
result.prod(a, b) result.prod(a, b)

View File

@ -81,7 +81,7 @@ func square*[C](r: var Fp6[C], a: Fp6[C]) =
v4 += a.c2 v4 += a.c2
v5.prod(a.c1, a.c2) v5.prod(a.c1, a.c2)
v5.double() v5.double()
v4.square(v4) v4.square()
r.c0 = Xi * v5 r.c0 = Xi * v5
r.c0 += v3 r.c0 += v3
r.c2.sum(v2, v4) r.c2.sum(v2, v4)
@ -178,9 +178,9 @@ func inv*[C](r: var Fp6[C], a: Fp6[C]) =
r.c2.prod(v2, v3) r.c2.prod(v2, v3)
func `*=`*(a: var Fp6, b: Fp6) {.inline.} = func `*=`*(a: var Fp6, b: Fp6) {.inline.} =
var t: Fp6 # Need to ensure different buffers for ``a`` and result
t.prod(a, b) let t = a
a = t a.prod(t, b)
func `*`*(a, b: Fp6): Fp6 {.inline.} = func `*`*(a, b: Fp6): Fp6 {.inline, noInit.} =
result.prod(a, b) result.prod(a, b)

View File

@ -53,8 +53,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)":
test(BN254) test(BN254)
test(BLS12_381) test(BLS12_381)
test(P256)
test(Secp256k1)
test "Squaring 1 returns 1": test "Squaring 1 returns 1":
template test(C: static Curve) = template test(C: static Curve) =
@ -76,8 +74,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)":
testInstance() testInstance()
test(BN254) test(BN254)
test(P256)
test(Secp256k1)
test(BLS12_377) test(BLS12_377)
test(BLS12_381) test(BLS12_381)
test(BN446) test(BN446)
@ -129,30 +125,29 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)":
test(BLS12_381): test(BLS12_381):
r.prod(One, x) r.prod(One, x)
check: bool(r == x) check: bool(r == x)
test(P256):
r.prod(x, Zero) test "Multiplication and Squaring are consistent":
check: bool(r == Zero) template test(C: static Curve) =
test(P256): block:
r.prod(Zero, x) proc testInstance() =
check: bool(r == Zero) for _ in 0 ..< Iters:
test(P256): let a = rng.random(Fp2[C])
r.prod(x, One) var rMul{.noInit.}, rSqr{.noInit.}: Fp2[C]
check: bool(r == x)
test(P256): rMul.prod(a, a)
r.prod(One, x) rSqr.square(a)
check: bool(r == x)
test(Secp256k1): check: bool(rMul == rSqr)
r.prod(x, Zero)
check: bool(r == Zero) testInstance()
test(Secp256k1):
r.prod(Zero, x) test(BN254)
check: bool(r == Zero) test(BLS12_377)
test(Secp256k1): test(BLS12_381)
r.prod(x, One) test(BN446)
check: bool(r == x) test(FKM12_447)
test(Secp256k1): test(BLS12_461)
r.prod(One, x) test(BN462)
check: bool(r == x)
test "𝔽p2 = 𝔽p[𝑖] addition is associative and commutative": test "𝔽p2 = 𝔽p[𝑖] addition is associative and commutative":
proc abelianGroup(curve: static Curve) = proc abelianGroup(curve: static Curve) =
@ -197,8 +192,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)":
bool(r0 == r4) bool(r0 == r4)
abelianGroup(BN254) abelianGroup(BN254)
abelianGroup(P256)
abelianGroup(Secp256k1)
abelianGroup(BLS12_377) abelianGroup(BLS12_377)
abelianGroup(BLS12_381) abelianGroup(BLS12_381)
abelianGroup(BN446) abelianGroup(BN446)
@ -249,8 +242,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)":
bool(r0 == r4) bool(r0 == r4)
commutativeRing(BN254) commutativeRing(BN254)
commutativeRing(P256)
commutativeRing(Secp256k1)
commutativeRing(BLS12_377) commutativeRing(BLS12_377)
commutativeRing(BLS12_381) commutativeRing(BLS12_381)
commutativeRing(BN446) commutativeRing(BN446)
@ -274,8 +265,6 @@ suite "𝔽p2 = 𝔽p[𝑖] (irreducible polynomial x²+1)":
check: bool(r == one) check: bool(r == one)
mulInvOne(BN254) mulInvOne(BN254)
mulInvOne(P256)
mulInvOne(Secp256k1)
mulInvOne(BLS12_377) mulInvOne(BLS12_377)
mulInvOne(BLS12_381) mulInvOne(BLS12_381)
mulInvOne(BN446) mulInvOne(BN446)

View File

@ -227,6 +227,29 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
r.prod(One, x) r.prod(One, x)
check: bool(r == x) check: bool(r == x)
test "Multiplication and Squaring are consistent":
template test(C: static Curve) =
block:
proc testInstance() =
for _ in 0 ..< 1: # Iters:
let a = rng.random(Fp6[C])
var rMul{.noInit.}, rSqr{.noInit.}: Fp6[C]
rMul.prod(a, a)
rSqr.square(a)
check: bool(rMul == rSqr)
testInstance()
test(BN254)
test(BLS12_377)
test(BLS12_381)
test(BN446)
test(FKM12_447)
test(BLS12_461)
test(BN462)
test "𝔽p6 = 𝔽p2[∛(1+𝑖)] addition is associative and commutative": test "𝔽p6 = 𝔽p2[∛(1+𝑖)] addition is associative and commutative":
proc abelianGroup(curve: static Curve) = proc abelianGroup(curve: static Curve) =
for _ in 0 ..< Iters: for _ in 0 ..< Iters:
@ -270,8 +293,6 @@ suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
bool(r0 == r4) bool(r0 == r4)
abelianGroup(BN254) abelianGroup(BN254)
abelianGroup(P256)
abelianGroup(Secp256k1)
abelianGroup(BLS12_377) abelianGroup(BLS12_377)
abelianGroup(BLS12_381) abelianGroup(BLS12_381)
abelianGroup(BN446) abelianGroup(BN446)