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