arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/plonky2_verifier/gate.go
plonky2_verifier/gate.goRaw
  1package plonky2_verifier
  2
  3import (
  4	. "gnark-plonky2-verifier/field"
  5	"regexp"
  6	"strconv"
  7	"strings"
  8)
  9
 10type gate interface {
 11	Id() string
 12	EvalUnfiltered(p *PlonkChip, vars EvaluationVars) []QuadraticExtension
 13}
 14
 15func GateInstanceFromId(gateId string) gate {
 16	if strings.HasPrefix(gateId, "ArithmeticGate") {
 17		numOpsRaw := strings.Split(gateId, ":")[1]
 18		numOpsRaw = strings.Split(numOpsRaw, "}")[0]
 19		numOpsRaw = strings.TrimSpace(numOpsRaw)
 20		numOps, err := strconv.Atoi(numOpsRaw)
 21		if err != nil {
 22			panic("Invalid gate ID for ArithmeticGate")
 23		}
 24		return NewArithmeticGate(uint64(numOps))
 25	}
 26
 27	if strings.HasPrefix(gateId, "ConstantGate") {
 28		numConstsRaw := strings.Split(gateId, ":")[1]
 29		numConstsRaw = strings.Split(numConstsRaw, "}")[0]
 30		numConstsRaw = strings.TrimSpace(numConstsRaw)
 31		numConsts, err := strconv.Atoi(numConstsRaw)
 32		if err != nil {
 33			panic("Invalid gate ID")
 34		}
 35		return NewConstantGate(uint64(numConsts))
 36	}
 37
 38	if gateId == "NoopGate" {
 39		return NewNoopGate()
 40	}
 41
 42	if gateId == "PublicInputGate" {
 43		return NewPublicInputGate()
 44	}
 45
 46	if strings.HasPrefix(gateId, "PoseidonGate") {
 47		return NewPoseidonGate()
 48	}
 49
 50	if strings.HasPrefix(gateId, "BaseSumGate") {
 51		// Has the format "BaseSumGate { num_limbs: 32 } + Base: 2"
 52
 53		regEx := "BaseSumGate { num_limbs: (?P<numLimbs>[0-9]+) } \\+ Base: (?P<base>[0-9]+)"
 54		r, err := regexp.Compile(regEx)
 55		if err != nil {
 56			panic("Invalid BaseSumGate regular expression")
 57		}
 58
 59		matches := getRegExMatches(r, gateId)
 60		numLimbsStr, hasNumLimbs := matches["numLimbs"]
 61		baseStr, hasBase := matches["base"]
 62		if !hasNumLimbs || !hasBase {
 63			panic("Invalid BaseSumGate ID")
 64		}
 65
 66		numLimbs, err := strconv.Atoi(numLimbsStr)
 67		if err != nil {
 68			panic("Invalid BaseSumGate ID: " + err.Error())
 69		}
 70
 71		base, err := strconv.Atoi(baseStr)
 72		if err != nil {
 73			panic("Invalid BaseSumGate ID: " + err.Error())
 74		}
 75
 76		return NewBaseSumGate(uint64(numLimbs), uint64(base))
 77	}
 78
 79	if strings.HasPrefix(gateId, "RandomAccessGate") {
 80		// Has the format "RandomAccessGate { bits: 2, num_copies: 13, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
 81
 82		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]+)>"
 83		r, err := regexp.Compile(regEx)
 84		if err != nil {
 85			panic("Invalid RandomAccessGate regular expression")
 86		}
 87
 88		matches := getRegExMatches(r, gateId)
 89		bitsStr, hasBits := matches["bits"]
 90		numCopiesStr, hasNumCopies := matches["numCopies"]
 91		numExtraConstantsStr, hasNumExtraConstants := matches["numExtraConstants"]
 92		if !hasBits || !hasNumCopies || !hasNumExtraConstants {
 93			panic("Invalid RandomAccessGate ID")
 94		}
 95
 96		bits, err := strconv.Atoi(bitsStr)
 97		if err != nil {
 98			panic("Invalid RandomAccessGate ID: " + err.Error())
 99		}
100
101		numCopies, err := strconv.Atoi(numCopiesStr)
102		if err != nil {
103			panic("Invalid RandomAccessGate ID: " + err.Error())
104		}
105
106		numExtraConstants, err := strconv.Atoi(numExtraConstantsStr)
107		if err != nil {
108			panic("Invalid RandomAccessGate ID: " + err.Error())
109		}
110
111		return NewRandomAccessGate(uint64(bits), uint64(numCopies), uint64(numExtraConstants))
112	}
113
114	return nil
115	//panic(fmt.Sprintf("Unknown gate ID %s", gateId))
116}
117
118func getRegExMatches(r *regexp.Regexp, gateId string) map[string]string {
119	matches := r.FindStringSubmatch(gateId)
120	result := make(map[string]string)
121	for i, name := range r.SubexpNames() {
122		if i != 0 && name != "" {
123			result[name] = matches[i]
124		}
125	}
126
127	return result
128}
129
130func (p *PlonkChip) computeFilter(
131	row uint64,
132	groupRange Range,
133	s QuadraticExtension,
134	manySelector bool,
135) QuadraticExtension {
136	product := p.qeAPI.ONE_QE
137	for i := groupRange.start; i < groupRange.end; i++ {
138		if i == uint64(row) {
139			continue
140		}
141
142		product = p.qeAPI.MulExtension(product, p.qeAPI.SubExtension(p.qeAPI.FieldToQE(NewFieldElement(i)), s))
143	}
144
145	if manySelector {
146		product = p.qeAPI.MulExtension(product, p.qeAPI.SubExtension(p.qeAPI.FieldToQE(NewFieldElement(UNUSED_SELECTOR)), s))
147	}
148
149	return product
150}
151
152func (p *PlonkChip) evalFiltered(
153	g gate,
154	vars EvaluationVars,
155	row uint64,
156	selectorIndex uint64,
157	groupRange Range,
158	numSelectors uint64,
159) []QuadraticExtension {
160	filter := p.computeFilter(row, groupRange, vars.localConstants[selectorIndex], numSelectors > 1)
161
162	vars.RemovePrefix(numSelectors)
163
164	unfiltered := g.EvalUnfiltered(p, vars)
165	for i := range unfiltered {
166		unfiltered[i] = p.qeAPI.MulExtension(unfiltered[i], filter)
167	}
168	return unfiltered
169}