From 148d54f614dd139e4254882bb6c45c465e626565 Mon Sep 17 00:00:00 2001 From: Balazs Komuves Date: Wed, 22 Nov 2023 15:55:18 +0100 Subject: [PATCH] export SageMath verification script (bn128 curve only) --- groth16/files/export_sage.nim | 152 ++++++++++++++++++++++++++++++++++ groth16/test_proof.nim | 8 +- 2 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 groth16/files/export_sage.nim diff --git a/groth16/files/export_sage.nim b/groth16/files/export_sage.nim new file mode 100644 index 0000000..5a0da72 --- /dev/null +++ b/groth16/files/export_sage.nim @@ -0,0 +1,152 @@ + +# +# export proof, public input and verifier as a SageMath script +# + +import std/strutils +import std/streams + +import constantine/math/arithmetic except Fp, Fr + +import groth16/bn128 +import groth16/zkey_types +from groth16/prover import Proof + +#------------------------------------------------------------------------------- + +func toSpaces(str: string): string = spaces(str.len) + +func sageFp(prefix: string, x: Fp): string = prefix & "Fp(" & toDecimalFp(x) & ")" +func sageFr(prefix: string, x: Fr): string = prefix & "Fr(" & toDecimalFr(x) & ")" + +func sageFp2(prefix: string, z: Fp2): string = + sageFp( prefix & "mkFp2(" , z.coords[0]) & ",\n" & + sageFp( toSpaces(prefix) & " " , z.coords[1]) & ")" + +func sageG1(prefix: string, p: G1): string = + sageFp( prefix & "E(" , p.x) & ",\n" & + sageFp( toSpaces(prefix) & " " , p.y) & ")" + +func sageG2(prefix: string, p: G2): string = + sageFp2( prefix & "E2(" , p.x) & ",\n" & + sageFp2( toSpaces(prefix) & " " , p.y) & ")" + +#------------------------------------------------------------------------------- + +proc exportVKey(h: Stream, vkey: VKey ) = + let spec = vkey.spec + h.writeLine("alpha1 = \\") ; h.writeLine(sageG1(" ", spec.alpha1)) + h.writeLine("beta2 = \\") ; h.writeLine(sageG2(" ", spec.beta2 )) + h.writeLine("gamma2 = \\") ; h.writeLine(sageG2(" ", spec.gamma2)) + h.writeLine("delta2 = \\") ; h.writeLine(sageG2(" ", spec.delta2)) + + let pts = vkey.vpoints.pointsIC + h.writeLine("pointsIC = \\") + for i in 0.. = Fp[]" + , "Fp2. = Fp.extension(x^2+1)" + , "def mkFp2(a,b):" + , " return ( a + u*b )" + , "R. = Fp2[]" + , "Fp12. = Fp2.extension(x^6 - (9+u))" + , "E12 = E.base_extend(Fp12)" + , "" + , "# twisted curve" + , "B_twist = Fp2(19485874751759354771024239261021720505790618469301721065564631296452457478373 + 266929791119991161246907387137283842545076965332900288569378510910307636690*u )" + , "E2 = EllipticCurve(Fp2,[0,B_twist])" + , "size_E2 = E2.cardinality();" + , "cofactor_E2 = size_E2 / r;" + , "print(\"|E2| = \", size_E2 );" + , "print(\"h(E2) = \", cofactor_E2 );" + , "" + , "# map from E2 to E12" + , "def Psi(pt):" + , " pt.normalize_coordinates()" + , " x = pt[0]" + , " y = pt[1]" + , " return E12( Fp12(w^2 * x) , Fp12(w^3 * y) )" + , "" + , "def pairing(P,Q):" + , " return E12(P).ate_pairing( Psi(Q), n=r, k=12, t=bn_t, q=p^12 )" + , "" + ] + +const sage_bn128 : string = join(sage_bn128_lines, sep="\n") + +#------------------------------------------------------------------------------- + +const verify_lines : seq[string] = + @[ "pubG1 = pointsIC[0]" + , "for i in [1..len(pubIO)-1]:" + , " pubG1 = pubG1 + pubIO[i]*pointsIC[i]" + , "" + , "lhs = pairing( -piA , piB )" + , "rhs1 = pairing( alpha1 , beta2 )" + , "rhs2 = pairing( piC , delta2 )" + , "rhs3 = pairing( pubG1 , gamma2 )" + , "eq = lhs * rhs1 * rhs2 * rhs3" + , "print(\"verification suceeded =\\n\",eq == 1)" + ] + +const verify_script : string = join(verify_lines, sep="\n") + +#------------------------------------------------------------------------------- + +proc exportSage*(fpath: string, vkey: VKey, prf: Proof) = + + let h = openFileStream(fpath, fmWrite) + defer: h.close() + + h.writeLine(sage_bn128) + h.exportVKey(vkey); + h.exportProof(prf); + h.writeLine(verify_script) + +#------------------------------------------------------------------------------- + diff --git a/groth16/test_proof.nim b/groth16/test_proof.nim index 2a30a4e..cf3d603 100644 --- a/groth16/test_proof.nim +++ b/groth16/test_proof.nim @@ -12,7 +12,7 @@ import groth16/fake_setup #------------------------------------------------------------------------------- -proc testProveAndVerify*( zkey_fname, wtns_fname: string): Proof = +proc testProveAndVerify*( zkey_fname, wtns_fname: string): (VKey,Proof) = echo("parsing witness & zkey files...") let witness = parseWitness( wtns_fname) @@ -29,11 +29,11 @@ proc testProveAndVerify*( zkey_fname, wtns_fname: string): Proof = let ok = verifyProof( vkey, proof ) echo("verification succeeded = ",ok) - return proof + return (vkey,proof) #------------------------------------------------------------------------------- -proc testFakeSetupAndVerify*( r1cs_fname, wtns_fname: string, flavour=Snarkjs): Proof = +proc testFakeSetupAndVerify*( r1cs_fname, wtns_fname: string, flavour=Snarkjs): (VKey,Proof) = echo("trusted setup flavour = ",flavour) echo("parsing witness & r1cs files...") @@ -57,4 +57,4 @@ proc testFakeSetupAndVerify*( r1cs_fname, wtns_fname: string, flavour=Snarkjs): let ok = verifyProof( vkey, proof ) echo("verification succeeded = ",ok) - return proof + return (vkey,proof)