freecoding.school100% FREE · NO SIGNUP
Proof PeaksISSUE #10 of 38

kzg commitments · polynomial openings

ZeekaVSThe Collision
Zeeka saysKZG commits to a whole polynomial in one group element, then opens it at any point with a constant-size proof — the divisibility check (x−z) | (p(x)−y) is its heart.

KZG (Kate) commitments compress an entire polynomial into a single group element using a trusted-setup structured reference string. To open p(x) at a point z with claimed value y, the prover shows that p(x) − y is divisible by (x − z) — equivalently, that the quotient q(x) = (p(x) − y)/(x − z) exists with no remainder. Verification is one pairing equation and constant-size, no matter how big the polynomial.

KZG underpins proto-danksharding blobs (EIP-4844) and many zk-rollups because it lets a chain commit to large data and later prove individual pieces cheaply. The full scheme hides the evaluation behind pairings; the demo runs the real polynomial-division identity over GF(97), which is exactly the algebra the proof certifies.

Power-ups you unlock

The Collision attacks — common mistakes

Boss battleFor p(x)=5+3x+2x² over GF(97), open at z=4 and verify p(x)−y is divisible by (x−4).

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>
// KZG core (illustrative): opening p(x) at z proves (x−z) | (p(x)−y).
// Real polynomial division over GF(97); pairing-hiding is described in the lesson.
const p=97, mod=(n)=>((n%p)+p)%p;
const pwf=(a,e)=>{ let r=1; a=mod(a); while(e>0){ if(e&1) r=mod(r*a); a=mod(a*a); e>>=1; } return r; };
const ev=(c,x)=> mod(c.reduce((s,a,i)=> s + a*pwf(x,i), 0));
const P=[5,3,2], z=4;                              // p(x) = 5 + 3x + 2x²  (low→high)
const y = ev(P,z);                                 // claimed evaluation p(z)
const hi=[...P].reverse(); hi[hi.length-1]=mod(hi[hi.length-1]-y);   // p(x) − y, high→low
const qHi=[]; let carry=0, rem=0;                  // synthetic division by (x − z)
for(let i=0;i<hi.length;i++){
  const cur=mod(hi[i]+carry);
  if(i<hi.length-1){ qHi.push(cur); carry=mod(cur*z); } else { rem=cur; }
}
const q=[...qHi].reverse();                         // quotient, low→high
const r=11;                                         // spot-check at a random point
const recon = mod( ev(q,r)*mod(r - z) + y );        // q(x)·(x−z) + y
document.getElementById('o').textContent = [
  'p(x) = 5 + 3x + 2x²   over GF(97)',
  'open at z=4 → y = p(4) = ' + y,
  'quotient q(x) coeffs (low→high) = [' + q.join(', ') + ']   remainder = ' + rem,
  'check q(x)·(x−z)+y at x=11 → ' + recon + '   p(11) = ' + ev(P,r),
  'divisible? ' + (rem === 0 && recon === ev(P,r)) + '   → the opening is valid'
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Pedersen Commitments · Homomorphic AddsMerkle Patricia Tries · Ethereum State Deep ›