Skip to content

Commit 33b129b

Browse files
committed
Ability to do keygen, proof and verification separately for libsnark backend
1 parent 8d715ff commit 33b129b

File tree

4 files changed

+201
-1
lines changed

4 files changed

+201
-1
lines changed

examples/libsnark_examples/cube.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# from __future__ import print_function
2+
3+
import sys
4+
5+
import pysnark.runtime
6+
from pysnark.runtime import snark, PrivVal
7+
8+
pysnark.runtime.autoprove = False
9+
pysnark.runtime.operation = "prove"
10+
@snark
11+
def cube(x):
12+
return x*x*x
13+
14+
print("The cube of", sys.argv[1], "is", cube(int(sys.argv[1])))
15+

examples/libsnark_examples/verify.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
# from __future__ import print_function
3+
4+
import sys
5+
6+
from pysnark.libsnark.backend import verify_only
7+
print("Verification of proof", sys.argv[1], "pubvals ", sys.argv[2], "using verification key", sys.argv[3]," is ", verify_only(sys.argv[3],sys.argv[2],sys.argv[1]))
8+

pysnark/libsnark/backend.py

+174-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,54 @@ def add_constraint(v, w, y):
3636

3737
use_groth=False
3838

39+
40+
41+
keygen_pk_file = "pysnark_pk"
42+
keygen_vk_file = "pysnark_vk"
43+
44+
prover_pk_file = "pysnark_pk"
45+
prover_proof_file = "pysnark_proof"
46+
prover_pubvals_file = "pysnark_pubvals"
47+
48+
verifier_vk_file = "pysnark_vk"
49+
verifier_proof_file = "pysnark_proof"
50+
verifier_pubvals_file = "pysnark_pubvals"
51+
52+
def process_snark(operation,namevals):
53+
54+
global keygen_pk_file,keygen_vk_file,prover_pk_file,prover_proof_file,prover_pubvals_file,verifier_vk_file,verifier_proof_file,verifier_pubvals_file
55+
keygen_only_flag=False
56+
prove_only_flag=False
57+
verify_only_flag=False
58+
59+
if operation=="keygen":
60+
keygen_only_flag=True
61+
if keygen_pk_file in namevals: keygen_pk_file=namevals[keygen_pk_file]
62+
if keygen_vk_file in namevals: keygen_pk_file=namevals[keygen_vk_file]
63+
elif operation=="prove":
64+
prove_only_flag=True
65+
if prover_pk_file in namevals: prover_pk_file=namevals[prover_pk_file]
66+
if prover_proof_file in namevals: prover_proof_file=namevals[proof_proof_file]
67+
if prover_pubvals_file in namevals: prover_pubvals_file=namevals[proof_pubvals_file]
68+
elif operation=="verify":
69+
verify_only_flag=True
70+
if verifier_vk_file in namevals: verifier_vk_file=namevals[verifier_vk_file]
71+
if verifier_proof_file in namevals: verifier_proof_file=namevals[verifier_proof_file]
72+
if verifier_pubvals_file in namevals: verifier_pubvals_file=namevals[verifier_pubvals_file]
73+
else:
74+
print("Unrecognised operation",operation)
75+
return
76+
77+
if keygen_only_flag:
78+
retval = (pk,vk)= keygen_only(keygen_pk_file,keygen_vk_file) #(pk,vk)
79+
elif prove_only_flag:
80+
retval = prove_only(prover_pk_file,prover_proof_file,prover_pubvals_file) #(proof,pubvals)
81+
elif verify_only_flag:
82+
retval=verify_only(verifier_vk_file,verifier_pubvals_file,verifier_proof_file)
83+
print("Verified ?",retval)
84+
85+
return retval
86+
3987
def prove(do_keygen=True, do_write=True, do_print=True):
4088
if pb.num_constraints()==0:
4189
# libsnark does not work in this case, add a no-op
@@ -81,5 +129,130 @@ def rounded(val): return val if val<=modd2 else val-mod
81129
if do_print: print("*** Verification status:", verifier_strong_IC(keypair.vk, pubvals, proof), file=sys.stderr)
82130

83131
return (keypair.vk, proof, pubvals)
132+
133+
134+
def keygen_only(pk_fname="pysnark_pk",vk_fname="pysnark_vk",do_print=True):
135+
try:
136+
pk_fname_file = open(pk_fname,"w")
137+
vk_fname_file = open(vk_fname,"w")
138+
except:
139+
print("File open issue")
140+
raise RuntimeError("*** File open issue")
141+
sys.exit()
142+
if pb.num_constraints()==0:
143+
# libsnark does not work in this case, add a no-op
144+
pb.add_r1cs_constraint(libsnark.R1csConstraint(libsnark.LinearCombination(),libsnark.LinearCombination(),libsnark.LinearCombination()))
145+
146+
cs=pb.get_constraint_system_pubs()
147+
pubvals=pb.primary_input_pubs()
148+
privvals=pb.auxiliary_input_pubs()
149+
150+
generator = (libsnark.zkgg_generator if use_groth else libsnark.zk_generator)
151+
152+
keypair=generator(cs)
153+
keypair.pk.write(pk_fname_file)
154+
keypair.vk.write(vk_fname_file)
155+
return (keypair.pk, keypair.vk)
156+
157+
def make_pubvals_file(pk_fname_file,pubvals):
158+
pubfile=pk_fname_file
159+
for i in range(pubvals.size()):
160+
s=str(pubvals.at(i))+"\n"
161+
pubfile.write(s)
162+
print(s)
163+
pubfile.close()
164+
165+
def prove_only(pk_fname="pysnark_pk",proof_log="pysnark_log",pubvals_fname="pysnark_pubvals",do_print=True):
166+
try:
167+
proof_log_file = open(proof_log,"w")
168+
pk_fname_file = open(pk_fname,"r")
169+
pubvals_file = open(pubvals_fname,"w")
170+
except:
171+
print("File open issue")
172+
raise RuntimeError("*** File open issue")
173+
sys.exit()
174+
175+
if pb.num_constraints()==0:
176+
# libsnark does not work in this case, add a no-op
177+
pb.add_r1cs_constraint(libsnark.R1csConstraint(libsnark.LinearCombination(),libsnark.LinearCombination(),libsnark.LinearCombination()))
178+
179+
cs=pb.get_constraint_system_pubs()
180+
pubvals=pb.primary_input_pubs()
181+
privvals=pb.auxiliary_input_pubs()
182+
183+
prover = (libsnark.zkgg_prover if use_groth else libsnark.zk_prover)
184+
write_proof = (libsnark.zkgg_write_proof if use_groth else libsnark.zk_write_proof)
185+
read_key = libsnark.ZKProvingKey_read
186+
#read_key = libsnark.zk_read_key
187+
188+
if do_print: print("*** Trying to read pk", file=sys.stderr)
189+
keypair_pk=read_key(pk_fname_file)
190+
if not keypair_pk:
191+
raise RuntimeError("*** Unable to read proving key")
192+
193+
if do_print:
194+
print("*** PySNARK: generating proof pysnark_log (" +
195+
"sat=" + str(pb.is_satisfied()) +
196+
", #io=" + str(pubvals.size()) +
197+
", #witness=" + str(privvals.size()) +
198+
", #constraint=" + str(pb.num_constraints()) +
199+
")", file=sys.stderr)
200+
201+
proof=prover(keypair_pk, pubvals, privvals);
202+
proof.write(proof_log_file)
203+
proof_log_file.close()
204+
make_pubvals_file(pubvals_file,pubvals)
205+
206+
#write_proof(proof, pubvals, proof_log)
207+
return (proof, pubvals)
208+
209+
210+
def create_pubvals_from_file(pubfile,pb) :
211+
ff=pubfile.readlines()
212+
for i in range(len(ff)):
213+
pubv=libsnark.PbVariable()
214+
pubv.allocate(pb)
215+
pb.setpublic(pubv)
216+
pubval = int(ff[i].strip())
217+
pb.setval(pubv,pubval)
218+
219+
pubvals=pb.primary_input_pubs()
220+
return pubvals
221+
222+
223+
def verify_only(vk_fname="pysnark_vk",pubval_fname="pysnark_pubvals", proof_fname="pysnark_proof", do_print=True):
224+
try:
225+
vk_file = open(vk_fname,"r")
226+
proof_file = open(proof_fname,"r")
227+
pubfile = open(pubval_fname,"r")
228+
except:
229+
print("File open issue")
230+
raise RuntimeError("*** File open issue")
231+
sys.exit()
232+
233+
mod = libsnark.get_modulus()
234+
modd2 = mod//2
235+
def rounded(val): return val if val<=modd2 else val-mod
236+
237+
read_vk = libsnark.ZKVerificationKey_read
238+
read_proof = libsnark.ZKProof_read
239+
verifier_strong_IC = (libsnark.zkgg_verifier_strong_IC if use_groth else libsnark.zk_verifier_strong_IC)
240+
241+
242+
keypair_vk = read_vk(vk_file)
243+
vk_file.close()
244+
245+
pb=libsnark.ProtoboardPub()
246+
pubvals = create_pubvals_from_file(pubfile,pb)
247+
pubfile.close()
248+
249+
proof = read_proof(proof_file)
250+
proof_file.close()
251+
252+
if do_print: print("*** Public inputs: " + " ".join([str(rounded(pubvals.at(i))) for i in range(pubvals.size())]), file=sys.stderr)
253+
verified = verifier_strong_IC(keypair_vk, pubvals, proof)
254+
if do_print: print("*** Verification status:", verified, file=sys.stderr)
255+
256+
return verified
257+
84258

85-

pysnark/runtime.py

+4
Original file line numberDiff line numberDiff line change
@@ -777,9 +777,13 @@ def snark__(*args, **kwargs):
777777
return snark__
778778

779779
autoprove = True
780+
operation = None
781+
namevals = {}
780782

781783
def final():
782784
if autoprove: backend.prove()
785+
else :
786+
if backend.process_snark: backend.process_snark(operation,namevals)
783787

784788
import atexit
785789
from .atexitmaybe import maybe

0 commit comments

Comments
 (0)