arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/challenger/challenger.go
challenger/challenger.goRaw
  1package challenger
  2
  3import (
  4	"fmt"
  5
  6	"github.com/consensys/gnark/frontend"
  7	"github.com/succinctlabs/gnark-plonky2-verifier/fri"
  8	gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
  9	"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
 10	"github.com/succinctlabs/gnark-plonky2-verifier/types"
 11	"github.com/succinctlabs/gnark-plonky2-verifier/variables"
 12)
 13
 14type Chip struct {
 15	api               frontend.API `gnark:"-"`
 16	poseidonChip      *poseidon.GoldilocksChip
 17	poseidonBN254Chip *poseidon.BN254Chip
 18	spongeState       poseidon.GoldilocksState
 19	inputBuffer       []gl.Variable
 20	outputBuffer      []gl.Variable
 21}
 22
 23func NewChip(api frontend.API) *Chip {
 24	var spongeState poseidon.GoldilocksState
 25	var inputBuffer []gl.Variable
 26	var outputBuffer []gl.Variable
 27	for i := 0; i < poseidon.SPONGE_WIDTH; i++ {
 28		spongeState[i] = gl.Zero()
 29	}
 30	poseidonChip := poseidon.NewGoldilocksChip(api)
 31	poseidonBN254Chip := poseidon.NewBN254Chip(api)
 32	return &Chip{
 33		api:               api,
 34		poseidonChip:      poseidonChip,
 35		poseidonBN254Chip: poseidonBN254Chip,
 36		spongeState:       spongeState,
 37		inputBuffer:       inputBuffer,
 38		outputBuffer:      outputBuffer,
 39	}
 40}
 41
 42func (c *Chip) ObserveElement(element gl.Variable) {
 43	// Clear the output buffer
 44	c.outputBuffer = make([]gl.Variable, 0)
 45	c.inputBuffer = append(c.inputBuffer, element)
 46	if len(c.inputBuffer) == poseidon.SPONGE_RATE {
 47		c.duplexing()
 48	}
 49}
 50
 51func (c *Chip) ObserveElements(elements []gl.Variable) {
 52	for i := 0; i < len(elements); i++ {
 53		c.ObserveElement(elements[i])
 54	}
 55}
 56
 57func (c *Chip) ObserveHash(hash poseidon.GoldilocksHashOut) {
 58	elements := c.poseidonChip.ToVec(hash)
 59	c.ObserveElements(elements)
 60}
 61
 62func (c *Chip) ObserveBN254Hash(hash poseidon.BN254HashOut) {
 63	elements := c.poseidonBN254Chip.ToVec(hash)
 64	c.ObserveElements(elements)
 65}
 66
 67func (c *Chip) ObserveCap(cap []poseidon.BN254HashOut) {
 68	for i := 0; i < len(cap); i++ {
 69		c.ObserveBN254Hash(cap[i])
 70	}
 71}
 72
 73func (c *Chip) ObserveExtensionElement(element gl.QuadraticExtensionVariable) {
 74	c.ObserveElements(element[:])
 75}
 76
 77func (c *Chip) ObserveExtensionElements(elements []gl.QuadraticExtensionVariable) {
 78	for i := 0; i < len(elements); i++ {
 79		c.ObserveExtensionElement(elements[i])
 80	}
 81}
 82
 83func (c *Chip) ObserveOpenings(openings fri.Openings) {
 84	for i := 0; i < len(openings.Batches); i++ {
 85		c.ObserveExtensionElements(openings.Batches[i].Values)
 86	}
 87}
 88
 89func (c *Chip) ObserveFriConfig(
 90	config types.FriConfig,
 91) {
 92	c.ObserveElement(gl.NewVariable(config.RateBits))
 93	c.ObserveElement(gl.NewVariable(config.CapHeight))
 94	c.ObserveElement(gl.NewVariable(config.ProofOfWorkBits))
 95	for i := 0; i < len(config.ReductionStrategy); i++ {
 96		c.ObserveElement(gl.NewVariable(config.ReductionStrategy[i]))
 97	}
 98	c.ObserveElement(gl.NewVariable(config.NumQueryRounds))
 99}
100
101func (c *Chip) ObserveFriParams(
102	params types.FriParams,
103) {
104	c.ObserveFriConfig(params.Config)
105	c.ObserveElement(gl.NewVariable(0)) // Hiding, should be always false as hiding is not supported in gnark-plonky2-verifier
106	c.ObserveElement(gl.NewVariable(params.DegreeBits))
107	for i := 0; i < len(params.ReductionArityBits); i++ {
108		c.ObserveElement(gl.NewVariable(params.ReductionArityBits[i]))
109	}
110}
111
112func (c *Chip) GetChallenge() gl.Variable {
113	if len(c.inputBuffer) != 0 || len(c.outputBuffer) == 0 {
114		c.duplexing()
115	}
116
117	challenge := c.outputBuffer[len(c.outputBuffer)-1]
118	c.outputBuffer = c.outputBuffer[:len(c.outputBuffer)-1]
119
120	return challenge
121}
122
123func (c *Chip) GetNChallenges(n uint64) []gl.Variable {
124	challenges := make([]gl.Variable, n)
125	for i := uint64(0); i < n; i++ {
126		challenges[i] = c.GetChallenge()
127	}
128	return challenges
129}
130
131func (c *Chip) GetExtensionChallenge() gl.QuadraticExtensionVariable {
132	values := c.GetNChallenges(2)
133	return gl.QuadraticExtensionVariable{values[0], values[1]}
134}
135
136func (c *Chip) GetHash() poseidon.GoldilocksHashOut {
137	return [poseidon.POSEIDON_GL_HASH_SIZE]gl.Variable{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
138}
139
140func (c *Chip) GetFriChallenges(
141	commitPhaseMerkleCaps []variables.FriMerkleCap,
142	finalPoly variables.PolynomialCoeffs,
143	powWitness gl.Variable,
144	config types.FriConfig,
145) variables.FriChallenges {
146	numFriQueries := config.NumQueryRounds
147	friAlpha := c.GetExtensionChallenge()
148
149	var friBetas []gl.QuadraticExtensionVariable
150	for i := 0; i < len(commitPhaseMerkleCaps); i++ {
151		c.ObserveCap(commitPhaseMerkleCaps[i])
152		friBetas = append(friBetas, c.GetExtensionChallenge())
153	}
154
155	c.ObserveExtensionElements(finalPoly.Coeffs)
156	c.ObserveElement(powWitness)
157
158	friPowResponse := c.GetChallenge()
159	friQueryIndices := c.GetNChallenges(numFriQueries)
160
161	return variables.FriChallenges{
162		FriAlpha:        friAlpha,
163		FriBetas:        friBetas,
164		FriPowResponse:  friPowResponse,
165		FriQueryIndices: friQueryIndices,
166	}
167}
168
169func (c *Chip) duplexing() {
170	if len(c.inputBuffer) > poseidon.SPONGE_RATE {
171		fmt.Println(len(c.inputBuffer))
172		panic("something went wrong")
173	}
174
175	glApi := gl.New(c.api)
176
177	for i := 0; i < len(c.inputBuffer); i++ {
178		c.spongeState[i] = glApi.Reduce(c.inputBuffer[i])
179	}
180	// Clear the input buffer
181	c.inputBuffer = make([]gl.Variable, 0)
182	c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
183
184	// Clear the output buffer
185	c.outputBuffer = make([]gl.Variable, 0)
186	for i := 0; i < poseidon.SPONGE_RATE; i++ {
187		c.outputBuffer = append(c.outputBuffer, c.spongeState[i])
188	}
189}