package plonky2_verifier import ( "github.com/consensys/gnark/frontend" ) type V = frontend.Variable type Challenger struct { sponge_state: [SPONGE_WIDTH]V input_buffer: []V output_buffer: []V } func NewChallenger() Challenger { var sponge_state [SPONGE_WIDTH]V for i := 0; i < SPONGE_WIDTH; i++ { sponge_state[i] = 0 } return Challenger { sponge_state: sponge_state, input_buffer: []V{}, output_buffer: []V{}, } } func (c *Challenger) observe_elements(elements []V) { for _, element := range elements { c.observe_element(element) } } func (c *Challenger) observe_hash(hash []V) { c.observe_elements(hash) } func (c *Challenger) observe_element(element V) { c.output_buffer = V[]{} c.input_buffer = append(c.input_buffer, element) if len(c.input_buffer) == SPONGE_RATE { c.duplexing() } } func (c *Challenger) observe_cap(cap [][]V) { for _, hash := range cap { c.observe_hash(hash) } } func (c *Challenger) duplexing() { if len(c.input_buffer) > SPONGE_RATE { panic("buffer too large") } for i, input := range c.input_buffer { c.sponge_state[i] = input } c.input_buffer = V[]{} c.sponge_state = poseidon(c.sponge_state) c.output_buffer = c.sponge_state[:SPONGE_RATE] } func (c *Challenger) get_challenge() V { if len(c.input_buffer) > 0 || len(c.output_buffer) == 0 { c.duplexing() } result := c.output_buffer[len(c.output_buffer) - 1] c.output_buffer = c.output_buffer[:len(c.output_buffer) - 1] return result } func (c *Challenger) get_n_challenges(n int) []V { result := make([]V, n) for i := 0; i < n; i++ { result[i] = c.get_challenge() } return result }