Add curve configuration + BN254 config (zkSnarks, ZCash, Ethereum 1 precompile)

This commit is contained in:
Mamy André-Ratsimbazafy 2020-02-08 14:55:49 +01:00
parent f18a958d5e
commit bd2b10817e
No known key found for this signature in database
GPG Key ID: 7B88AD1FE79492E1
2 changed files with 187 additions and 0 deletions

View File

@ -0,0 +1,37 @@
# 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
# Internal
./private/curves_config_parser
# ############################################################
#
# Configuration of finite fields
#
# ############################################################
# Finite fields are preconfigured in this file
# To workaround the following limitation https://github.com/nim-lang/Nim/issues/11142
# i.e. an object can be parametrized by a compiletime bigint
# we instead have the fields, curve points and Montgomery objects
# be parametrized over an enum.
# Note, in the past the convention was to name a curve by its conjectured security level.
# as this might change with advances in research, the new convention is
# to name curves according to the length of the prime bit length.
# i.e. the BN254 was previously named BN128.
declareCurves:
# Barreto-Naehrig curve, Prime 254 bit, 128-bit security, https://eprint.iacr.org/2013/879.pdf
# Usage: Zero-Knowledge Proofs / zkSNARKs in ZCash and Ethereum 1
# https://eips.ethereum.org/EIPS/eip-196
curve BN254:
bitsize: 254
modulus: "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
# Equation: Y^2 = X^3 + 3

View File

@ -0,0 +1,150 @@
# 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
# Standard library
macros,
# Internal
../io, ../bigints
# Macro to parse declarative curves configuration.
macro declareCurves*(curves: untyped): untyped =
## Parse curve configuration and generates
##
## type Curve = enum
## BN254
## ...
##
## const CurveBitSize* = array[
## BN254: 254,
## ...
## ]
##
## TODO: Ensure that the modulus is not inlined at runtime
## to avoid codesize explosion.
## const BN254_Modulus = fromHex(BigInt[254], "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
##
## func fieldModulus*(curve: static Curve): auto =
## when curve == BN254_Modulus: BN254_Modulus
## ...
curves.expectKind(nnkStmtList)
# curve BN254:
# bitsize: 254
# modulus: "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
#
# is parsed into
#
# StmtList
# Command
# Ident "curve"
# Ident "BN254"
# StmtList
# Call
# Ident "bitsize"
# StmtList
# IntLit 254
# Call
# Ident "modulus"
# StmtList
# StrLit "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
var Curves: seq[NimNode]
var CurveBitSize = nnKBracket.newTree()
var curveModStmts = newStmtList()
var curveModWhenStmt = nnkWhenStmt.newTree()
for curveDesc in curves:
curveDesc.expectKind(nnkCommand)
doAssert curveDesc[0].eqIdent"curve"
curveDesc[1].expectKind(nnkIdent) # Curve name
curveDesc[2].expectKind(nnkStmtList)
curveDesc[2][0].expectKind(nnkCall)
curveDesc[2][1].expectKind(nnkCall)
let curve = curveDesc[1]
let sizeSection = curveDesc[2][0]
doAssert sizeSection[0].eqIdent"bitsize"
sizeSection[1].expectKind(nnkStmtList)
let bitSize = sizeSection[1][0]
let modSection = curveDesc[2][1]
doAssert modSection[0].eqIdent"modulus"
modSection[1].expectKind(nnkStmtList)
let modulus = modSection[1][0]
Curves.add curve
# "BN254: 254" for array construction
CurveBitSize.add nnkExprColonExpr.newTree(
curve, bitSize
)
# const BN254_Modulus = fromHex(BigInt[254], "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
let modulusID = ident($curve & "_Modulus")
curveModStmts.add newConstStmt(
modulusID,
newCall(
bindSym"fromHex",
nnkBracketExpr.newTree(
bindSym"BigInt",
bitSize
),
modulus
)
)
# when curve == BN254: BN254_Modulus
curveModWhenStmt.add nnkElifBranch.newTree(
nnkInfix.newTree(
ident"==",
ident"curve",
curve
),
modulusID
)
result = newStmtList()
result.add newEnum(
name = ident"Curve",
fields = Curves,
public = true,
pure = false
)
result.add quote do:
const CurveBitSize: array[Curve, int] = `CurveBitSize`
result.add curveModStmts
# Add 'else: {.error: "Unreachable".}' to the when statements
curveModWhenStmt.add nnkElse.newTree(
nnkPragma.newTree(
nnkExprColonExpr.newTree(
ident"error",
newLit"Unreachable: the curve does not exist."
)
)
)
result.add newProc(
name = nnkPostfix.newTree(ident"*", ident"fieldModulus"),
params = [
ident"auto",
newIdentDefs(
name = ident"curve",
kind = nnkStaticTy.newTree(ident"Curve")
)
],
body = curveModWhenStmt,
procType = nnkFuncDef,
pragmas = nnkPragma.newTree(ident"compileTime")
)
# echo result.toStrLit