I'm trying to understand my zokrates
code and how it processes zk-SNARK step by step in accordance to this article.
The article breaks down the zk-SNARK into three steps.
- A key generator,
G
, takes in a secrete parameterlambda
and a programC
to produce thepk
, which is the proving key, and thevk
, which is the verification key:
(pk, vk) = G(C, lambda)
C
here is just a function that takes in the preimage and the returns true if the hash value is the same as the preimage:
// w is the preimage, x is the hashed value of w
function C(x, w) {
return ( sha256(w) == x );
}
- The prover uses the preimage
s
, the known hashH
and the proving keypk
and generates the proofprf
through the proof generating algorithemP
:
prf = P(pk, H, s)
- Finally, the verifier runs the verification function using the proof from the prover:
V(vk, H, prf)
The result is true if the prf
is correct, which essentially proves that the prover knows the witness.
Now, I have a zokrates code here that takes it two values "a" and "b".
def main(private field a, field b) -> (field):
field h = if a * a == b then 1 else 0 fi
return h
- My first question is, what are these two values equivalent to in the aforementioned example? Is one of them lambda? Also, is the expression "a * a == b" equivalent to the function C mentioned above? I'm having difficulty understanding what these values and the expression are.
When I execute:
~/zokrates setup
I get the following output:
zokrates@0a96d8e9989b:~/code/square$ ~/zokrates setup
Performing setup...
def main(_0, _1) -> (1):
(1 * _0) * (1 * _0) == 1 * _4
# _2, _3 = ConditionEq((-1) * _1 + 1 * _4)
((-1) * _1 + 1 * _4) * (1 * _3) == 1 * _2
(1 * ~one + (-1) * _2) * ((-1) * _1 + 1 * _4) == 0
(1 * ~one) * (1 * ~one + (-1) * _2) == 1 * ~out_0
return ~out_0
WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/reference/proving_schemes.html#g16-malleability for implications.
Has generated 7 points
Setup completed.
I'm not sure where the proving key and the verification key are in this output. How does fit into the example above, in terms of what the lambda value is or the C function is?:
- My second question is, what exactly am I doing when I am "creating a witness"?
When I execute the following, a witness is supposed to be created:
~/zokrates compute-witness -a <a> <b> ... <n>
I was under the impression that a "witness" is the preimage that the prover already has. Isn't "witness" something that prover is wanting to prove to the verifier that she has knowledge of this?
The output given to me when I executed the command was this:
zokrates@0a96d8e9989b:~/code/square$ ~/zokrates compute-witness -a a b
Computing witness...
def main(_0, _1) -> (1):
(1 * _0) * (1 * _0) == 1 * _4
# _2, _3 = ConditionEq((-1) * _1 + 1 * _4)
((-1) * _1 + 1 * _4) * (1 * _3) == 1 * _2
(1 * ~one + (-1) * _2) * ((-1) * _1 + 1 * _4) == 0
(1 * ~one) * (1 * ~one + (-1) * _2) == 1 * ~out_0
return ~out_0
Could not parse argument: a
What exactly is happening here?