3
$\begingroup$

I'm looking through the test and examples of libsnark, let's take for example here: https://github.com/christianlundkvist/libsnark-tutorial/blob/master/src/test-gadget.cpp

at line 19 there's:

  default_r1cs_ppzksnark_pp::init_public_params();
  1. Is this the step that generates the toxic waste?

If so, then the same protoboard is used to generate the verification and proving keys, but then also to create the proof:

  const r1cs_ppzksnark_proof<default_r1cs_ppzksnark_pp> proof = r1cs_ppzksnark_prover<default_r1cs_ppzksnark_pp>(keypair.pk, pb.primary_input(), pb.auxiliary_input());

but shouldn't the prover and the generator be different entities? On the other hand, if I look into the initialisation (init_public_param) in the end I end up in the definition of public_params for curves in libff:

https://github.com/scipr-lab/libff/blob/master/libff/algebra/curves/public_params.hpp

which is just a list of templates, there's nothing private about it.

  1. How should the generator step be separated from the prover step?

  2. The prover has everything (public and private info), so he can indeed generate the circuit from scratch, but the verifier should "not" accept the keypair from the prover, correct?

  3. Finally, the generator (who knows everything, public and private info) prepares the keys, sends them to the prover and the verifier. The prover constructs its own pb (protoboard) because he needs the pb.primary_input() and pb.auxiliary_input() to create the proof, then uses its own pb with the generator's proving key to generate the proof. In my experiments the keys generated by the generator and by the prover are the same even if I initialise 2 different pbs, this is counter intuitive to me because the prover can impersonate the generator. Are the keys the same because the init process of the protoboard is the same?

Thanks for anyone who read this far! Any hint is appreciated T.

$\endgroup$

1 Answer 1

2
$\begingroup$

The line:

  default_r1cs_ppzksnark_pp::init_public_params();

is used to specify the public parameters used by the proving system ($\mathbb{G}_1, \mathbb{G}_2, \mathbb{G}_T, \mathbb{F}_p,$ ... etc). These are known by the generator, prover, and verifier and therefore are not secret.

You are 100% correct that the prover and generator should be different entities - the generator uses random "toxic waste" values to generate the keying material. Anyone who knows these toxic waste values can break the soundness guarantees of the protocol and forge proofs for statements of which it doesn't know a witness.

To answer your other questions:

  1. How should the generator step be separated from the prover step?

The generator should only run once by a trusted party and publish the resulting proving and verifying keys. In practice, secure multiparty computation (MPC) protocols are used such that as long as $1$-out-of-$n$ of the participating parties are honest, the toxic waste is never learned by any of the participants. This is what ZCash did for instance: https://z.cash/technology/paramgen/

  1. The prover has everything (public and private info), so he can indeed generate the circuit from scratch, but the verifier should "not" accept the keypair from the prover, correct?

This is correct. In fact, anyone can generate the circuit (and some corresponding prover/verifier keys) from scratch, because a witness is not required in order to generate these. However, a verifier should never blindly trust keys that were given to it.

  1. Finally, the generator (who knows everything, public and private info) prepares the keys, sends them to the prover and the verifier. The prover constructs its own pb (protoboard) because he needs the pb.primary_input() and pb.auxiliary_input() to create the proof, then uses its own pb with the generator's proving key to generate the proof. In my experiments the keys generated by the generator and by the prover are the same even if I initialise 2 different pbs, this is counter intuitive to me because the prover can impersonate the generator. Are the keys the same because the init process of the protoboard is the same?

I have a feeling that your experiments are off. Libsnark gets randomness from /dev/urandom, so two different invocations of the generator should result in different toxic waste values, and accordingly different keying material. The generator is executed on the line:

const r1cs_ppzksnark_keypair<default_r1cs_ppzksnark_pp> keypair = r1cs_ppzksnark_generator<default_r1cs_ppzksnark_pp>(constraint_system);

If you run this step multiple times, you'll receive a new keypair each time.

$\endgroup$
1
  • $\begingroup$ thank you very much for the answers! I'll double check what is going on with my last point, I've split up the process and let every entity create files (generator creates keys, prover uses the keys "from files" and generate proof). I'll make a test trying to verify a proof with a mix of verification and proving keys coming from a mix of generator and prover (I know it's obviously going to fail, I just need to see it and went on with other developments). While writing files I encountered this: github.com/scipr-lab/libsnark/issues/181 but that's probably another question:) $\endgroup$
    – T. Rossi
    Sep 29, 2020 at 22:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.