package gates
|
|
|
|
import (
|
|
"github.com/consensys/gnark/frontend"
|
|
"github.com/succinctlabs/gnark-plonky2-verifier/field"
|
|
)
|
|
|
|
type EvaluateGatesChip struct {
|
|
api frontend.API
|
|
qeAPI *field.QuadraticExtensionAPI
|
|
|
|
gates []Gate
|
|
numGateConstraints uint64
|
|
|
|
selectorsInfo SelectorsInfo
|
|
}
|
|
|
|
func NewEvaluateGatesChip(
|
|
api frontend.API,
|
|
qeAPI *field.QuadraticExtensionAPI,
|
|
gates []Gate,
|
|
numGateConstraints uint64,
|
|
selectorsInfo SelectorsInfo,
|
|
) *EvaluateGatesChip {
|
|
return &EvaluateGatesChip{
|
|
api: api,
|
|
qeAPI: qeAPI,
|
|
|
|
gates: gates,
|
|
numGateConstraints: numGateConstraints,
|
|
|
|
selectorsInfo: selectorsInfo,
|
|
}
|
|
}
|
|
|
|
func (g *EvaluateGatesChip) computeFilter(
|
|
row uint64,
|
|
groupRange Range,
|
|
s field.QuadraticExtension,
|
|
manySelector bool,
|
|
) field.QuadraticExtension {
|
|
product := g.qeAPI.ONE_QE
|
|
for i := groupRange.start; i < groupRange.end; i++ {
|
|
if i == uint64(row) {
|
|
continue
|
|
}
|
|
|
|
product = g.qeAPI.MulExtension(product, g.qeAPI.SubExtension(g.qeAPI.FieldToQE(field.NewFieldConst(i)), s))
|
|
}
|
|
|
|
if manySelector {
|
|
product = g.qeAPI.MulExtension(product, g.qeAPI.SubExtension(g.qeAPI.FieldToQE(field.NewFieldConst(UNUSED_SELECTOR)), s))
|
|
}
|
|
|
|
return product
|
|
}
|
|
|
|
func (g *EvaluateGatesChip) evalFiltered(
|
|
gate Gate,
|
|
vars EvaluationVars,
|
|
row uint64,
|
|
selectorIndex uint64,
|
|
groupRange Range,
|
|
numSelectors uint64,
|
|
) []field.QuadraticExtension {
|
|
filter := g.computeFilter(row, groupRange, vars.localConstants[selectorIndex], numSelectors > 1)
|
|
|
|
vars.RemovePrefix(numSelectors)
|
|
|
|
unfiltered := gate.EvalUnfiltered(g.api, g.qeAPI, vars)
|
|
for i := range unfiltered {
|
|
unfiltered[i] = g.qeAPI.MulExtension(unfiltered[i], filter)
|
|
}
|
|
return unfiltered
|
|
}
|
|
|
|
func (g *EvaluateGatesChip) EvaluateGateConstraints(vars EvaluationVars) []field.QuadraticExtension {
|
|
constraints := make([]field.QuadraticExtension, g.numGateConstraints)
|
|
for i := range constraints {
|
|
constraints[i] = g.qeAPI.ZERO_QE
|
|
}
|
|
|
|
for i, gate := range g.gates {
|
|
selectorIndex := g.selectorsInfo.selectorIndices[i]
|
|
|
|
gateConstraints := g.evalFiltered(
|
|
gate,
|
|
vars,
|
|
uint64(i),
|
|
selectorIndex,
|
|
g.selectorsInfo.groups[selectorIndex],
|
|
g.selectorsInfo.NumSelectors(),
|
|
)
|
|
|
|
for i, constraint := range gateConstraints {
|
|
if uint64(i) >= g.numGateConstraints {
|
|
panic("num_constraints() gave too low of a number")
|
|
}
|
|
constraints[i] = g.qeAPI.AddExtension(constraints[i], constraint)
|
|
}
|
|
}
|
|
|
|
return constraints
|
|
}
|