Zeeka saysSome SNARKs need a one-time trusted setup. A powers-of-tau ceremony has many people contribute randomness so the secret stays safe as long as a single participant is honest.
SNARKs like Groth16 need a structured reference string built from a secret τ — the powers g^(τ⁰), g^(τ¹), …. If anyone learns τ (the "toxic waste"), they can forge proofs, so τ must be destroyed. A powers-of-tau ceremony spreads the risk: each participant multiplies in fresh randomness and then deletes it, so the final τ is the product of everyone's contributions.
The security guarantee is 1-of-n honest: as long as a single participant truly deleted their share, no one can reconstruct τ — even if everyone else colludes. The demo builds a 3-party SRS and shows that knowing 2 of 3 contributions cannot recover the secret. Universal setups (KZG) go further: one ceremony serves many circuits.
Power-ups you unlock
Produces a structured reference string of powers g^(τ^i)
The secret τ must never be reconstructable (the toxic waste)
Each participant multiplies in fresh randomness, then deletes it
Secure if at least one of n participants deleted their share
Universal setups (KZG) are reusable across many circuits
The Collision attacks — common mistakes
A single-party setup — one leak compromises everything
Participants who do not actually destroy their randomness
Assuming a per-circuit setup can be reused for another circuit
Skipping public verification that contributions were applied
Boss battleSimulate a 3-party ceremony and show that knowing 2 of 3 contributions cannot recover the secret τ.
Example code
<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
// powers of tau: τ = ∏ contributions. secure if ≥1 participant deleted theirs.
const p=1009, g=11, pw=(a,e,m)=>{ let r=1; a%=m; while(e>0){ if(e&1) r=(r*a)%m; a=(a*a)%m; e>>=1; } return r; };
const contrib=[3, 7, 5]; // each party's secret, deleted after use
let tau=1; contrib.forEach(c => { tau=(tau*c)%(p-1); });
const srs=[]; for(let i=0;i<4;i++) srs.push(pw(g, pw(tau,i,p-1), p)); // [g^τ⁰ … g^τ³]
const attackerKnows=[3,7]; // learns 2 of 3 (party 3 deleted)
const guess=attackerKnows.reduce((a,b)=>(a*b)%(p-1),1);
document.getElementById('o').textContent = [
'3 participants, τ = 3·7·5 = ' + tau + ' (mod ' + (p-1) + ')',
'SRS = [g^τ⁰ … g^τ³] = ' + srs.join(', '),
'attacker knows 2 of 3 (party 3 deleted theirs):',
' best guess of τ = ' + guess + ' vs real ' + tau + ' → ' + (guess===tau?'BROKEN':'still hidden'),
'1-of-n honest is enough → one deletion secures the ceremony'
].join('\n');
</script></body></html>