Self-contained bindings generation (#196)

* First draft at bindings generation

* finite field bindings PoC

* support openarray, export NimMain

* PoC extension fields and elliptic curve bindings

* Pasta

* expose more bindings, remove nimZeroMem, remove tracer when unused, codegen name_mangling`gensym issue

* workaround bad C gensym codegen with {.inline.} pragma in non-dirty template nested in generic proc instantiated by template
This commit is contained in:
Mamy Ratsimbazafy 2022-08-06 19:05:54 +02:00 committed by GitHub
parent 7d29cb947a
commit 99c9730793
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1288 additions and 52 deletions

View File

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

View File

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

View File

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

View File

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

331
bindings/gen_bindings.nim Normal file
View File

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

215
bindings/gen_header.nim Normal file
View File

@ -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 <stddef.h>
#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 <stdint.h>
#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);
"""

View File

@ -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 <stddef.h>
#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 <stdint.h>
#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

View File

@ -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 <stddef.h>
#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 <stdint.h>
#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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,8 @@ import
./h2c_utilities,
../hashes
export abstractions, arithmetic # generic sandwich
# ############################################################
#
# Hashing to Elliptic Curve

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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