From 4b8487b0df70ca73ad4750857a44785401242064 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 13 Nov 2023 11:03:42 -0600 Subject: [PATCH] nimbify package --- example/example.nim | 6 +- groth16.nimble | 13 ++ misc.nim | 49 ------- bn128.nim => src/bn128.nim | 184 ++++++++++++------------- container.nim => src/container.nim | 18 +-- domain.nim => src/domain.nim | 0 export_json.nim => src/export_json.nim | 14 +- groth16.nim => src/groth16.nim | 0 src/misc.nim | 44 ++++++ ntt.nim => src/ntt.nim | 0 poly.nim => src/poly.nim | 133 ++++++++++-------- r1cs.nim => src/r1cs.nim | 0 witness.nim => src/witness.nim | 18 +-- zkey.nim => src/zkey.nim | 0 zkey_types.nim => src/zkey_types.nim | 0 tests/config.nims | 1 + test_proof.nim => tests/test_proof.nim | 14 +- 17 files changed, 257 insertions(+), 237 deletions(-) create mode 100644 groth16.nimble delete mode 100644 misc.nim rename bn128.nim => src/bn128.nim (86%) rename container.nim => src/container.nim (88%) rename domain.nim => src/domain.nim (100%) rename export_json.nim => src/export_json.nim (90%) rename groth16.nim => src/groth16.nim (100%) create mode 100644 src/misc.nim rename ntt.nim => src/ntt.nim (100%) rename poly.nim => src/poly.nim (80%) rename r1cs.nim => src/r1cs.nim (100%) rename witness.nim => src/witness.nim (93%) rename zkey.nim => src/zkey.nim (100%) rename zkey_types.nim => src/zkey_types.nim (100%) create mode 100644 tests/config.nims rename test_proof.nim => tests/test_proof.nim (90%) diff --git a/example/example.nim b/example/example.nim index d62933c..7112fcf 100644 --- a/example/example.nim +++ b/example/example.nim @@ -1,6 +1,7 @@ +import pkg/groth16 -import ../test_proof -import ../export_json +import ../tests/test_proof +import ../src/export_json let zkey_fname : string = "./build/product.zkey" let wtns_fname : string = "./build/product.wtns" @@ -8,4 +9,3 @@ let proof = testProveAndVerify( zkey_fname, wtns_fname) exportPublicIO( "./build/nim_public.json" , proof ) exportProof( "./build/nim_proof.json" , proof ) - diff --git a/groth16.nimble b/groth16.nimble new file mode 100644 index 0000000..9533964 --- /dev/null +++ b/groth16.nimble @@ -0,0 +1,13 @@ +# Package + +version = "0.1.0" +author = "Dmitriy Ryajov" +description = "A circom/snarkjs compatible groth16 implementation" +license = "MIT" +srcDir = "src" + + +# Dependencies + +requires "nim >= 1.6.14", + "https://github.com/mratsim/constantine#5f7ba18" diff --git a/misc.nim b/misc.nim deleted file mode 100644 index 9e446cd..0000000 --- a/misc.nim +++ /dev/null @@ -1,49 +0,0 @@ - -# -# miscellaneous routines -# - -#------------------------------------------------------------------------------- - -func delta*(i, j: int) : int = - return (if (i == j): 1 else: 0) - -#------------------------------------------------------------------------------- - -func floorLog2* (x : int) : int = - var k = -1 - var y = x - while (y > 0): - k += 1 - y = y shr 1 - return k - -func ceilingLog2* (x : int) : int = - if (x==0): - return -1 - else: - return (floorLog2(x-1) + 1) - -#------------------- - -#[ -import std/math - -proc sanityCheckLog2* () = - for i in 0..18: - let x = float64(i) - echo( i," | ",floorLog2(i),"=",floor(log2(x))," | ",ceilingLog2(i),"=",ceil(log2(x)) ) -]# - -#------------------------------------------------------------------------------- - -#[ -func rotateSeq[T](xs: seq[T], ofs: int): seq[T] = - let n = xs.len - var ys : seq[T] - for i in (0.. 0): if bitand(e,1) > 0: a *= s e = (e shr 1) square(s) return a -func smallPowFr*(base: Fr, expo: int): Fr = +func smallPowFr*(base: Fr, expo: int): Fr = if expo >= 0: return smallPowFr( base, uint(expo) ) else: @@ -233,7 +233,7 @@ proc debugPrintFr*(prefix: string, x: Fr) = proc debugPrintFrSeq*(msg: string, xs: seq[Fr]) = echo "---------------------" echo msg - for x in xs: + for x in xs: debugPrintFr( " " , x ) proc debugPrintG1*(msg: string, pt: G1) = @@ -249,7 +249,7 @@ proc debugPrintG2*(msg: string, pt: G2) = #------------------------------------------------------------------------------- # Montgomery batch inversion -func batchInverse*( xs: seq[Fr] ) : seq[Fr] = +func batchInverse*( xs: seq[Fr] ) : seq[Fr] = let n = xs.len assert(n>0) var us : seq[Fr] = newSeq[Fr](n+1) @@ -269,9 +269,9 @@ proc sanityCheckBatchInverse*() = let n = xs.len # for i in 0.. bool ) = let sectId = int( stream.readUint32() ) @@ -76,7 +76,7 @@ proc parseContainer*[T] ( expectedMagic: string , expectedVersion: int , fname: string , user: var T - , callback: SectionCallback[T] + , callback: SectionCallback[T] , filt: (int) -> bool ) = let stream = newFileStream(fname, mode = fmRead) diff --git a/domain.nim b/src/domain.nim similarity index 100% rename from domain.nim rename to src/domain.nim diff --git a/export_json.nim b/src/export_json.nim similarity index 90% rename from export_json.nim rename to src/export_json.nim index 6f069be..babd8ce 100644 --- a/export_json.nim +++ b/src/export_json.nim @@ -11,22 +11,22 @@ from ./groth16 import Proof #------------------------------------------------------------------------------- -func toQuotedDecimalFp(x: Fp): string = +func toQuotedDecimalFp(x: Fp): string = let s : string = toDecimalFp(x) return ("\"" & s & "\"") -func toQuotedDecimalFr(x: Fr): string = +func toQuotedDecimalFr(x: Fr): string = let s : string = toDecimalFr(x) return ("\"" & s & "\"") #------------------------------------------------------------------------------- # exports the public input/output into as a JSON file -proc exportPublicIO*( fpath: string, prf: Proof ) = +proc exportPublicIO*( fpath: string, prf: Proof ) = # debugPrintFrSeq("public IO",prf.publicIO) - let n : int = prf.publicIO.len + let n : int = prf.publicIO.len assert( n > 0 ) assert( bool(prf.publicIO[0] == oneFr) ) @@ -65,7 +65,7 @@ proc writeG2( f: File, p: G2 ) = #------------------------------------------------------------------------------- # exports the proof into as a JSON file -proc exportProof*( fpath: string, prf: Proof ) = +proc exportProof*( fpath: string, prf: Proof ) = let f = open(fpath, fmWrite) defer: f.close() @@ -82,7 +82,7 @@ proc exportProof*( fpath: string, prf: Proof ) = #[ #import std/sequtils -func getFakeProof*() : Proof = +func getFakeProof*() : Proof = let pub : seq[Fr] = map( [1,101,102,103,117,119] , intToFr ) let p = unsafeMkG1( intToFp(666) , intToFp(777) ) let r = unsafeMkG1( intToFp(888) , intToFp(999) ) @@ -91,7 +91,7 @@ func getFakeProof*() : Proof = let q = unsafeMkG2( x , y ) return Proof( publicIO:pub, pi_a:p, pi_b:q, pi_c:r ) -proc exportFakeProof*() = +proc exportFakeProof*() = let prf = getFakeProof() exportPublicIO( "fake_pub.json" , prf ) exportProof( "fake_prf.json" , prf ) diff --git a/groth16.nim b/src/groth16.nim similarity index 100% rename from groth16.nim rename to src/groth16.nim diff --git a/src/misc.nim b/src/misc.nim new file mode 100644 index 0000000..a63e267 --- /dev/null +++ b/src/misc.nim @@ -0,0 +1,44 @@ + +# +# miscellaneous routines +# + +#------------------------------------------------------------------------------- + +func floorLog2* (x : int) : int = + var k = -1 + var y = x + while (y > 0): + k += 1 + y = y shr 1 + return k + +func ceilingLog2* (x : int) : int = + if (x==0): + return -1 + else: + return (floorLog2(x-1) + 1) + +#------------------- + +when isMainModule: + + import std/math + + proc sanityCheckLog2* () = + for i in 0..18: + let x = float64(i) + echo( i," | ",floorLog2(i),"=",floor(log2(x))," | ",ceilingLog2(i),"=",ceil(log2(x)) ) + + sanityCheckLog2() + + #------------------------------------------------------------------------------- + + func rotateSeq[T](xs: seq[T], ofs: int): seq[T] = + let n = xs.len + var ys : seq[T] + for i in (0..= 0): d -= 1 return d -func polyIsZero*(P: Poly) : bool = +func polyIsZero*(P: Poly) : bool = let xs = P.coeffs ; let n = xs.len var b = true for i in 0..= i = k - j >= k - min(k , n2-1) - # 0 >= j = k - i >= k - min(k , n1-1) + # 0 >= j = k - i >= k - min(k , n1-1) let A : int = max( 0 , k - min(k , n2-1) ) let B : int = min( k , n1-1 ) zs[k] = zeroFr @@ -124,7 +124,7 @@ func polyMulNaive*(P, Q : Poly): Poly = #------------------------------------------------------------------------------- # multiply two polynomials using FFT -func polyMulFFT*(P, Q: Poly): Poly = +func polyMulFFT*(P, Q: Poly): Poly = let n1 = P.coeffs.len let n2 = Q.coeffs.len @@ -135,7 +135,7 @@ func polyMulFFT*(P, Q: Poly): Poly = let us : seq[Fr] = extendAndForwardNTT( P.coeffs, D ) let vs : seq[Fr] = extendAndForwardNTT( Q.coeffs, D ) let zs : seq[Fr] = collect( newSeq, (for i in 0..=1 ) var cs : seq[Fr] = newSeq[Fr]( N+1 ) cs[0] = negFr(b) @@ -168,31 +168,31 @@ func generalizedVanishingPoly*(N: int, a: Fr, b: Fr): Poly = return Poly(coeffs: cs) # the vanishing polynomial `(x^N - 1)` -func vanishingPoly*(N: int): Poly = +func vanishingPoly*(N: int): Poly = return generalizedVanishingPoly(N, oneFr, oneFr) -func vanishingPoly*(D: Domain): Poly = +func vanishingPoly*(D: Domain): Poly = return vanishingPoly(D.domainSize) #------------------------------------------------------------------------------- type QuotRem*[T] = object - quot* : T - rem* : T + quot* : T + rem* : T # divide by the vanishing polynomial `(x^N - 1)` # returns the quotient and remainder -func polyQuotRemByVanishing*(P: Poly, N: int): QuotRem[Poly] = +func polyQuotRemByVanishing*(P: Poly, N: int): QuotRem[Poly] = assert( N>=1 ) let deg : int = polyDegree(P) - let src : seq[Fr] = P.coeffs + let src : seq[Fr] = P.coeffs var quot : seq[Fr] = newSeq[Fr]( max(1, deg - N + 1) ) var rem : seq[Fr] = newSeq[Fr]( N ) if deg < N: rem = src - + else: # compute quotient @@ -212,7 +212,7 @@ func polyQuotRemByVanishing*(P: Poly, N: int): QuotRem[Poly] = return QuotRem[Poly]( quot:Poly(coeffs:quot), rem:Poly(coeffs:rem) ) # divide by the vanishing polynomial `(x^N - 1)` -func polyDivideByVanishing*(P: Poly, N: int): Poly = +func polyDivideByVanishing*(P: Poly, N: int): Poly = let qr = polyQuotRemByVanishing(P, N) assert( polyIsZero(qr.rem) ) return qr.quot @@ -230,7 +230,7 @@ func lagrangePoly(D: Domain, k: int): Poly = for i in 0..