gnark-plonky2-verifier/verifier/internal/plonk/challenger.go
verifier/internal/plonk/challenger.goRaw
1package plonk
2
3import (
4 "fmt"
5
6 "github.com/consensys/gnark/frontend"
7 "github.com/succinctlabs/gnark-plonky2-verifier/field"
8 "github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
9 "github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
10 "github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/fri"
11)
12
13type ChallengerChip struct {
14 api frontend.API `gnark:"-"`
15 field field.FieldAPI `gnark:"-"`
16 poseidonChip *poseidon.PoseidonChip
17 spongeState [poseidon.SPONGE_WIDTH]field.F
18 inputBuffer []field.F
19 outputBuffer []field.F
20}
21
22func NewChallengerChip(api frontend.API, fieldAPI field.FieldAPI, poseidonChip *poseidon.PoseidonChip) *ChallengerChip {
23 var spongeState [poseidon.SPONGE_WIDTH]field.F
24 var inputBuffer []field.F
25 var outputBuffer []field.F
26
27 for i := 0; i < poseidon.SPONGE_WIDTH; i++ {
28 spongeState[i] = field.ZERO_F
29 }
30
31 return &ChallengerChip{
32 api: api,
33 field: fieldAPI,
34 poseidonChip: poseidonChip,
35 spongeState: spongeState,
36 inputBuffer: inputBuffer,
37 outputBuffer: outputBuffer,
38 }
39}
40
41func (c *ChallengerChip) ObserveElement(element field.F) {
42 c.outputBuffer = clearBuffer(c.outputBuffer)
43 c.inputBuffer = append(c.inputBuffer, element)
44 if len(c.inputBuffer) == poseidon.SPONGE_RATE {
45 c.duplexing()
46 }
47}
48
49func (c *ChallengerChip) ObserveElements(elements []field.F) {
50 for i := 0; i < len(elements); i++ {
51 c.ObserveElement(elements[i])
52 }
53}
54
55func (c *ChallengerChip) ObserveHash(hash poseidon.Hash) {
56 c.ObserveElements(hash[:])
57}
58
59func (c *ChallengerChip) ObserveCap(cap []poseidon.Hash) {
60 for i := 0; i < len(cap); i++ {
61 c.ObserveHash(cap[i])
62 }
63}
64
65func (c *ChallengerChip) ObserveExtensionElement(element field.QuadraticExtension) {
66 c.ObserveElements(element[:])
67}
68
69func (c *ChallengerChip) ObserveExtensionElements(elements []field.QuadraticExtension) {
70 for i := 0; i < len(elements); i++ {
71 c.ObserveExtensionElement(elements[i])
72 }
73}
74
75func (c *ChallengerChip) ObserveOpenings(openings fri.FriOpenings) {
76 for i := 0; i < len(openings.Batches); i++ {
77 c.ObserveExtensionElements(openings.Batches[i].Values)
78 }
79}
80
81func (c *ChallengerChip) GetChallenge() field.F {
82 if len(c.inputBuffer) != 0 || len(c.outputBuffer) == 0 {
83 c.duplexing()
84 }
85
86 challenge := c.outputBuffer[len(c.outputBuffer)-1]
87 c.outputBuffer = c.outputBuffer[:len(c.outputBuffer)-1]
88
89 return challenge
90}
91
92func (c *ChallengerChip) GetNChallenges(n uint64) []field.F {
93 challenges := make([]field.F, n)
94 for i := uint64(0); i < n; i++ {
95 challenges[i] = c.GetChallenge()
96 }
97 return challenges
98}
99
100func (c *ChallengerChip) GetExtensionChallenge() field.QuadraticExtension {
101 values := c.GetNChallenges(2)
102 return field.QuadraticExtension{values[0], values[1]}
103}
104
105func (c *ChallengerChip) GetHash() poseidon.Hash {
106 return [4]field.F{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
107}
108
109func (c *ChallengerChip) GetFriChallenges(commitPhaseMerkleCaps []common.MerkleCap, finalPoly common.PolynomialCoeffs, powWitness field.F, degreeBits uint64, config common.FriConfig) common.FriChallenges {
110 numFriQueries := config.NumQueryRounds
111 friAlpha := c.GetExtensionChallenge()
112
113 var friBetas []field.QuadraticExtension
114 for i := 0; i < len(commitPhaseMerkleCaps); i++ {
115 c.ObserveCap(commitPhaseMerkleCaps[i])
116 friBetas = append(friBetas, c.GetExtensionChallenge())
117 }
118
119 c.ObserveExtensionElements(finalPoly.Coeffs)
120 c.ObserveElement(powWitness)
121
122 friPowResponse := c.GetChallenge()
123 friQueryIndices := c.GetNChallenges(numFriQueries)
124
125 return common.FriChallenges{
126 FriAlpha: friAlpha,
127 FriBetas: friBetas,
128 FriPowResponse: friPowResponse,
129 FriQueryIndices: friQueryIndices,
130 }
131}
132
133func clearBuffer(buffer []field.F) []field.F {
134 return make([]field.F, 0)
135}
136
137func (c *ChallengerChip) duplexing() {
138 if len(c.inputBuffer) > poseidon.SPONGE_RATE {
139 fmt.Println(len(c.inputBuffer))
140 panic("something went wrong")
141 }
142
143 for i := 0; i < len(c.inputBuffer); i++ {
144 c.spongeState[i] = c.inputBuffer[i]
145 }
146 c.inputBuffer = clearBuffer(c.inputBuffer)
147 c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
148 clearBuffer(c.outputBuffer)
149 for i := 0; i < poseidon.SPONGE_RATE; i++ {
150 c.outputBuffer = append(c.outputBuffer, c.spongeState[i])
151 // c.outputBuffer[i] = c.spongeState[i]
152 }
153}