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	poseidonBN128Chip *poseidon.PoseidonBN128Chip
 18	spongeState       [poseidon.SPONGE_WIDTH]frontend.Variable
 19	inputBuffer       []field.F
 20	outputBuffer      []field.F
 21}
 22
 23func NewChallengerChip(api frontend.API, fieldAPI field.FieldAPI, poseidonChip *poseidon.PoseidonChip, poseidonBN128Chip *poseidon.PoseidonBN128Chip) *ChallengerChip {
 24	var spongeState [poseidon.SPONGE_WIDTH]frontend.Variable
 25	var inputBuffer []field.F
 26	var outputBuffer []field.F
 27
 28	for i := 0; i < poseidon.SPONGE_WIDTH; i++ {
 29		spongeState[i] = frontend.Variable(0)
 30	}
 31
 32	return &ChallengerChip{
 33		api:               api,
 34		field:             fieldAPI,
 35		poseidonChip:      poseidonChip,
 36		poseidonBN128Chip: poseidonBN128Chip,
 37		spongeState:       spongeState,
 38		inputBuffer:       inputBuffer,
 39		outputBuffer:      outputBuffer,
 40	}
 41}
 42
 43func (c *ChallengerChip) ObserveElement(element field.F) {
 44	c.outputBuffer = clearBuffer(c.outputBuffer)
 45	c.inputBuffer = append(c.inputBuffer, element)
 46	if len(c.inputBuffer) == poseidon.SPONGE_RATE {
 47		c.duplexing()
 48	}
 49}
 50
 51func (c *ChallengerChip) ObserveElements(elements []field.F) {
 52	for i := 0; i < len(elements); i++ {
 53		c.ObserveElement(elements[i])
 54	}
 55}
 56
 57func (c *ChallengerChip) ObserveHash(hash poseidon.PoseidonHashOut) {
 58	elements := c.poseidonChip.ToVec(hash)
 59	c.ObserveElements(elements)
 60}
 61
 62func (c *ChallengerChip) ObserveBN128Hash(hash poseidon.PoseidonBN128HashOut) {
 63	elements := c.poseidonBN128Chip.ToVec(hash)
 64	c.ObserveElements(elements)
 65}
 66
 67func (c *ChallengerChip) ObserveCap(cap []poseidon.PoseidonBN128HashOut) {
 68	for i := 0; i < len(cap); i++ {
 69		c.ObserveBN128Hash(cap[i])
 70	}
 71}
 72
 73func (c *ChallengerChip) ObserveExtensionElement(element field.QuadraticExtension) {
 74	c.ObserveElements(element[:])
 75}
 76
 77func (c *ChallengerChip) ObserveExtensionElements(elements []field.QuadraticExtension) {
 78	for i := 0; i < len(elements); i++ {
 79		c.ObserveExtensionElement(elements[i])
 80	}
 81}
 82
 83func (c *ChallengerChip) ObserveOpenings(openings fri.FriOpenings) {
 84	for i := 0; i < len(openings.Batches); i++ {
 85		c.ObserveExtensionElements(openings.Batches[i].Values)
 86	}
 87}
 88
 89func (c *ChallengerChip) GetChallenge() field.F {
 90	if len(c.inputBuffer) != 0 || len(c.outputBuffer) == 0 {
 91		c.duplexing()
 92	}
 93
 94	challenge := c.outputBuffer[len(c.outputBuffer)-1]
 95	c.outputBuffer = c.outputBuffer[:len(c.outputBuffer)-1]
 96
 97	return challenge
 98}
 99
100func (c *ChallengerChip) GetNChallenges(n uint64) []field.F {
101	challenges := make([]field.F, n)
102	for i := uint64(0); i < n; i++ {
103		challenges[i] = c.GetChallenge()
104	}
105	return challenges
106}
107
108func (c *ChallengerChip) GetExtensionChallenge() field.QuadraticExtension {
109	values := c.GetNChallenges(2)
110	return field.QuadraticExtension{values[0], values[1]}
111}
112
113func (c *ChallengerChip) GetHash() poseidon.PoseidonHashOut {
114	return [4]field.F{c.GetChallenge(), c.GetChallenge(), c.GetChallenge(), c.GetChallenge()}
115}
116
117func (c *ChallengerChip) GetFriChallenges(commitPhaseMerkleCaps []common.MerkleCap, finalPoly common.PolynomialCoeffs, powWitness field.F, degreeBits uint64, config common.FriConfig) common.FriChallenges {
118	numFriQueries := config.NumQueryRounds
119	friAlpha := c.GetExtensionChallenge()
120
121	var friBetas []field.QuadraticExtension
122	for i := 0; i < len(commitPhaseMerkleCaps); i++ {
123		c.ObserveCap(commitPhaseMerkleCaps[i])
124		friBetas = append(friBetas, c.GetExtensionChallenge())
125	}
126
127	c.ObserveExtensionElements(finalPoly.Coeffs)
128	c.ObserveElement(powWitness)
129
130	friPowResponse := c.GetChallenge()
131	friQueryIndices := c.GetNChallenges(numFriQueries)
132
133	return common.FriChallenges{
134		FriAlpha:        friAlpha,
135		FriBetas:        friBetas,
136		FriPowResponse:  friPowResponse,
137		FriQueryIndices: friQueryIndices,
138	}
139}
140
141func clearBuffer(buffer []field.F) []field.F {
142	return make([]field.F, 0)
143}
144
145func (c *ChallengerChip) duplexing() {
146	if len(c.inputBuffer) > poseidon.SPONGE_RATE {
147		fmt.Println(len(c.inputBuffer))
148		panic("something went wrong")
149	}
150
151	for i := 0; i < len(c.inputBuffer); i++ {
152		c.spongeState[i] = c.field.Reduce(c.inputBuffer[i]).Limbs[0]
153	}
154	c.inputBuffer = clearBuffer(c.inputBuffer)
155	c.spongeState = c.poseidonChip.Poseidon(c.spongeState)
156	clearBuffer(c.outputBuffer)
157	for i := 0; i < poseidon.SPONGE_RATE; i++ {
158		c.outputBuffer = append(c.outputBuffer, c.field.NewElement(c.spongeState[i]))
159	}
160}