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}