arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
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}