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		numLimbs, hasNumLimbs := matches["numLimbs"]
 61		base, hasBase := matches["base"]
 62		if !hasNumLimbs || !hasBase {
 63			panic("Invalid BaseSumGate ID")
 64		}
 65
 66		return NewBaseSumGate(uint64(numLimbs), uint64(base))
 67	}
 68
 69	if strings.HasPrefix(gateId, "RandomAccessGate") {
 70		// Has the format "RandomAccessGate { bits: 2, num_copies: 13, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
 71
 72		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]+)>"
 73		r, err := regexp.Compile(regEx)
 74		if err != nil {
 75			panic("Invalid RandomAccessGate regular expression")
 76		}
 77
 78		matches := getRegExMatches(r, gateId)
 79		bits, hasBits := matches["bits"]
 80		numCopies, hasNumCopies := matches["numCopies"]
 81		numExtraConstants, hasNumExtraConstants := matches["numExtraConstants"]
 82		if !hasBits || !hasNumCopies || !hasNumExtraConstants {
 83			panic("Invalid RandomAccessGate ID")
 84		}
 85
 86		return NewRandomAccessGate(uint64(bits), uint64(numCopies), uint64(numExtraConstants))
 87	}
 88
 89	if strings.HasPrefix(gateId, "ArithmeticExtension") {
 90		// Has the format "ArithmeticExtensionGate { num_ops: 10 }"
 91
 92		regEx := "ArithmeticExtensionGate { num_ops: (?P<numOps>[0-9]+) }"
 93		r, err := regexp.Compile(regEx)
 94		if err != nil {
 95			panic("Invalid ArithmeticExtensionGate regular expression")
 96		}
 97
 98		matches := getRegExMatches(r, gateId)
 99		numOps, hasNumOps := matches["numOps"]
100		if !hasNumOps {
101			panic("Invalid ArithmeticExtensionGate ID")
102		}
103
104		return NewArithmeticExtensionGate(uint64(numOps))
105	}
106
107	if strings.HasPrefix(gateId, "MultiplicationExtension") {
108		// Has the format "ArithmeticExtensionGate { num_ops: 10 }"
109
110		regEx := "MultiplicationExtension { num_ops: (?P<numOps>[0-9]+) }"
111		r, err := regexp.Compile(regEx)
112		if err != nil {
113			panic("Invalid MultiplicationExtension regular expression")
114		}
115
116		matches := getRegExMatches(r, gateId)
117		numOps, hasNumOps := matches["numOps"]
118		if !hasNumOps {
119			panic("Invalid MultiplicationExtension ID")
120		}
121
122		return NewMultiplicationExtensionGate(uint64(numOps))
123	}
124
125	if strings.HasPrefix(gateId, "ReducingExtensionGate") {
126		// Has the format "ReducingExtensionGate { num_coeffs: 33 }"
127
128		regEx := "ReducingExtensionGate { num_coeffs: (?P<numCoeffs>[0-9]+) }"
129		r, err := regexp.Compile(regEx)
130		if err != nil {
131			panic("Invalid ReducingExtensionGate regular expression")
132		}
133
134		matches := getRegExMatches(r, gateId)
135		numCoeffs, hasNumCoeffs := matches["numCoeffs"]
136		if !hasNumCoeffs {
137			panic("Invalid ReducingExtensionGate ID")
138		}
139
140		return NewReducingExtensionGate(uint64(numCoeffs))
141	}
142
143	if strings.HasPrefix(gateId, "ReducingGate") {
144		// Has the format "ReducingGate { num_coeffs: 33 }"
145
146		regEx := "ReducingGate { num_coeffs: (?P<numCoeffs>[0-9]+) }"
147		r, err := regexp.Compile(regEx)
148		if err != nil {
149			panic("Invalid ReducingGate regular expression")
150		}
151
152		matches := getRegExMatches(r, gateId)
153		numCoeffs, hasNumCoeffs := matches["numCoeffs"]
154		if !hasNumCoeffs {
155			panic("Invalid ReducingGate ID")
156		}
157
158		return NewReducingGate(uint64(numCoeffs))
159	}
160
161	if strings.HasPrefix(gateId, "ExponentiationGate") {
162		// Has the format "ExponentiationGate { num_power_bits: 67, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
163
164		regEx := "ExponentiationGate { num_power_bits: (?P<numPowerBits>[0-9]+), _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=(?P<base>[0-9]+)>"
165		r, err := regexp.Compile(regEx)
166		if err != nil {
167			panic("Invalid ExponentiationGate regular expression")
168		}
169
170		matches := getRegExMatches(r, gateId)
171		numPowerBits, hasNumPowerBits := matches["numPowerBits"]
172		if !hasNumPowerBits {
173			panic("Invalid ExponentiationGate ID")
174		}
175
176		return NewExponentiationGate(uint64(numPowerBits))
177	}
178
179	return nil
180	//panic(fmt.Sprintf("Unknown gate ID %s", gateId))
181}
182
183func getRegExMatches(r *regexp.Regexp, gateId string) map[string]int {
184	matches := r.FindStringSubmatch(gateId)
185	result := make(map[string]int)
186	for i, name := range r.SubexpNames() {
187		if i != 0 && name != "" {
188			value, err := strconv.Atoi(matches[i])
189			if err != nil {
190				panic("Invalid field value for \"name\": " + err.Error())
191			}
192			result[name] = value
193		}
194	}
195
196	return result
197}
198
199func (p *PlonkChip) computeFilter(
200	row uint64,
201	groupRange Range,
202	s QuadraticExtension,
203	manySelector bool,
204) QuadraticExtension {
205	product := p.qeAPI.ONE_QE
206	for i := groupRange.start; i < groupRange.end; i++ {
207		if i == uint64(row) {
208			continue
209		}
210
211		product = p.qeAPI.MulExtension(product, p.qeAPI.SubExtension(p.qeAPI.FieldToQE(NewFieldElement(i)), s))
212	}
213
214	if manySelector {
215		product = p.qeAPI.MulExtension(product, p.qeAPI.SubExtension(p.qeAPI.FieldToQE(NewFieldElement(UNUSED_SELECTOR)), s))
216	}
217
218	return product
219}
220
221func (p *PlonkChip) evalFiltered(
222	g gate,
223	vars EvaluationVars,
224	row uint64,
225	selectorIndex uint64,
226	groupRange Range,
227	numSelectors uint64,
228) []QuadraticExtension {
229	filter := p.computeFilter(row, groupRange, vars.localConstants[selectorIndex], numSelectors > 1)
230
231	vars.RemovePrefix(numSelectors)
232
233	unfiltered := g.EvalUnfiltered(p, vars)
234	for i := range unfiltered {
235		unfiltered[i] = p.qeAPI.MulExtension(unfiltered[i], filter)
236	}
237	return unfiltered
238}