circom2 for zkSNARK
zkSNARK
High-level idea
- Turn your problem (graph isomorphism, discrete log, etc.) into a function whose inputs you want to hide.
- Turn that function into an equivalent set of R1CS (or other)
equations
- Basically, an arithmetic circuit, that is a bunch of
+
and*
operations on prime field elements - Simplified: equations of the form \(x_i + x_j = x_k, or x_i * x_j = x_k\)
- Basically, an arithmetic circuit, that is a bunch of
- Generate a ZKP for satisfiability of the R1CS
zkSNARK prove constraints
The best is those zk protocols that generate a proof of the same size regardless of the length of the computation and the verification also takes the same time.
Example:
1 | Function inputs: x1, x2, x3, x4 |
zkSNARK: I know some secret (x1,x2,x3,x4) such that the result of this computation f is OUT. Here's is a signature that prove that I know such a tuple, without telling you what the tuple actually is.
From the perspective of a human, the procedure of the computation is made as follows:
1 | Function inputs: x1, x2, x3, x4 |
However, from perspective of SNARK generating the proof, where only
+
and *
is made as follows: SNARK prover
inputs: x1, x2, x3, x4, y1, y2, OUT SNARK prover output: a “signature”
that only verifies if the following constraints are satisfied:
1 | y1 == x1 + x2 |
The SNARK basically is just a proof of satifaction of some
constraints. For the snark machinery, it will see seven varibles
x1, x2, x3, x4, y1, y2, OUT
. The prover's out is a
signature、a proof that should only be valid if the above three
equations are ture. OUT is the value that will be reveal to the
verifier. The snark proof is about proving that the prover knows some
six values satisfy this three equations for a particular public value of
OUT. Proving that I know some solution to this set of equations is
equivalent to proving that I have executed this function.
If you care about actually hiding some inputs, then the funtion you are computiong is better to be a funtion that cannot be recoverable or reversed, which is zkSNARK. But sometime you dont care about that, you just care about a succict proof of the computation, which is SNARK.
If the example include division, such as:
1 | Function inputs: x1, x2, x3, x4 |
Then, the computation can be seen as follows:
From the perspective of human,
1 | Function inputs: x1, x2, x3, x4 |
From the perspective of prover, (note the equivalence of the two representation)
1 | SNARK prover inputs: x1, x2, x3, x4, y1, y2, OUT |
In zkrepl, the code can be shown as follows:
1 | pragma circom 2.1.4; |
Note: In the end of the INPUT and before the }
, no comma
is allowed, or the error "Expected double-quoted property name in JSON
at position 62" will be reported.
1 | pragma circom 2.1.4; |
The circom is a specification of a constraint system that you are allowed to prove satisfaction, rather than a program To elimanate the intermediate value redundancy for us, the circom provide the function like what we precompute the intermediate value in python or somewhere else.
1 | pragma circom 2.1.4; |
Num2Bits
1 | pragma circom 2.1.4; |
simplify the above code,
1 | pragma circom 2.1.4; |
Errors like the following report, normally the problem is that a semicolon is forget to be put at the end of a sentences.
1 | error[P1000]: UnrecognizedToken { token: (586, Token(78, "}"), 587), expected: ["\"!=\"", "\"%\"", "\"&\"", "\"&&\"", "\")\"", "\"*\"", "\"**\"", "\"+\"", "\",\"", "\"-\"", "\"-->\"", "\"/\"", "\":\"", "\";\"", "\"<\"", "\"<--\"", "\"<<\"", "\"<=\"", "\"<==\"", "\"=\"", "\"==\"", "\"===\"", "\"==>\"", "\">\"", "\">=\"", "\">>\"", "\"?\"", "\"\\\\\"", "\"]\"", "\"^\"", "\"|\"", "\"||\""] } |
Note: the private input signal should be declared as
signal input
.
template and component
template is more like the declaration, and component is more like the initiation.
The input signal of a template allows us to connect a wire into the subcomponent of the whole subcircuit
1 | pragma circom 2.1.4; |
Poseidon hash function is a snark friendly hash, which is composed of a bunch of pluses and times operations.