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}