diff --git a/benchmarks/bench_elliptic_template.nim b/benchmarks/bench_elliptic_template.nim index b2ed489..fd83738 100644 --- a/benchmarks/bench_elliptic_template.nim +++ b/benchmarks/bench_elliptic_template.nim @@ -31,6 +31,8 @@ import ../tests/math/support/ec_reference_scalar_mult export notes +export abstractions # generic sandwich on SecretBool and SecretBool in Jacobian sum + proc separator*() = separator(177) macro fixEllipticDisplay(T: typedesc): untyped = diff --git a/benchmarks/bench_summary_template.nim b/benchmarks/bench_summary_template.nim index 6b71e33..b876ca5 100644 --- a/benchmarks/bench_summary_template.nim +++ b/benchmarks/bench_summary_template.nim @@ -39,6 +39,7 @@ export ec_shortweierstrass_projective, ec_shortweierstrass_jacobian +export abstractions # generic sandwich on SecretBool and SecretBool in Jacobian sum export zoo_pairings # generic sandwich https://github.com/nim-lang/Nim/issues/11225 export notes proc separator*() = separator(152) diff --git a/bindings/constantine_bls12_381.nim b/bindings/constantine_bls12_381.nim new file mode 100644 index 0000000..d1e22f4 --- /dev/null +++ b/bindings/constantine_bls12_381.nim @@ -0,0 +1,78 @@ +# 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 ./gen_bindings, gen_header + +type + bls12381_fr = Fr[BLS12_381] + bls12381_fp = Fp[BLS12_381] + bls12381_fp2 = Fp2[BLS12_381] + bls12381_ec_g1_aff = ECP_ShortW_Aff[Fp[BLS12_381], G1] + bls12381_ec_g1_jac = ECP_ShortW_Jac[Fp[BLS12_381], G1] + bls12381_ec_g1_prj = ECP_ShortW_Prj[Fp[BLS12_381], G1] + bls12381_ec_g2_aff = ECP_ShortW_Aff[Fp2[BLS12_381], G2] + bls12381_ec_g2_jac = ECP_ShortW_Jac[Fp2[BLS12_381], G2] + bls12381_ec_g2_prj = ECP_ShortW_Prj[Fp2[BLS12_381], G2] + +collectBindings(cBindings): + genBindingsField(bls12381_fr) + genBindingsField(bls12381_fp) + genBindingsFieldSqrt(bls12381_fp) + genBindingsExtField(bls12381_fp2) + genBindingsExtFieldSqrt(bls12381_fp2) + genBindings_EC_ShortW_Affine(bls12381_ec_g1_aff, bls12381_fp) + genBindings_EC_ShortW_NonAffine(bls12381_ec_g1_jac, bls12381_ec_g1_aff, bls12381_fp) + genBindings_EC_ShortW_NonAffine(bls12381_ec_g1_prj, bls12381_ec_g1_aff, bls12381_fp) + genBindings_EC_ShortW_Affine(bls12381_ec_g2_aff, bls12381_fp2) + genBindings_EC_ShortW_NonAffine(bls12381_ec_g2_jac, bls12381_ec_g2_aff, bls12381_fp2) + genBindings_EC_ShortW_NonAffine(bls12381_ec_g2_prj, bls12381_ec_g2_aff, bls12381_fp2) + +# Write header +when isMainModule and defined(CttGenerateHeaders): + import std/os + + proc main() = + echo "Running bindings generation for " & getAppFilename().extractFilename() + + var header: string + header = genBuiltinsTypes() + header &= '\n' + header &= genCttBaseTypedef() + header &= '\n' + header &= genWordsRequired() + header &= '\n' + header &= genField("bls12381_fr", BLS12_381.getCurveOrderBitWidth()) + header &= '\n' + header &= genField("bls12381_fp", BLS12_381.getCurveBitWidth()) + header &= '\n' + header &= genExtField("bls12381_fp2", 2, "bls12381_fp") + header &= '\n' + header &= genEllipticCurvePoint("bls12381_ec_g1_aff", "x, y", "bls12381_fp") + header &= '\n' + header &= genEllipticCurvePoint("bls12381_ec_g1_jac", "x, y, z", "bls12381_fp") + header &= '\n' + header &= genEllipticCurvePoint("bls12381_ec_g1_prj", "x, y, z", "bls12381_fp") + header &= '\n' + header &= genEllipticCurvePoint("bls12381_ec_g2_aff", "x, y", "bls12381_fp2") + header &= '\n' + header &= genEllipticCurvePoint("bls12381_ec_g2_jac", "x, y, z", "bls12381_fp2") + header &= '\n' + header &= genEllipticCurvePoint("bls12381_ec_g2_prj", "x, y, z", "bls12381_fp2") + header &= '\n' + header &= cBindings + header &= '\n' + header &= declNimMain("bls12381") + + header = genCpp(header) + header = genHeader("BLS12381", header) + header = genHeaderLicense() & header + + writeFile("constantine_bls12_381.h", header) + + + main() \ No newline at end of file diff --git a/bindings/constantine_pasta.nim b/bindings/constantine_pasta.nim new file mode 100644 index 0000000..987fc76 --- /dev/null +++ b/bindings/constantine_pasta.nim @@ -0,0 +1,78 @@ +# 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 ./gen_bindings, ./gen_header + +type + pallas_fr = Fr[Pallas] + pallas_fp = Fp[Pallas] + vesta_fr = Fr[Vesta] + vesta_fp = Fp[Vesta] + pallas_ec_aff = ECP_ShortW_Aff[Fp[Pallas], G1] + pallas_ec_jac = ECP_ShortW_Aff[Fp[Pallas], G1] + pallas_ec_prj = ECP_ShortW_Aff[Fp[Pallas], G1] + vesta_ec_aff = ECP_ShortW_Aff[Fp[Vesta], G1] + vesta_ec_jac = ECP_ShortW_Aff[Fp[Vesta], G1] + vesta_ec_prj = ECP_ShortW_Aff[Fp[Vesta], G1] + +collectBindings(cBindings): + genBindingsField(pallas_fr) + genBindingsField(pallas_fp) + genBindingsFieldSqrt(pallas_fp) + genBindingsField(vesta_fr) + genBindingsField(vesta_fp) + genBindingsFieldSqrt(vesta_fp) + genBindings_EC_ShortW_Affine(pallas_ec_aff, pallas_fp) + genBindings_EC_ShortW_Affine(vesta_ec_aff, pallas_fp) + +# Write header +when isMainModule and defined(CttGenerateHeaders): + import std/os + + proc main() = + echo "Running bindings generation for " & getAppFilename().extractFilename() + + var header: string + header = genBuiltinsTypes() + header &= '\n' + header &= genCttBaseTypedef() + header &= '\n' + header &= genWordsRequired() + header &= '\n' + header &= genField("pallas_fr", Pallas.getCurveOrderBitWidth()) + header &= '\n' + header &= genField("pallas_fp", Pallas.getCurveBitWidth()) + header &= '\n' + header &= genField("vesta_fr", Vesta.getCurveOrderBitWidth()) + header &= '\n' + header &= genField("vesta_fp", Vesta.getCurveBitWidth()) + header &= '\n' + header &= genEllipticCurvePoint("pallas_ec_aff", "x, y", "pallas_fp") + header &= '\n' + header &= genEllipticCurvePoint("pallas_ec_jac", "x, y, z", "pallas_fp") + header &= '\n' + header &= genEllipticCurvePoint("pallas_ec_prj", "x, y, z", "pallas_fp") + header &= '\n' + header &= genEllipticCurvePoint("vesta_ec_aff", "x, y", "vesta_fp") + header &= '\n' + header &= genEllipticCurvePoint("vesta_ec_jac", "x, y, z", "vesta_fp") + header &= '\n' + header &= genEllipticCurvePoint("vesta_ec_prj", "x, y, z", "vesta_fp") + header &= '\n' + header &= cBindings + header &= '\n' + header &= declNimMain("pasta") + + header = genCpp(header) + header = genHeader("PASTA", header) + header = genHeaderLicense() & header + + writeFile("constantine_pasta.h", header) + + + main() \ No newline at end of file diff --git a/bindings/gen_bindings.nim b/bindings/gen_bindings.nim new file mode 100644 index 0000000..e997fa9 --- /dev/null +++ b/bindings/gen_bindings.nim @@ -0,0 +1,331 @@ +# 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 + ../constantine/math/config/curves, + ../constantine/curves_primitives + +export curves, curves_primitives + +# Overview +# ------------------------------------------------------------ +# +# This files provides template for C bindings generation + +template genBindingsField*(Field: untyped) = + {.push cdecl, dynlib, exportc, raises: [].} # No exceptions allowed + + func `ctt _ Field _ unmarshalBE`(dst: var Field, src: openarray[byte]) = + ## Deserialize + unmarshalBE(dst, src) + + func `ctt _ Field _ marshalBE`(dst: var openarray[byte], src: Field) = + marshalBE(dst, src) + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ is_eq`(a, b: Field): SecretBool = + a == b + + func `ctt _ Field _ is_zero`(a: Field): SecretBool = + a.isZero() + + func `ctt _ Field _ is_one`(a: Field): SecretBool = + a.isOne() + + func `ctt _ Field _ is_minus_one`(a: Field): SecretBool = + a.isMinusOne() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ set_zero`(a: var Field) = + a.setZero() + + func `ctt _ Field _ set_one`(a: var Field) = + a.setOne() + + func `ctt _ Field _ set_minus_one`(a: var Field) = + a.setMinusOne() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ neg`(a: var Field) = + a.neg() + + func `ctt _ Field _ sum`(r: var Field, a, b: Field) = + r.sum(a,b) + + func `ctt _ Field _ add_in_place`(a: var Field, b: Field) = + a += b + + func `ctt _ Field _ diff`(r: var Field, a, b: Field) = + r.diff(a,b) + + func `ctt _ Field _ sub_in_place`(a: var Field, b: Field) = + a -= b + + func `ctt _ Field _ double`(r: var Field, a: Field) = + r.double(a) + + func `ctt _ Field _ double_in_place`(a: var Field) = + a.double() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ prod`(r: var Field, a, b: Field) = + r.prod(a,b) + + func `ctt _ Field _ mul_in_place`(a: var Field, b: Field) = + a *= b + + func `ctt _ Field _ square`(r: var Field, a: Field) = + r.square(a) + + func `ctt _ Field _ square_in_place`(a: var Field) = + a.square() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ div2`(a: var Field) = + a.div2() + + func `ctt _ Field _ inv`(r: var Field, a: Field) = + r.inv(a) + + func `ctt _ Field _ inv_in_place`(a: var Field) = + a.inv() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ ccopy`(a: var Field, b: Field, ctl: SecretBool) = + a.ccopy(b, ctl) + + func `ctt _ Field _ cswap`(a, b: var Field, ctl: SecretBool) = + a.cswap(b, ctl) + + func `ctt _ Field _ csetZero`(a: var Field, ctl: SecretBool) = + a.csetZero(ctl) + + func `ctt _ Field _ csetOne`(a: var Field, ctl: SecretBool) = + a.csetOne(ctl) + + func `ctt _ Field _ cneg_in_place`(a: var Field, ctl: SecretBool) = + a.cneg(ctl) + + func `ctt _ Field _ cadd_in_place`(a: var Field, b: Field, ctl: SecretBool) = + a.cadd(b, ctl) + + func `ctt _ Field _ csub_in_place`(a: var Field, b: Field, ctl: SecretBool) = + a.csub(b, ctl) + + {.pop.} + + +template genBindingsFieldSqrt*(Field: untyped) = + {.push cdecl, dynlib, exportc, raises: [].} # No exceptions allowed + + func `ctt _ Field _ is_square`(a: Field): SecretBool = + a.isSquare() + + func `ctt _ Field _ invsqrt`(r: var Field, a: Field) = + r.invsqrt(a) + + func `ctt _ Field _ invsqrt_in_place`(r: var Field, a: Field): SecretBool = + r.invsqrt_if_square(a) + + func `ctt _ Field _ sqrt_in_place`(a: var Field) = + a.sqrt() + + func `ctt _ Field _ sqrt_if_square_in_place`(a: var Field): SecretBool = + a.sqrt_if_square() + + func `ctt _ Field _ sqrt_invsqrt`(sqrt, invsqrt: var Field, a: Field) = + sqrt_invsqrt(sqrt, invsqrt, a) + + func `ctt _ Field _ sqrt_invsqrt_if_square`(sqrt, invsqrt: var Field, a: Field): SecretBool = + sqrt_invsqrt_if_square(sqrt, invsqrt, a) + + func `ctt _ Field _ sqrt_ratio_if_square`(r: var Field, u, v: Field): SecretBool = + r.sqrt_ratio_if_square(u, v) + + {.pop.} + + +template genBindingsExtField*(Field: untyped) = + {.push cdecl, dynlib, exportc, raises: [].} # No exceptions allowed + + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ is_eq`(a, b: Field): SecretBool = + a == b + + func `ctt _ Field _ is_zero`(a: Field): SecretBool = + a.isZero() + + func `ctt _ Field _ is_one`(a: Field): SecretBool = + a.isOne() + + func `ctt _ Field _ is_minus_one`(a: Field): SecretBool = + a.isMinusOne() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ set_zero`(a: var Field) = + a.setZero() + + func `ctt _ Field _ set_one`(a: var Field) = + a.setOne() + + func `ctt _ Field _ set_minus_one`(a: var Field) = + a.setMinusOne() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ neg`(a: var Field) = + a.neg() + + func `ctt _ Field _ sum`(r: var Field, a, b: Field) = + r.sum(a,b) + + func `ctt _ Field _ add_in_place`(a: var Field, b: Field) = + a += b + + func `ctt _ Field _ diff`(r: var Field, a, b: Field) = + r.diff(a,b) + + func `ctt _ Field _ sub_in_place`(a: var Field, b: Field) = + a -= b + + func `ctt _ Field _ double`(r: var Field, a: Field) = + r.double(a) + + func `ctt _ Field _ double_in_place`(a: var Field) = + a.double() + + func `ctt _ Field _ conj`(r: var Field, a: Field) = + r.conj(a) + + func `ctt _ Field _ conj_in_place`(a: var Field) = + a.conj() + + func `ctt _ Field _ conjneg`(r: var Field, a: Field) = + r.conjneg(a) + + func `ctt _ Field _ conjneg_in_place`(a: var Field) = + a.conjneg() + + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ prod`(r: var Field, a, b: Field) = + r.prod(a,b) + + func `ctt _ Field _ mul_in_place`(a: var Field, b: Field) = + a *= b + + func `ctt _ Field _ square`(r: var Field, a: Field) = + r.square(a) + + func `ctt _ Field _ square_in_place`(a: var Field) = + a.square() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ div2`(a: var Field) = + a.div2() + + func `ctt _ Field _ inv`(r: var Field, a: Field) = + r.inv(a) + + func `ctt _ Field _ inv_in_place`(a: var Field) = + a.inv() + # -------------------------------------------------------------------------------------- + func `ctt _ Field _ csetZero`(a: var Field, ctl: SecretBool) = + a.csetZero(ctl) + + func `ctt _ Field _ csetOne`(a: var Field, ctl: SecretBool) = + a.csetOne(ctl) + + func `ctt _ Field _ cneg_in_place`(a: var Field, ctl: SecretBool) = + a.cneg(ctl) + + func `ctt _ Field _ cadd_in_place`(a: var Field, b: Field, ctl: SecretBool) = + a.cadd(b, ctl) + + func `ctt _ Field _ csub_in_place`(a: var Field, b: Field, ctl: SecretBool) = + a.csub(b, ctl) + + {.pop.} + +template genBindingsExtFieldSqrt*(Field: untyped) = + {.push cdecl, dynlib, exportc, raises: [].} # No exceptions allowed + + func `ctt _ Field _ is_square`(a: Field): SecretBool = + a.isSquare() + + func `ctt _ Field _ sqrt_in_place`(a: var Field) = + a.sqrt() + + func `ctt _ Field _ sqrt_if_square_in_place`(a: var Field): SecretBool = + a.sqrt_if_square() + + {.pop} + +template genBindings_EC_ShortW_Affine*(ECP, Field: untyped) = + {.push cdecl, dynlib, exportc, raises: [].} # No exceptions allowed + + # -------------------------------------------------------------------------------------- + func `ctt _ ECP _ is_eq`(P, Q: ECP): SecretBool = + P == Q + + func `ctt _ ECP _ is_inf`(P: ECP): SecretBool = + P.isInf() + + func `ctt _ ECP _ set_inf`(P: var ECP) = + P.setInf() + + func `ctt _ ECP _ ccopy`(P: var ECP, Q: ECP, ctl: SecretBool) = + P.ccopy(Q, ctl) + + func `ctt _ ECP _ is_on_curve`(x, y: Field): SecretBool = + isOnCurve(x, y, ECP.G) + + func `ctt _ ECP _ neg`(P: var ECP, Q: ECP) = + P.neg(Q) + + func `ctt _ ECP _ neg_in_place`(P: var ECP) = + P.neg() + + {.pop.} + +template genBindings_EC_ShortW_NonAffine*(ECP, ECP_Aff, Field: untyped) = + {.push cdecl, dynlib, exportc, raises: [].} # No exceptions allowed + + # -------------------------------------------------------------------------------------- + func `ctt _ ECP _ is_eq`(P, Q: ECP): SecretBool = + P == Q + + func `ctt _ ECP _ is_inf`(P: ECP): SecretBool = + P.isInf() + + func `ctt _ ECP _ set_inf`(P: var ECP) = + P.setInf() + + func `ctt _ ECP _ ccopy`(P: var ECP, Q: ECP, ctl: SecretBool) = + P.ccopy(Q, ctl) + + func `ctt _ ECP _ neg`(P: var ECP, Q: ECP) = + P.neg(Q) + + func `ctt _ ECP _ neg_in_place`(P: var ECP) = + P.neg() + + func `ctt _ ECP _ cneg_in_place`(P: var ECP, ctl: SecretBool) = + P.neg() + + func `ctt _ ECP _ sum`(r: var ECP, P, Q: ECP) = + r.sum(P, Q) + + func `ctt _ ECP _ add_in_place`(P: var ECP, Q: ECP) = + P += Q + + func `ctt _ ECP _ diff`(r: var ECP, P, Q: ECP) = + r.diff(P, Q) + + func `ctt _ ECP _ double`(r: var ECP, P: ECP) = + r.double(P) + + func `ctt _ ECP _ double_in_place`(P: var ECP) = + P.double() + + func `ctt _ ECP _ affine`(dst: var ECP_Aff, src: ECP) = + dst.affine(src) + + func `ctt _ ECP _ from_affine`(dst: var ECP, src: ECP_Aff) = + dst.fromAffine(src) + + {.pop.} \ No newline at end of file diff --git a/bindings/gen_header.nim b/bindings/gen_header.nim new file mode 100644 index 0000000..d48d126 --- /dev/null +++ b/bindings/gen_header.nim @@ -0,0 +1,215 @@ +# 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 + std/[strformat, strutils, macros, strtabs] + +# Overview +# ------------------------------------------------------------ +# +# This files provides template for C header generation + +proc genHeaderLicense*(): string = + """ +/* + * 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. + */ +""" + +proc genHeader*(name, body: string): string = + &""" +#ifndef __CTT_H_{name}__ +#define __CTT_H_{name}__ + +{body} + +#endif +""" + +proc genCpp*(body: string): string {.raises:[ValueError].} = + &""" +#ifdef __cplusplus +extern "C" {{ +#endif + +{body} + +#ifdef __cplusplus +}} +#endif +""" + +# Types' declarations +# ------------------------------------------- + +proc genBuiltinsTypes*(): string = + """ +#if defined{__SIZE_TYPE__} && defined(__PTRDIFF_TYPE__) +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#else +#include +#endif + +#if defined(__UINT8_TYPE__) && defined(__UINT32_TYPE__) && defined(__UINT64_TYPE__) +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; +#else +#include +#endif +""" + +proc genCttBaseTypedef*(): string = + """ +typedef size_t secret_word; +typedef size_t secret_bool; +typedef uint8_t byte; +""" + +proc genWordsRequired*(): string = + """ +#define WordBitWidth (sizeof(secret_word)*8) +#define words_required(bits) ((bits+WordBitWidth-1)/WordBitWidth) +""" + +proc genField*(name: string, bits: int): string = + &"typedef struct {{ secret_word limbs[words_required({bits})]; }} {name};" + +proc genExtField*(name: string, degree: int, basename: string): string = + &"typedef struct {{ {basename} c[{degree}]; }} {name};" + +proc genEllipticCurvePoint*(name, coords, basename: string): string = + &"typedef struct {{ {basename} {coords}; }} {name};" + +# Subroutines' declarations +# ------------------------------------------- + +let TypeMap {.compileTime.} = newStringTable({ + "SecretBool": "secret_bool", + "SecretWord": "secret_word" +}) + +proc toCrettype(node: NimNode): string = + node.expectKind({nnkEmpty, nnkSym}) + if node.kind == nnkEmpty: + # align iwth secret_bool and secret_word + "void " + else: + TypeMap[$node] + +proc toCtrivialParam(name: string, typ: NimNode): string = + typ.expectKind({nnkVarTy, nnkSym}) + + let isVar = typ.kind == nnkVarTy + let constify = if isVar: "" + else: "const " + + let sTyp = if isVar: $typ[0] + else: $typ + + if sTyp in TypeMap: + # Pass-by-value + constify & TypeMap[sTyp] & " " & name + else: + # Pass-by-reference + constify & sTyp & "* " & name + +proc toCparam(name: string, typ: NimNode): string = + typ.expectKind({nnkVarTy, nnkCall, nnkSym}) + + if typ.kind == nnkCall: + typ[0].expectKind(nnkOpenSymChoice) + doAssert typ[0][0].eqIdent"[]" + doAssert typ[1].eqIdent"openArray" + let sTyp = $typ[2] + if sTyp in TypeMap: + "const " & TypeMap[sTyp] & " " & name & "[], ptrdiff_t " & name & "_len" + else: + "const " & sTyp & " " & name & "[], ptrdiff_t " & name & "_len" + elif typ.kind == nnkVarTy and typ[0].kind == nnkCall: + typ[0][0].expectKind(nnkOpenSymChoice) + doAssert typ[0][0][0].eqIdent"[]" + doAssert typ[0][1].eqIdent"openArray" + let sTyp = $typ[0][2] + if sTyp in TypeMap: + TypeMap[sTyp] & " " & name & "[], ptrdiff_t " & name & "_len" + else: + sTyp & " " & name & "[], ptrdiff_t " & name & "_len" + else: + toCtrivialParam(name, typ) + +macro collectBindings*(cBindingsStr: untyped, body: typed): untyped = + ## Collect function definitions from a generator template + + body.expectKind(nnkStmtList) + + var cBindings: string + + for generator in body: + generator.expectKind(nnkStmtList) + cBindings &= "\n" + for fnDef in generator: + if fnDef.kind notin {nnkProcDef, nnkFuncDef}: + continue + + cBindings &= "\n" + # rettype name(pType0* pName0, pType1* pName1, ...); + cBindings &= fnDef.params[0].toCrettype() + cBindings &= ' ' + cBindings &= $fnDef.name + cBindings &= '(' + for i in 1 ..< fnDef.params.len: + if i != 1: cBindings &= ", " + + let paramDef = fnDef.params[i] + paramDef.expectKind(nnkIdentDefs) + let pType = paramDef[^2] + # No default value + paramDef[^1].expectKind(nnkEmpty) + + for j in 0 ..< paramDef.len - 2: + if j != 0: cBindings &= ", " + var name = $paramDef[j] + cBindings &= toCparam(name.split('`')[0], pType) + + cBindings &= ");" + + if defined(CttGenerateHeaders): + result = newConstStmt(cBindingsStr, newLit cBindings) + else: + result = body + + +# Nim internals +# ------------------------------------------- + +proc declNimMain*(libName: string): string = + ## Create the NimMain function. + ## It initializes: + ## - the Nim runtime if seqs, strings or heap-allocated types are used, + ## this is the case only if Constantine is multithreaded. + ## - runtime CPU features detection + ## + ## Assumes library is compiled with --nimMainPrefix:ctt_{libName}_ + &""" + +/* + * Initializes the library: + * - the Nim runtime if heap-allocated types are used, + * this is the case only if Constantine is multithreaded. + * - runtime CPU features detection + */ +void ctt_{libName}_NimMain(void); +""" \ No newline at end of file diff --git a/bindings/generated/constantine_bls12_381.h b/bindings/generated/constantine_bls12_381.h new file mode 100644 index 0000000..1c7251e --- /dev/null +++ b/bindings/generated/constantine_bls12_381.h @@ -0,0 +1,246 @@ +/* + * 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. + */ +#ifndef __CTT_H_BLS12381__ +#define __CTT_H_BLS12381__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined{__SIZE_TYPE__} && defined(__PTRDIFF_TYPE__) +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#else +#include +#endif + +#if defined(__UINT8_TYPE__) && defined(__UINT32_TYPE__) && defined(__UINT64_TYPE__) +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; +#else +#include +#endif + +typedef size_t secret_word; +typedef size_t secret_bool; +typedef uint8_t byte; + +#define WordBitWidth (sizeof(secret_word)*8) +#define words_required(bits) ((bits+WordBitWidth-1)/WordBitWidth) + +typedef struct { secret_word limbs[words_required(255)]; } bls12381_fr; +typedef struct { secret_word limbs[words_required(381)]; } bls12381_fp; +typedef struct { bls12381_fp c[2]; } bls12381_fp2; +typedef struct { bls12381_fp x, y; } bls12381_ec_g1_aff; +typedef struct { bls12381_fp x, y, z; } bls12381_ec_g1_jac; +typedef struct { bls12381_fp x, y, z; } bls12381_ec_g1_prj; +typedef struct { bls12381_fp2 x, y; } bls12381_ec_g2_aff; +typedef struct { bls12381_fp2 x, y, z; } bls12381_ec_g2_jac; +typedef struct { bls12381_fp2 x, y, z; } bls12381_ec_g2_prj; + + +void ctt_bls12381_fr_unmarshalBE(bls12381_fr* dst, const byte src[], ptrdiff_t src_len); +void ctt_bls12381_fr_marshalBE(byte dst[], ptrdiff_t dst_len, const bls12381_fr* src); +secret_bool ctt_bls12381_fr_is_eq(const bls12381_fr* a, const bls12381_fr* b); +secret_bool ctt_bls12381_fr_is_zero(const bls12381_fr* a); +secret_bool ctt_bls12381_fr_is_one(const bls12381_fr* a); +secret_bool ctt_bls12381_fr_is_minus_one(const bls12381_fr* a); +void ctt_bls12381_fr_set_zero(bls12381_fr* a); +void ctt_bls12381_fr_set_one(bls12381_fr* a); +void ctt_bls12381_fr_set_minus_one(bls12381_fr* a); +void ctt_bls12381_fr_neg(bls12381_fr* a); +void ctt_bls12381_fr_sum(bls12381_fr* r, const bls12381_fr* a, const bls12381_fr* b); +void ctt_bls12381_fr_add_in_place(bls12381_fr* a, const bls12381_fr* b); +void ctt_bls12381_fr_diff(bls12381_fr* r, const bls12381_fr* a, const bls12381_fr* b); +void ctt_bls12381_fr_sub_in_place(bls12381_fr* a, const bls12381_fr* b); +void ctt_bls12381_fr_double(bls12381_fr* r, const bls12381_fr* a); +void ctt_bls12381_fr_double_in_place(bls12381_fr* a); +void ctt_bls12381_fr_prod(bls12381_fr* r, const bls12381_fr* a, const bls12381_fr* b); +void ctt_bls12381_fr_mul_in_place(bls12381_fr* a, const bls12381_fr* b); +void ctt_bls12381_fr_square(bls12381_fr* r, const bls12381_fr* a); +void ctt_bls12381_fr_square_in_place(bls12381_fr* a); +void ctt_bls12381_fr_div2(bls12381_fr* a); +void ctt_bls12381_fr_inv(bls12381_fr* r, const bls12381_fr* a); +void ctt_bls12381_fr_inv_in_place(bls12381_fr* a); +void ctt_bls12381_fr_ccopy(bls12381_fr* a, const bls12381_fr* b, const secret_bool ctl); +void ctt_bls12381_fr_cswap(bls12381_fr* a, bls12381_fr* b, const secret_bool ctl); +void ctt_bls12381_fr_csetZero(bls12381_fr* a, const secret_bool ctl); +void ctt_bls12381_fr_csetOne(bls12381_fr* a, const secret_bool ctl); +void ctt_bls12381_fr_cneg_in_place(bls12381_fr* a, const secret_bool ctl); +void ctt_bls12381_fr_cadd_in_place(bls12381_fr* a, const bls12381_fr* b, const secret_bool ctl); +void ctt_bls12381_fr_csub_in_place(bls12381_fr* a, const bls12381_fr* b, const secret_bool ctl); + +void ctt_bls12381_fp_unmarshalBE(bls12381_fp* dst, const byte src[], ptrdiff_t src_len); +void ctt_bls12381_fp_marshalBE(byte dst[], ptrdiff_t dst_len, const bls12381_fp* src); +secret_bool ctt_bls12381_fp_is_eq(const bls12381_fp* a, const bls12381_fp* b); +secret_bool ctt_bls12381_fp_is_zero(const bls12381_fp* a); +secret_bool ctt_bls12381_fp_is_one(const bls12381_fp* a); +secret_bool ctt_bls12381_fp_is_minus_one(const bls12381_fp* a); +void ctt_bls12381_fp_set_zero(bls12381_fp* a); +void ctt_bls12381_fp_set_one(bls12381_fp* a); +void ctt_bls12381_fp_set_minus_one(bls12381_fp* a); +void ctt_bls12381_fp_neg(bls12381_fp* a); +void ctt_bls12381_fp_sum(bls12381_fp* r, const bls12381_fp* a, const bls12381_fp* b); +void ctt_bls12381_fp_add_in_place(bls12381_fp* a, const bls12381_fp* b); +void ctt_bls12381_fp_diff(bls12381_fp* r, const bls12381_fp* a, const bls12381_fp* b); +void ctt_bls12381_fp_sub_in_place(bls12381_fp* a, const bls12381_fp* b); +void ctt_bls12381_fp_double(bls12381_fp* r, const bls12381_fp* a); +void ctt_bls12381_fp_double_in_place(bls12381_fp* a); +void ctt_bls12381_fp_prod(bls12381_fp* r, const bls12381_fp* a, const bls12381_fp* b); +void ctt_bls12381_fp_mul_in_place(bls12381_fp* a, const bls12381_fp* b); +void ctt_bls12381_fp_square(bls12381_fp* r, const bls12381_fp* a); +void ctt_bls12381_fp_square_in_place(bls12381_fp* a); +void ctt_bls12381_fp_div2(bls12381_fp* a); +void ctt_bls12381_fp_inv(bls12381_fp* r, const bls12381_fp* a); +void ctt_bls12381_fp_inv_in_place(bls12381_fp* a); +void ctt_bls12381_fp_ccopy(bls12381_fp* a, const bls12381_fp* b, const secret_bool ctl); +void ctt_bls12381_fp_cswap(bls12381_fp* a, bls12381_fp* b, const secret_bool ctl); +void ctt_bls12381_fp_csetZero(bls12381_fp* a, const secret_bool ctl); +void ctt_bls12381_fp_csetOne(bls12381_fp* a, const secret_bool ctl); +void ctt_bls12381_fp_cneg_in_place(bls12381_fp* a, const secret_bool ctl); +void ctt_bls12381_fp_cadd_in_place(bls12381_fp* a, const bls12381_fp* b, const secret_bool ctl); +void ctt_bls12381_fp_csub_in_place(bls12381_fp* a, const bls12381_fp* b, const secret_bool ctl); + +secret_bool ctt_bls12381_fp_is_square(const bls12381_fp* a); +void ctt_bls12381_fp_invsqrt(bls12381_fp* r, const bls12381_fp* a); +secret_bool ctt_bls12381_fp_invsqrt_in_place(bls12381_fp* r, const bls12381_fp* a); +void ctt_bls12381_fp_sqrt_in_place(bls12381_fp* a); +secret_bool ctt_bls12381_fp_sqrt_if_square_in_place(bls12381_fp* a); +void ctt_bls12381_fp_sqrt_invsqrt(bls12381_fp* sqrt, bls12381_fp* invsqrt, const bls12381_fp* a); +secret_bool ctt_bls12381_fp_sqrt_invsqrt_if_square(bls12381_fp* sqrt, bls12381_fp* invsqrt, const bls12381_fp* a); +secret_bool ctt_bls12381_fp_sqrt_ratio_if_square(bls12381_fp* r, const bls12381_fp* u, const bls12381_fp* v); + +secret_bool ctt_bls12381_fp2_is_eq(const bls12381_fp2* a, const bls12381_fp2* b); +secret_bool ctt_bls12381_fp2_is_zero(const bls12381_fp2* a); +secret_bool ctt_bls12381_fp2_is_one(const bls12381_fp2* a); +secret_bool ctt_bls12381_fp2_is_minus_one(const bls12381_fp2* a); +void ctt_bls12381_fp2_set_zero(bls12381_fp2* a); +void ctt_bls12381_fp2_set_one(bls12381_fp2* a); +void ctt_bls12381_fp2_set_minus_one(bls12381_fp2* a); +void ctt_bls12381_fp2_neg(bls12381_fp2* a); +void ctt_bls12381_fp2_sum(bls12381_fp2* r, const bls12381_fp2* a, const bls12381_fp2* b); +void ctt_bls12381_fp2_add_in_place(bls12381_fp2* a, const bls12381_fp2* b); +void ctt_bls12381_fp2_diff(bls12381_fp2* r, const bls12381_fp2* a, const bls12381_fp2* b); +void ctt_bls12381_fp2_sub_in_place(bls12381_fp2* a, const bls12381_fp2* b); +void ctt_bls12381_fp2_double(bls12381_fp2* r, const bls12381_fp2* a); +void ctt_bls12381_fp2_double_in_place(bls12381_fp2* a); +void ctt_bls12381_fp2_conj(bls12381_fp2* r, const bls12381_fp2* a); +void ctt_bls12381_fp2_conj_in_place(bls12381_fp2* a); +void ctt_bls12381_fp2_conjneg(bls12381_fp2* r, const bls12381_fp2* a); +void ctt_bls12381_fp2_conjneg_in_place(bls12381_fp2* a); +void ctt_bls12381_fp2_prod(bls12381_fp2* r, const bls12381_fp2* a, const bls12381_fp2* b); +void ctt_bls12381_fp2_mul_in_place(bls12381_fp2* a, const bls12381_fp2* b); +void ctt_bls12381_fp2_square(bls12381_fp2* r, const bls12381_fp2* a); +void ctt_bls12381_fp2_square_in_place(bls12381_fp2* a); +void ctt_bls12381_fp2_div2(bls12381_fp2* a); +void ctt_bls12381_fp2_inv(bls12381_fp2* r, const bls12381_fp2* a); +void ctt_bls12381_fp2_inv_in_place(bls12381_fp2* a); +void ctt_bls12381_fp2_csetZero(bls12381_fp2* a, const secret_bool ctl); +void ctt_bls12381_fp2_csetOne(bls12381_fp2* a, const secret_bool ctl); +void ctt_bls12381_fp2_cneg_in_place(bls12381_fp2* a, const secret_bool ctl); +void ctt_bls12381_fp2_cadd_in_place(bls12381_fp2* a, const bls12381_fp2* b, const secret_bool ctl); +void ctt_bls12381_fp2_csub_in_place(bls12381_fp2* a, const bls12381_fp2* b, const secret_bool ctl); + +secret_bool ctt_bls12381_fp2_is_square(const bls12381_fp2* a); +void ctt_bls12381_fp2_sqrt_in_place(bls12381_fp2* a); +secret_bool ctt_bls12381_fp2_sqrt_if_square_in_place(bls12381_fp2* a); + +secret_bool ctt_bls12381_ec_g1_aff_is_eq(const bls12381_ec_g1_aff* P, const bls12381_ec_g1_aff* Q); +secret_bool ctt_bls12381_ec_g1_aff_is_inf(const bls12381_ec_g1_aff* P); +void ctt_bls12381_ec_g1_aff_set_inf(bls12381_ec_g1_aff* P); +void ctt_bls12381_ec_g1_aff_ccopy(bls12381_ec_g1_aff* P, const bls12381_ec_g1_aff* Q, const secret_bool ctl); +secret_bool ctt_bls12381_ec_g1_aff_is_on_curve(const bls12381_fp* x, const bls12381_fp* y); +void ctt_bls12381_ec_g1_aff_neg(bls12381_ec_g1_aff* P, const bls12381_ec_g1_aff* Q); +void ctt_bls12381_ec_g1_aff_neg_in_place(bls12381_ec_g1_aff* P); + +secret_bool ctt_bls12381_ec_g1_jac_is_eq(const bls12381_ec_g1_jac* P, const bls12381_ec_g1_jac* Q); +secret_bool ctt_bls12381_ec_g1_jac_is_inf(const bls12381_ec_g1_jac* P); +void ctt_bls12381_ec_g1_jac_set_inf(bls12381_ec_g1_jac* P); +void ctt_bls12381_ec_g1_jac_ccopy(bls12381_ec_g1_jac* P, const bls12381_ec_g1_jac* Q, const secret_bool ctl); +void ctt_bls12381_ec_g1_jac_neg(bls12381_ec_g1_jac* P, const bls12381_ec_g1_jac* Q); +void ctt_bls12381_ec_g1_jac_neg_in_place(bls12381_ec_g1_jac* P); +void ctt_bls12381_ec_g1_jac_cneg_in_place(bls12381_ec_g1_jac* P, const secret_bool ctl); +void ctt_bls12381_ec_g1_jac_sum(bls12381_ec_g1_jac* r, const bls12381_ec_g1_jac* P, const bls12381_ec_g1_jac* Q); +void ctt_bls12381_ec_g1_jac_add_in_place(bls12381_ec_g1_jac* P, const bls12381_ec_g1_jac* Q); +void ctt_bls12381_ec_g1_jac_diff(bls12381_ec_g1_jac* r, const bls12381_ec_g1_jac* P, const bls12381_ec_g1_jac* Q); +void ctt_bls12381_ec_g1_jac_double(bls12381_ec_g1_jac* r, const bls12381_ec_g1_jac* P); +void ctt_bls12381_ec_g1_jac_double_in_place(bls12381_ec_g1_jac* P); +void ctt_bls12381_ec_g1_jac_affine(bls12381_ec_g1_aff* dst, const bls12381_ec_g1_jac* src); +void ctt_bls12381_ec_g1_jac_from_affine(bls12381_ec_g1_jac* dst, const bls12381_ec_g1_aff* src); + +secret_bool ctt_bls12381_ec_g1_prj_is_eq(const bls12381_ec_g1_prj* P, const bls12381_ec_g1_prj* Q); +secret_bool ctt_bls12381_ec_g1_prj_is_inf(const bls12381_ec_g1_prj* P); +void ctt_bls12381_ec_g1_prj_set_inf(bls12381_ec_g1_prj* P); +void ctt_bls12381_ec_g1_prj_ccopy(bls12381_ec_g1_prj* P, const bls12381_ec_g1_prj* Q, const secret_bool ctl); +void ctt_bls12381_ec_g1_prj_neg(bls12381_ec_g1_prj* P, const bls12381_ec_g1_prj* Q); +void ctt_bls12381_ec_g1_prj_neg_in_place(bls12381_ec_g1_prj* P); +void ctt_bls12381_ec_g1_prj_cneg_in_place(bls12381_ec_g1_prj* P, const secret_bool ctl); +void ctt_bls12381_ec_g1_prj_sum(bls12381_ec_g1_prj* r, const bls12381_ec_g1_prj* P, const bls12381_ec_g1_prj* Q); +void ctt_bls12381_ec_g1_prj_add_in_place(bls12381_ec_g1_prj* P, const bls12381_ec_g1_prj* Q); +void ctt_bls12381_ec_g1_prj_diff(bls12381_ec_g1_prj* r, const bls12381_ec_g1_prj* P, const bls12381_ec_g1_prj* Q); +void ctt_bls12381_ec_g1_prj_double(bls12381_ec_g1_prj* r, const bls12381_ec_g1_prj* P); +void ctt_bls12381_ec_g1_prj_double_in_place(bls12381_ec_g1_prj* P); +void ctt_bls12381_ec_g1_prj_affine(bls12381_ec_g1_aff* dst, const bls12381_ec_g1_prj* src); +void ctt_bls12381_ec_g1_prj_from_affine(bls12381_ec_g1_prj* dst, const bls12381_ec_g1_aff* src); + +secret_bool ctt_bls12381_ec_g2_aff_is_eq(const bls12381_ec_g2_aff* P, const bls12381_ec_g2_aff* Q); +secret_bool ctt_bls12381_ec_g2_aff_is_inf(const bls12381_ec_g2_aff* P); +void ctt_bls12381_ec_g2_aff_set_inf(bls12381_ec_g2_aff* P); +void ctt_bls12381_ec_g2_aff_ccopy(bls12381_ec_g2_aff* P, const bls12381_ec_g2_aff* Q, const secret_bool ctl); +secret_bool ctt_bls12381_ec_g2_aff_is_on_curve(const bls12381_fp2* x, const bls12381_fp2* y); +void ctt_bls12381_ec_g2_aff_neg(bls12381_ec_g2_aff* P, const bls12381_ec_g2_aff* Q); +void ctt_bls12381_ec_g2_aff_neg_in_place(bls12381_ec_g2_aff* P); + +secret_bool ctt_bls12381_ec_g2_jac_is_eq(const bls12381_ec_g2_jac* P, const bls12381_ec_g2_jac* Q); +secret_bool ctt_bls12381_ec_g2_jac_is_inf(const bls12381_ec_g2_jac* P); +void ctt_bls12381_ec_g2_jac_set_inf(bls12381_ec_g2_jac* P); +void ctt_bls12381_ec_g2_jac_ccopy(bls12381_ec_g2_jac* P, const bls12381_ec_g2_jac* Q, const secret_bool ctl); +void ctt_bls12381_ec_g2_jac_neg(bls12381_ec_g2_jac* P, const bls12381_ec_g2_jac* Q); +void ctt_bls12381_ec_g2_jac_neg_in_place(bls12381_ec_g2_jac* P); +void ctt_bls12381_ec_g2_jac_cneg_in_place(bls12381_ec_g2_jac* P, const secret_bool ctl); +void ctt_bls12381_ec_g2_jac_sum(bls12381_ec_g2_jac* r, const bls12381_ec_g2_jac* P, const bls12381_ec_g2_jac* Q); +void ctt_bls12381_ec_g2_jac_add_in_place(bls12381_ec_g2_jac* P, const bls12381_ec_g2_jac* Q); +void ctt_bls12381_ec_g2_jac_diff(bls12381_ec_g2_jac* r, const bls12381_ec_g2_jac* P, const bls12381_ec_g2_jac* Q); +void ctt_bls12381_ec_g2_jac_double(bls12381_ec_g2_jac* r, const bls12381_ec_g2_jac* P); +void ctt_bls12381_ec_g2_jac_double_in_place(bls12381_ec_g2_jac* P); +void ctt_bls12381_ec_g2_jac_affine(bls12381_ec_g2_aff* dst, const bls12381_ec_g2_jac* src); +void ctt_bls12381_ec_g2_jac_from_affine(bls12381_ec_g2_jac* dst, const bls12381_ec_g2_aff* src); + +secret_bool ctt_bls12381_ec_g2_prj_is_eq(const bls12381_ec_g2_prj* P, const bls12381_ec_g2_prj* Q); +secret_bool ctt_bls12381_ec_g2_prj_is_inf(const bls12381_ec_g2_prj* P); +void ctt_bls12381_ec_g2_prj_set_inf(bls12381_ec_g2_prj* P); +void ctt_bls12381_ec_g2_prj_ccopy(bls12381_ec_g2_prj* P, const bls12381_ec_g2_prj* Q, const secret_bool ctl); +void ctt_bls12381_ec_g2_prj_neg(bls12381_ec_g2_prj* P, const bls12381_ec_g2_prj* Q); +void ctt_bls12381_ec_g2_prj_neg_in_place(bls12381_ec_g2_prj* P); +void ctt_bls12381_ec_g2_prj_cneg_in_place(bls12381_ec_g2_prj* P, const secret_bool ctl); +void ctt_bls12381_ec_g2_prj_sum(bls12381_ec_g2_prj* r, const bls12381_ec_g2_prj* P, const bls12381_ec_g2_prj* Q); +void ctt_bls12381_ec_g2_prj_add_in_place(bls12381_ec_g2_prj* P, const bls12381_ec_g2_prj* Q); +void ctt_bls12381_ec_g2_prj_diff(bls12381_ec_g2_prj* r, const bls12381_ec_g2_prj* P, const bls12381_ec_g2_prj* Q); +void ctt_bls12381_ec_g2_prj_double(bls12381_ec_g2_prj* r, const bls12381_ec_g2_prj* P); +void ctt_bls12381_ec_g2_prj_double_in_place(bls12381_ec_g2_prj* P); +void ctt_bls12381_ec_g2_prj_affine(bls12381_ec_g2_aff* dst, const bls12381_ec_g2_prj* src); +void ctt_bls12381_ec_g2_prj_from_affine(bls12381_ec_g2_prj* dst, const bls12381_ec_g2_aff* src); + +/* + * Initializes the library: + * - the Nim runtime if heap-allocated types are used, + * this is the case only if Constantine is multithreaded. + * - runtime CPU features detection + */ +void ctt_bls12381_NimMain(void); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/bindings/generated/constantine_pasta.h b/bindings/generated/constantine_pasta.h new file mode 100644 index 0000000..c76b7bb --- /dev/null +++ b/bindings/generated/constantine_pasta.h @@ -0,0 +1,223 @@ +/* + * 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. + */ +#ifndef __CTT_H_PASTA__ +#define __CTT_H_PASTA__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined{__SIZE_TYPE__} && defined(__PTRDIFF_TYPE__) +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#else +#include +#endif + +#if defined(__UINT8_TYPE__) && defined(__UINT32_TYPE__) && defined(__UINT64_TYPE__) +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; +#else +#include +#endif + +typedef size_t secret_word; +typedef size_t secret_bool; +typedef uint8_t byte; + +#define WordBitWidth (sizeof(secret_word)*8) +#define words_required(bits) ((bits+WordBitWidth-1)/WordBitWidth) + +typedef struct { secret_word limbs[words_required(255)]; } pallas_fr; +typedef struct { secret_word limbs[words_required(255)]; } pallas_fp; +typedef struct { secret_word limbs[words_required(255)]; } vesta_fr; +typedef struct { secret_word limbs[words_required(255)]; } vesta_fp; +typedef struct { pallas_fp x, y; } pallas_ec_aff; +typedef struct { pallas_fp x, y, z; } pallas_ec_jac; +typedef struct { pallas_fp x, y, z; } pallas_ec_prj; +typedef struct { vesta_fp x, y; } vesta_ec_aff; +typedef struct { vesta_fp x, y, z; } vesta_ec_jac; +typedef struct { vesta_fp x, y, z; } vesta_ec_prj; + + +void ctt_pallas_fr_unmarshalBE(pallas_fr* dst, const byte src[], ptrdiff_t src_len); +void ctt_pallas_fr_marshalBE(byte dst[], ptrdiff_t dst_len, const pallas_fr* src); +secret_bool ctt_pallas_fr_is_eq(const pallas_fr* a, const pallas_fr* b); +secret_bool ctt_pallas_fr_is_zero(const pallas_fr* a); +secret_bool ctt_pallas_fr_is_one(const pallas_fr* a); +secret_bool ctt_pallas_fr_is_minus_one(const pallas_fr* a); +void ctt_pallas_fr_set_zero(pallas_fr* a); +void ctt_pallas_fr_set_one(pallas_fr* a); +void ctt_pallas_fr_set_minus_one(pallas_fr* a); +void ctt_pallas_fr_neg(pallas_fr* a); +void ctt_pallas_fr_sum(pallas_fr* r, const pallas_fr* a, const pallas_fr* b); +void ctt_pallas_fr_add_in_place(pallas_fr* a, const pallas_fr* b); +void ctt_pallas_fr_diff(pallas_fr* r, const pallas_fr* a, const pallas_fr* b); +void ctt_pallas_fr_sub_in_place(pallas_fr* a, const pallas_fr* b); +void ctt_pallas_fr_double(pallas_fr* r, const pallas_fr* a); +void ctt_pallas_fr_double_in_place(pallas_fr* a); +void ctt_pallas_fr_prod(pallas_fr* r, const pallas_fr* a, const pallas_fr* b); +void ctt_pallas_fr_mul_in_place(pallas_fr* a, const pallas_fr* b); +void ctt_pallas_fr_square(pallas_fr* r, const pallas_fr* a); +void ctt_pallas_fr_square_in_place(pallas_fr* a); +void ctt_pallas_fr_div2(pallas_fr* a); +void ctt_pallas_fr_inv(pallas_fr* r, const pallas_fr* a); +void ctt_pallas_fr_inv_in_place(pallas_fr* a); +void ctt_pallas_fr_ccopy(pallas_fr* a, const pallas_fr* b, const secret_bool ctl); +void ctt_pallas_fr_cswap(pallas_fr* a, pallas_fr* b, const secret_bool ctl); +void ctt_pallas_fr_csetZero(pallas_fr* a, const secret_bool ctl); +void ctt_pallas_fr_csetOne(pallas_fr* a, const secret_bool ctl); +void ctt_pallas_fr_cneg_in_place(pallas_fr* a, const secret_bool ctl); +void ctt_pallas_fr_cadd_in_place(pallas_fr* a, const pallas_fr* b, const secret_bool ctl); +void ctt_pallas_fr_csub_in_place(pallas_fr* a, const pallas_fr* b, const secret_bool ctl); + +void ctt_pallas_fp_unmarshalBE(pallas_fp* dst, const byte src[], ptrdiff_t src_len); +void ctt_pallas_fp_marshalBE(byte dst[], ptrdiff_t dst_len, const pallas_fp* src); +secret_bool ctt_pallas_fp_is_eq(const pallas_fp* a, const pallas_fp* b); +secret_bool ctt_pallas_fp_is_zero(const pallas_fp* a); +secret_bool ctt_pallas_fp_is_one(const pallas_fp* a); +secret_bool ctt_pallas_fp_is_minus_one(const pallas_fp* a); +void ctt_pallas_fp_set_zero(pallas_fp* a); +void ctt_pallas_fp_set_one(pallas_fp* a); +void ctt_pallas_fp_set_minus_one(pallas_fp* a); +void ctt_pallas_fp_neg(pallas_fp* a); +void ctt_pallas_fp_sum(pallas_fp* r, const pallas_fp* a, const pallas_fp* b); +void ctt_pallas_fp_add_in_place(pallas_fp* a, const pallas_fp* b); +void ctt_pallas_fp_diff(pallas_fp* r, const pallas_fp* a, const pallas_fp* b); +void ctt_pallas_fp_sub_in_place(pallas_fp* a, const pallas_fp* b); +void ctt_pallas_fp_double(pallas_fp* r, const pallas_fp* a); +void ctt_pallas_fp_double_in_place(pallas_fp* a); +void ctt_pallas_fp_prod(pallas_fp* r, const pallas_fp* a, const pallas_fp* b); +void ctt_pallas_fp_mul_in_place(pallas_fp* a, const pallas_fp* b); +void ctt_pallas_fp_square(pallas_fp* r, const pallas_fp* a); +void ctt_pallas_fp_square_in_place(pallas_fp* a); +void ctt_pallas_fp_div2(pallas_fp* a); +void ctt_pallas_fp_inv(pallas_fp* r, const pallas_fp* a); +void ctt_pallas_fp_inv_in_place(pallas_fp* a); +void ctt_pallas_fp_ccopy(pallas_fp* a, const pallas_fp* b, const secret_bool ctl); +void ctt_pallas_fp_cswap(pallas_fp* a, pallas_fp* b, const secret_bool ctl); +void ctt_pallas_fp_csetZero(pallas_fp* a, const secret_bool ctl); +void ctt_pallas_fp_csetOne(pallas_fp* a, const secret_bool ctl); +void ctt_pallas_fp_cneg_in_place(pallas_fp* a, const secret_bool ctl); +void ctt_pallas_fp_cadd_in_place(pallas_fp* a, const pallas_fp* b, const secret_bool ctl); +void ctt_pallas_fp_csub_in_place(pallas_fp* a, const pallas_fp* b, const secret_bool ctl); + +secret_bool ctt_pallas_fp_is_square(const pallas_fp* a); +void ctt_pallas_fp_invsqrt(pallas_fp* r, const pallas_fp* a); +secret_bool ctt_pallas_fp_invsqrt_in_place(pallas_fp* r, const pallas_fp* a); +void ctt_pallas_fp_sqrt_in_place(pallas_fp* a); +secret_bool ctt_pallas_fp_sqrt_if_square_in_place(pallas_fp* a); +void ctt_pallas_fp_sqrt_invsqrt(pallas_fp* sqrt, pallas_fp* invsqrt, const pallas_fp* a); +secret_bool ctt_pallas_fp_sqrt_invsqrt_if_square(pallas_fp* sqrt, pallas_fp* invsqrt, const pallas_fp* a); +secret_bool ctt_pallas_fp_sqrt_ratio_if_square(pallas_fp* r, const pallas_fp* u, const pallas_fp* v); + +void ctt_vesta_fr_unmarshalBE(vesta_fr* dst, const byte src[], ptrdiff_t src_len); +void ctt_vesta_fr_marshalBE(byte dst[], ptrdiff_t dst_len, const vesta_fr* src); +secret_bool ctt_vesta_fr_is_eq(const vesta_fr* a, const vesta_fr* b); +secret_bool ctt_vesta_fr_is_zero(const vesta_fr* a); +secret_bool ctt_vesta_fr_is_one(const vesta_fr* a); +secret_bool ctt_vesta_fr_is_minus_one(const vesta_fr* a); +void ctt_vesta_fr_set_zero(vesta_fr* a); +void ctt_vesta_fr_set_one(vesta_fr* a); +void ctt_vesta_fr_set_minus_one(vesta_fr* a); +void ctt_vesta_fr_neg(vesta_fr* a); +void ctt_vesta_fr_sum(vesta_fr* r, const vesta_fr* a, const vesta_fr* b); +void ctt_vesta_fr_add_in_place(vesta_fr* a, const vesta_fr* b); +void ctt_vesta_fr_diff(vesta_fr* r, const vesta_fr* a, const vesta_fr* b); +void ctt_vesta_fr_sub_in_place(vesta_fr* a, const vesta_fr* b); +void ctt_vesta_fr_double(vesta_fr* r, const vesta_fr* a); +void ctt_vesta_fr_double_in_place(vesta_fr* a); +void ctt_vesta_fr_prod(vesta_fr* r, const vesta_fr* a, const vesta_fr* b); +void ctt_vesta_fr_mul_in_place(vesta_fr* a, const vesta_fr* b); +void ctt_vesta_fr_square(vesta_fr* r, const vesta_fr* a); +void ctt_vesta_fr_square_in_place(vesta_fr* a); +void ctt_vesta_fr_div2(vesta_fr* a); +void ctt_vesta_fr_inv(vesta_fr* r, const vesta_fr* a); +void ctt_vesta_fr_inv_in_place(vesta_fr* a); +void ctt_vesta_fr_ccopy(vesta_fr* a, const vesta_fr* b, const secret_bool ctl); +void ctt_vesta_fr_cswap(vesta_fr* a, vesta_fr* b, const secret_bool ctl); +void ctt_vesta_fr_csetZero(vesta_fr* a, const secret_bool ctl); +void ctt_vesta_fr_csetOne(vesta_fr* a, const secret_bool ctl); +void ctt_vesta_fr_cneg_in_place(vesta_fr* a, const secret_bool ctl); +void ctt_vesta_fr_cadd_in_place(vesta_fr* a, const vesta_fr* b, const secret_bool ctl); +void ctt_vesta_fr_csub_in_place(vesta_fr* a, const vesta_fr* b, const secret_bool ctl); + +void ctt_vesta_fp_unmarshalBE(vesta_fp* dst, const byte src[], ptrdiff_t src_len); +void ctt_vesta_fp_marshalBE(byte dst[], ptrdiff_t dst_len, const vesta_fp* src); +secret_bool ctt_vesta_fp_is_eq(const vesta_fp* a, const vesta_fp* b); +secret_bool ctt_vesta_fp_is_zero(const vesta_fp* a); +secret_bool ctt_vesta_fp_is_one(const vesta_fp* a); +secret_bool ctt_vesta_fp_is_minus_one(const vesta_fp* a); +void ctt_vesta_fp_set_zero(vesta_fp* a); +void ctt_vesta_fp_set_one(vesta_fp* a); +void ctt_vesta_fp_set_minus_one(vesta_fp* a); +void ctt_vesta_fp_neg(vesta_fp* a); +void ctt_vesta_fp_sum(vesta_fp* r, const vesta_fp* a, const vesta_fp* b); +void ctt_vesta_fp_add_in_place(vesta_fp* a, const vesta_fp* b); +void ctt_vesta_fp_diff(vesta_fp* r, const vesta_fp* a, const vesta_fp* b); +void ctt_vesta_fp_sub_in_place(vesta_fp* a, const vesta_fp* b); +void ctt_vesta_fp_double(vesta_fp* r, const vesta_fp* a); +void ctt_vesta_fp_double_in_place(vesta_fp* a); +void ctt_vesta_fp_prod(vesta_fp* r, const vesta_fp* a, const vesta_fp* b); +void ctt_vesta_fp_mul_in_place(vesta_fp* a, const vesta_fp* b); +void ctt_vesta_fp_square(vesta_fp* r, const vesta_fp* a); +void ctt_vesta_fp_square_in_place(vesta_fp* a); +void ctt_vesta_fp_div2(vesta_fp* a); +void ctt_vesta_fp_inv(vesta_fp* r, const vesta_fp* a); +void ctt_vesta_fp_inv_in_place(vesta_fp* a); +void ctt_vesta_fp_ccopy(vesta_fp* a, const vesta_fp* b, const secret_bool ctl); +void ctt_vesta_fp_cswap(vesta_fp* a, vesta_fp* b, const secret_bool ctl); +void ctt_vesta_fp_csetZero(vesta_fp* a, const secret_bool ctl); +void ctt_vesta_fp_csetOne(vesta_fp* a, const secret_bool ctl); +void ctt_vesta_fp_cneg_in_place(vesta_fp* a, const secret_bool ctl); +void ctt_vesta_fp_cadd_in_place(vesta_fp* a, const vesta_fp* b, const secret_bool ctl); +void ctt_vesta_fp_csub_in_place(vesta_fp* a, const vesta_fp* b, const secret_bool ctl); + +secret_bool ctt_vesta_fp_is_square(const vesta_fp* a); +void ctt_vesta_fp_invsqrt(vesta_fp* r, const vesta_fp* a); +secret_bool ctt_vesta_fp_invsqrt_in_place(vesta_fp* r, const vesta_fp* a); +void ctt_vesta_fp_sqrt_in_place(vesta_fp* a); +secret_bool ctt_vesta_fp_sqrt_if_square_in_place(vesta_fp* a); +void ctt_vesta_fp_sqrt_invsqrt(vesta_fp* sqrt, vesta_fp* invsqrt, const vesta_fp* a); +secret_bool ctt_vesta_fp_sqrt_invsqrt_if_square(vesta_fp* sqrt, vesta_fp* invsqrt, const vesta_fp* a); +secret_bool ctt_vesta_fp_sqrt_ratio_if_square(vesta_fp* r, const vesta_fp* u, const vesta_fp* v); + +secret_bool ctt_pallas_ec_aff_is_eq(const pallas_ec_aff* P, const pallas_ec_aff* Q); +secret_bool ctt_pallas_ec_aff_is_inf(const pallas_ec_aff* P); +void ctt_pallas_ec_aff_set_inf(pallas_ec_aff* P); +void ctt_pallas_ec_aff_ccopy(pallas_ec_aff* P, const pallas_ec_aff* Q, const secret_bool ctl); +secret_bool ctt_pallas_ec_aff_is_on_curve(const pallas_fp* x, const pallas_fp* y); +void ctt_pallas_ec_aff_neg(pallas_ec_aff* P, const pallas_ec_aff* Q); +void ctt_pallas_ec_aff_neg_in_place(pallas_ec_aff* P); + +secret_bool ctt_vesta_ec_aff_is_eq(const vesta_ec_aff* P, const vesta_ec_aff* Q); +secret_bool ctt_vesta_ec_aff_is_inf(const vesta_ec_aff* P); +void ctt_vesta_ec_aff_set_inf(vesta_ec_aff* P); +void ctt_vesta_ec_aff_ccopy(vesta_ec_aff* P, const vesta_ec_aff* Q, const secret_bool ctl); +secret_bool ctt_vesta_ec_aff_is_on_curve(const pallas_fp* x, const pallas_fp* y); +void ctt_vesta_ec_aff_neg(vesta_ec_aff* P, const vesta_ec_aff* Q); +void ctt_vesta_ec_aff_neg_in_place(vesta_ec_aff* P); + +/* + * Initializes the library: + * - the Nim runtime if heap-allocated types are used, + * this is the case only if Constantine is multithreaded. + * - runtime CPU features detection + */ +void ctt_pasta_NimMain(void); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/constantine.nimble b/constantine.nimble index 9781f0c..56bd076 100644 --- a/constantine.nimble +++ b/constantine.nimble @@ -333,9 +333,49 @@ proc buildAllBenches(useAsm = true) = buildBench("bench_hash_to_curve", useAsm = useAsm) echo "All benchmarks compile successfully." +proc genBindings(bindingsName, prefixNimMain: string) = + proc compile(libName: string, flags = "") = + # -d:danger to avoid boundsCheck, overflowChecks that would trigger exceptions or allocations in a crypto library. + # Those are internally guaranteed at compile-time by fixed-sized array + # and checked at runtime with an appropriate error code if any for user-input. + # -gc:arc Constantine stack allocates everything. Inputs are through unmanaged ptr+len. + # In the future, Constantine might use: + # - heap-allocated sequences and objects manually managed or managed by destructors for multithreading. + # - heap-allocated strings for hex-string or decimal strings + exec "nim c -f " & flags & " --noMain -d:danger --app:lib --gc:arc " & + " --nimMainPrefix:" & prefixNimMain & + " --out:" & libName & " --outdir:bindings/generated " & + " --nimcache:nimcache/bindings/" & bindingsName & + " bindings/" & bindingsName & ".nim" + + when defined(windows): + compile bindingsName & ".dll" + + elif defined(macosx): + compile "lib" & bindingsName & ".dylib.arm", "--cpu:arm64 -l:'-target arm64-apple-macos11' -t:'-target arm64-apple-macos11'" + compile "lib" & bindingsName & ".dylib.x64", "--cpu:amd64 -l:'-target x86_64-apple-macos10.12' -t:'-target x86_64-apple-macos10.12'" + exec "lipo bindings/generated/lib" & bindingsName & ".dylib.arm " & + " bindings/generated/lib" & bindingsName & ".dylib.x64 " & + " -output bindings/generated/lib" & bindingsName & ".dylib -create" + + else: + compile "lib" & bindingsName & ".so" + +proc genHeaders(bindingsName: string) = + exec "nim c -r -d:release -d:CttGenerateHeaders " & + " --out:" & bindingsName & "_gen_header.exe --outdir:bindings/generated " & + " --nimcache:nimcache/bindings/" & bindingsName & "_header" & + " bindings/" & bindingsName & ".nim" + # Tasks # ---------------------------------------------------------------- +task bindings, "Generate Constantine bindings": + genBindings("constantine_bls12_381", "ctt_bls12381_") + genHeaders("constantine_bls12_381") + genBindings("constantine_pasta", "ctt_pasta_") + genHeaders("constantine_pasta") + task test, "Run all tests": # -d:testingCurves is configured in a *.nim.cfg for convenience runTests(requireGMP = true) diff --git a/constantine/blssig_pop_on_bls12381_g2.nim b/constantine/blssig_pop_on_bls12381_g2.nim index 1dcc894..a42fa5e 100644 --- a/constantine/blssig_pop_on_bls12381_g2.nim +++ b/constantine/blssig_pop_on_bls12381_g2.nim @@ -20,6 +20,7 @@ import signatures/bls_signatures export + abstractions, # generic sandwich on SecretBool and SecretBool in Jacobian sumImpl curves, # generic sandwich on matchingBigInt extension_fields, # generic sandwich on extension field access hashes, # generic sandwich on sha256 diff --git a/constantine/curves_primitives.nim b/constantine/curves_primitives.nim index 65dc45d..c8a603a 100644 --- a/constantine/curves_primitives.nim +++ b/constantine/curves_primitives.nim @@ -16,7 +16,7 @@ import curves/zoo_subgroups, curves/zoo_generators ], - ./math/io/[io_bigints, io_ec], + ./math/io/[io_bigints, io_fields, io_ec], ./math/isogenies/frobenius, ./math/pairings, ./math/pairing/[ @@ -39,7 +39,7 @@ import # ------------------------------------------------------------ export - abstractions.SecretBool, + abstractions, curves.Curve # Scalar field Fr and Prime Field Fp @@ -60,6 +60,9 @@ func marshalBE*(dst: var openarray[byte], src: FF) = raw.fromField(src) dst.marshal(src, bigEndian) +export arithmetic.ccopy +export arithmetic.cswap + export arithmetic.`==` export arithmetic.isZero export arithmetic.isOne @@ -122,6 +125,7 @@ export ec_shortweierstrass.fromAffine export ec_shortweierstrass.batchAffine export ec_shortweierstrass.sum +export ec_shortweierstrass.`+=` export ec_shortweierstrass.double export ec_shortweierstrass.diff # export ec_shortweierstrass.madd @@ -144,8 +148,14 @@ export # extension_fields.Fp6, # extension_fields.Fp12 +# Generic sandwich - https://github.com/nim-lang/Nim/issues/11225 +export extension_fields.c0, extension_fields.`c0=` +export extension_fields.c1, extension_fields.`c1=` +export extension_fields.c2, extension_fields.`c2=` + export extension_fields.setZero export extension_fields.setOne +export extension_fields.setMinusOne export extension_fields.`==` export extension_fields.isZero @@ -172,6 +182,7 @@ export extension_fields.cadd export extension_fields.`*=` export extension_fields.prod +export extension_fields.square export extension_fields.inv export extension_fields.isSquare diff --git a/constantine/hash_to_curve/hash_to_curve.nim b/constantine/hash_to_curve/hash_to_curve.nim index baa75d5..ec5b2bf 100644 --- a/constantine/hash_to_curve/hash_to_curve.nim +++ b/constantine/hash_to_curve/hash_to_curve.nim @@ -19,6 +19,8 @@ import ./h2c_utilities, ../hashes +export abstractions, arithmetic # generic sandwich + # ############################################################ # # Hashing to Elliptic Curve diff --git a/constantine/math/config/curves_prop_field_derived.nim b/constantine/math/config/curves_prop_field_derived.nim index dc7d5c8..4cec258 100644 --- a/constantine/math/config/curves_prop_field_derived.nim +++ b/constantine/math/config/curves_prop_field_derived.nim @@ -34,27 +34,31 @@ proc bindConstant(ff: NimNode, property: string): NimNode = T.expectKind(nnkBracketExpr) doAssert T[0].eqIdent("typedesc") - if T[1].kind == nnkBracketExpr: # typedesc[Fp[BLS12_381]] - # doAssert T[1][0].eqIdent"Fp" or T[1][0].eqIdent"Fr", "Found ident: '" & $T[1][0] & "' instead of 'Fp' or 'Fr'" + let curve = + if T[1].kind == nnkBracketExpr: # typedesc[Fp[BLS12_381]] as used internally + # doAssert T[1][0].eqIdent"Fp" or T[1][0].eqIdent"Fr", "Found ident: '" & $T[1][0] & "' instead of 'Fp' or 'Fr'" + T[1][1].expectKind(nnkIntLit) # static enum are ints in the VM + $Curve(T[1][1].intVal) + else: # typedesc[bls12381_fp] alias as used for C exports + let T1 = getTypeInst(T[1].getImpl()[2]) + if T1.kind != nnkBracketExpr or + T1[1].kind != nnkIntLit: + echo T.repr() + echo T1.repr() + echo getTypeInst(T1).treerepr() + error "getTypeInst didn't return the full instantiation." & + " Dealing with types in macros is hard, complain at https://github.com/nim-lang/RFCs/issues/44" + $Curve(T1[1].intVal) - T[1][1].expectKind(nnkIntLit) # static enum are ints in the VM - - let curve = $Curve(T[1][1].intVal) - let curve_fp = bindSym(curve & "_Fp_" & property) - let curve_fr = bindSym(curve & "_Fr_" & property) - result = quote do: - when `ff` is Fp: - `curve_fp` - elif `ff` is Fr: - `curve_fr` - else: - {.error: "Unreachable, received type: " & $`ff`.} - - else: - echo T.repr() - echo getTypeInst(T[1]).treerepr - error "getTypeInst didn't return the full instantiation." & - " Dealing with types in macros is hard, complain at https://github.com/nim-lang/RFCs/issues/44" + let curve_fp = bindSym(curve & "_Fp_" & property) + let curve_fr = bindSym(curve & "_Fr_" & property) + result = quote do: + when `ff` is Fp: + `curve_fp` + elif `ff` is Fr: + `curve_fr` + else: + {.error: "Unreachable, received type: " & $`ff`.} template fieldMod*(Field: type FF): auto = when Field is Fp: diff --git a/constantine/math/elliptic/ec_shortweierstrass_affine.nim b/constantine/math/elliptic/ec_shortweierstrass_affine.nim index c3b9586..8518970 100644 --- a/constantine/math/elliptic/ec_shortweierstrass_affine.nim +++ b/constantine/math/elliptic/ec_shortweierstrass_affine.nim @@ -84,7 +84,7 @@ func isOnCurve*[F](x, y: F, G: static Subgroup): SecretBool = ## Returns true if the (x, y) coordinates ## represents a point of the elliptic curve - var y2, rhs {.noInit.}: F + var y2 {.noInit.}, rhs {.noInit.}: F y2.square(y) rhs.curve_eq_rhs(x, G) diff --git a/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim b/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim index 71694a8..4181e3a 100644 --- a/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim +++ b/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim @@ -159,8 +159,8 @@ func cneg*(P: var ECP_ShortW_Jac, ctl: CTBool) {.inline.} = template sumImpl[F; G: static Subgroup]( r: var ECP_ShortW_Jac[F, G], P, Q: ECP_ShortW_Jac[F, G], - CoefA: untyped - ) = + CoefA: typed + ) {.dirty.} = ## Elliptic curve point addition for Short Weierstrass curves in Jacobian coordinates ## with the curve ``a`` being a parameter for summing on isogenous curves. ## @@ -254,13 +254,13 @@ template sumImpl[F; G: static Subgroup]( const CoefA_eq_minus3 = false when CoefA_eq_zero: - var a = H - var b = HH_or_YY + var a {.noInit.} = H + var b {.noInit.} = HH_or_YY a.ccopy(P.x, isDbl) # H or X₁ b.ccopy(P.x, isDbl) # HH or X₁ HHH_or_Mpre.prod(a, b) # HHH or X₁² - var M = HHH_or_Mpre # Assuming on doubling path + var M{.noInit.} = HHH_or_Mpre # Assuming on doubling path M.div2() # X₁²/2 M += HHH_or_Mpre # 3X₁²/2 R_or_M.ccopy(M, isDbl) @@ -273,7 +273,7 @@ template sumImpl[F; G: static Subgroup]( b.ccopy(HH_or_YY, not isDbl) # HH or X₁-ZZ HHH_or_Mpre.prod(a, b) # HHH or X₁²-ZZ² - var M = HHH_or_Mpre # Assuming on doubling path + var M{.noInit.} = HHH_or_Mpre # Assuming on doubling path M.div2() # (X₁²-ZZ²)/2 M += HHH_or_Mpre # 3(X₁²-ZZ²)/2 R_or_M.ccopy(M, isDbl) @@ -281,8 +281,8 @@ template sumImpl[F; G: static Subgroup]( else: # TODO: Costly `a` coefficients can be computed # by merging their computation with Z₃ = Z₁*Z₂*H (add) or Z₃ = Y₁*Z₁ (dbl) - var a = H - var b = HH_or_YY + var a{.noInit.} = H + var b{.noInit.} = HH_or_YY a.ccopy(P.x, isDbl) b.ccopy(P.x, isDbl) HHH_or_Mpre.prod(a, b) # HHH or X₁² diff --git a/constantine/math/extension_fields/towers.nim b/constantine/math/extension_fields/towers.nim index 92a718a..3129984 100644 --- a/constantine/math/extension_fields/towers.nim +++ b/constantine/math/extension_fields/towers.nim @@ -94,6 +94,12 @@ func setOne*(a: var ExtensionField) = staticFor i, 1, a.coords.len: a.coords[i].setZero() +func setMinusOne*(a: var ExtensionField) = + ## Set ``a`` to -1 in the extension field + a.coords[0].setMinusOne() + staticFor i, 1, a.coords.len: + a.coords[i].setZero() + func fromBig*(a: var ExtensionField, src: BigInt) = ## Set ``a`` to the bigint value in the extension field a.coords[0].fromBig(src) diff --git a/constantine/platforms/endians.nim b/constantine/platforms/endians.nim index 44ff953..4640af4 100644 --- a/constantine/platforms/endians.nim +++ b/constantine/platforms/endians.nim @@ -67,7 +67,6 @@ func dumpRawInt*[T: byte|char]( "cursor (" & $cursor & ") + sizeof(src) (" & $sizeof(src) & ") <= dst.len (" & $dst.len & ")" - type U = typeof(src) const L = uint sizeof(src) when endian == littleEndian: diff --git a/metering/tracer.nim b/metering/tracer.nim index 8702363..6bf2149 100644 --- a/metering/tracer.nim +++ b/metering/tracer.nim @@ -45,30 +45,30 @@ type when SupportsGetTicks: cumulatedCycles*: int64 +template mtag(tagname: string){.pragma.} + ## This will allow tagging proc in the future with + ## "Fp", "ec", "polynomial" + +const CttMeter {.booldefine.} = off +const CttTrace {.booldefine.} = off # For manual "debug-echo"-style timing. + var ctMetrics{.compileTime.}: seq[Metadata] ## Metrics are collected here, this is just a temporary holder of compileTime values ## Unfortunately the "seq" is emptied when passing the compileTime/runtime boundaries ## due to Nim bugs -var Metrics*: seq[Metadata] - ## We can't directly use it at compileTime because it doesn't exist. - ## We need `Metrics = static(ctMetrics)` - ## To transfer the compileTime content to runtime at an opportune time. - -template mtag(tagname: string){.pragma.} - ## This will allow tagging proc in the future with - ## "Fp", "ec", "polynomial" - -proc resetMetering*() = - Metrics = static(ctMetrics) - -const CttMeter {.booldefine.} = off - -const CttTrace {.booldefine.} = off # For manual "debug-echo"-style timing. when CttTrace: # strformat doesn't work in templates. from strutils import alignLeft, formatFloat + var Metrics*: seq[Metadata] + ## We can't directly use it at compileTime because it doesn't exist. + ## We need `Metrics = static(ctMetrics)` + ## To transfer the compileTime content to runtime at an opportune time. + + proc resetMetering*() = + Metrics = static(ctMetrics) + # Symbols # -------------------------------------------------- diff --git a/tests/math/t_ec_sage_template.nim b/tests/math/t_ec_sage_template.nim index 27690f7..a0e8916 100644 --- a/tests/math/t_ec_sage_template.nim +++ b/tests/math/t_ec_sage_template.nim @@ -14,7 +14,7 @@ import # Internals ../../constantine/platforms/abstractions, ../../constantine/math/config/curves, - ../../constantine/math/extension_fields, + ../../constantine/math/[arithmetic, extension_fields], ../../constantine/math/io/[io_bigints, io_ec], ../../constantine/math/elliptic/[ ec_shortweierstrass_affine, @@ -25,7 +25,7 @@ import # Test utilities ./support/ec_reference_scalar_mult -export unittest # Generic sandwich +export unittest, abstractions, arithmetic # Generic sandwich # Serialization # -------------------------------------------------------------------------- diff --git a/tests/math/t_ec_template.nim b/tests/math/t_ec_template.nim index c97cdba..5e15dab 100644 --- a/tests/math/t_ec_template.nim +++ b/tests/math/t_ec_template.nim @@ -18,8 +18,7 @@ import # Internals ../../constantine/platforms/abstractions, ../../constantine/math/config/curves, - ../../constantine/math/arithmetic, - ../../constantine/math/extension_fields, + ../../constantine/math/[arithmetic, extension_fields], ../../constantine/math/elliptic/[ ec_shortweierstrass_affine, ec_shortweierstrass_jacobian, @@ -33,7 +32,7 @@ import ../../helpers/prng_unsafe, ./support/ec_reference_scalar_mult -export unittest # Generic sandwich +export unittest, abstractions, arithmetic # Generic sandwich type RandomGen* = enum