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	evalZeroPoly := 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		evalZeroPoly,
 39		denominator,
 40	)
 41}
 42
 43func (p *PlonkChip) checkPartialProducts(
 44	numerators []QuadraticExtension,
 45	denominators []QuadraticExtension,
 46	challengeNum uint64,
 47) []QuadraticExtension {
 48	numPartProds := p.commonData.NumPartialProducts
 49	quotDegreeFactor := p.commonData.QuotientDegreeFactor
 50
 51	productAccs := make([]QuadraticExtension, 0, 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, 0, 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	return partialProductChecks
 75}
 76
 77func (p *PlonkChip) evalVanishingPoly() []QuadraticExtension {
 78	// Calculate the k[i] * x
 79	sIDs := make([]QuadraticExtension, p.commonData.Config.NumRoutedWires)
 80
 81	for i := uint64(0); i < p.commonData.Config.NumRoutedWires; i++ {
 82		sIDs[i] = p.qe.ScalarMulExtension(p.proofChallenges.PlonkZeta, p.commonData.KIs[i])
 83	}
 84
 85	// Calculate zeta^n
 86	zetaPowN := p.expPowerOf2Extension(p.proofChallenges.PlonkZeta)
 87
 88	// Calculate L_0(zeta)
 89	l0Zeta := p.evalL0(p.proofChallenges.PlonkZeta, zetaPowN)
 90
 91	vanishingZ1Terms := make([]QuadraticExtension, 0, p.commonData.Config.NumChallenges)
 92	vanishingPartialProductsTerms := make([]QuadraticExtension, 0, p.commonData.Config.NumChallenges*p.commonData.NumPartialProducts)
 93	for i := uint64(0); i < p.commonData.Config.NumChallenges; i++ {
 94		// L_0(zeta) (Z(zeta) - 1) = 0
 95		z1_term := p.qe.SubExtension(
 96			p.qe.MulExtension(l0Zeta, p.openings.PlonkZs[i]),
 97			l0Zeta,
 98		)
 99		vanishingZ1Terms = append(vanishingZ1Terms, z1_term)
100
101		numeratorValues := make([]QuadraticExtension, 0, p.commonData.Config.NumRoutedWires)
102		denominatorValues := make([]QuadraticExtension, 0, p.commonData.Config.NumRoutedWires)
103		for j := uint64(0); j < p.commonData.Config.NumRoutedWires; j++ {
104			// The numerator is `beta * s_id + wire_value + gamma`, and the denominator is
105			// `beta * s_sigma + wire_value + gamma`.
106
107			wireValuePlusGamma := p.qe.AddExtension(
108				p.openings.Wires[j],
109				p.qe.FieldToQE(p.proofChallenges.PlonkGammas[i]),
110			)
111
112			numerator := p.qe.AddExtension(
113				p.qe.MulExtension(
114					p.qe.FieldToQE(p.proofChallenges.PlonkBetas[i]),
115					sIDs[j],
116				),
117				wireValuePlusGamma,
118			)
119
120			denominator := p.qe.AddExtension(
121				p.qe.MulExtension(
122					p.qe.FieldToQE(p.proofChallenges.PlonkBetas[i]),
123					p.openings.PlonkSigmas[j],
124				),
125				wireValuePlusGamma,
126			)
127
128			numeratorValues = append(numeratorValues, numerator)
129			denominatorValues = append(denominatorValues, denominator)
130		}
131
132		vanishingPartialProductsTerms = append(
133			vanishingPartialProductsTerms,
134			p.checkPartialProducts(numeratorValues, denominatorValues, i)...,
135		)
136	}
137
138	return vanishingPartialProductsTerms
139}
140
141func (p *PlonkChip) Verify() {
142	p.evalVanishingPoly()
143}