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
  7type PlonkChip struct {
  8	qe *QuadraticExtensionAPI
  9
 10	commonData      CommonCircuitData
 11	proofChallenges ProofChallenges
 12	openings        OpeningSet
 13
 14	DEGREE        F
 15	DEGREE_BITS_F F
 16	DEGREE_QE     QuadraticExtension
 17}
 18
 19func NewPlonkChip(qe *QuadraticExtensionAPI, commonData CommonCircuitData) *PlonkChip {
 20	// TODO:  Should degreeBits be verified that it fits within the field and that degree is within uint64?
 21
 22	return &PlonkChip{
 23		qe: qe,
 24
 25		commonData: commonData,
 26
 27		DEGREE:        NewFieldElement(1 << commonData.DegreeBits),
 28		DEGREE_BITS_F: NewFieldElement(commonData.DegreeBits),
 29		DEGREE_QE:     QuadraticExtension{NewFieldElement(1 << commonData.DegreeBits), NewFieldElement(0)},
 30	}
 31}
 32
 33func (p *PlonkChip) expPowerOf2Extension(x QuadraticExtension) QuadraticExtension {
 34	for i := uint64(0); i < p.commonData.DegreeBits; i++ {
 35		x = p.qe.SquareExtension(x)
 36	}
 37
 38	return x
 39}
 40
 41func (p *PlonkChip) evalL0(x QuadraticExtension, xPowN QuadraticExtension) QuadraticExtension {
 42	// L_0(x) = (x^n - 1) / (n * (x - 1))
 43	evalZeroPoly := p.qe.SubExtension(
 44		xPowN,
 45		p.qe.ONE,
 46	)
 47	denominator := p.qe.SubExtension(
 48		p.qe.ScalarMulExtension(x, p.DEGREE),
 49		p.DEGREE_QE,
 50	)
 51	return p.qe.DivExtension(
 52		evalZeroPoly,
 53		denominator,
 54	)
 55}
 56
 57func (p *PlonkChip) checkPartialProducts(
 58	numerators []QuadraticExtension,
 59	denominators []QuadraticExtension,
 60	challengeNum uint64,
 61) []QuadraticExtension {
 62	numPartProds := p.commonData.NumPartialProducts
 63	quotDegreeFactor := p.commonData.QuotientDegreeFactor
 64
 65	productAccs := make([]QuadraticExtension, 0, numPartProds+2)
 66	productAccs = append(productAccs, p.openings.PlonkZs[challengeNum])
 67	productAccs = append(productAccs, p.openings.PartialProducts[challengeNum*numPartProds:(challengeNum+1)*numPartProds]...)
 68	productAccs = append(productAccs, p.openings.PlonkZsNext[challengeNum])
 69
 70	partialProductChecks := make([]QuadraticExtension, 0, numPartProds)
 71
 72	for i := uint64(0); i <= numPartProds; i += 1 {
 73		ppStartIdx := i * quotDegreeFactor
 74		numeProduct := numerators[ppStartIdx]
 75		denoProduct := denominators[ppStartIdx]
 76		for j := uint64(1); j < quotDegreeFactor; j++ {
 77			numeProduct = p.qe.MulExtension(numeProduct, numerators[ppStartIdx+j])
 78			denoProduct = p.qe.MulExtension(denoProduct, denominators[ppStartIdx+j])
 79		}
 80
 81		partialProductCheck := p.qe.SubExtension(
 82			p.qe.MulExtension(productAccs[i], numeProduct),
 83			p.qe.MulExtension(productAccs[i+1], denoProduct),
 84		)
 85
 86		partialProductChecks = append(partialProductChecks, partialProductCheck)
 87	}
 88	return partialProductChecks
 89}
 90
 91func (p *PlonkChip) evalVanishingPoly() []QuadraticExtension {
 92	// Calculate the k[i] * x
 93	sIDs := make([]QuadraticExtension, p.commonData.Config.NumRoutedWires)
 94
 95	for i := uint64(0); i < p.commonData.Config.NumRoutedWires; i++ {
 96		sIDs[i] = p.qe.ScalarMulExtension(p.proofChallenges.PlonkZeta, p.commonData.KIs[i])
 97	}
 98
 99	// Calculate zeta^n
100	zetaPowN := p.expPowerOf2Extension(p.proofChallenges.PlonkZeta)
101
102	// Calculate L_0(zeta)
103	l0Zeta := p.evalL0(p.proofChallenges.PlonkZeta, zetaPowN)
104
105	vanishingZ1Terms := make([]QuadraticExtension, 0, p.commonData.Config.NumChallenges)
106	vanishingPartialProductsTerms := make([]QuadraticExtension, 0, p.commonData.Config.NumChallenges*p.commonData.NumPartialProducts)
107	for i := uint64(0); i < p.commonData.Config.NumChallenges; i++ {
108		// L_0(zeta) (Z(zeta) - 1) = 0
109		z1_term := p.qe.MulExtension(
110			l0Zeta,
111			p.qe.SubExtension(p.openings.PlonkZs[i], p.qe.ONE))
112		vanishingZ1Terms = append(vanishingZ1Terms, z1_term)
113
114		numeratorValues := make([]QuadraticExtension, 0, p.commonData.Config.NumRoutedWires)
115		denominatorValues := make([]QuadraticExtension, 0, p.commonData.Config.NumRoutedWires)
116		for j := uint64(0); j < p.commonData.Config.NumRoutedWires; j++ {
117			// The numerator is `beta * s_id + wire_value + gamma`, and the denominator is
118			// `beta * s_sigma + wire_value + gamma`.
119
120			wireValuePlusGamma := p.qe.AddExtension(
121				p.openings.Wires[j],
122				p.qe.FieldToQE(p.proofChallenges.PlonkGammas[i]),
123			)
124
125			numerator := p.qe.AddExtension(
126				p.qe.MulExtension(
127					p.qe.FieldToQE(p.proofChallenges.PlonkBetas[i]),
128					sIDs[j],
129				),
130				wireValuePlusGamma,
131			)
132
133			denominator := p.qe.AddExtension(
134				p.qe.MulExtension(
135					p.qe.FieldToQE(p.proofChallenges.PlonkBetas[i]),
136					p.openings.PlonkSigmas[j],
137				),
138				wireValuePlusGamma,
139			)
140
141			numeratorValues = append(numeratorValues, numerator)
142			denominatorValues = append(denominatorValues, denominator)
143		}
144
145		vanishingPartialProductsTerms = append(
146			vanishingPartialProductsTerms,
147			p.checkPartialProducts(numeratorValues, denominatorValues, i)...,
148		)
149	}
150
151	return append(vanishingZ1Terms, vanishingPartialProductsTerms...)
152}
153
154func (p *PlonkChip) Verify() {
155	p.evalVanishingPoly()
156
157	/*
158		vanishingPolys := p.evalVanishingPoly()
159
160		for _, vp := range vanishingPolys {
161			//fmt.Println(vp)
162	}*/
163}