Zcash Counterfeiting Vulnerability Successfully Remediated


I’m surprised that there hasn’t been a mass exodus of ZEC leaving the Sprout Shielded Pool today. As of right now, there’s still over 265,000 ZEC in that pool:


@hloo I would like to know when the “official” Sprout -> Sapling migration tool from Zcash Company will be available. This news should bump that tools development to the top of the list of things to do.

I personally haven’t made the switch yet because I was waiting for it. Any ETA @nathan-at-least ?


Ariel has submitted a paper describing the vulnerability to eprint. We have plans to update the article when that is available.

The vulnerability was found in the zk-SNARK proving system referred to as the Pinocchio protocol for Sprout shielded addresses. Since Sapling, both Sprout shielded addresses and Sapling shielded addresses use a new proving system referred to as Groth16.


It is imporant to note the vuln is not in the original Pinocchio protocol by Parno et. al but in the variant of it [BCTV14] used by Zcash until the Sapling upgrade.

Until the paper appears on eprint, you can see it here https://github.com/arielgabizon/bctv/blob/master/bctv.pdf


This is my basic level understanding since I’m not sure the paper will answer (for most people) how this affects Zcash:

From the vulnerability details section of the blog post:

The key generation procedure of [BCTV14], in step 3, produces various elements that are the result of evaluating polynomials related to the statement being proven. Some of these elements are unused by the prover and were included by mistake; but their presence allows a cheating prover to circumvent a consistency check, and thereby transform the proof of one statement into a valid-looking proof of a different statement.

So essentially someone would be able to create invalid proofs that appear valid when verifying.

What does that mean, then? Well, from the zk-SNARKs explainer page we can read that a sender of a shielded transaction uses a proof to show the input values sum to the output values for each shielded transfer.

This would allow an attacker to create a shielded transfer (via joinsplit) with any output value they want while appearing valid to nodes verifying the transaction.


Well explained, Paige. Paraphrasing, an easy way to think of it is: The bug would have let you turn a legit ZEC note you had, of any value, say 0.0001 ZEC; to another prefectly legit note of any other value of your choosing, say 1,000,000 ZEC.


Wow! Creating is one thing, how easy is it to spend this counterfeit currency?


The note created is prefectly legit, arguably you could not even call it counterfeit. So it is spent like any other note.
What is actually counterfeit is the SNARK proof that convinced the miners to accept this note in the commitment tree. We hoped initially there was a way to distinguish the counterfiet SNARK proof from a legit one, but seems they are completely indistinguishable


So will we ever know if this actually happened? How much created? If it was ever spent?


A negative value in the sprout value pool would indicate that counterfeiting has occurred. Status of each pool is shown here: https://zcha.in/statistics/network

Deprecating sprout addresses with no anomalies in the sprout value pool is the most concrete resolution: https://github.com/zcash/zcash/issues/3788


Is there another way to check if some counterfeiting occured or is this the only one?

Would it be possible to check suspect high value transactions from the past for example? For example all single transactions over 50,000 ZEC?


From the blog post:

The Zcash Company studied the blockchain for evidence of exploitation: An attack might leave a specific kind of footprint. We found no such footprint.

Just speculation, but this statement in the blog post leads me to believe that there may be a way to see if it was exploited via chain analysis, but details about the detection method would not be wise to disclose publicly.


I can’t think about a single reason why ways of detection shouldn’t be disclosed publicly …
What do i miss?


Why would you publish publicly the fingerprint so an attacker could take steps to avoid it?

Again, I have no idea if such a thing exists, just speculation.


The vulnerability doesn’t excist anymore so it’s all about researching IF the vulnerability was exploited or not.


Maybe the footprint is afterwards, when sending the newly minted ZEC for the first time? We don’t know enough yet.


While the vulnerability doesn’t exist any counterfeit ZEC that was hypothetically generated could just be sitting in the shielded pool. To generate real value it’d need to be withdrawn.

I’d guess it’s as simple as looking at value changes in the shielded pool and not seeing any huge movement indicative of an attack (particularly when say movements of the founders’ reward funds would be known to the people looking). I mean after all if you could do this probably cashing out sooner rather than later would be a good idea if your goal is to maximise profits, but clearly we won’t know until Sprout is deprecated (and even then we’ll never truly know, but it won’t be relevant anymore).


@paige Thanks for the information and explanation!

From my understaning the counterfeiting would of taken place during a transaction and not during mining than? So the coins could appear inside a z-add aka hidden from the public?

Was the turnstile added because of this bug, or was this already on the roadmap?

Maybe im not understanding the turnstile correctly.

With the turnstile, wouldnt that only work if a person exploited the bug and made more coins than have been lost in all the sprout z-add? If people have lost z-add coins and can never convert them into the new Sapling addresses, there could be thousands of hidden coins that have been lost that will never be calculated or withdrawn, skewing the numbers.

Sure there is still a chance the exploiter might take out too much, and the Sprout Shielded Pool would show it, but currently they would have around 200K coin room to work with right now. And its public knowledge how close they would be to being exposed.

Its nice having a audit system in place, but it seems there is some holes in the system and cant be relied on to inform us of counterfeiting.


We’re not sitting on any secret method of detection. The time for secrets is over, thank god. Now we can go back to being fully transparent and being able to focus fully on new improvements instead of opsec, mitigation, remediation, and disclosure!

A perfectly-executed counterfeiting attack would be undetectable by any cryptographic means. The “footprints” mentioned in the blog post are about evidence that would be left if an attacker made mistakes. They might take an existing proof from the blockchain and use that as the base to generate their forgery, or they might generate multiple forgeries, and if so they might not hide all of the evidence connecting the various proofs. @arielgabizon wrote a script that scanned the blockchain for such evidence and did not find any.

There’s no way to detect counterfeiting unless the attacker makes this mistake, or of course if the Sprout pool value goes negative. As we’ve seen in Bytecoin’s counterfeiting exploitation and other exploits in the wild, attackers sometimes make mistakes that leave behind evidence.


I see, thank you for the explanation @zooko