arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/plonky2_verifier/exponentiation_gate.go
plonky2_verifier/exponentiation_gate.goRaw
 1package plonky2_verifier
 2
 3import (
 4	"fmt"
 5	. "gnark-plonky2-verifier/field"
 6)
 7
 8type ExponentiationGate struct {
 9	numPowerBits uint64
10}
11
12func NewExponentiationGate(numPowerBits uint64) *ExponentiationGate {
13	return &ExponentiationGate{
14		numPowerBits: numPowerBits,
15	}
16}
17
18func (g *ExponentiationGate) Id() string {
19	return fmt.Sprintf("ExponentiationGate { num_power_bits: %d }", g.numPowerBits)
20}
21
22func (g *ExponentiationGate) wireBase() uint64 {
23	return 0
24}
25
26// / The `i`th bit of the exponent, in little-endian order.
27func (g *ExponentiationGate) wirePowerBit(i uint64) uint64 {
28	if i >= g.numPowerBits {
29		panic("Invalid power bit index")
30	}
31	return 1 + i
32}
33
34func (g *ExponentiationGate) wireOutput() uint64 {
35	return 1 + g.numPowerBits
36}
37
38func (g *ExponentiationGate) wireIntermediateValue(i uint64) uint64 {
39	if i >= g.numPowerBits {
40		panic("Invalid intermediate value index")
41	}
42	return 2 + g.numPowerBits + i
43}
44
45func (g *ExponentiationGate) EvalUnfiltered(p *PlonkChip, vars EvaluationVars) []QuadraticExtension {
46	base := vars.localWires[g.wireBase()]
47
48	var powerBits []QuadraticExtension
49	for i := uint64(0); i < g.numPowerBits; i++ {
50		powerBits = append(powerBits, vars.localWires[g.wirePowerBit(i)])
51	}
52
53	var intermediateValues []QuadraticExtension
54	for i := uint64(0); i < g.numPowerBits; i++ {
55		intermediateValues = append(intermediateValues, vars.localWires[g.wireIntermediateValue(i)])
56	}
57
58	output := vars.localWires[g.wireOutput()]
59
60	var constraints []QuadraticExtension
61
62	for i := uint64(0); i < g.numPowerBits; i++ {
63		var prevIntermediateValue QuadraticExtension
64		if i == 0 {
65			prevIntermediateValue = p.qeAPI.ONE_QE
66		} else {
67			prevIntermediateValue = p.qeAPI.SquareExtension(intermediateValues[i-1])
68		}
69
70		// powerBits is in LE order, but we accumulate in BE order.
71		curBit := powerBits[g.numPowerBits-i-1]
72
73		// Do a polynomial representation of generaized select (where the selector variable doesn't have to be binary)
74		// if b { x } else { y }
75		// i.e. `bx - (by-y)`.
76		tmp := p.qeAPI.MulExtension(curBit, p.qeAPI.ONE_QE)
77		tmp = p.qeAPI.SubExtension(tmp, p.qeAPI.ONE_QE)
78		mulBy := p.qeAPI.MulExtension(curBit, base)
79		mulBy = p.qeAPI.SubExtension(mulBy, tmp)
80		intermediateValueDiff := p.qeAPI.MulExtension(prevIntermediateValue, mulBy)
81		intermediateValueDiff = p.qeAPI.SubExtension(intermediateValueDiff, intermediateValues[i])
82		constraints = append(constraints, intermediateValueDiff)
83	}
84
85	outputDiff := p.qeAPI.SubExtension(output, intermediateValues[g.numPowerBits-1])
86	constraints = append(constraints, outputDiff)
87
88	return constraints
89}