Create a zk-SNARK smart contract verifying that the prover owns a Secret satisfying the following equation: Hash(Secret * Multiplier) = X
, using the Pedersen hash function.
Create a circuit called pedersen-multiplier.zok
import "hashes/pedersen/512bit" as pedersen_hash;
import "utils/pack/u32/nonStrictUnpack256" as unpacker;
import "utils/pack/u32/pack256" as packer;
def main(private field my_secret, public field multiplier) -> field {
u32[8] input_unpacked = unpacker(my_secret * multiplier);
u32[8] zeros = [0; 8];
u32[16] pedersen_input = [...input_unpacked ,...zeros];
u32[8] hash = pedersen_hash(pedersen_input);
return packer(hash);
}
For this example a basic and unstruted setup is used.
$ zokrates compile -i pedersen-multiplier.zok
$ zokrates setup
You can check that verification.key
and abi.json
have been generated by ZoKrates. These 2 files will be used to create the Pact verifier contract.
$ pact_zk_gen gen-module --module-name pedersen-mult-verifier --proof-type string
If everything is fine, the file pedersen-mult-verifier.pact
has been created.
This file is a valid Pact module. It can be deployed on-chain.
It contrains the following function:
(defun verify:bool (multiplier:integer out:integer proof:string)
This function will be called to verify the proof given by the prover. The 3 parameters are:
- multiplier: public argument multiplier of the circuit.
- out: output of the circuit (ie: The hash).
- proof: proof to verify in a stringified format
To test the module, we need:
- the Pact interpreter
- the toolbox pact-util-lib
First run the circuit, and generate a proof. For this example, we choose Secret=123456789
and Multiplier of 26
.
$ zokrates compute-witness -a 123456789 26
$ zokrates generate-proof
A proof.json
file should have been generated by ZoKrates. It contains our inputs and the zk-SNARK proof.
Now let's create a REPL example:
$ pact_zk_gen gen-test
If the tool complains of not finding the pact-util-lib
directory, you can help it by adding the --util-lib-dir
parameter.
If everything is fine, the file pedersen-mult-verifier.repl
has been created.
We can check that it contains a call to our verification module:
(pedersen-mult-verifier.verify 26 2933680909359551385860926297411111605298109531248341983485101731930035552281 "DK0Y2C3h7tI720JHVcyzl1xTU336qrzMXroq9tH9IOECow7sahTOZx-Xgr90-OinVBD3Wx1hdxgAIksC4cWVxQHu0_n0VuDI-C7OWJ4haDWB4T7vHLiR2ViLnAdUlrhyMCjUkKRDPq0VpZFkQj_QzSn937w_A7e2A3h-Gi5uP31cFPxcCFxpP-62f35TPARfR-cupre-E3hcWIbR1E24KAkDjQU74p_WwTYquUHZewunmLqquf3MAj2oGrWdsptveQL6snKuJk5vUYhlfGvkeSo7TPdRJ_SKXmFU31T7folEQEQxJgCjowIOqpl3DsIsyl7kdpVd_n0LnZOI6prDX0V8")
- 1st parameter:
293368....
is the hash. - 2nd parameter
26
is the output multiplier. - 3rd parameter:
"DK0Y2C3h7tI72...
is the zk-SNARK proof
Run the test:
$ pact pedersen-mult-verifier.repl
Proof verification result: true
Load successful
Well done, we've just proven to the smart contract that we know the secret satisfying the equation.