3

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.

T. Rossi
  • 177
  • 4

1 Answers1

2

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.