2 Answers
2

My understanding is that the verifier is anyone that maintains the blockchain.

All nodes that fully-validate transactions will be acting as zk-SNARK verifiers.

In particular, is the transaction graph still public?

The transaction graph for shielded transactions is as private as it is feasible to be.

When a note is created, a commitment cm to the note is made public (effectively a hash of the note). When the note is spent, its nullifier nf is derived (effectively another hash) and made public. To the person spending the note, the local transaction graph looks like this:

(... -> tx1 -> cm)[<--- note --->](nf -> tx2 -> ...)

But to all other nodes on the network, all they see is:

(... -> tx1 -> cm) (nf -> tx2 -> ...)

That is, they see when some note was created, and when some note was spent, but without knowing the private information (and assuming they can't find pre-images for the hash functions), they can't directly link the two events. They can exclude certain combinations of transactions, however:

A note cannot be spent before it was created, so when a nullifier is published, everyone knows that it corresponds to some commitment that was published previously, but not to any commitment that was published later.

Some nullifiers and commitments can be reasonably excluded based on other revealed information, e.g. if an exchange's records get leaked, or if they are in transactions that also involve transparent inputs and outputs. In particular, if you send funds from a t-address to a z-address and then on to another t-address, you get basically no privacy. See my previous answer about this for more information.

If I decide to send x amount of Zcash to another user, what is the statement that zkSNARKs will hide?

The specific statement (for the Sprout circuit) being proved with the zk-SNARK (and therefore hidden) is given in section 4.9.1 of the Zcash protocol spec. Summarising its parts here:

Nullifier integrity: the published nullifiers correctly correspond to the input notes being spent.

Note commitment integrity: the published commitments correctly correspond to the output notes being created.

Merkle path validity: there is a valid path from the commitments of the input notes to the commitment Merkle tree anchor rt.

This enforces that the notes being spent were previously created.

Balance: The sum of the input note values is equal to the sum of the output note values (plus any funds entering or leaving the transparent pool, e.g. fees).

Spend authority: the provided spending key for each input note correctly corresponds to the public key the note was created for.

And a couple of other correctness requirements.

This is the majority of the consensus rules that get applied to transparent transactions. The only one missing is the double-spend rule, which is still checked outside the circuit (by checking that a nullifier has never been seen before).

The most high level view is that it proves somewhere exists some set of UTXOs and the sum of their values is equal or larger than sum of this transaction outputs. The exact shielded value is encrypted inside the transaction and is never disclosed.

Everyone who runs a full node and has access to the trusted setup data (which you have to download in order to run full node) can validate shielded transaction. Nobody, nevertheless, learns details of which exact UTXO have been used and what their values were.