Trusted Setup
Every Groth16 circuit needs a one-time setup that produces its proving key and its verifying key. This page explains what that setup guarantees, what it does not guarantee, and how Orbinum's keys were produced.
What a Groth16 setup is
The setup runs in two phases:
| Phase | Scope | Output |
|---|---|---|
| 1. Powers of Tau | Any circuit up to a size bound | A shared file of structured parameters |
| 2. Circuit-specific | One circuit, one version | The proving key (.zkey, and .ark for arkworks) and the verifying key |
Each contribution mixes in secret random values. Together these values are the setup's toxic waste. If they are discarded, nobody can produce a valid proof without a valid witness. In a multi-party setup, the keys are sound as long as one contributor discarded their share.
Phase 2 cannot be skipped. A key from phase 1 alone has delta equal to ±gamma or ± the G2
generator, and with it anyone can forge a proof from public key data. The chain refuses such a key
at registration (see Extrinsics).
What the toxic waste could and could not do
Whoever held the complete toxic waste for a circuit could forge proofs, meaning valid proofs for public values that have no valid witness.
| A forger could | Because |
|---|---|
| Shield a note worth more than the deposit | The shield proof is all that ties a commitment's value to the amount paid in |
| Spend notes that do not exist, minting private value | The transfer and unshield proofs are all that show membership and conservation of value |
| Withdraw that value through unshield | The pool pays out from the deposits backing every note, so the loss falls on all depositors together |
A forger could not:
- Deanonymise anyone. A Groth16 proof under a well-formed key reveals nothing about its witness, whoever generated the key. Note contents are protected by the commitment hash and the memo encryption, and neither depends on the setup.
- Spend a particular person's note. That requires the note's nullifier, which is
Poseidon2(commitment, spending_key), and so requires the owner's spending key.
So a compromised setup is a soundness failure (inflation), not a privacy failure.
Current state
The keys registered on the chain today come from a single-contributor setup:
| Phase | How it was run |
|---|---|
| 1 | The Hermez Powers of Tau (powersOfTau28_hez_final_16.ptau, up to 2^16 constraints), a public multi-party ceremony. The file is checked against its published blake2b-512 hash before use. |
| 2 | One contributor per circuit, using fresh random entropy, finished with a public beacon: the hash of a finalized Orbinum testnet block, with 2^10 iterations. |
| Circuit | Version | Beacon block |
|---|---|---|
| Transfer (1) | 3 | #1190708 0x63dca3b61d162679b1acad67bbd7276bfb235a40972792e377fe1ba62910f81f |
| Unshield (2) | 3 | #1190708 0x63dca3b61d162679b1acad67bbd7276bfb235a40972792e377fe1ba62910f81f |
| Shield (3) | 1 | #1118341 0x4a194296be34a87bdb073fa8f678380d3e45c790ffca9fc0ce94de2ec0568ed8 |
The soundness of phase 2 rests on one contributor having discarded their entropy. This is acceptable for a testnet. A public multi-party ceremony is planned before mainnet. It will produce new keys, which will be registered as new circuit versions through the normal rotation.
Checking the keys
Two independent checks are possible:
- The chain uses the published key.
@orbinum/circuitsships amanifest.jsonwith avk_hashfor every circuit version. The chain reports the hash of each registered key throughzkVerifier_getAllCircuitVersions. Both areblake2_256of the arkworks-compressed verifying key, so they must be equal. The app runs this comparison before it proves. - The published key comes from the circuit. The package also contains each circuit's
.r1csand.zkey. Runningsnarkjs zkey verify <circuit>.r1cs powersOfTau28_hez_final_16.ptau <circuit>.zkeychecks that the proving key was derived from that circuit and that Powers of Tau file, with the recorded contributions and beacon.
Neither check can prove that the contributor discarded their entropy. Only a multi-party ceremony removes the need to trust that.
Related
- ZK Proofs: Groth16 over BN254 and the proof flow
- On-Chain Verification: how keys are stored and selected
- Verification Key Rotation: registering new keys and the current on-chain state
- ZK Verifier Reference:
vk_hash, storage and RPC