arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/plonky2_verifier/plonk.go
plonky2_verifier/plonk.goRaw
  1package plonky2_verifier
  2
  3import (
  4	. "gnark-ed25519/field"
  5
  6	"github.com/consensys/gnark/frontend"
  7)
  8
  9type PlonkChip struct {
 10	api   frontend.API
 11	field frontend.API
 12	qe    *QuadraticExtensionAPI
 13
 14	commonData      CommonCircuitData
 15	proofChallenges ProofChallenges
 16	openings        OpeningSet
 17}
 18
 19func (p *PlonkChip) expPowerOf2Extension(x QuadraticExtension) QuadraticExtension {
 20	for i := uint64(0); i < p.commonData.DegreeBits; i++ {
 21		x = p.qe.SquareExtension(x)
 22	}
 23
 24	return x
 25}
 26
 27func (p *PlonkChip) evalL0(x QuadraticExtension, xPowN QuadraticExtension) QuadraticExtension {
 28	// L_0(x) = (x^n - 1) / (n * (x - 1))
 29	eval_zero_poly := p.qe.SubExtension(
 30		xPowN,
 31		p.qe.ONE,
 32	)
 33	denominator := p.qe.SubExtension(
 34		p.qe.ScalarMulExtension(x, p.qe.DEGREE_BITS_F),
 35		p.qe.DEGREE_BITS_QE,
 36	)
 37	return p.qe.DivExtension(
 38		eval_zero_poly,
 39		denominator,
 40	)
 41}
 42
 43func (p *PlonkChip) checkPartialProducts(
 44	numerators []QuadraticExtension,
 45	denominators []QuadraticExtension,
 46	challengeNum uint64) []QuadraticExtension {
 47
 48	numPartProds := p.commonData.NumPartialProducts
 49	quotDegreeFactor := p.commonData.QuotientDegreeFactor
 50
 51	productAccs := make([]QuadraticExtension, numPartProds+2)
 52	productAccs = append(productAccs, p.openings.PlonkZs[challengeNum])
 53	productAccs = append(productAccs, p.openings.PartialProducts[challengeNum*numPartProds:(challengeNum+1)*numPartProds]...)
 54	productAccs = append(productAccs, p.openings.PlonkZsNext[challengeNum])
 55
 56	partialProductChecks := make([]QuadraticExtension, numPartProds)
 57
 58	for i := uint64(0); i < numPartProds; i += 1 {
 59		ppStartIdx := i * quotDegreeFactor
 60		numeProduct := numerators[ppStartIdx]
 61		denoProduct := denominators[ppStartIdx]
 62		for j := uint64(1); j < quotDegreeFactor; j++ {
 63			numeProduct = p.qe.MulExtension(numeProduct, numerators[ppStartIdx+j])
 64			denoProduct = p.qe.MulExtension(denoProduct, denominators[ppStartIdx+j])
 65		}
 66
 67		partialProductCheck := p.qe.SubExtension(
 68			p.qe.MulExtension(productAccs[i], numeProduct),
 69			p.qe.MulExtension(productAccs[i+1], denoProduct),
 70		)
 71
 72		partialProductChecks = append(partialProductChecks, partialProductCheck)
 73	}
 74
 75	return partialProductChecks
 76}
 77
 78func (p *PlonkChip) evalVanishingPoly() []QuadraticExtension {
 79	// Calculate the k[i] * x
 80	s_ids := make([]QuadraticExtension, p.commonData.Config.NumRoutedWires)
 81
 82	for i := uint64(0); i < p.commonData.Config.NumRoutedWires; i++ {
 83		p.qe.ScalarMulExtension(p.proofChallenges.PlonkZeta, p.commonData.KIs[i])
 84	}
 85
 86	// Calculate zeta^n
 87	zeta_pow_n := p.expPowerOf2Extension(p.proofChallenges.PlonkZeta)
 88
 89	// Calculate L_0(zeta)
 90	l_0_zeta := p.evalL0(p.proofChallenges.PlonkZeta, zeta_pow_n)
 91
 92	vanishing_z1_terms := make([]QuadraticExtension, p.commonData.Config.NumChallenges)
 93	vanishing_partial_products_terms := make([]QuadraticExtension, p.commonData.Config.NumChallenges*p.commonData.NumPartialProducts)
 94	numerator_values := make([]QuadraticExtension, p.commonData.Config.NumChallenges*p.commonData.Config.NumRoutedWires)
 95	denominator_values := make([]QuadraticExtension, p.commonData.Config.NumChallenges*p.commonData.Config.NumRoutedWires)
 96	for i := uint64(0); i < p.commonData.Config.NumChallenges; i++ {
 97		// L_0(zeta) (Z(zeta) - 1) = 0
 98		z1_term := p.qe.SubExtension(
 99			p.qe.MulExtension(l_0_zeta, p.openings.PlonkZs[i]),
100			l_0_zeta,
101		)
102		vanishing_z1_terms = append(vanishing_z1_terms, z1_term)
103
104		for j := uint64(0); j < p.commonData.Config.NumRoutedWires; j++ {
105			// The numerator is `beta * s_id + wire_value + gamma`, and the denominator is
106			// `beta * s_sigma + wire_value + gamma`.
107			wire_value_plus_gamma := p.qe.AddExtension(
108				p.openings.Wires[j],
109				p.qe.FieldToQE(p.proofChallenges.PlonkGammas[i]),
110			)
111			numerator := p.qe.AddExtension(
112				p.qe.MulExtension(
113					p.qe.FieldToQE(p.proofChallenges.PlonkBetas[i]),
114					s_ids[j],
115				),
116				wire_value_plus_gamma,
117			)
118
119			denominator := p.qe.AddExtension(
120				p.qe.MulExtension(
121					p.qe.FieldToQE(p.proofChallenges.PlonkBetas[i]),
122					p.openings.PlonkSigmas[j],
123				),
124				wire_value_plus_gamma,
125			)
126
127			numerator_values = append(numerator_values, numerator)
128			denominator_values = append(denominator_values, denominator)
129		}
130
131		vanishing_partial_products_terms = append(
132			vanishing_partial_products_terms,
133			p.checkPartialProducts(numerator_values, denominator_values, i)...,
134		)
135	}
136
137	return vanishing_partial_products_terms
138}
139
140func (p *PlonkChip) Verify() {
141	p.evalVanishingPoly()
142}