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.SPONGE_WIDTH]gl.Variable
 19	inputBuffer       []gl.Variable
 20	outputBuffer      []gl.Variable
 21}
 22
 23func NewChip(api frontend.API) *Chip {
 24	var spongeState [poseidon.SPONGE_WIDTH]gl.Variable
 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	c.outputBuffer = clearBuffer(c.outputBuffer)
 44	c.inputBuffer = append(c.inputBuffer, element)
 45	if len(c.inputBuffer) == poseidon.SPONGE_RATE {
 46		c.duplexing()
 47	}
 48}
 49
 50func (c *Chip) ObserveElements(elements []gl.Variable) {
 51	for i := 0; i < len(elements); i++ {
 52		c.ObserveElement(elements[i])
 53	}
 54}
 55
 56func (c *Chip) ObserveHash(hash poseidon.GoldilocksHashOut) {
 57	elements := c.poseidonChip.ToVec(hash)
 58	c.ObserveElements(elements)
 59}
 60
 61func (c *Chip) ObserveBN254Hash(hash poseidon.BN254HashOut) {
 62	elements := c.poseidonBN254Chip.ToVec(hash)
 63	c.ObserveElements(elements)
 64}
 65
 66func (c *Chip) ObserveCap(cap []poseidon.BN254HashOut) {
 67	for i := 0; i < len(cap); i++ {
 68		c.ObserveBN254Hash(cap[i])
 69	}
 70}
 71
 72func (c *Chip) ObserveExtensionElement(element gl.QuadraticExtensionVariable) {
 73	c.ObserveElements(element[:])
 74}
 75
 76func (c *Chip) ObserveExtensionElements(elements []gl.QuadraticExtensionVariable) {
 77	for i := 0; i < len(elements); i++ {
 78		c.ObserveExtensionElement(elements[i])
 79	}
 80}
 81
 82func (c *Chip) ObserveOpenings(openings fri.Openings) {
 83	for i := 0; i < len(openings.Batches); i++ {
 84		c.ObserveExtensionElements(openings.Batches[i].Values)
 85	}
 86}
 87
 88func (c *Chip) GetChallenge() gl.Variable {
 89	if len(c.inputBuffer) != 0 || len(c.outputBuffer) == 0 {
 90		c.duplexing()
 91	}
 92
 93	challenge := c.outputBuffer[len(c.outputBuffer)-1]
 94	c.outputBuffer = c.outputBuffer[:len(c.outputBuffer)-1]
 95
 96	return challenge
 97}
 98
 99func (c *Chip) GetNChallenges(n uint64) []gl.Variable {
100	challenges := make([]gl.Variable, n)
101	for i := uint64(0); i < n; i++ {
102		challenges[i] = c.GetChallenge()
103	}
104	return challenges
105}
106
107func (c *Chip) GetExtensionChallenge() gl.QuadraticExtensionVariable {
108	values := c.GetNChallenges(2)
109	return gl.QuadraticExtensionVariable{values[0], values[1]}
110}
111
112func (c *Chip) GetHash() poseidon.GoldilocksHashOut {
113	return [4]gl.Variable{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
114}
115
116func (c *Chip) GetFriChallenges(
117	commitPhaseMerkleCaps []variables.FriMerkleCap,
118	finalPoly variables.PolynomialCoeffs,
119	powWitness gl.Variable,
120	degreeBits uint64,
121	config types.FriConfig,
122) variables.FriChallenges {
123	numFriQueries := config.NumQueryRounds
124	friAlpha := c.GetExtensionChallenge()
125
126	var friBetas []gl.QuadraticExtensionVariable
127	for i := 0; i < len(commitPhaseMerkleCaps); i++ {
128		c.ObserveCap(commitPhaseMerkleCaps[i])
129		friBetas = append(friBetas, c.GetExtensionChallenge())
130	}
131
132	c.ObserveExtensionElements(finalPoly.Coeffs)
133	c.ObserveElement(powWitness)
134
135	friPowResponse := c.GetChallenge()
136	friQueryIndices := c.GetNChallenges(numFriQueries)
137
138	return variables.FriChallenges{
139		FriAlpha:        friAlpha,
140		FriBetas:        friBetas,
141		FriPowResponse:  friPowResponse,
142		FriQueryIndices: friQueryIndices,
143	}
144}
145
146func clearBuffer(buffer []gl.Variable) []gl.Variable {
147	return make([]gl.Variable, 0)
148}
149
150func (c *Chip) duplexing() {
151	if len(c.inputBuffer) > poseidon.SPONGE_RATE {
152		fmt.Println(len(c.inputBuffer))
153		panic("something went wrong")
154	}
155
156	glApi := gl.New(c.api)
157
158	for i := 0; i < len(c.inputBuffer); i++ {
159		c.spongeState[i] = glApi.Reduce(c.inputBuffer[i])
160	}
161	c.inputBuffer = clearBuffer(c.inputBuffer)
162	c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
163	clearBuffer(c.outputBuffer)
164	for i := 0; i < poseidon.SPONGE_RATE; i++ {
165		c.outputBuffer = append(c.outputBuffer, c.spongeState[i])
166	}
167}