From d61680e1ad986222c09ae82ea3d18b82bac30306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Tue, 14 Apr 2020 18:30:59 +0200 Subject: [PATCH] Fix substraction being addition following tower refactor --- constantine/arithmetic/limbs_modular.nim | 5 ++- .../cubic_extensions.nim | 18 ++++++--- .../tower_field_extensions/tower_common.nim | 12 +++--- tests/test_fp12.nim | 40 ++++++++++++++++++- tests/test_fp2.nim | 37 +++++++++++++++++ tests/test_fp6.nim | 37 +++++++++++++++++ 6 files changed, 135 insertions(+), 14 deletions(-) diff --git a/constantine/arithmetic/limbs_modular.nim b/constantine/arithmetic/limbs_modular.nim index 726ece0..7487c39 100644 --- a/constantine/arithmetic/limbs_modular.nim +++ b/constantine/arithmetic/limbs_modular.nim @@ -121,7 +121,10 @@ func steinsGCD*(v: var Limbs, a: Limbs, F, M: Limbs, bits: int, mp1div2: Limbs) debug: doAssert bool a.isZero() - doAssert bool b.isOne() # GCD always exist if a and M are relatively prime + # GCD exist (always true if a and M are relatively prime) + doAssert bool b.isOne() or + # or not (on prime fields iff input was zero) and no GCD fallback output is zero + (a.isZero() and v.isZero()) # ############################################################ # diff --git a/constantine/tower_field_extensions/cubic_extensions.nim b/constantine/tower_field_extensions/cubic_extensions.nim index 4ca4996..e4e2c4b 100644 --- a/constantine/tower_field_extensions/cubic_extensions.nim +++ b/constantine/tower_field_extensions/cubic_extensions.nim @@ -18,18 +18,26 @@ func square*(r: var CubicExt, a: CubicExt) = ## Returns r = a² # Algorithm is Chung-Hasan Squaring SQR2 # http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf + # https://www.lirmm.fr/arith18/papers/Chung-Squaring.pdf # - # TODO: change to SQR1 or SQR3 (requires div2) - # which are faster for the sizes we are interested in. + # Cost in base field operation + # M -> Mul, S -> Square, B -> Bitshift (doubling/div2), A -> Add + # + # SQR1: 3M + 2S + 5B + 9A + # SQR2: 2M + 3S + 5B + 11A + # SQR3: 1M + 4S + 6B + 15A + # Schoolbook: 3S + 3M + 6B + 2A + # + # TODO: Implement all variants, bench and select one depending on number of limbs and extension degree. mixin prod, square, sum - var v2{.noInit.}, v3{.noInit.}, v4{.noInit.}, v5{.noInit.}: typeof(r.c0) + var v3{.noInit.}, v4{.noInit.}, v5{.noInit.}: typeof(r.c0) v4.prod(a.c0, a.c1) v4.double() v5.square(a.c2) r.c1 = β * v5 r.c1 += v4 - v2.diff(v4, v5) + r.c2.diff(v4, v5) v3.square(a.c0) v4.diff(a.c0, a.c1) v4 += a.c2 @@ -38,7 +46,7 @@ func square*(r: var CubicExt, a: CubicExt) = v4.square() r.c0 = β * v5 r.c0 += v3 - r.c2.sum(v2, v4) + r.c2 += v4 r.c2 += v5 r.c2 -= v3 diff --git a/constantine/tower_field_extensions/tower_common.nim b/constantine/tower_field_extensions/tower_common.nim index 1e3a3da..92b358f 100644 --- a/constantine/tower_field_extensions/tower_common.nim +++ b/constantine/tower_field_extensions/tower_common.nim @@ -74,7 +74,7 @@ func isZero*(a: ExtensionField): CTBool[Word] = func isOne*(a: ExtensionField): CTBool[Word] = ## Constant-time check if one result = CtTrue - for fieldName, fA in fields(a): + for fieldName, fA in fieldPairs(a): when fieldName == "c0": result = result and fA.isOne() else: @@ -121,11 +121,11 @@ func sum*(r: var CubicExt, a, b: CubicExt) = func diff*(r: var QuadraticExt, a, b: QuadraticExt) = ## Diff ``a`` and ``b`` into ``r`` - r.c0.sum(a.c0, b.c0) - r.c1.sum(a.c1, b.c1) + r.c0.diff(a.c0, b.c0) + r.c1.diff(a.c1, b.c1) func diff*(r: var CubicExt, a, b: CubicExt) = ## Diff ``a`` and ``b`` into ``r`` - r.c0.sum(a.c0, b.c0) - r.c1.sum(a.c1, b.c1) - r.c2.sum(a.c2, b.c2) + r.c0.diff(a.c0, b.c0) + r.c1.diff(a.c1, b.c1) + r.c2.diff(a.c2, b.c2) diff --git a/tests/test_fp12.nim b/tests/test_fp12.nim index b94a014..783d44b 100644 --- a/tests/test_fp12.nim +++ b/tests/test_fp12.nim @@ -31,7 +31,6 @@ echo "test_fp12 xoshiro512** seed: ", seed # will significantly slow down testing (100x is possible) suite "𝔽p12 = 𝔽p6[w] (irreducible polynomial w² - γ)": - test "Comparison sanity checks": proc test(C: static Curve) = var z, o {.noInit.}: Fp12[C] @@ -44,6 +43,43 @@ suite "𝔽p12 = 𝔽p6[w] (irreducible polynomial w² - γ)": test(BN254_Snarks) test(BLS12_381) + test "Addition, substraction negation are consistent": + proc test(C: static Curve) = + # Try to exercise all code paths for in-place/out-of-place add/sum/sub/diff/double/neg + # (1 - (-a) - b + (-a) - 2a) + (2a + 2b + (-b)) == 1 + var accum {.noInit.}, One {.noInit.}, a{.noInit.}, na{.noInit.}, b{.noInit.}, nb{.noInit.}, a2 {.noInit.}, b2 {.noInit.}: Fp12[C] + + One.setOne() + a = rng.random(Fp12[C]) + a2 = a + a2.double() + na.neg(a) + + b = rng.random(Fp12[C]) + b2.double(b) + nb.neg(b) + + accum.diff(One, na) + accum -= b + accum += na + accum -= a2 + + var t{.noInit.}: Fp12[C] + t.sum(a2, b2) + t += nb + + accum += t + check: bool accum.isOne() + + # test(BN254_Nogami) + test(BN254_Snarks) + test(BLS12_377) + test(BLS12_381) + # test(BN446) + # test(FKM12_447) + # test(BLS12_461) + # test(BN462) + test "Squaring 1 returns 1": template test(C: static Curve) = block: @@ -489,7 +525,7 @@ suite "𝔽p12 = 𝔽p6[w] (irreducible polynomial w² - γ)": var z: Fp12[curve] z.setZero() - var zInv{.noInit.}: Fp6[curve] + var zInv{.noInit.}: Fp12[curve] zInv.inv(z) check: bool zInv.isZero() diff --git a/tests/test_fp2.nim b/tests/test_fp2.nim index 1994a5d..702ac0b 100644 --- a/tests/test_fp2.nim +++ b/tests/test_fp2.nim @@ -67,6 +67,43 @@ suite "𝔽p2 = 𝔽p[µ] (irreducible polynomial x²+µ)": test(BN254_Snarks) test(BLS12_381) + test "Addition, substraction negation are consistent": + proc test(C: static Curve) = + # Try to exercise all code paths for in-place/out-of-place add/sum/sub/diff/double/neg + # (1 - (-a) - b + (-a) - 2a) + (2a + 2b + (-b)) == 1 + var accum {.noInit.}, One {.noInit.}, a{.noInit.}, na{.noInit.}, b{.noInit.}, nb{.noInit.}, a2 {.noInit.}, b2 {.noInit.}: Fp2[C] + + One.setOne() + a = rng.random(Fp2[C]) + a2 = a + a2.double() + na.neg(a) + + b = rng.random(Fp2[C]) + b2.double(b) + nb.neg(b) + + accum.diff(One, na) + accum -= b + accum += na + accum -= a2 + + var t{.noInit.}: Fp2[C] + t.sum(a2, b2) + t += nb + + accum += t + check: bool accum.isOne() + + # test(BN254_Nogami) + test(BN254_Snarks) + test(BLS12_377) + test(BLS12_381) + # test(BN446) + # test(FKM12_447) + # test(BLS12_461) + # test(BN462) + test "Squaring 1 returns 1": template test(C: static Curve) = block: diff --git a/tests/test_fp6.nim b/tests/test_fp6.nim index a06b45c..3bcf624 100644 --- a/tests/test_fp6.nim +++ b/tests/test_fp6.nim @@ -43,6 +43,43 @@ suite "𝔽p6 = 𝔽p2[v] (irreducible polynomial v³ - ξ)": test(BN254_Snarks) test(BLS12_381) + test "Addition, substraction negation are consistent": + proc test(C: static Curve) = + # Try to exercise all code paths for in-place/out-of-place add/sum/sub/diff/double/neg + # (1 - (-a) - b + (-a) - 2a) + (2a + 2b + (-b)) == 1 + var accum {.noInit.}, One {.noInit.}, a{.noInit.}, na{.noInit.}, b{.noInit.}, nb{.noInit.}, a2 {.noInit.}, b2 {.noInit.}: Fp6[C] + + One.setOne() + a = rng.random(Fp6[C]) + a2 = a + a2.double() + na.neg(a) + + b = rng.random(Fp6[C]) + b2.double(b) + nb.neg(b) + + accum.diff(One, na) + accum -= b + accum += na + accum -= a2 + + var t{.noInit.}: Fp6[C] + t.sum(a2, b2) + t += nb + + accum += t + check: bool accum.isOne() + + # test(BN254_Nogami) + test(BN254_Snarks) + test(BLS12_377) + test(BLS12_381) + # test(BN446) + # test(FKM12_447) + # test(BLS12_461) + # test(BN462) + test "Squaring 1 returns 1": template test(C: static Curve) = block: