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