I’ve been trying to understand how Zcash and Libsnark works for the past week. Here is my current understanding. Is it correct? Please explain if not correct.

There is a proof attached to any private transaction. It proves the following statement: “I know a private key for an address for which there exist unspent inputs, and do not exist any output transactions.”

Here is how it is proven. Developers of Zcash written a function in C language, which looks through all the transactions in blockchain and returns True if the statement above is correct, and False otherwise. Then Zcash developers use the Libsnark library, given this C function as an input, they output public parameters, which include proving key and verification key. Proving and verification keys are distributed with Zcash software for everyone to use.

Then, when Alice wants to send some money to Bob anonymously, she uses the proving key, her private key with money in it as an input, she generates a private transaction with a proof.

Everyone else uses verification key to make sure the private transaction is correct, meaning if they knew sender’s address and amount, and if they run the C function above on that transaction, it would return True.

My understanding is that proving key contains many randomly generated requests to a proof, and the requests are in form of quadratic polynomials, which should be satisfied by a proof. Is it correct? Are these requests known to sender/prover Alice? Why can’t she create a fake solution that would satisfy this particular subset of proofs, but does not satisfy other requests, which are not being checked?

My understanding is that PCP proofs are always probabilistic, meaning the proofs are not absolute, and there is a small chance that Alice can spend money she does not have. What is the chance of that in case of Zcash? I assume this chance is diminishingly small and is about the same as for Alice to randomly generate someone elses private key with money in it.