gnark-plonky2-verifier/plonky2_verifier/challenger.go
plonky2_verifier/challenger.goRaw
1package plonky2_verifier
2
3import (
4 "github.com/consensys/gnark/frontend"
5)
6
7type V = frontend.Variable
8
9type Challenger struct {
10 sponge_state: [SPONGE_WIDTH]V
11 input_buffer: []V
12 output_buffer: []V
13}
14
15func NewChallenger() Challenger {
16 var sponge_state [SPONGE_WIDTH]V
17 for i := 0; i < SPONGE_WIDTH; i++ {
18 sponge_state[i] = 0
19 }
20 return Challenger {
21 sponge_state: sponge_state,
22 input_buffer: []V{},
23 output_buffer: []V{},
24 }
25}
26
27func (c *Challenger) observe_elements(elements []V) {
28 for _, element := range elements {
29 c.observe_element(element)
30 }
31}
32
33func (c *Challenger) observe_hash(hash []V) {
34 c.observe_elements(hash)
35}
36
37func (c *Challenger) observe_element(element V) {
38 c.output_buffer = V[]{}
39 c.input_buffer = append(c.input_buffer, element)
40 if len(c.input_buffer) == SPONGE_RATE {
41 c.duplexing()
42 }
43}
44
45func (c *Challenger) observe_cap(cap [][]V) {
46 for _, hash := range cap {
47 c.observe_hash(hash)
48 }
49}
50
51func (c *Challenger) duplexing() {
52 if len(c.input_buffer) > SPONGE_RATE { panic("buffer too large") }
53
54 for i, input := range c.input_buffer {
55 c.sponge_state[i] = input
56 }
57 c.input_buffer = V[]{}
58
59 c.sponge_state = poseidon(c.sponge_state)
60
61 c.output_buffer = c.sponge_state[:SPONGE_RATE]
62}
63
64func (c *Challenger) get_challenge() V {
65 if len(c.input_buffer) > 0 || len(c.output_buffer) == 0 {
66 c.duplexing()
67 }
68 result := c.output_buffer[len(c.output_buffer) - 1]
69 c.output_buffer = c.output_buffer[:len(c.output_buffer) - 1]
70 return result
71}
72
73func (c *Challenger) get_n_challenges(n int) []V {
74 result := make([]V, n)
75 for i := 0; i < n; i++ {
76 result[i] = c.get_challenge()
77 }
78 return result
79}