Add BLS12-381 curve:

- don't create "Mod" in curve parser: compile-time type incompatibility
- don't use "Mod" in const sections: compile-time type incompat  --> create a macro to get montgomery magics instead of a const array
This commit is contained in:
Mamy André-Ratsimbazafy 2020-02-16 00:44:01 +01:00
parent 05a2c6a34b
commit bd1430157f
No known key found for this signature in database
GPG Key ID: 7B88AD1FE79492E1
4 changed files with 42 additions and 50 deletions

View File

@ -48,6 +48,10 @@ when not defined(testingCurves):
bitsize: 254
modulus: "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
# Equation: Y^2 = X^3 + 3
curve BLS12_381:
bitsize: 381
modulus: "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
# Equation: y^2 = x^3 + 4
else:
# Fake curve for testing field arithmetic
declareCurves:
@ -57,22 +61,28 @@ else:
# ############################################################
#
# Autogeneration of precomputed constants in ROM
# Curve Modulus Accessor
#
# ############################################################
const MontyNegInvModWord* = block:
## Store the Montgomery Magic Constant "Negative Inverse mod 2^63" in ROM
var buf: array[Curve, BaseType]
for curve in Curve:
buf[curve] = curve.Mod.mres.negInvModWord
buf
{.experimental: "dynamicBindSym".}
macro genR2modP(T: typed): untyped =
## Store the Montgomery Magic Constant "R^2 mod N" in ROM
macro Mod*(C: static Curve): untyped =
## Get the Modulus associated to a curve
result = bindSym($C & "_Modulus")
# ############################################################
#
# Autogeneration of precomputed Montgomery constants in ROM
#
# ############################################################
macro genMontyMagics(T: typed): untyped =
## Store
## - the Montgomery magic constant "R^2 mod N" in ROM
## For each curve under the private symbol "MyCurve_R2modP"
## - the Montgomery magic constant -1/P mod 2^WordBitSize
## For each curve under the private symbol "MyCurve_NegInvModWord
T.getImpl.expectKind(nnkTypeDef)
T.getImpl[2].expectKind(nnkEnumTy)
@ -92,11 +102,26 @@ macro genR2modP(T: typed): untyped =
)
)
)
result.add newConstStmt(
ident($curve & "_NegInvModWord"), newCall(
bindSym"negInvModWord",
# The curve parser creates modulus
# under symbol "MyCurve_Modulus"
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# echo result.toStrLit
genR2modP(Curve)
genMontyMagics(Curve)
macro getR2modP*(C: static Curve): untyped =
## Get the Montgomery Magic Constant Associated to a curve
## Get the Montgomery "R^2 mod P" constant associated to a curve field modulus
result = bindSym($C & "_R2modP")
macro getNegInvModWord*(C: static Curve): untyped =
## Get the Montgomery "-1/P[0] mod 2^WordBitSize" constant associated to a curve field modulus
result = bindSym($C & "_NegInvModWord")

View File

@ -58,7 +58,6 @@ macro declareCurves*(curves: untyped): untyped =
var Curves: seq[NimNode]
var CurveBitSize = nnKBracket.newTree()
var curveModStmts = newStmtList()
var curveModWhenStmt = nnkIfStmt.newTree()
let Fq = ident"Fq"
@ -105,15 +104,6 @@ macro declareCurves*(curves: untyped): untyped =
)
)
# when curve == BN254: BN254_Modulus
curveModWhenStmt.add nnkElifBranch.newTree(
nnkInfix.newTree(
ident"==",
ident"curve",
curve
),
newAssignment(ident"result", modulusID)
)
# end for ---------------------------------------------------
result = newStmtList()
@ -172,29 +162,6 @@ macro declareCurves*(curves: untyped): untyped =
)
)
# Add 'else: error"Unreachable" to the when statements
curveModWhenStmt.add nnkElse.newTree(
newCall(
bindSym"error",
newLit"Unreachable: the curve does not exist."
)
)
result.add curveModStmts
# proc Mod(curve: static Curve): auto
result.add newProc(
name = nnkPostfix.newTree(ident"*", ident"Mod"),
params = [
ident"auto",
newIdentDefs(
name = ident"curve",
kind = ident"Curve"
)
],
body = curveModWhenStmt,
procType = nnkFuncDef,
pragmas = nnkPragma.newTree(ident"compileTime")
)
# echo result.toStrLit()

View File

@ -22,7 +22,7 @@ func fromUint*(dst: var Fq,
## Parse a regular unsigned integer
## and store it into a BigInt of size `bits`
let raw = (type dst.mres).fromRawUint(cast[array[sizeof(src), byte]](src), cpuEndian)
dst.mres.unsafeMontyResidue(raw, Fq.C.Mod.mres, Fq.C.getR2modP(), MontyNegInvModWord[Fq.C])
dst.mres.unsafeMontyResidue(raw, Fq.C.Mod.mres, Fq.C.getR2modP(), Fq.C.getNegInvModWord())
func serializeRawUint*(dst: var openarray[byte],
src: Fq,

View File

@ -51,12 +51,12 @@ debug:
func fromBig*(T: type Fq, src: BigInt): T =
## Convert a BigInt to its Montgomery form
result.mres.unsafeMontyResidue(src, Fq.C.Mod.mres, Fq.C.getR2modP(), MontyNegInvModWord[Fq.C])
result.mres.unsafeMontyResidue(src, Fq.C.Mod.mres, Fq.C.getR2modP(), Fq.C.getNegInvModWord())
func toBig*(src: Fq): auto =
## Convert a finite-field element to a BigInt in natral representation
result = src.mres
result.unsafeRedC(Fq.C.Mod.mres, MontyNegInvModWord[Fq.C])
result.unsafeRedC(Fq.C.Mod.mres, Fq.C.getNegInvModWord())
# ############################################################
#
@ -114,4 +114,4 @@ func `*`*(a, b: Fq): Fq {.noInit.} =
## as Fq elements are usually large and this
## routine will zero init internally the result.
result.mres.setInternalBitLength()
result.mres.montyMul(a.mres, b.mres, Fq.C.Mod.mres, MontyNegInvModWord[Fq.C])
result.mres.montyMul(a.mres, b.mres, Fq.C.Mod.mres, Fq.C.getNegInvModWord())