From bd1430157f17c57a105a74f9f55e97b87a2e715e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Sun, 16 Feb 2020 00:44:01 +0100 Subject: [PATCH] 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 --- constantine/config/curves.nim | 51 +++++++++++++++++++++------- constantine/config/curves_parser.nim | 33 ------------------ constantine/io/io_fields.nim | 2 +- constantine/math/finite_fields.nim | 6 ++-- 4 files changed, 42 insertions(+), 50 deletions(-) diff --git a/constantine/config/curves.nim b/constantine/config/curves.nim index 439eb85..f616ef9 100644 --- a/constantine/config/curves.nim +++ b/constantine/config/curves.nim @@ -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 - ## For each curve under the private symbol "MyCurve_R2modP" +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") diff --git a/constantine/config/curves_parser.nim b/constantine/config/curves_parser.nim index a5ec6f7..7d80550 100644 --- a/constantine/config/curves_parser.nim +++ b/constantine/config/curves_parser.nim @@ -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() diff --git a/constantine/io/io_fields.nim b/constantine/io/io_fields.nim index 9abd7c9..e1eb7ec 100644 --- a/constantine/io/io_fields.nim +++ b/constantine/io/io_fields.nim @@ -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, diff --git a/constantine/math/finite_fields.nim b/constantine/math/finite_fields.nim index 6f276e3..48f4311 100644 --- a/constantine/math/finite_fields.nim +++ b/constantine/math/finite_fields.nim @@ -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())