From 7d29cb947af419af152dae380f95bdc5e3593518 Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Sat, 16 Jul 2022 13:34:27 +0200 Subject: [PATCH] Prepare for bindings generation --- constantine/curves_primitives.nim | 211 ++++++++++++++++++ constantine/math/arithmetic/finite_fields.nim | 2 +- constantine/math/config/curves_prop_curve.nim | 9 +- .../math/config/curves_prop_field_core.nim | 12 +- constantine/math/config/type_ff.nim | 2 +- constantine/math/io/io_ec.nim | 12 +- constantine/math/io/io_extfields.nim | 16 +- constantine/math/io/io_fields.nim | 8 +- constantine/math/pairings.nim | 2 +- research/kzg_poly_commit/fft_g1.nim | 23 +- 10 files changed, 252 insertions(+), 45 deletions(-) create mode 100644 constantine/curves_primitives.nim diff --git a/constantine/curves_primitives.nim b/constantine/curves_primitives.nim new file mode 100644 index 0000000..65dc45d --- /dev/null +++ b/constantine/curves_primitives.nim @@ -0,0 +1,211 @@ +# 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. + +import + ./platforms/abstractions, + ./math/config/[curves, type_ff], + ./math/[ + ec_shortweierstrass, + extension_fields, + arithmetic, + curves/zoo_subgroups, + curves/zoo_generators + ], + ./math/io/[io_bigints, io_ec], + ./math/isogenies/frobenius, + ./math/pairings, + ./math/pairing/[ + cyclotomic_subgroup, + lines_eval + ], + ./math/curves/zoo_pairings, + ./hash_to_curve/hash_to_curve + +# ############################################################ +# +# Generator for low-level primitives API +# +# ############################################################ + +{.push raises: [].} # No exceptions allowed in core cryptographic operations +{.push inline.} + +# Base types +# ------------------------------------------------------------ + +export + abstractions.SecretBool, + curves.Curve + +# Scalar field Fr and Prime Field Fp +# ------------------------------------------------------------ + +export + type_ff.Fp, + type_ff.Fr, + type_ff.FF + +func unmarshalBE*(dst: var FF, src: openarray[byte]) = + var raw {.noInit.}: typeof dst.mres + raw.unmarshal(src, bigEndian) + dst.fromBig(raw) + +func marshalBE*(dst: var openarray[byte], src: FF) = + var raw {.noInit.}: typeof src.mres + raw.fromField(src) + dst.marshal(src, bigEndian) + +export arithmetic.`==` +export arithmetic.isZero +export arithmetic.isOne +export arithmetic.isMinusOne + +export arithmetic.setZero +export arithmetic.setOne +export arithmetic.setMinusOne + +export arithmetic.neg +export arithmetic.sum +export arithmetic.`+=` +export arithmetic.diff +export arithmetic.`-=` +export arithmetic.double + +export arithmetic.prod +export arithmetic.`*=` +export arithmetic.square +export arithmetic.square_repeated + +export arithmetic.csetZero +export arithmetic.csetOne +export arithmetic.cneg +export arithmetic.cadd +export arithmetic.csub + +export arithmetic.div2 +export arithmetic.inv + +export arithmetic.isSquare +export arithmetic.invsqrt +export arithmetic.sqrt +export arithmetic.sqrt_invsqrt +export arithmetic.sqrt_invsqrt_if_square +export arithmetic.sqrt_if_square +export arithmetic.invsqrt_if_square +export arithmetic.sqrt_ratio_if_square + +# Elliptic curve +# ------------------------------------------------------------ + +export + ec_shortweierstrass.Subgroup, + ec_shortweierstrass.ECP_ShortW_Aff, + ec_shortweierstrass.ECP_ShortW_Jac, + ec_shortweierstrass.ECP_ShortW_Prj, + ec_shortweierstrass.ECP_ShortW + +export ec_shortweierstrass.`==` +export ec_shortweierstrass.isInf +export ec_shortweierstrass.setInf +export ec_shortweierstrass.ccopy +export ec_shortweierstrass.isOnCurve +export ec_shortweierstrass.neg +export ec_shortweierstrass.cneg + +export ec_shortweierstrass.affine +export ec_shortweierstrass.fromAffine +export ec_shortweierstrass.batchAffine + +export ec_shortweierstrass.sum +export ec_shortweierstrass.double +export ec_shortweierstrass.diff +# export ec_shortweierstrass.madd + +export ec_shortweierstrass.scalarMul + +export zoo_generators.getGenerator +export zoo_subgroups.clearCofactor +export zoo_subgroups.isInSubgroup + +export frobenius.frobenius_psi + +# Extension fields +# ------------------------------------------------------------ + +export + extension_fields.Fp2 + # TODO: deal with Fp2->Fp6 vs Fp3->Fp6 and Fp2->Fp6->Fp12 vs Fp2->Fp4->Fp12 + # extension_fields.Fp4, + # extension_fields.Fp6, + # extension_fields.Fp12 + +export extension_fields.setZero +export extension_fields.setOne + +export extension_fields.`==` +export extension_fields.isZero +export extension_fields.isOne +export extension_fields.isMinusOne + +export extension_fields.ccopy + +export extension_fields.neg +export extension_fields.`+=` +export extension_fields.`-=` +export extension_fields.double +export extension_fields.div2 +export extension_fields.sum +export extension_fields.diff +export extension_fields.conj +export extension_fields.conjneg + +export extension_fields.csetZero +export extension_fields.csetOne +export extension_fields.cneg +export extension_fields.csub +export extension_fields.cadd + +export extension_fields.`*=` +export extension_fields.prod +export extension_fields.inv + +export extension_fields.isSquare +export extension_fields.sqrt_if_square +export extension_fields.sqrt + +export frobenius.frobenius_map + +# Pairings +# ------------------------------------------------------------ + +export + lines_eval.Line + +export lines_eval.line_double +export lines_eval.line_add +export lines_eval.mul_by_line +export lines_eval.mul_by_2_lines + +export cyclotomic_subgroup.finalExpEasy +export cyclotomic_subgroup.cyclotomic_inv +export cyclotomic_subgroup.cyclotomic_square +export cyclotomic_subgroup.cycl_sqr_repeated +export cyclotomic_subgroup.cyclotomic_exp +export cyclotomic_subgroup.isInCyclotomicSubgroup + +export zoo_pairings.cycl_exp_by_curve_param +export zoo_pairings.cycl_exp_by_curve_param_div2 +export zoo_pairings.millerLoopAddchain +export zoo_pairings.isInPairingSubgroup + +export pairings.pairing + +# Hashing to Elliptic Curve +# ------------------------------------------------------------ + +export hash_to_curve.hash_to_curve \ No newline at end of file diff --git a/constantine/math/arithmetic/finite_fields.nim b/constantine/math/arithmetic/finite_fields.nim index 37f16a8..1aae4a3 100644 --- a/constantine/math/arithmetic/finite_fields.nim +++ b/constantine/math/arithmetic/finite_fields.nim @@ -82,7 +82,7 @@ func ccopy*(a: var FF, b: FF, ctl: SecretBool) {.meter.} = ## Time and memory accesses are the same whether a copy occurs or not ccopy(a.mres, b.mres, ctl) -func cswap*(a, b: var FF, ctl: CTBool) {.meter.} = +func cswap*(a, b: var FF, ctl: SecretBool) {.meter.} = ## Swap ``a`` and ``b`` if ``ctl`` is true ## ## Constant-time: diff --git a/constantine/math/config/curves_prop_curve.nim b/constantine/math/config/curves_prop_curve.nim index 7b51c84..8fdc7b7 100644 --- a/constantine/math/config/curves_prop_curve.nim +++ b/constantine/math/config/curves_prop_curve.nim @@ -9,7 +9,6 @@ import # Standard library std/macros, # Internal - ./type_bigint, ./curves_declaration, ./curves_parser_curve export CurveFamily, Curve, SexticTwist @@ -22,6 +21,10 @@ export CurveFamily, Curve, SexticTwist {.experimental: "dynamicBindSym".} +template getCurveBitwidth*(C: Curve): int = + ## Returns the number of bits taken by the curve modulus + CurveBitWidth[C] + macro getCurveOrder*(C: static Curve): untyped = ## Get the curve order `r` ## i.e. the number of points on the elliptic curve @@ -35,10 +38,6 @@ macro getCurveOrderBitwidth*(C: static Curve): untyped = ident"bits" ) -template matchingOrderBigInt*(C: static Curve): untyped = - # Workaround: https://github.com/nim-lang/Nim/issues/16774 - BigInt[CurveOrderBitWidth[C]] - template family*(C: Curve): CurveFamily = CurveFamilies[C] diff --git a/constantine/math/config/curves_prop_field_core.nim b/constantine/math/config/curves_prop_field_core.nim index 8458be5..668c278 100644 --- a/constantine/math/config/curves_prop_field_core.nim +++ b/constantine/math/config/curves_prop_field_core.nim @@ -27,16 +27,18 @@ macro Mod*(C: static Curve): untyped = ## Get the Modulus associated to a curve result = bindSym($C & "_Modulus") -template getCurveBitwidth*(C: Curve): int = - ## Returns the number of bits taken by the curve modulus - CurveBitWidth[C] - template matchingBigInt*(C: static Curve): untyped = + ## BigInt type necessary to store the prime field Fp # Workaround: https://github.com/nim-lang/Nim/issues/16774 BigInt[CurveBitWidth[C]] +template matchingOrderBigInt*(C: static Curve): untyped = + ## BigInt type necessary to store the scalar field Fr + # Workaround: https://github.com/nim-lang/Nim/issues/16774 + BigInt[CurveOrderBitWidth[C]] + template matchingLimbs2x*(C: Curve): untyped = - const N2 = wordsRequired(getCurveBitwidth(C)) * 2 # TODO upstream, not precomputing N2 breaks semcheck + const N2 = wordsRequired(CurveBitWidth[C]) * 2 # TODO upstream, not precomputing N2 breaks semcheck array[N2, SecretWord] # TODO upstream, using Limbs[N2] breaks semcheck func has_P_3mod4_primeModulus*(C: static Curve): static bool = diff --git a/constantine/math/config/type_ff.nim b/constantine/math/config/type_ff.nim index d2d10a2..c2f837f 100644 --- a/constantine/math/config/type_ff.nim +++ b/constantine/math/config/type_ff.nim @@ -11,7 +11,7 @@ import ./curves_declaration, ./curves_prop_field_core -export matchingBigInt +export matchingBigInt, matchingOrderBigInt type Fp*[C: static Curve] = object diff --git a/constantine/math/io/io_ec.nim b/constantine/math/io/io_ec.nim index e247a9d..d4f9b74 100644 --- a/constantine/math/io/io_ec.nim +++ b/constantine/math/io/io_ec.nim @@ -53,7 +53,7 @@ func toHex*[EC: ECP_ShortW_Prj or ECP_ShortW_Jac or ECP_ShortW_Aff](P: EC, inden result.appendHex(aff.y) result &= "\n" & sp & ")" -func fromHex*(dst: var (ECP_ShortW_Prj or ECP_ShortW_Jac), x, y: string): bool {.raises: [ValueError].}= +func fromHex*(dst: var (ECP_ShortW_Prj or ECP_ShortW_Jac), x, y: string): bool = ## Convert hex strings to a G1 curve point ## Returns true if point exist or if input is the point at infinity (all 0) ## Returns `false` if there is no point with coordinates (`x`, `y`) on the curve @@ -66,7 +66,7 @@ func fromHex*(dst: var (ECP_ShortW_Prj or ECP_ShortW_Jac), x, y: string): bool { dst.z.csetZero(isInf) return bool(isOnCurve(dst.x, dst.y, dst.G) or isInf) -func fromHex*(dst: var (ECP_ShortW_Prj or ECP_ShortW_Jac), x0, x1, y0, y1: string): bool {.raises: [ValueError].}= +func fromHex*(dst: var (ECP_ShortW_Prj or ECP_ShortW_Jac), x0, x1, y0, y1: string): bool = ## Convert hex strings to a G2 curve point ## Returns `false` ## if there is no point with coordinates (`x`, `y`) on the curve @@ -79,7 +79,7 @@ func fromHex*(dst: var (ECP_ShortW_Prj or ECP_ShortW_Jac), x0, x1, y0, y1: strin dst.z.csetZero(isInf) return bool(isOnCurve(dst.x, dst.y, dst.G) or isInf) -func fromHex*(dst: var ECP_ShortW_Aff, x, y: string): bool {.raises: [ValueError].}= +func fromHex*(dst: var ECP_ShortW_Aff, x, y: string): bool = ## Convert hex strings to a G1 curve point ## Returns true if point exist or if input is the point at infinity (all 0) ## Returns `false` if there is no point with coordinates (`x`, `y`) on the curve @@ -89,7 +89,7 @@ func fromHex*(dst: var ECP_ShortW_Aff, x, y: string): bool {.raises: [ValueError dst.y.fromHex(y) return bool(isOnCurve(dst.x, dst.y, dst.G) or dst.isInf()) -func fromHex*(dst: var ECP_ShortW_Aff, x0, x1, y0, y1: string): bool {.raises: [ValueError].}= +func fromHex*(dst: var ECP_ShortW_Aff, x0, x1, y0, y1: string): bool = ## Convert hex strings to a G2 curve point ## Returns true if point exist or if input is the point at infinity (all 0) ## Returns `false` if there is no point with coordinates (`x`, `y`) on the curve @@ -100,9 +100,9 @@ func fromHex*(dst: var ECP_ShortW_Aff, x0, x1, y0, y1: string): bool {.raises: [ return bool(isOnCurve(dst.x, dst.y, dst.G) or dst.isInf()) func fromHex*[EC: ECP_ShortW_Prj or ECP_ShortW_Jac or ECP_ShortW_Aff]( - _: type EC, x, y: string): EC {.raises: [ValueError].} = + _: type EC, x, y: string): EC = doAssert result.fromHex(x, y) func fromHex*[EC: ECP_ShortW_Prj or ECP_ShortW_Jac or ECP_ShortW_Aff]( - _: type EC, x0, x1, y0, y1: string): EC {.raises: [ValueError].} = + _: type EC, x0, x1, y0, y1: string): EC = doAssert result.fromHex(x0, x1, y0, y1) \ No newline at end of file diff --git a/constantine/math/io/io_extfields.nim b/constantine/math/io/io_extfields.nim index c02b309..f7c3f62 100644 --- a/constantine/math/io/io_extfields.nim +++ b/constantine/math/io/io_extfields.nim @@ -57,34 +57,34 @@ func toHex*(f: Fp2 or Fp4 or Fp6 or Fp12, indent = 0, order: static Endianness = ## - no leaks result.appendHex(f, indent, order) -func fromHex*(dst: var Fp2, c0, c1: string) {.raises: [ValueError].}= +func fromHex*(dst: var Fp2, c0, c1: string) = ## Convert 2 coordinates to an element of 𝔽p2 ## with dst = c0 + β * c1 ## β is the quadratic non-residue chosen to construct 𝔽p2 dst.c0.fromHex(c0) dst.c1.fromHex(c1) -func fromHex*(T: typedesc[Fp2], c0, c1: string): T {.raises: [ValueError].}= +func fromHex*(T: typedesc[Fp2], c0, c1: string): T = ## Convert 2 coordinates to an element of 𝔽p2 ## with dst = c0 + β * c1 ## β is the quadratic non-residue chosen to construct 𝔽p2 result.fromHex(c0, c1) func fromHex*(dst: var Fp4, - c0, c1, c2, c3: string) {.raises: [ValueError].}= + c0, c1, c2, c3: string) = ## Convert 4 coordinates to an element of 𝔽p4 dst.c0.fromHex(c0, c1) dst.c1.fromHex(c2, c3) func fromHex*(T: typedesc[Fp4], c0, c1, c2: string, - c3, c4, c5: string): T {.raises: [ValueError].}= + c3, c4, c5: string): T = ## Convert 4 coordinates to an element of 𝔽p4 result.fromHex(c0, c1, c2, c3) func fromHex*(dst: var Fp6, c0, c1, c2: string, - c3, c4, c5: string) {.raises: [ValueError].}= + c3, c4, c5: string) = ## Convert 6 coordinates to an element of 𝔽p6 dst.c0.fromHex(c0, c1) dst.c1.fromHex(c2, c3) @@ -92,14 +92,14 @@ func fromHex*(dst: var Fp6, func fromHex*(T: typedesc[Fp6], c0, c1, c2: string, - c3, c4, c5: string): T {.raises: [ValueError].}= + c3, c4, c5: string): T = ## Convert 6 coordinates to an element of 𝔽p6 result.fromHex(c0, c1, c2, c3, c4, c5) func fromHex*(dst: var Fp12, c0, c1, c2, c3: string, c4, c5, c6, c7: string, - c8, c9, c10, c11: string) {.raises: [ValueError].}= + c8, c9, c10, c11: string) = ## Convert 12 coordinates to an element of 𝔽p12 when dst.c0 is Fp6: dst.c0.fromHex(c0, c1, c2, c3, c4, c5) @@ -112,7 +112,7 @@ func fromHex*(dst: var Fp12, func fromHex*(T: typedesc[Fp12], c0, c1, c2, c3: string, c4, c5, c6, c7: string, - c8, c9, c10, c11: string): T {.raises: [ValueError].}= + c8, c9, c10, c11: string): T = ## Convert 12 coordinates to an element of 𝔽p12 result.fromHex(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) diff --git a/constantine/math/io/io_fields.nim b/constantine/math/io/io_fields.nim index f97fb96..def901c 100644 --- a/constantine/math/io/io_fields.nim +++ b/constantine/math/io/io_fields.nim @@ -82,7 +82,7 @@ func toHex*(f: FF, order: static Endianness = bigEndian): string = ## - no leaks result.appendHex(f, order) -func fromHex*(dst: var FF, hexString: string) {.raises: [ValueError].}= +func fromHex*(dst: var FF, hexString: string) = ## Convert a hex string to a element of Fp or Fr ## Warning: protocols might want a specific function that checks ## that the input is in [0, modulus) range @@ -90,7 +90,7 @@ func fromHex*(dst: var FF, hexString: string) {.raises: [ValueError].}= let raw {.noinit.} = fromHex(dst.mres.typeof, hexString) dst.fromBig(raw) -func fromHex*(T: type FF, hexString: string): T {.noInit, raises: [ValueError].}= +func fromHex*(T: type FF, hexString: string): T {.noInit.}= ## Convert a hex string to a element of Fp ## Warning: protocols might want a specific function that checks ## that the input is in [0, modulus) range @@ -106,7 +106,7 @@ func toDecimal*(f: FF): string = # TODO constant-time f.toBig().toDecimal() -func fromDecimal*(dst: var FF, decimalString: string) {.raises: [ValueError].}= +func fromDecimal*(dst: var FF, decimalString: string) = ## Convert a decimal string. The input must be packed ## with no spaces or underscores. ## This assumes that bits and decimal length are **public.** @@ -126,7 +126,7 @@ func fromDecimal*(dst: var FF, decimalString: string) {.raises: [ValueError].}= let raw {.noinit.} = fromDecimal(dst.mres.typeof, decimalString) dst.fromBig(raw) -func fromDecimal*(T: type FF, hexString: string): T {.noInit, raises: [ValueError].}= +func fromDecimal*(T: type FF, hexString: string): T {.noInit.}= ## Convert a decimal string. The input must be packed ## with no spaces or underscores. ## This assumes that bits and decimal length are **public.** diff --git a/constantine/math/pairings.nim b/constantine/math/pairings.nim index e143fd1..1abc42f 100644 --- a/constantine/math/pairings.nim +++ b/constantine/math/pairings.nim @@ -11,7 +11,7 @@ import ./pairing/[pairing_bn, pairing_bls12], ./extension_fields -template pairing*[C](gt: var Fp12[C], P, Q: typed) = +func pairing*[C](gt: var Fp12[C], P, Q: auto) {.inline.} = when family(C) == BarretoNaehrig: pairing_bn(gt, P, Q) elif family(C) == BarretoLynnScott: diff --git a/research/kzg_poly_commit/fft_g1.nim b/research/kzg_poly_commit/fft_g1.nim index 50b0788..e47af00 100644 --- a/research/kzg_poly_commit/fft_g1.nim +++ b/research/kzg_poly_commit/fft_g1.nim @@ -10,12 +10,7 @@ import ../../constantine/platforms/primitives, ../../constantine/math/config/curves, ../../constantine/math/arithmetic, - ../../constantine/math/elliptic/[ - ec_scalar_mul, - ec_shortweierstrass_affine, - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian, - ], + ../../constantine/math/ec_shortweierstrass, ../../constantine/math/io/[io_fields, io_ec], # Research ./strided_views, @@ -213,7 +208,7 @@ when isMainModule: std/[times, monotimes, strformat], ../../helpers/prng_unsafe - type G1 = ECP_ShortW_Prj[Fp[BLS12_381], G1] + type EC_G1 = ECP_ShortW_Prj[Fp[BLS12_381], G1] var Generator1: ECP_ShortW_Aff[Fp[BLS12_381], G1] doAssert Generator1.fromHex( "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", @@ -221,18 +216,18 @@ when isMainModule: ) proc roundtrip() = - let fftDesc = FFTDescriptor[G1].init(maxScale = 4) - var data = newSeq[G1](fftDesc.maxWidth) + let fftDesc = FFTDescriptor[EC_G1].init(maxScale = 4) + var data = newSeq[EC_G1](fftDesc.maxWidth) data[0].fromAffine(Generator1) for i in 1 ..< fftDesc.maxWidth: data[i].madd(data[i-1], Generator1) - var coefs = newSeq[G1](data.len) + var coefs = newSeq[EC_G1](data.len) let fftOk = fft(fftDesc, coefs, data) doAssert fftOk == FFTS_Success # display("coefs", 0, coefs) - var res = newSeq[G1](data.len) + var res = newSeq[EC_G1](data.len) let ifftOk = ifft(fftDesc, res, coefs) doAssert ifftOk == FFTS_Success # display("res", 0, coefs) @@ -272,13 +267,13 @@ when isMainModule: for scale in 4 ..< 10: # Setup - let desc = FFTDescriptor[G1].init(uint8 scale) - var data = newSeq[G1](desc.maxWidth) + let desc = FFTDescriptor[EC_G1].init(uint8 scale) + var data = newSeq[EC_G1](desc.maxWidth) data[0].fromAffine(Generator1) for i in 1 ..< desc.maxWidth: data[i].madd(data[i-1], Generator1) - var coefsOut = newSeq[G1](data.len) + var coefsOut = newSeq[EC_G1](data.len) # Bench let start = getMonotime()