Prepare for bindings generation

This commit is contained in:
Mamy Ratsimbazafy 2022-07-16 13:34:27 +02:00
parent e29e529f18
commit 7d29cb947a
No known key found for this signature in database
GPG Key ID: 6227262F49BE273A
10 changed files with 252 additions and 45 deletions

View File

@ -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

View File

@ -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:

View File

@ -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]

View File

@ -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 =

View File

@ -11,7 +11,7 @@ import
./curves_declaration,
./curves_prop_field_core
export matchingBigInt
export matchingBigInt, matchingOrderBigInt
type
Fp*[C: static Curve] = object

View File

@ -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)

View File

@ -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)

View File

@ -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.**

View File

@ -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:

View File

@ -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()