You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.5 KiB

package plonky2_verifier
import (
. "gnark-plonky2-verifier/field"
"regexp"
"strconv"
"strings"
)
type gate interface {
Id() string
EvalUnfiltered(p *PlonkChip, vars EvaluationVars) []QuadraticExtension
}
func GateInstanceFromId(gateId string) gate {
if strings.HasPrefix(gateId, "ArithmeticGate") {
numOpsRaw := strings.Split(gateId, ":")[1]
numOpsRaw = strings.Split(numOpsRaw, "}")[0]
numOpsRaw = strings.TrimSpace(numOpsRaw)
numOps, err := strconv.Atoi(numOpsRaw)
if err != nil {
panic("Invalid gate ID for ArithmeticGate")
}
return NewArithmeticGate(uint64(numOps))
}
if strings.HasPrefix(gateId, "ConstantGate") {
numConstsRaw := strings.Split(gateId, ":")[1]
numConstsRaw = strings.Split(numConstsRaw, "}")[0]
numConstsRaw = strings.TrimSpace(numConstsRaw)
numConsts, err := strconv.Atoi(numConstsRaw)
if err != nil {
panic("Invalid gate ID")
}
return NewConstantGate(uint64(numConsts))
}
if gateId == "NoopGate" {
return NewNoopGate()
}
if gateId == "PublicInputGate" {
return NewPublicInputGate()
}
if strings.HasPrefix(gateId, "PoseidonGate") {
return NewPoseidonGate()
}
if strings.HasPrefix(gateId, "BaseSumGate") {
// Has the format "BaseSumGate { num_limbs: 32 } + Base: 2"
regEx := "BaseSumGate { num_limbs: (?P<numLimbs>[0-9]+) } \\+ Base: (?P<base>[0-9]+)"
r, err := regexp.Compile(regEx)
if err != nil {
panic("Invalid BaseSumGate regular expression")
}
matches := getRegExMatches(r, gateId)
numLimbsStr, hasNumLimbs := matches["numLimbs"]
baseStr, hasBase := matches["base"]
if !hasNumLimbs || !hasBase {
panic("Invalid BaseSumGate ID")
}
numLimbs, err := strconv.Atoi(numLimbsStr)
if err != nil {
panic("Invalid BaseSumGate ID: " + err.Error())
}
base, err := strconv.Atoi(baseStr)
if err != nil {
panic("Invalid BaseSumGate ID: " + err.Error())
}
return NewBaseSumGate(uint64(numLimbs), uint64(base))
}
if strings.HasPrefix(gateId, "RandomAccessGate") {
// Has the format "RandomAccessGate { bits: 2, num_copies: 13, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
regEx := "RandomAccessGate { bits: (?P<bits>[0-9]+), num_copies: (?P<numCopies>[0-9]+), num_extra_constants: (?P<numExtraConstants>[0-9]+), _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=(?P<base>[0-9]+)>"
r, err := regexp.Compile(regEx)
if err != nil {
panic("Invalid RandomAccessGate regular expression")
}
matches := getRegExMatches(r, gateId)
bitsStr, hasBits := matches["bits"]
numCopiesStr, hasNumCopies := matches["numCopies"]
numExtraConstantsStr, hasNumExtraConstants := matches["numExtraConstants"]
if !hasBits || !hasNumCopies || !hasNumExtraConstants {
panic("Invalid RandomAccessGate ID")
}
bits, err := strconv.Atoi(bitsStr)
if err != nil {
panic("Invalid RandomAccessGate ID: " + err.Error())
}
numCopies, err := strconv.Atoi(numCopiesStr)
if err != nil {
panic("Invalid RandomAccessGate ID: " + err.Error())
}
numExtraConstants, err := strconv.Atoi(numExtraConstantsStr)
if err != nil {
panic("Invalid RandomAccessGate ID: " + err.Error())
}
return NewRandomAccessGate(uint64(bits), uint64(numCopies), uint64(numExtraConstants))
}
return nil
//panic(fmt.Sprintf("Unknown gate ID %s", gateId))
}
func getRegExMatches(r *regexp.Regexp, gateId string) map[string]string {
matches := r.FindStringSubmatch(gateId)
result := make(map[string]string)
for i, name := range r.SubexpNames() {
if i != 0 && name != "" {
result[name] = matches[i]
}
}
return result
}
func (p *PlonkChip) computeFilter(
row uint64,
groupRange Range,
s QuadraticExtension,
manySelector bool,
) QuadraticExtension {
product := p.qeAPI.ONE_QE
for i := groupRange.start; i < groupRange.end; i++ {
if i == uint64(row) {
continue
}
product = p.qeAPI.MulExtension(product, p.qeAPI.SubExtension(p.qeAPI.FieldToQE(NewFieldElement(i)), s))
}
if manySelector {
product = p.qeAPI.MulExtension(product, p.qeAPI.SubExtension(p.qeAPI.FieldToQE(NewFieldElement(UNUSED_SELECTOR)), s))
}
return product
}
func (p *PlonkChip) evalFiltered(
g gate,
vars EvaluationVars,
row uint64,
selectorIndex uint64,
groupRange Range,
numSelectors uint64,
) []QuadraticExtension {
filter := p.computeFilter(row, groupRange, vars.localConstants[selectorIndex], numSelectors > 1)
vars.RemovePrefix(numSelectors)
unfiltered := g.EvalUnfiltered(p, vars)
for i := range unfiltered {
unfiltered[i] = p.qeAPI.MulExtension(unfiltered[i], filter)
}
return unfiltered
}